Skip to content
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

Deprecate Structure.ntypesp replaced by Structure.n_elems #3562

Merged
merged 2 commits into from
Jan 17, 2024
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
2 changes: 1 addition & 1 deletion pymatgen/core/lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -1517,7 +1517,7 @@ def is_hexagonal(self, hex_angle_tol: float = 5, hex_length_tol: float = 0.01) -
angles = self.angles
right_angles = [i for i in range(3) if abs(angles[i] - 90) < hex_angle_tol]
hex_angles = [
i for i in range(3) if abs(angles[i] - 60) < hex_angle_tol or abs(angles[i] - 120) < hex_angle_tol
idx for idx in range(3) if abs(angles[idx] - 60) < hex_angle_tol or abs(angles[idx] - 120) < hex_angle_tol
]

return (
Expand Down
6 changes: 6 additions & 0 deletions pymatgen/core/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,16 @@ def species_and_occu(self) -> list[Composition]:
return [site.species for site in self]

@property
@deprecated(message="Use n_type_sp instead.")
def ntypesp(self) -> int:
"""Number of types of atoms."""
return len(self.types_of_species)

@property
def n_elems(self) -> int:
"""Number of types of atoms."""
return len(self.types_of_species)

@property
def types_of_species(self) -> tuple[Element | Species | DummySpecies]:
"""List of types of specie."""
Expand Down
42 changes: 22 additions & 20 deletions pymatgen/io/abinit/abiobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,17 @@ def species_by_znucl(structure: Structure) -> list[Species]:
return types


def structure_to_abivars(structure, enforce_znucl=None, enforce_typat=None, **kwargs):
def structure_to_abivars(
structure: Structure, enforce_znucl: list | None = None, enforce_typat: list | None = None, **kwargs
):
"""
Receives a structure and returns a dictionary with ABINIT variables.

Args:
enforce_znucl: List of ntypat entries with the value of Z for each type of atom.
Used to change the default ordering.
enforce_typat: List with natom entries with the type index.
Fortran conventions: start to count from 1.
Used to change the default ordering.
enforce_znucl (list): ntypat entries with the value of Z for each type of atom.
Used to change the default ordering. Defaults to None.
enforce_typat (list): natom entries with the type index.
Fortran conventions: start to count from 1. Used to change the default ordering.
"""
if not structure.is_ordered:
raise ValueError(
Expand All @@ -205,7 +206,6 @@ def structure_to_abivars(structure, enforce_znucl=None, enforce_typat=None, **kw
)

n_atoms = len(structure)
n_types_atom = structure.ntypesp
enforce_order = False

if enforce_znucl is not None or enforce_typat is not None:
Expand All @@ -219,19 +219,21 @@ def structure_to_abivars(structure, enforce_znucl=None, enforce_typat=None, **kw
f"enforce_typat contains {len(enforce_typat)} entries while it should be {len(structure)=}"
)

if len(enforce_znucl) != n_types_atom:
raise ValueError(f"enforce_znucl contains {len(enforce_znucl)} entries while it should be {n_types_atom=}")
if len(enforce_znucl) != structure.n_elems:
raise ValueError(
f"enforce_znucl contains {len(enforce_znucl)} entries while it should be {structure.n_elems=}"
)

if not enforce_order:
if enforce_order:
znucl_type = enforce_znucl
typat = enforce_typat or [] # or [] added for mypy
else:
types_of_specie = species_by_znucl(structure)

znucl_type = [specie.number for specie in types_of_specie]
typat = np.zeros(n_atoms, int)
for atm_idx, site in enumerate(structure):
typat[atm_idx] = types_of_specie.index(site.specie) + 1
else:
znucl_type = enforce_znucl
typat = enforce_typat

r_prim = ArrayWithUnit(structure.lattice.matrix, "ang").to("bohr")
ang_deg = structure.lattice.angles
Expand All @@ -245,19 +247,19 @@ def structure_to_abivars(structure, enforce_znucl=None, enforce_typat=None, **kw
# Info on atoms.
dct = {
"natom": n_atoms,
"ntypat": n_types_atom,
"ntypat": structure.n_elems,
"typat": typat,
"znucl": znucl_type,
"xred": x_red,
"properties": structure.properties,
}

# Add info on the lattice.
# Should we use (rprim, acell) or (angdeg, acell) to specify the lattice?
# Should we use (rprim, acell) or (ang_deg, acell) to specify the lattice?
geo_mode = kwargs.pop("geomode", "rprim")
if geo_mode == "automatic":
geo_mode = "rprim"
if structure.lattice.is_hexagonal: # or structure.lattice.is_rhombohedral
if structure.lattice.is_hexagonal(): # or structure.lattice.is_rhombohedral
geo_mode = "angdeg"
ang_deg = structure.lattice.angles
# Here one could polish a bit the numerical values if they are not exact.
Expand All @@ -281,15 +283,15 @@ def structure_to_abivars(structure, enforce_znucl=None, enforce_typat=None, **kw
return dct


def contract(s):
def contract(string):
"""
assert contract("1 1 1 2 2 3") == "3*1 2*2 1*3"
assert contract("1 1 3 2 3") == "2*1 1*3 1*2 1*3"
"""
if not s:
return s
if not string:
return string

tokens = s.split()
tokens = string.split()
old = tokens[0]
count = [[1, old]]

Expand Down
9 changes: 3 additions & 6 deletions pymatgen/io/cp2k/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,12 +1230,9 @@ def create_subsys(self, structure: Structure | Molecule) -> None:
if isinstance(structure, Structure):
subsys.insert(Cell(structure.lattice))
else:
x = max(structure.cart_coords[:, 0])
y = max(structure.cart_coords[:, 1])
z = max(structure.cart_coords[:, 2])
x = x if x else 1
y = y if y else 1
z = z if z else 1
x = max(*structure.cart_coords[:, 0], 1)
y = max(*structure.cart_coords[:, 1], 1)
z = max(*structure.cart_coords[:, 2], 1)
cell = Cell(lattice=Lattice([[10 * x, 0, 0], [0, 10 * y, 0], [0, 0, 10 * z]]))
cell.add(Keyword("PERIODIC", "NONE"))
subsys.insert(cell)
Expand Down
2 changes: 1 addition & 1 deletion pymatgen/io/shengbte.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def from_structure(cls, structure: Structure, reciprocal_density: int | None = 5
types = [types_dict[i] + 1 for i in structure.atomic_numbers]

control_dict = {
"nelements": structure.ntypesp,
"nelements": structure.n_elems,
"natoms": len(structure),
"norientations": 0,
"lfactor": 0.1,
Expand Down
4 changes: 2 additions & 2 deletions pymatgen/io/vasp/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2759,7 +2759,7 @@ def incar(self) -> Incar:
defaults = {
"ALGO": "Fast",
"ISIF": 3,
"LANGEVIN_GAMMA": [10] * self.structure.ntypesp,
"LANGEVIN_GAMMA": [10] * self.structure.n_elems,
"LANGEVIN_GAMMA_L": 1,
"MDALGO": 3,
"PMASS": 10,
Expand All @@ -2771,7 +2771,7 @@ def incar(self) -> Incar:
self.user_incar_settings = defaults

# Set NPT-AIMD ENCUT = 1.5 * VASP_default
enmax = [self.potcar[i].keywords["ENMAX"] for i in range(self.structure.ntypesp)]
enmax = [self.potcar[idx].keywords["ENMAX"] for idx in range(self.structure.n_elems)]
encut = max(enmax) * 1.5
self._config_dict["INCAR"]["ENCUT"] = encut

Expand Down
10 changes: 5 additions & 5 deletions tests/core/test_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def setUp(self):
self.struct = IStructure(self.lattice, ["Si"] * 2, coords)
assert len(self.struct) == 2, "Wrong number of sites in structure!"
assert self.struct.is_ordered
assert self.struct.ntypesp == 1
assert self.struct.n_elems == 1
coords = [[0, 0, 0], [0.0, 0, 0.0000001]]
with pytest.raises(
StructureError, match=f"sites are less than {self.struct.DISTANCE_TOLERANCE} Angstrom apart"
Expand Down Expand Up @@ -967,7 +967,7 @@ def test_append_insert_remove_replace_substitute(self):
struct = self.struct
struct.insert(1, "O", [0.5, 0.5, 0.5])
assert struct.formula == "Si2 O1"
assert struct.ntypesp == 2
assert struct.n_elems == 2
assert struct.symbol_set == ("O", "Si")
assert struct.indices_from_symbol("Si") == (0, 2)
assert struct.indices_from_symbol("O") == (1,)
Expand All @@ -977,7 +977,7 @@ def test_append_insert_remove_replace_substitute(self):
assert struct.indices_from_symbol("O") == (1,)
struct.append("N", [0.25, 0.25, 0.25])
assert struct.formula == "Si1 N1 O1"
assert struct.ntypesp == 3
assert struct.n_elems == 3
assert struct.symbol_set == ("N", "O", "Si")
assert struct.indices_from_symbol("Si") == (0,)
assert struct.indices_from_symbol("O") == (1,)
Expand All @@ -987,15 +987,15 @@ def test_append_insert_remove_replace_substitute(self):
assert struct.symbol_set == ("Ge", "N", "O")
struct.replace_species({"Ge": "Si"})
assert struct.formula == "Si1 N1 O1"
assert struct.ntypesp == 3
assert struct.n_elems == 3

struct.replace_species({"Si": {"Ge": 0.5, "Si": 0.5}})
assert struct.formula == "Si0.5 Ge0.5 N1 O1"
# this should change the .5Si .5Ge sites to .75Si .25Ge
struct.replace_species({"Ge": {"Ge": 0.5, "Si": 0.5}})
assert struct.formula == "Si0.75 Ge0.25 N1 O1"

assert struct.ntypesp == 4
assert struct.n_elems == 4

struct.replace_species({"Ge": "Si"})
struct.substitute(1, "hydroxyl")
Expand Down
8 changes: 4 additions & 4 deletions tests/io/abinit/test_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def test_api(self):

inp = BasicAbinitInput(structure=unit_cell, pseudos=abiref_file("14si.pspnc"))

shiftk = [[0.5, 0.5, 0.5], [0.5, 0.0, 0.0], [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]]
assert_array_equal(calc_shiftk(inp.structure), shiftk)
shift_k = [[0.5, 0.5, 0.5], [0.5, 0.0, 0.0], [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]]
assert_array_equal(calc_shiftk(inp.structure), shift_k)
assert num_valence_electrons(inp.structure, inp.pseudos) == 8

repr(inp), str(inp)
Expand Down Expand Up @@ -81,8 +81,8 @@ def test_api(self):
inp.set_vars_ifnotin(ecut=-10)
assert inp["ecut"] == 5

_, tmpname = tempfile.mkstemp(text=True)
inp.write(filepath=tmpname)
_, tmp_name = tempfile.mkstemp(text=True)
inp.write(filepath=tmp_name)

# Cannot change structure variables directly.
with pytest.raises(inp.Error):
Expand Down
2 changes: 1 addition & 1 deletion tests/io/vasp/test_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ def test_incar(self):
assert incar["EDIFF"] == approx(1e-5)
assert incar["LANGEVIN_GAMMA_L"] == 1
assert incar["LANGEVIN_GAMMA"] == [10, 10, 10]
enmax = max(npt_set.potcar[i].keywords["ENMAX"] for i in range(self.struct.ntypesp))
enmax = max(npt_set.potcar[idx].keywords["ENMAX"] for idx in range(self.struct.n_elems))
assert incar["ENCUT"] == approx(1.5 * enmax)
assert incar["ALGO"] == "Fast"
assert incar["ISIF"] == 3
Expand Down