Skip to content

Document rare structure dependence of MaterialsProjectCompatibility corrections #2731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ def elastic_centered_graph(self, start_node=None):
)
logging.debug(
f" Delta image from node {str(node)} to neighbor {str(node_neighbor)} : "
f"({', '.join([str(iii) for iii in myddelta])})"
f"({', '.join(map(str, myddelta))})"
)
# Loop on the edges of this neighbor
for n1, n2, key, edata in node_neighbor_edges:
Expand Down Expand Up @@ -905,13 +905,14 @@ def from_graph(cls, g):
def description(self, full=False):
"""
Args:
full ():
full (bool): Whether to return a short or full description.

Returns:
str: A description of the connected component.
"""
out = ["Connected component with environment nodes :"]
if not full:
out.extend([str(en) for en in sorted(self.graph.nodes())])
out.extend(map(str, sorted(self.graph.nodes())))
return "\n".join(out)
for en in sorted(self.graph.nodes()):
out.append(f"{en}, connected to :")
Expand Down
5 changes: 2 additions & 3 deletions pymatgen/analysis/diffraction/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def get_plot(
for two_theta, i, hkls in zip(xrd.x, xrd.y, xrd.hkls):
if two_theta_range[0] <= two_theta <= two_theta_range[1]:
hkl_tuples = [hkl["hkl"] for hkl in hkls]
label = ", ".join([str(hkl_tuple) for hkl_tuple in hkl_tuples]) # 'full' label
label = ", ".join(map(str, hkl_tuples)) # 'full' label
ax.plot([two_theta, two_theta], [0, i], color="k", linewidth=3, label=label)

if annotate_peaks == "full":
Expand All @@ -131,7 +131,7 @@ def get_plot(
)
elif annotate_peaks == "compact":
if all(all(i < 10 for i in hkl_tuple) for hkl_tuple in hkl_tuples):
label = ",".join(["".join([str(i) for i in hkl_tuple]) for hkl_tuple in hkl_tuples])
label = ",".join(["".join(map(str, hkl_tuple)) for hkl_tuple in hkl_tuples])
# 'compact' label. Would be unclear for indices >= 10
# It would have more than 3 figures, e.g. 1031

Expand Down Expand Up @@ -222,7 +222,6 @@ def get_unique_families(hkls):
Returns:
{hkl: multiplicity}: A dict with unique hkl and multiplicity.
"""

# TODO: Definitely can be sped up.
def is_perm(hkl1, hkl2):
h1 = np.abs(hkl1)
Expand Down
44 changes: 22 additions & 22 deletions pymatgen/analysis/structure_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,11 @@ def connectivity_array(self):
Provides connectivity array.

Returns:
connectivity: An array of shape [atomi, atomj, imagej]. atomi is
connectivity: An array of shape [atom_i, atom_j, image_j]. atom_i is
the index of the atom in the input structure. Since the second
atom can be outside of the unit cell, it must be described
by both an atom index and an image index. Array data is the
solid angle of polygon between atomi and imagej of atomj
solid angle of polygon between atom_i and image_j of atom_j
"""
# shape = [site, axis]
cart_coords = np.array(self.s.cart_coords)
Expand All @@ -290,24 +290,24 @@ def connectivity_array(self):
connectivity = np.zeros(cs)
vts = np.array(vt.vertices)
for (ki, kj), v in vt.ridge_dict.items():
atomi = ki // n_images
atomj = kj // n_images
atom_i = ki // n_images
atom_j = kj // n_images

imagei = ki % n_images
imagej = kj % n_images
image_i = ki % n_images
image_j = kj % n_images

if imagei != n_images // 2 and imagej != n_images // 2:
if image_i != n_images // 2 and image_j != n_images // 2:
continue

if imagei == n_images // 2:
# atomi is in original cell
if image_i == n_images // 2:
# atom_i is in original cell
val = solid_angle(vt.points[ki], vts[v])
connectivity[atomi, atomj, imagej] = val
connectivity[atom_i, atom_j, image_j] = val

if imagej == n_images // 2:
# atomj is in original cell
if image_j == n_images // 2:
# atom_j is in original cell
val = solid_angle(vt.points[kj], vts[v])
connectivity[atomj, atomi, imagei] = val
connectivity[atom_j, atom_i, image_i] = val

if -10.101 in vts[v]:
warn("Found connectivity with infinite vertex. Cutoff is too low, and results may be incorrect")
Expand All @@ -327,10 +327,10 @@ def get_connections(self):
with their real-space distances.
"""
con = []
maxconn = self.max_connectivity
for ii in range(0, maxconn.shape[0]):
for jj in range(0, maxconn.shape[1]):
if maxconn[ii][jj] != 0:
max_conn = self.max_connectivity
for ii in range(0, max_conn.shape[0]):
for jj in range(0, max_conn.shape[1]):
if max_conn[ii][jj] != 0:
dist = self.s.get_distance(ii, jj)
con.append([ii, jj, dist])
return con
Expand Down Expand Up @@ -383,7 +383,7 @@ def get_max_bond_lengths(structure, el_radius_updates=None):

Args:
structure: (structure)
el_radius_updates: (dict) symbol->float to update atomic radii
el_radius_updates: (dict) symbol->float to update atom_ic radii

Returns: (dict) - (Element1, Element2) -> float. The two elements are
ordered by Z.
Expand Down Expand Up @@ -488,9 +488,9 @@ def parse_oxide(self) -> tuple[str, int]:
is_superoxide = False
is_ozonide = True
try:
nbonds = len(set(bond_atoms))
n_bonds = len(set(bond_atoms))
except UnboundLocalError:
nbonds = 0
n_bonds = 0
if is_ozonide:
str_oxide = "ozonide"
elif is_superoxide:
Expand All @@ -500,8 +500,8 @@ def parse_oxide(self) -> tuple[str, int]:
else:
str_oxide = "oxide"
if str_oxide == "oxide":
nbonds = int(comp["O"])
return str_oxide, nbonds
n_bonds = int(comp["O"])
return str_oxide, n_bonds


def oxide_type(
Expand Down
6 changes: 3 additions & 3 deletions pymatgen/core/trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ def write_Xdatcar(
syms = [site.specie.symbol for site in self[0]]
site_symbols = [a[0] for a in itertools.groupby(syms)]
syms = [site.specie.symbol for site in self[0]]
natoms = [len(tuple(a[1])) for a in itertools.groupby(syms)]
n_atoms = [len(tuple(a[1])) for a in itertools.groupby(syms)]

for si, frac_coords in enumerate(self.frac_coords):
# Only print out the info block if
Expand All @@ -377,10 +377,10 @@ def write_Xdatcar(
_lattice = self.lattice[si]

for latt_vec in _lattice:
lines.append(f'{" ".join([str(el) for el in latt_vec])}')
lines.append(f'{" ".join(map(str, latt_vec))}')

lines.append(" ".join(site_symbols))
lines.append(" ".join([str(x) for x in natoms]))
lines.append(" ".join(map(str, n_atoms)))

lines.append(f"Direct configuration= {si + 1}")

Expand Down
19 changes: 13 additions & 6 deletions pymatgen/entries/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,14 +818,21 @@ def __init__(
@cached_class
class MaterialsProject2020Compatibility(Compatibility):
"""
This class implements the Materials Project 2020 energy correction scheme,
which incorporates uncertainty quantification and allows for mixing of GGA
and GGA+U entries (see References).
This class implements the Materials Project 2020 energy correction scheme, which
incorporates uncertainty quantification and allows for mixing of GGA and GGA+U entries
(see References).

Note that this scheme should only be applied to VASP calculations that use the
Materials Project input set parameters (see pymatgen.io.vasp.sets.MPRelaxSet).
Using this compatibility scheme on calculations with different parameters is not
valid.
Materials Project input set parameters (see pymatgen.io.vasp.sets.MPRelaxSet). Using
this compatibility scheme on calculations with different parameters is not valid.

Note: While the correction scheme is largely composition-based, the energy corrections
applied to ComputedEntry and ComputedStructureEntry can differ for O and S-containing
structures if entry.data['oxidation_states'] is not populated or explicitly set. This
occurs because pymatgen will use atomic distances to classify O and S anions as
superoxide/peroxide/oxide and sulfide/polysulfide, resp. when oxidation states are not
provided. If you want the most accurate corrections possible, supply pre-defined
oxidation states to entry.data or pass ComputedStructureEntry.
"""

def __init__(
Expand Down
18 changes: 9 additions & 9 deletions pymatgen/io/vasp/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def get_string(self, direct: bool = True, vasp4_compatible: bool = False, signif

if self.true_names and not vasp4_compatible:
lines.append(" ".join(self.site_symbols))
lines.append(" ".join([str(x) for x in self.natoms]))
lines.append(" ".join(map(str, self.natoms)))
if self.selective_dynamics:
lines.append("Selective dynamics")
lines.append("direct" if direct else "cartesian")
Expand Down Expand Up @@ -721,7 +721,7 @@ def get_string(self, sort_keys: bool = False, pretty: bool = False) -> str:

lines.append([k, " ".join(value)])
elif isinstance(self[k], list):
lines.append([k, " ".join([str(i) for i in self[k]])])
lines.append([k, " ".join(map(str, self[k]))])
else:
lines.append([k, self[k]])

Expand Down Expand Up @@ -1512,17 +1512,17 @@ def __str__(self):
style = self.style.name.lower()[0]
if style == "l":
lines.append(self.coord_type)
for i in range(len(self.kpts)):
lines.append(" ".join([str(x) for x in self.kpts[i]]))
for idx, kpt in enumerate(self.kpts):
lines.append(" ".join(map(str, kpt)))
if style == "l":
lines[-1] += " ! " + self.labels[i]
if i % 2 == 1:
lines[-1] += " ! " + self.labels[idx]
if idx % 2 == 1:
lines[-1] += "\n"
elif self.num_kpts > 0:
if self.labels is not None:
lines[-1] += f" {int(self.kpts_weights[i])} {self.labels[i]}"
lines[-1] += f" {int(self.kpts_weights[idx])} {self.labels[idx]}"
else:
lines[-1] += f" {int(self.kpts_weights[i])}"
lines[-1] += f" {int(self.kpts_weights[idx])}"

# Print tetrahedron parameters if the number of tetrahedrons > 0
if style not in "lagm" and self.tet_number > 0:
Expand All @@ -1534,7 +1534,7 @@ def __str__(self):

# Print shifts for automatic kpoints types if not zero.
if self.num_kpts <= 0 and tuple(self.kpts_shift) != (0, 0, 0):
lines.append(" ".join([str(x) for x in self.kpts_shift]))
lines.append(" ".join(map(str, self.kpts_shift)))
return "\n".join(lines) + "\n"

def as_dict(self):
Expand Down
8 changes: 4 additions & 4 deletions pymatgen/symmetry/tests/test_maggroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def test_is_compatible(self):

def test_symmetry_ops(self):

msg_1_symmops = "\n".join([str(op) for op in self.msg_1.symmetry_ops])
msg_1_symmops = "\n".join(map(str, self.msg_1.symmetry_ops))
msg_1_symmops_ref = """x, y, z, +1
-x+3/4, -y+3/4, z, +1
-x, -y, -z, +1
Expand Down Expand Up @@ -110,7 +110,7 @@ def test_symmetry_ops(self):
x+3/4, -y+1/2, z+1/4, -1"""
self.assertStrContentEqual(msg_1_symmops, msg_1_symmops_ref)

msg_2_symmops = "\n".join([str(op) for op in self.msg_2.symmetry_ops])
msg_2_symmops = "\n".join(map(str, self.msg_2.symmetry_ops))
msg_2_symmops_ref = """x, y, z, +1
-x, y+1/2, -z, +1
-x, -y, -z, +1
Expand All @@ -121,7 +121,7 @@ def test_symmetry_ops(self):
x+1/2, y, -z+1/2, -1"""
self.assertStrContentEqual(msg_2_symmops, msg_2_symmops_ref)

msg_3_symmops = "\n".join([str(op) for op in self.msg_3.symmetry_ops])
msg_3_symmops = "\n".join(map(str, self.msg_3.symmetry_ops))
msg_3_symmops_ref = """x, y, z, +1
x, -y, -z, +1
-x, y, -z+1/2, +1
Expand All @@ -140,7 +140,7 @@ def test_symmetry_ops(self):
-x, -y+1/2, z, -1"""
assert msg_3_symmops == msg_3_symmops_ref

msg_4_symmops = "\n".join([str(op) for op in self.msg_4.symmetry_ops])
msg_4_symmops = "\n".join(map(str, self.msg_4.symmetry_ops))
msg_4_symmops_ref = """x, y, z, +1
-x, -y, -z, +1
x+1/2, y, z, -1
Expand Down