Skip to content

Commit 9a0eb81

Browse files
authored
Breaking: remove single-use PolarizationLattice which inherited from Structure (antipattern) (#3585)
* breaking: remove PolarizationLattice which inherited from Structure (antipattern) and refactor get_same_branch_polarization_data() * rename d|s vars
1 parent f345f2f commit 9a0eb81

File tree

13 files changed

+93
-88
lines changed

13 files changed

+93
-88
lines changed

pymatgen/analysis/elasticity/elastic.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,9 +1002,9 @@ def generate_pseudo(strain_states, order=3):
10021002
difference derivative of the stress with respect to the strain state
10031003
absent_syms: symbols of the tensor absent from the PI expression
10041004
"""
1005-
s = sp.Symbol("s")
1005+
symb = sp.Symbol("s")
10061006
nstates = len(strain_states)
1007-
ni = np.array(strain_states) * s
1007+
ni = np.array(strain_states) * symb
10081008
pseudo_inverses, absent_symbols = [], []
10091009
for degree in range(2, order + 1):
10101010
cvec, carr = get_symbol_list(degree)
@@ -1015,14 +1015,14 @@ def generate_pseudo(strain_states, order=3):
10151015
for _ in range(degree - 1):
10161016
exps = np.dot(exps, strain_v)
10171017
exps /= math.factorial(degree - 1)
1018-
sarr[n] = [sp.diff(exp, s, degree - 1) for exp in exps]
1018+
sarr[n] = [sp.diff(exp, symb, degree - 1) for exp in exps]
10191019
svec = sarr.ravel()
10201020
present_symbols = set.union(*(exp.atoms(sp.Symbol) for exp in svec))
10211021
absent_symbols += [set(cvec) - present_symbols]
1022-
m = np.zeros((6 * nstates, len(cvec)))
1022+
pseudo_mat = np.zeros((6 * nstates, len(cvec)))
10231023
for n, c in enumerate(cvec):
1024-
m[:, n] = v_diff(svec, c)
1025-
pseudo_inverses.append(np.linalg.pinv(m))
1024+
pseudo_mat[:, n] = v_diff(svec, c)
1025+
pseudo_inverses.append(np.linalg.pinv(pseudo_mat))
10261026
return pseudo_inverses, absent_symbols
10271027

10281028

pymatgen/analysis/ferroelectricity/polarization.py

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,20 @@
4646

4747
from __future__ import annotations
4848

49+
from typing import TYPE_CHECKING
50+
4951
import numpy as np
5052
from scipy.interpolate import UnivariateSpline
5153

5254
from pymatgen.core.lattice import Lattice
5355
from pymatgen.core.structure import Structure
5456

57+
if TYPE_CHECKING:
58+
from collections.abc import Sequence
59+
60+
from pymatgen.core.sites import PeriodicSite
61+
62+
5563
__author__ = "Tess Smidt"
5664
__copyright__ = "Copyright 2017, The Materials Project"
5765
__version__ = "1.0"
@@ -73,7 +81,7 @@ def zval_dict_from_potcar(potcar):
7381
return zval_dict
7482

7583

76-
def calc_ionic(site, structure: Structure, zval):
84+
def calc_ionic(site: PeriodicSite, structure: Structure, zval: float) -> np.ndarray:
7785
"""
7886
Calculate the ionic dipole moment using ZVAL from pseudopotential.
7987
@@ -103,31 +111,27 @@ def get_total_ionic_dipole(structure, zval_dict):
103111
return np.sum(tot_ionic, axis=0)
104112

105113

106-
class PolarizationLattice(Structure):
107-
"""TODO Why is a Lattice inheriting a structure? This is ridiculous."""
108-
109-
def get_nearest_site(self, coords, site, r=None):
110-
"""
111-
Given coords and a site, find closet site to coords.
114+
def get_nearest_site(struct: Structure, coords: Sequence[float], site: PeriodicSite, r: float | None = None):
115+
"""
116+
Given coords and a site, find closet site to coords.
112117
113-
Args:
114-
coords (3x1 array): Cartesian coords of center of sphere
115-
site: site to find closest to coords
116-
r: radius of sphere. Defaults to diagonal of unit cell
118+
Args:
119+
coords (3x1 array): Cartesian coords of center of sphere
120+
site: site to find closest to coords
121+
r (float): radius of sphere. Defaults to diagonal of unit cell
117122
118-
Returns:
119-
Closest site and distance.
120-
"""
121-
index = self.index(site)
122-
if r is None:
123-
r = np.linalg.norm(np.sum(self.lattice.matrix, axis=0))
124-
ns = self.get_sites_in_sphere(coords, r, include_index=True)
125-
# Get sites with identical index to site
126-
ns = [n for n in ns if n[2] == index]
127-
# Sort by distance to coords
128-
ns.sort(key=lambda x: x[1])
129-
# Return PeriodicSite and distance of closest image
130-
return ns[0][0:2]
123+
Returns:
124+
Closest site and distance.
125+
"""
126+
index = struct.index(site)
127+
r = r or np.linalg.norm(np.sum(struct.lattice.matrix, axis=0))
128+
ns = struct.get_sites_in_sphere(coords, r, include_index=True)
129+
# Get sites with identical index to site
130+
ns = [n for n in ns if n[2] == index]
131+
# Sort by distance to coords
132+
ns.sort(key=lambda x: x[1])
133+
# Return PeriodicSite and distance of closest image
134+
return ns[0][0:2]
131135

132136

133137
class Polarization:
@@ -298,18 +302,18 @@ def get_same_branch_polarization_data(self, convert_to_muC_per_cm2=True, all_in_
298302
for idx in range(n_elecs):
299303
lattice = lattices[idx]
300304
frac_coord = np.divide(np.array([p_tot[idx]]), np.array(lattice.lengths))
301-
d = PolarizationLattice(lattice, ["C"], [np.array(frac_coord).ravel()])
302-
d_structs.append(d)
303-
site = d[0]
305+
struct = Structure(lattice, ["C"], [np.array(frac_coord).ravel()])
306+
d_structs.append(struct)
307+
site = struct[0]
304308
# Adjust nonpolar polarization to be closest to zero.
305309
# This is compatible with both a polarization of zero or a half quantum.
306310
prev_site = [0, 0, 0] if idx == 0 else sites[-1].coords
307-
new_site = d.get_nearest_site(prev_site, site)
311+
new_site = get_nearest_site(struct, prev_site, site)
308312
sites.append(new_site[0])
309313

310314
adjust_pol = []
311-
for site, d in zip(sites, d_structs):
312-
adjust_pol.append(np.multiply(site.frac_coords, np.array(d.lattice.lengths)).ravel())
315+
for site, struct in zip(sites, d_structs):
316+
adjust_pol.append(np.multiply(site.frac_coords, np.array(struct.lattice.lengths)).ravel())
313317
return np.array(adjust_pol)
314318

315319
def get_lattice_quanta(self, convert_to_muC_per_cm2=True, all_in_polar=True):

pymatgen/analysis/graphs.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,11 +1290,11 @@ def __str__(self):
12901290
return out
12911291

12921292
def __repr__(self):
1293-
s = "Structure Graph"
1294-
s += f"\nStructure: \n{self.structure!r}"
1295-
s += f"\nGraph: {self.name}\n"
1296-
s += self._edges_to_str(self.graph)
1297-
return s
1293+
out = "Structure Graph"
1294+
out += f"\nStructure: \n{self.structure!r}"
1295+
out += f"\nGraph: {self.name}\n"
1296+
out += self._edges_to_str(self.graph)
1297+
return out
12981298

12991299
def __len__(self):
13001300
"""length of Structure / number of nodes in graph"""

pymatgen/analysis/structure_analyzer.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,15 @@ def __init__(self, structure: Structure, cutoff=10):
250250
cutoff (float) Cutoff distance.
251251
"""
252252
self.cutoff = cutoff
253-
self.s = structure
254-
recp_len = np.array(self.s.lattice.reciprocal_lattice.abc)
255-
i = np.ceil(cutoff * recp_len / (2 * pi))
256-
offsets = np.mgrid[-i[0] : i[0] + 1, -i[1] : i[1] + 1, -i[2] : i[2] + 1].T
253+
self.structure = structure
254+
recip_vec = np.array(self.structure.lattice.reciprocal_lattice.abc)
255+
cutoff_vec = np.ceil(cutoff * recip_vec / (2 * pi))
256+
offsets = np.mgrid[
257+
-cutoff_vec[0] : cutoff_vec[0] + 1, -cutoff_vec[1] : cutoff_vec[1] + 1, -cutoff_vec[2] : cutoff_vec[2] + 1
258+
].T
257259
self.offsets = np.reshape(offsets, (-1, 3))
258260
# shape = [image, axis]
259-
self.cart_offsets = self.s.lattice.get_cartesian_coords(self.offsets)
261+
self.cart_offsets = self.structure.lattice.get_cartesian_coords(self.offsets)
260262

261263
@property
262264
def connectivity_array(self):
@@ -271,12 +273,12 @@ def connectivity_array(self):
271273
solid angle of polygon between atom_i and image_j of atom_j
272274
"""
273275
# shape = [site, axis]
274-
cart_coords = np.array(self.s.cart_coords)
276+
cart_coords = np.array(self.structure.cart_coords)
275277
# shape = [site, image, axis]
276278
all_sites = cart_coords[:, None, :] + self.cart_offsets[None, :, :]
277279
vt = Voronoi(all_sites.reshape((-1, 3)))
278280
n_images = all_sites.shape[1]
279-
cs = (len(self.s), len(self.s), len(self.cart_offsets))
281+
cs = (len(self.structure), len(self.structure), len(self.cart_offsets))
280282
connectivity = np.zeros(cs)
281283
vts = np.array(vt.vertices)
282284
for (ki, kj), v in vt.ridge_dict.items():
@@ -321,7 +323,7 @@ def get_connections(self):
321323
for ii in range(max_conn.shape[0]):
322324
for jj in range(max_conn.shape[1]):
323325
if max_conn[ii][jj] != 0:
324-
dist = self.s.get_distance(ii, jj)
326+
dist = self.structure.get_distance(ii, jj)
325327
con.append([ii, jj, dist])
326328
return con
327329

@@ -335,9 +337,9 @@ def get_sitej(self, site_index, image_index):
335337
site_index (int): index of the site (3 in the example)
336338
image_index (int): index of the image (12 in the example)
337339
"""
338-
atoms_n_occu = self.s[site_index].species
339-
lattice = self.s.lattice
340-
coords = self.s[site_index].frac_coords + self.offsets[image_index]
340+
atoms_n_occu = self.structure[site_index].species
341+
lattice = self.structure.lattice
342+
coords = self.structure[site_index].frac_coords + self.offsets[image_index]
341343
return PeriodicSite(atoms_n_occu, coords, lattice)
342344

343345

pymatgen/analysis/surface_analysis.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,8 @@ def chempot_vs_gamma_plot_one(
861861
# w.r.t. bulk. Label with formula if non-stoichiometric
862862
ucell_comp = self.ucell_entry.composition.reduced_composition
863863
if entry.adsorbates:
864-
s = entry.cleaned_up_slab
865-
clean_comp = s.composition.reduced_composition
864+
struct = entry.cleaned_up_slab
865+
clean_comp = struct.composition.reduced_composition
866866
else:
867867
clean_comp = entry.composition.reduced_composition
868868

pymatgen/core/composition.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ def get_reduced_formula_and_factor(self, iupac_ordering: bool = False) -> tuple[
365365
all_int = all(abs(x - round(x)) < Composition.amount_tolerance for x in self.values())
366366
if not all_int:
367367
return self.formula.replace(" ", ""), 1
368-
d = {key: int(round(val)) for key, val in self.get_el_amt_dict().items()}
369-
formula, factor = reduce_formula(d, iupac_ordering=iupac_ordering)
368+
el_amt_dict = {key: int(round(val)) for key, val in self.get_el_amt_dict().items()}
369+
formula, factor = reduce_formula(el_amt_dict, iupac_ordering=iupac_ordering)
370370

371371
if formula in Composition.special_formulas:
372372
formula = Composition.special_formulas[formula]

pymatgen/core/ion.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ def get_reduced_formula_and_factor(self, iupac_ordering: bool = False, hydrates:
136136
nH2O = int(nO) if nH >= 2 * nO else int(nH) // 2
137137
comp = self.composition - nH2O * Composition("H2O")
138138

139-
d = {k: int(round(v)) for k, v in comp.get_el_amt_dict().items()}
140-
(formula, factor) = reduce_formula(d, iupac_ordering=iupac_ordering)
139+
el_amt_dict = {k: int(round(v)) for k, v in comp.get_el_amt_dict().items()}
140+
(formula, factor) = reduce_formula(el_amt_dict, iupac_ordering=iupac_ordering)
141141

142142
if self.composition.get("H") == self.composition.get("O") is not None:
143143
formula = formula.replace("HO", "OH")

pymatgen/io/abinit/inputs.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -858,18 +858,18 @@ def to_str(self, post=None, with_structure=True, with_pseudos=True, exclude=None
858858
vname = name + post
859859
app(str(InputVariable(vname, value)))
860860

861-
s = "\n".join(lines)
861+
out = "\n".join(lines)
862862
if not with_pseudos:
863-
return s
863+
return out
864864

865865
# Add JSON section with pseudo potentials.
866866
ppinfo = ["\n\n\n#<JSON>"]
867-
d = {"pseudos": [p.as_dict() for p in self.pseudos]}
868-
ppinfo.extend(json.dumps(d, indent=4).splitlines())
867+
psp_dict = {"pseudos": [p.as_dict() for p in self.pseudos]}
868+
ppinfo.extend(json.dumps(psp_dict, indent=4).splitlines())
869869
ppinfo.append("</JSON>")
870870

871-
s += "\n#".join(ppinfo)
872-
return s
871+
out += "\n#".join(ppinfo)
872+
return out
873873

874874
@property
875875
def comment(self):

pymatgen/io/adf.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,18 +533,18 @@ def _setup_task(self, geo_subkeys):
533533
self.geo.remove_subkey("Frequencies")
534534

535535
def __str__(self):
536-
s = f"""TITLE {self.title}\n
536+
out = f"""TITLE {self.title}\n
537537
{self.units}
538538
{self.xc}
539539
{self.basis_set}
540540
{self.scf}
541541
{self.geo}"""
542-
s += "\n"
542+
out += "\n"
543543
for block_key in self.other_directives:
544544
if not isinstance(block_key, AdfKey):
545545
raise ValueError(f"{block_key} is not an AdfKey!")
546-
s += str(block_key) + "\n"
547-
return s
546+
out += str(block_key) + "\n"
547+
return out
548548

549549
def as_dict(self):
550550
"""A JSON-serializable dict representation of self."""

pymatgen/io/lammps/data.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,10 +563,10 @@ def disassemble(
563563
}
564564
ff_df = self.force_field[kw]
565565
for t in ff_df.itertuples(index=True, name=None):
566-
d = {"coeffs": list(t[1:]), "types": []}
566+
coeffs_dict = {"coeffs": list(t[1:]), "types": []}
567567
if class2_coeffs:
568-
d.update({k: list(v[t[0] - 1]) for k, v in class2_coeffs.items()})
569-
topo_coeffs[kw].append(d)
568+
coeffs_dict.update({k: list(v[t[0] - 1]) for k, v in class2_coeffs.items()})
569+
topo_coeffs[kw].append(coeffs_dict)
570570

571571
if self.topology:
572572

@@ -591,8 +591,8 @@ def label_topo(t) -> tuple:
591591

592592
if any(topo_coeffs):
593593
for v in topo_coeffs.values():
594-
for d in v:
595-
d["types"] = list(set(d["types"]))
594+
for coeffs_dict in v:
595+
coeffs_dict["types"] = list(set(coeffs_dict["types"]))
596596

597597
ff = ForceField(
598598
mass_info=mass_info,

0 commit comments

Comments
 (0)