Skip to content

Commit d1f08b8

Browse files
committed
Merge branch 'molmd_fix_development' of https://github.com/molmd/pymatgen into molmd_fix_3-9_dev
2 parents 9852bdd + d6d0f43 commit d1f08b8

File tree

4 files changed

+211
-47
lines changed

4 files changed

+211
-47
lines changed

pymatgen/core/bond_lengths.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,5 +394,41 @@
394394
"H"
395395
],
396396
"bond_order": 1.0
397+
},
398+
{
399+
"ref": "",
400+
"length": 1.787,
401+
"elements": [
402+
"Al",
403+
"O"
404+
],
405+
"bond_order": 1.0
406+
},
407+
{
408+
"ref": "",
409+
"length": 2.945,
410+
"elements": [
411+
"Al",
412+
"C"
413+
],
414+
"bond_order": 0.0
415+
},
416+
{
417+
"ref": "",
418+
"length": 3.376,
419+
"elements": [
420+
"Al",
421+
"F"
422+
],
423+
"bond_order": 0.0
424+
},
425+
{
426+
"ref": "",
427+
"length": 3.615,
428+
"elements": [
429+
"Al",
430+
"H"
431+
],
432+
"bond_order": 0.0
397433
}
398434
]

pymatgen/io/lammps/data.py

Lines changed: 166 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,12 @@ def from_ff_and_topologies(cls, box, ff, topologies, atom_style="full"):
735735
atom_style (str): Output atom_style. Default to "full".
736736
737737
"""
738-
atom_types = set.union(*(t.species for t in topologies))
738+
atom_types = set.union(*[t.species for t in topologies])
739+
print(f"atom_types:\n{atom_types}\n")
740+
print(f"ff object:\n{ff}\n")
741+
print(f"ff.maps:\n{ff.maps}\n")
742+
print(f"ff.maps['Atoms']:\n{ff.maps['Atoms']}\n")
743+
print(f"ff.maps['Atoms'].keys():\n{ff.maps['Atoms'].keys()}\n")
739744
assert atom_types.issubset(ff.maps["Atoms"].keys()), "Unknown atom type found in topologies"
740745

741746
items = dict(box=box, atom_style=atom_style, masses=ff.masses, force_field=ff.force_field)
@@ -1758,29 +1763,41 @@ def __init__(
17581763
length_increase=0.5,
17591764
check_ff_duplicates=True,
17601765
box_data_type="cubic",
1766+
system_molecule=None,
1767+
system_molecule_type=None,
1768+
sorted_mol_names=None,
17611769
):
17621770
"""
1763-
Low level constructor designed to work with lists of dictionaries that should
1764-
be able to be obtained from databases. Works for cubic boxes only using
1765-
real coordinates.
1766-
:param system_force_fields: [dict] Contains force field information using
1767-
the following format:
1771+
Low level constructor designed to work with lists of
1772+
dictionaries that should be able to be obtained from databases.
1773+
Works for cubic boxes only using real coordinates.
1774+
:param system_force_fields: [dict] Contains force field
1775+
information using the following format:
17681776
{ unique_molecule_name: {
17691777
'Molecule': pymatgen.Molecule,
17701778
'Labels': [atom_a, ...]
17711779
'Masses': [OrderedDict({species_1: mass_1, ...})],
17721780
'Nonbond': [[...], ...],
1773-
'Bonds': [{'coeffs': [...], 'types': [(i, j), ...]}, ...],
1774-
'Angles': [{'coeffs': [...], 'types': [(i, j, k), ...]}, ...],
1775-
'Dihedrals': [{'coeffs': [...], 'types': [(i, j, k, l), ...]}, ...],
1776-
'Impropers': [{'coeffs': [...], 'types': [(i, j, k, l), ...]}, ...],
1781+
'Bonds': [
1782+
{'coeffs': [...], 'types': [(i, j), ...]}, ...
1783+
],
1784+
'Angles': [
1785+
{'coeffs': [...], 'types': [(i, j, k), ...]}, ...
1786+
],
1787+
'Dihedrals': [
1788+
{'coeffs': [...], 'types': [(i, j, k, l), ...]}, ...
1789+
],
1790+
'Impropers': [
1791+
{'coeffs': [...], 'types': [(i, j, k, l), ...]}, ...
1792+
],
17771793
'Improper Topologies': [[a, b, c, d],...]
17781794
'Charges': [atom_a, ...]
17791795
}, ...}
1780-
:param system_mixture_data: [dict] Format depends on mixture_data_type input.
1781-
For mixture_data_type = 'concentration', this parameter contains molarity,
1782-
density, and molar weights of solutes and solvents using the
1783-
following format:
1796+
:param system_mixture_data: [dict] Format depends on
1797+
mixture_data_type input.
1798+
For mixture_data_type = 'concentration', this parameter
1799+
contains molarity, density, and molar weights of solutes and
1800+
solvents using the following format:
17841801
{
17851802
'Solutes': {unique_molecule_name: {
17861803
'Initial Molarity': molarity_1i,
@@ -1795,22 +1812,87 @@ def __init__(
17951812
'Molar Weight': molar_weight_1
17961813
}, ...}
17971814
}
1798-
For mixture_data_type = 'number of molecules', this parameter contains
1799-
the number of molecules for each species in the system in the following
1800-
format:
1815+
For mixture_data_type = 'number of molecules', this
1816+
parameter contains the number of molecules for each species
1817+
in the system in the following format:
18011818
{
18021819
unique_molecule_name: n_mols,
18031820
...
18041821
}
1805-
:param mixture_data_type: [str] controls the format of the system_mixture_data
1806-
parameter. Currently supports values of 'concentration' and
1807-
'number of molecules'. Defaults to "concentration".
1808-
:param cube_length: [float] length of system box in angstroms.
1809-
:param origin: [list] Optional. Change if the minimum xyz coordinates for
1810-
desired box are not [0,0,0].
1822+
:param box_data: [float, 3x2 array_like, LammpsBox] This
1823+
parameter controls the dimensions of the system box. The
1824+
format depends on the value of box_data_type.
1825+
For box_data_type = 'cubic', this parameter is a float and
1826+
sets the length of the cubic box.
1827+
For box_data_type = 'rectangular', this parameter is a 3x2
1828+
array_like and sets the bounds of the rectangular box.
1829+
For box_data_type = 'LammpsBox', this parameter is a pmg
1830+
LammpsBox object and sets the bounds of the box.
1831+
:param mixture_data_type: [str] controls the format of the
1832+
system_mixture_data parameter. Currently supports values of
1833+
'concentration', 'number of molecules', 'pmg molecule', and
1834+
'xyz'. Defaults to "concentration".
1835+
:param origin: [1x3 array_like] Optional. Change if the minimum
1836+
xyz coordinates for desired box are not [0,0,0].
18111837
:param seed: [int] Optional. Sets the seed for running packmol.
1812-
:param packmolrunner_inputs: [dict] Optional. Parameters for PackmolRunner
1813-
in pymatgen.io.lammps.utils
1838+
This parameter will update the 'seed' key in the
1839+
packmolrunner_inputs parameter. Defaults to 150.
1840+
:param packmolrunner_inputs: [dict] Optional. Parameters for
1841+
PackmolRunner in pymatgen.io.lammps.utils
1842+
:param length_increase: [int, float, or 1x3 array_like] Optional.
1843+
Because packmol will not always strictly adhere to the box
1844+
dimensions, this parameter sets the amount to increase the
1845+
box dimensions by n order to ensure that all molecules are
1846+
within the box. This is also relevant for interfacial
1847+
systems where there is a fixed boundary since LAMMPS does
1848+
not work if the atom is exactly on the boundary. This param
1849+
will increase the length of the box by this amount in the x,
1850+
y, and z directions. In effect, it will decrease the min box
1851+
value by half of its value and increase the max box value by
1852+
half of its value Defaults to 0.5. This means that the min
1853+
values of x, y, and z will be decreased by 0.25 and the max
1854+
values of x, y, and z will be increased by 0.25 by default.
1855+
If using the default value for liquid-only systems, it might
1856+
be advisable to set the origin to [0.25, 0.25, 0.25] to
1857+
ensure that the true box origin is at [0,0,0].
1858+
:param check_ff_duplicates: [bool] Optional. If True, the angle,
1859+
dihedral, and improper bond types will be checked for
1860+
duplicates (eg, for angles, the following two types are
1861+
duplicates: ("C", "O", "H") and ("H", "O", "C")). If
1862+
duplicates are found, a warning will be issued. Defaults to
1863+
True.
1864+
:param box_data_type: [str] Optional. Controls the format of the
1865+
box_data parameter. Currently supports values of 'cubic',
1866+
'rectangular', and 'LammpsBox'. Defaults to "cubic".
1867+
:param system_molecule: [pmg Molecule, str] Optional. If
1868+
mixture_data_type is 'pmg molecule', this parameter should
1869+
contain a pmg Molecule object containing all of the
1870+
molecules in the system. The order of the molecules in this
1871+
object should be similar to that created by the
1872+
PackmolRunner object. That is, all sites belonging to the
1873+
first molecule should be listed first, then all sites
1874+
belonging to the second molecule, and so on. Also, the sites
1875+
belonging to each molecular species should be sorted such
1876+
that all the sites belonging to the first molecular species
1877+
occur first, then all the sites belonging to the second
1878+
molecular species, and so on.
1879+
If mixture_data_type is 'xyz', this parameter should contain
1880+
a path to an xyz file containing the coordinates of all the
1881+
molecules in the system. The order of the molecules in this
1882+
file should be similar to the xyz file created by the
1883+
PackmolRunner object, and by extension, the 'pmg molecule'
1884+
version of this parameter.
1885+
If this parameter is used, then the system_mixture_data
1886+
should be the number of molecules in the system.
1887+
If None, the system molecule will be created from packmol
1888+
based on the system_mixture_data. Defaults to None.
1889+
:param system_molecule_type: [str] Optional. controls the format
1890+
of the system_molecule parameter. Currently supports values
1891+
of 'pmg molecule' and 'xyz'. Defaults to None.
1892+
:param sorted_mol_names: [list] Optional. Contains the unique
1893+
molecule names in the system. If None, the molecule names
1894+
will be sorted from most to least number of atoms. Defaults
1895+
to None.
18141896
"""
18151897
self._ff_list = system_force_fields
18161898
self._concentration_data = False
@@ -1830,40 +1912,79 @@ def __init__(
18301912
elif mixture_data_type == "number of molecules":
18311913
self._number_of_molecules_data = True
18321914
self._n_mol_dict = system_mixture_data
1833-
1915+
1916+
self._origin = origin
18341917
if box_data_type == "cubic":
18351918
self.length = box_data
1836-
self._initial_lammps_box = LammpsBox([[0.0, box_data],
1837-
[0.0, box_data],
1838-
[0.0, box_data]])
1919+
self._initial_lammps_box = LammpsBox([[self._origin[0], box_data],
1920+
[self._origin[1], box_data],
1921+
[self._origin[2], box_data]])
18391922
elif box_data_type == "rectangular":
18401923
self._initial_lammps_box = LammpsBox(box_data)
18411924
elif box_data_type == "LammpsBox":
18421925
self._initial_lammps_box = box_data
1843-
self._origin = origin
1926+
18441927

18451928
packmolrunner_inputs["control_params"]["seed"] = seed
18461929
self._packmolrunner_inputs = packmolrunner_inputs
18471930

18481931
self.xyz_high = [bound[1] for bound in self._initial_lammps_box.as_dict()["bounds"]]
18491932
self.xyz_low = [bound[0] for bound in self._initial_lammps_box.as_dict()["bounds"]]
18501933

1934+
if type(length_increase) in [int, float]:
1935+
self._length_increase_vector = [length_increase] * 3
1936+
elif len(length_increase) == 3:
1937+
self._length_increase_vector = length_increase
1938+
else:
1939+
raise ValueError(
1940+
"The length_increase parameter is not valid. It should be a \
1941+
float or int or a list of 3 floats or ints."
1942+
)
18511943
self._length_increase = length_increase
18521944
self._check_ff_duplicates = check_ff_duplicates
18531945

1946+
if system_molecule_type is None:
1947+
self._packmol_run_status = True
1948+
elif system_molecule_type in ["pmg molecule", "xyz"]:
1949+
self._packmol_run_status = False
1950+
if system_molecule_type == "xyz":
1951+
self._sys_molecule = Molecule.from_file(system_molecule)
1952+
else:
1953+
self._sys_molecule = system_molecule
1954+
if mixture_data_type != "number of molecules":
1955+
raise ValueError(
1956+
"The system_molecule_type parameter is not valid. \
1957+
Currently, the only valid value for this parameter is \
1958+
'number of molecules' if also using a system_molecule \
1959+
parameter."
1960+
)
1961+
else:
1962+
raise ValueError(
1963+
"The system_molecule_type parameter is not valid. Currently, \
1964+
the only valid values are 'pmg molecule' and 'xyz'."
1965+
)
1966+
1967+
self._sorted_mol_names = sorted_mol_names
1968+
1969+
18541970
@property
18551971
def sorted_mol_names(self):
18561972
"""
1857-
Sorts molecules from most to least number of atoms
1858-
:return molecule_name_list: [list] Contains the unique_molecule_names
1973+
Sorts molecules from most to least number of atoms. Only used if
1974+
sorted_mol_names is None.
1975+
:return molecule_name_list: [list] Contains the
1976+
unique_molecule_names
18591977
"""
1860-
molecule_name_list = list(self._ff_list.keys())
1861-
molecule_natoms_list = [len(self._ff_list[name]["Molecule"]) for
1862-
name in molecule_name_list]
1863-
molecule_name_list.sort(key=dict(zip(molecule_name_list,
1864-
molecule_natoms_list)).get,
1865-
reverse=True)
1866-
return molecule_name_list
1978+
if self._sorted_mol_names is not None:
1979+
return self._sorted_mol_names
1980+
else:
1981+
molecule_name_list = list(self._ff_list.keys())
1982+
molecule_natoms_list = [len(self._ff_list[name]["Molecule"]) for
1983+
name in molecule_name_list]
1984+
molecule_name_list.sort(key=dict(zip(molecule_name_list,
1985+
molecule_natoms_list)).get,
1986+
reverse=True)
1987+
return molecule_name_list
18671988

18681989
@property
18691990
def nmol_dict(self):
@@ -2097,15 +2218,18 @@ def _get_lammps_box(self, system_molecule):
20972218
:param system_molecule: [Molecule] Output from _run_packmol()
20982219
:return Mix_lmpbox: [pmg.LammpsBox] Object representing the simulation box
20992220
"""
2100-
final_xyz_low = np.subtract(self.xyz_low, np.ones(3) * self._length_increase * 0.5)
2101-
final_xyz_high = np.add(self.xyz_high, np.ones(3) * self._length_increase * 0.5)
2221+
final_xyz_low = np.subtract(self.xyz_low, np.multiply(self._length_increase_vector, 0.5))
2222+
final_xyz_high = np.add(self.xyz_high, np.multiply(self._length_increase_vector, 0.5))
21022223
final_bounds = np.asarray([final_xyz_low, final_xyz_high]).transpose()
21032224

21042225
mix_lmpbox = LammpsBox(final_bounds, self._initial_lammps_box.as_dict()["tilt"])
21052226
return mix_lmpbox
21062227

21072228
def build_lammps_data(self, atom_style="full"):
2108-
system_molecule = self._run_packmol()
2229+
if self._packmol_run_status:
2230+
system_molecule = self._run_packmol()
2231+
else:
2232+
system_molecule = self._sys_molecule
21092233
system_topologies = self._get_topologies(system_molecule)
21102234
system_lammps_box = self._get_lammps_box(system_molecule)
21112235
system_lammps_data = LammpsData.from_ff_and_topologies(

pymatgen/io/lammps/scripts/Dump_to_dumps_and_xyz.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"""
1414

1515
cwd = os.getcwd()
16-
dump_file_path_pattern = os.path.join(cwd, "dump.*.dump")
16+
dump_file_path_pattern = os.path.join(cwd, "*.lammpstrj.2000000")
1717

1818
Dump_files = glob.glob(dump_file_path_pattern)
1919

@@ -25,11 +25,11 @@
2525
Dumps = parse_lammps_dumps(Dump_file)
2626

2727
for Dump in Dumps:
28-
trj_name = Dump_file_name[:-4] + str(Dump.timestep) + ".lammpstrj"
28+
# trj_name = Dump_file_name[:-4] + str(Dump.timestep) + ".lammpstrj"
2929
xyz_name = Dump_file_name[:-4] + "alt." + str(Dump.timestep) + ".xyz"
3030
Dump.as_txt_file(trj_name, output=True)
3131
Dump.as_txt_file(xyz_name, convert="xyz", output=True)
32-
if Dump.timestep % 500000 == 0:
33-
run(["cp", trj_name, "trj_files/rdf_files"])
34-
run(["mv", trj_name, "trj_files"])
32+
# if Dump.timestep % 500000 == 0:
33+
# run(["cp", trj_name, "trj_files/rdf_files"])
34+
# run(["mv", trj_name, "trj_files"])
3535
run(["mv", xyz_name, "xyz_files"])

pymatgen/io/lammps/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ def __init__(
186186
filetype="xyz",
187187
control_params={"maxit": 20, "nloop": 600},
188188
auto_box=True,
189+
origin=[0.0, 0.0, 0.0],
189190
output_file="packed.xyz",
190191
bin="packmol",
191192
encode=False
@@ -207,6 +208,8 @@ def __init__(
207208
list of parameters containing dicts for each molecule
208209
auto_box:
209210
put the molecule assembly in a box
211+
origin:
212+
coordinates for the origin of the box
210213
output_file:
211214
output file name. The extension will be adjusted
212215
according to the filetype
@@ -227,6 +230,7 @@ def __init__(
227230
self.param_list = param_list
228231
self.input_file = input_file
229232
self.boxit = auto_box
233+
self.origin = origin
230234
self.control_params = control_params
231235
if not self.control_params.get("tolerance"):
232236
self.control_params["tolerance"] = tolerance

0 commit comments

Comments
 (0)