Skip to content

Commit 06c9d4e

Browse files
committed
Lots of changes, most of them trivial, but a few major bugfixes
Add applied pressure to LAMMPS fix ns/cell_mc, add corresponding pytest Fix serious sign error in lammps fix ns/type (detected when debugging pressure in cell_mc). Hopefully correct derivation documented in comment in ns_configs/ase_atoms/walks_lammps.py. NOTE: should probably add a test comparing ASE and LAMMPS dynamics for fixed mu, to ensure they behave the same Fix serious bug in step-size tuning that failed to reset walk counters before each pilot walk. Fix bug in initializing rngs when restarting from snapshot. Note that restart still isn't perfect because snapshots are in extxyz which has insufficient precision. This affects some of the restart tests, so loosen tolerance. HACK: handle calculators that create Calculator.results["energy"] when "free_energy" is passed to Calculator.calculate in properties Switch from ASE LJ to somewhat faster ASE Morse for pytests (update expected values) Fix bug in composition vs. full_composition pytest Fix searching for potential module in sampling pytests
1 parent 8040bd4 commit 06c9d4e

File tree

20 files changed

+277
-70
lines changed

20 files changed

+277
-70
lines changed

examples/EAM_LAMMPS/params.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
[configs.calculator.args]
3434

35-
cmds = ["pair_style eam/alloy", "pair_coeff * * /home/cluster2/bernstei/src/work/pymatnext/examples/EAM_LAMMPS/AlCu_Zhou04.eam.alloy Al Cu"]
35+
cmds = ["pair_style eam/alloy", "pair_coeff * * AlCu_Zhou04.eam.alloy Al Cu"]
3636

3737
types.13 = 1
3838
types.29 = 2

examples/EAM_LAMMPS/params_sGC.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
[configs.calculator.args]
3434

35-
cmds = ["pair_style eam/alloy", "pair_coeff * * /home/cluster2/bernstei/src/work/pymatnext/examples/EAM_LAMMPS/AlCu_Zhou04.eam.alloy Al Cu"]
35+
cmds = ["pair_style eam/alloy", "pair_coeff * * AlCu_Zhou04.eam.alloy Al Cu"]
3636

3737
types.13 = 1
3838
types.29 = 2

lammps_patches/new/src/NS/fix_ns_cellmc.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,9 @@ void FixNSCellMC::final_integrate()
371371

372372
// if potential energy - d(P V) is above Emax then reject move
373373
// need to include previous steps' cumulative dPV contributions, as well as current ones
374-
if (ecurrent - cumulative_dPV - dPV >= Emax) {
374+
if (ecurrent + cumulative_dPV + dPV >= Emax) {
375375
#ifdef DEBUG
376-
std::cout << "REJECT E == " << ecurrent << " - " << cumulative_dPV + dPV << " >= Emax == " << Emax << std::endl;
376+
std::cout << "REJECT E == " << ecurrent << " + " << cumulative_dPV + dPV << " >= Emax == " << Emax << std::endl;
377377
#endif
378378
// reject move, so don't touch cumulative_dPV, since type change that led to current dPV was reverted
379379

@@ -421,7 +421,7 @@ new_cell[1][2] = 0.0;
421421
new_cell[2][0] = domain->xz;
422422
new_cell[2][1] = domain->yz;
423423
new_cell[2][2] = domain->boxhi[2] - domain->boxlo[2];
424-
std::cout << "ACCEPT E == " << ecurrent " - " << cumulative_dPV << " < Emax == " << Emax << " min_aspect " << min_aspect_ratio_val(new_cell) << std::endl;
424+
std::cout << "ACCEPT E == " << ecurrent " + " << cumulative_dPV << " < Emax == " << Emax << " min_aspect " << min_aspect_ratio_val(new_cell) << std::endl;
425425
// std::cout << "final cell " << new_cell[0][0] << " " << new_cell[0][1] << " " << new_cell[0][2] << std::endl;
426426
// std::cout << " " << new_cell[1][0] << " " << new_cell[1][1] << " " << new_cell[1][2] << std::endl;
427427
// std::cout << " " << new_cell[2][0] << " " << new_cell[2][1] << " " << new_cell[2][2] << std::endl;

lammps_patches/new/src/NS/fix_ns_type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,9 @@ void FixNSType::final_integrate()
263263

264264
// if potential energy + d(mu N) is above Emax then reject move
265265
// need to include previous steps' cumulative dmuN contributions, as well as current ones
266-
if (ecurrent + cumulative_dmuN + dmuN >= Emax) {
266+
if (ecurrent - cumulative_dmuN - dmuN >= Emax) {
267267
#ifdef DEBUG
268-
std::cout << "REJECT E == " << ecurrent << " + " << cumulative_dmuN + dmuN << " >= Emax == " << Emax << " " << std::endl;
268+
std::cout << "REJECT E == " << ecurrent << " - " << cumulative_dmuN + dmuN << " >= Emax == " << Emax << " " << std::endl;
269269
#endif
270270
// reject move, so don't touch cumulative_dmuN, since type change that led to current dmuN was reverted
271271

pymatnext/cli/sample.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def parse_args(args_list=None):
7575
parser.add_argument("--random_seed", "-s", type=int, help="random seed overriding params.global.random_seed file")
7676
parser.add_argument("--output_filename_postfix", "-p", help="string to append to params.global.output_filename_prefix", default="")
7777
parser.add_argument("--max_iter", "-i", type=int, help="max number of NS iterations, overriding params")
78-
parser.add_argument("--restart_diff_nproc", "-d", action="store_true", help="allow restarts to use a different number of processors that previous partial run")
78+
parser.add_argument("--restart_diff_nproc", "-d", action="store_true", help="allow restarts to use a different number of processors than previous partial run")
7979
parser.add_argument("input", help="input json/yaml file")
8080
args = parser.parse_args(args_list)
8181

pymatnext/extras/lammps.patch

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
diff -N -u -r orig/src/NS/fix_ns_cellmc.cpp new/src/NS/fix_ns_cellmc.cpp
22
--- orig/src/NS/fix_ns_cellmc.cpp 1969-12-31 19:00:00.000000000 -0500
3-
+++ new/src/NS/fix_ns_cellmc.cpp 2023-04-03 08:16:30.856268936 -0400
3+
+++ new/src/NS/fix_ns_cellmc.cpp 2023-04-06 12:03:21.386180157 -0400
44
@@ -0,0 +1,474 @@
55
+/* ----------------------------------------------------------------------
66
+ LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
@@ -375,9 +375,9 @@ diff -N -u -r orig/src/NS/fix_ns_cellmc.cpp new/src/NS/fix_ns_cellmc.cpp
375375
+
376376
+ // if potential energy - d(P V) is above Emax then reject move
377377
+ // need to include previous steps' cumulative dPV contributions, as well as current ones
378-
+ if (ecurrent - cumulative_dPV - dPV >= Emax) {
378+
+ if (ecurrent + cumulative_dPV + dPV >= Emax) {
379379
+#ifdef DEBUG
380-
+ std::cout << "REJECT E == " << ecurrent << " - " << cumulative_dPV + dPV << " >= Emax == " << Emax << std::endl;
380+
+ std::cout << "REJECT E == " << ecurrent << " + " << cumulative_dPV + dPV << " >= Emax == " << Emax << std::endl;
381381
+#endif
382382
+ // reject move, so don't touch cumulative_dPV, since type change that led to current dPV was reverted
383383
+
@@ -425,7 +425,7 @@ diff -N -u -r orig/src/NS/fix_ns_cellmc.cpp new/src/NS/fix_ns_cellmc.cpp
425425
+new_cell[2][0] = domain->xz;
426426
+new_cell[2][1] = domain->yz;
427427
+new_cell[2][2] = domain->boxhi[2] - domain->boxlo[2];
428-
+ std::cout << "ACCEPT E == " << ecurrent " - " << cumulative_dPV << " < Emax == " << Emax << " min_aspect " << min_aspect_ratio_val(new_cell) << std::endl;
428+
+ std::cout << "ACCEPT E == " << ecurrent " + " << cumulative_dPV << " < Emax == " << Emax << " min_aspect " << min_aspect_ratio_val(new_cell) << std::endl;
429429
+ // std::cout << "final cell " << new_cell[0][0] << " " << new_cell[0][1] << " " << new_cell[0][2] << std::endl;
430430
+ // std::cout << " " << new_cell[1][0] << " " << new_cell[1][1] << " " << new_cell[1][2] << std::endl;
431431
+ // std::cout << " " << new_cell[2][0] << " " << new_cell[2][1] << " " << new_cell[2][2] << std::endl;
@@ -478,7 +478,7 @@ diff -N -u -r orig/src/NS/fix_ns_cellmc.cpp new/src/NS/fix_ns_cellmc.cpp
478478
+}
479479
diff -N -u -r orig/src/NS/fix_ns_cellmc.h new/src/NS/fix_ns_cellmc.h
480480
--- orig/src/NS/fix_ns_cellmc.h 1969-12-31 19:00:00.000000000 -0500
481-
+++ new/src/NS/fix_ns_cellmc.h 2023-04-01 17:15:39.278299788 -0400
481+
+++ new/src/NS/fix_ns_cellmc.h 2023-04-04 21:47:03.744996335 -0400
482482
@@ -0,0 +1,74 @@
483483
+/* -*- c++ -*- ----------------------------------------------------------
484484
+ LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
@@ -826,7 +826,7 @@ diff -N -u -r orig/src/NS/fix_ns_gmc.h new/src/NS/fix_ns_gmc.h
826826
+*/
827827
diff -N -u -r orig/src/NS/fix_ns_type.cpp new/src/NS/fix_ns_type.cpp
828828
--- orig/src/NS/fix_ns_type.cpp 1969-12-31 19:00:00.000000000 -0500
829-
+++ new/src/NS/fix_ns_type.cpp 2023-04-01 17:14:14.838079400 -0400
829+
+++ new/src/NS/fix_ns_type.cpp 2023-04-06 12:03:37.722019077 -0400
830830
@@ -0,0 +1,341 @@
831831
+/* ----------------------------------------------------------------------
832832
+ LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
@@ -1093,9 +1093,9 @@ diff -N -u -r orig/src/NS/fix_ns_type.cpp new/src/NS/fix_ns_type.cpp
10931093
+
10941094
+ // if potential energy + d(mu N) is above Emax then reject move
10951095
+ // need to include previous steps' cumulative dmuN contributions, as well as current ones
1096-
+ if (ecurrent + cumulative_dmuN + dmuN >= Emax) {
1096+
+ if (ecurrent - cumulative_dmuN - dmuN >= Emax) {
10971097
+#ifdef DEBUG
1098-
+ std::cout << "REJECT E == " << ecurrent << " + " << cumulative_dmuN + dmuN << " >= Emax == " << Emax << " " << std::endl;
1098+
+ std::cout << "REJECT E == " << ecurrent << " - " << cumulative_dmuN + dmuN << " >= Emax == " << Emax << " " << std::endl;
10991099
+#endif
11001100
+ // reject move, so don't touch cumulative_dmuN, since type change that led to current dmuN was reverted
11011101
+

pymatnext/ns.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,15 @@ def step_size_tune(self, n_configs=1, min_accept_rate=0.25, max_accept_rate=0.5,
339339
else:
340340
self.local_configs[0].copy_contents(ns_config)
341341

342+
self.local_configs[0].reset_walk_counters()
342343
accept_freq_contribution = self.local_configs[0].walk(self.max_val, self.local_walk_length, self.rng_local)
343344
accept_freq += np.asarray(accept_freq_contribution)
344345

345346
accept_freq = self.comm.allreduce(accept_freq, self.MPI.SUM)
346347

347348
if first_iter and self.comm.rank == 0:
348349
for name, size, max_size, freq in zip(step_size_names, self.local_configs[0].step_size.values(), max_step_size, accept_freq):
349-
print("step_size_tune initial", name, size, max_size, freq)
350+
print("step_size_tune initial", name, "size", size, "max", max_size, "freq", freq)
350351
first_iter = False
351352

352353
done = []
@@ -374,7 +375,7 @@ def step_size_tune(self, n_configs=1, min_accept_rate=0.25, max_accept_rate=0.5,
374375
break
375376

376377
if any(np.asarray(step_size) < 1.0e-12):
377-
raise RuntimeError(f"Stepsize got too small with automatic tuning {step_size}")
378+
raise RuntimeError(f"Stepsize got too small with automatic tuning {step_size} {step_size_names}")
378379

379380
if self.comm.rank == 0:
380381
for name, size in zip(step_size_names, self.local_configs[0].step_size.values()):
@@ -529,15 +530,15 @@ def read_rngs(self, bit_generator_states, different_nlocal=False):
529530
bit_generator_states = {"global": None, "locals": []}
530531

531532
# bcast globals
532-
self.rng_global.bit_generator.state = self.comm.bcast(bit_generator_states["global"], root=0)
533+
new_state = self.comm.bcast(bit_generator_states["global"], root=0)
534+
self.rng_global.bit_generator.state = new_state
533535

534536
# scatter or generate locals
535537
n_locals = self.comm.bcast(len(bit_generator_states["locals"]), root = 0)
536-
# print("BOB", n_locals, self.comm.size)
537-
if n_locals > self.comm.size:
538+
if n_locals == self.comm.size:
538539
self.rng_local.bit_generator.state = self.comm.scatter(bit_generator_states["locals"][:self.comm.size], root=0)
539540
else:
540-
# need more local generators than we have,generate all from global rng
541+
# number of read-in generators doesn't match number needed, start over by generating all from global rng
541542
self.rng_global, self.rng_local = new_rngs(self.comm.rank, None, self.rng_global)
542543

543544

pymatnext/ns_configs/ase_atoms/__init__.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def _parse_composition(composition):
7272
"""
7373
# parse composition and set up symbols and cls._Zs
7474
if isinstance(composition, str):
75-
composition_p = re.split(r"([A-Z][a-z]?[0-9]*)", re.sub("\s+", "", composition))
75+
composition_p = re.split(r"([A-Z][a-z]?[0-9]*)", re.sub(r"\s+", "", composition))
7676
if any([s != "" for s in composition_p[0::2]]):
7777
raise ValueError(f"Unknown characters in composition {composition}")
7878
composition_p = composition_p[1::2]
@@ -125,7 +125,8 @@ def initialize(cls, params):
125125
def __init__(self, params, compression=np.inf, source="random", rng=None, kB=ase.units.kB, allocate_only=False):
126126
check_fill_defaults(params, param_defaults_ase_atoms, label="configs")
127127

128-
assert len(self._Zs) > 0
128+
if len(self._Zs) == 0:
129+
NSConfig_ASE_Atoms.initialize(params)
129130

130131
# Save params for later construction of the calculator
131132
# Also save calc_type, since it's needed for some other setup tasks,
@@ -231,8 +232,16 @@ def __init__(self, params, compression=np.inf, source="random", rng=None, kB=ase
231232
self.atoms.prev_positions = np.zeros(self.atoms.positions.shape)
232233
self.atoms.prev_cell = np.zeros(self.atoms.cell.array.shape)
233234

235+
self.reset_walk_counters()
236+
237+
238+
def reset_walk_counters(self):
239+
"""Reset attempted and successful step counters
240+
"""
241+
234242
self.n_att_acc = np.zeros((len(NSConfig_ASE_Atoms._step_size_params), 2), dtype=np.int64)
235243

244+
236245
def init_calculator(self):
237246
"""Initialize calculator. Not part of constructor since some calculators (e.g. LAMMPS)
238247
cannot be pickled for mpi4py communication.
@@ -281,8 +290,8 @@ def init_calculator(self):
281290
Z_types[Z] = species_type
282291

283292
# make numpy arrays for (presumably?) faster lookup
284-
self.type_of_Z = np.zeros(max(Z_types.keys()) + 1, dtype=np.int)
285-
self.Z_of_type = np.zeros(max(Z_types.values()) + 1, dtype=np.int)
293+
self.type_of_Z = np.zeros(max(Z_types.keys()) + 1, dtype=int)
294+
self.Z_of_type = np.zeros(max(Z_types.values()) + 1, dtype=int)
286295
for Z, Z_type in Z_types.items():
287296
self.type_of_Z[Z] = Z_type
288297
self.Z_of_type[Z_type] = Z
@@ -431,7 +440,7 @@ def initial_calc_and_store(self):
431440
"""
432441
if self.calc_type == "ASE":
433442
self.calc.calculate(self.atoms, properties=["free_energy", "forces"])
434-
self.atoms.info["NS_energy"][...] = self.calc.results["free_energy"]
443+
self.atoms.info["NS_energy"][...] = self.calc.results.get("free_energy", self.calc.results.get("energy"))
435444
self.atoms.arrays["NS_forces"][...] = self.calc.results["forces"]
436445
elif self.calc_type == "LAMMPS":
437446
self.calc.reset_box([0.0, 0.0, 0.0], np.diag(self.atoms.cell), self.atoms.cell[0, 1], self.atoms.cell[1, 2], self.atoms.cell[0, 2])
@@ -573,7 +582,6 @@ def header_dict(self):
573582
"flat_V_prior": self.move_params["cell"]["flat_V_prior"],
574583
"extras": [ "volume", "natoms"] + ([f"x_{Z}" for Z in self._Zs] if len(self._Zs) > 1 else []) }
575584

576-
print("BOB NSConfigs_ASE_Atoms returning header_dict", header_dict)
577585
return header_dict
578586

579587

pymatnext/ns_configs/ase_atoms/walks_ase_calc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def walk_pos_gmc(ns_atoms, Emax, rng):
3232
# step and evaluate new energy, forces
3333
atoms.positions += atoms.arrays["NS_velocities"]
3434
atoms.calc.calculate(atoms, properties=["free_energy", "forces"])
35-
E = atoms.calc.results["free_energy"]
35+
E = atoms.calc.results.get("free_energy", atoms.calc.results.get("energy"))
3636
F = atoms.calc.results["forces"]
3737

3838
if E >= Emax: # reflect or fail
@@ -93,7 +93,7 @@ def _eval_and_accept_or_signal_revert(atoms, Emax, delta_PV=0.0, delta_muN=0.0):
9393
revert: bool, True if move is rejected and must be reverted
9494
"""
9595
atoms.calc.calculate(atoms, properties=["free_energy", "forces"])
96-
E = atoms.calc.results["free_energy"]
96+
E = atoms.calc.results.get("free_energy", atoms.calc.results.get("energy"))
9797
E_shift = atoms.info["NS_energy_shift"] + delta_PV - delta_muN
9898
if E + E_shift < Emax:
9999
# accept can happen here, because it's always the same action

pymatnext/ns_configs/ase_atoms/walks_lammps.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@
44

55
import lammps
66

7+
# avoiding every lammps fix from having to do the full energy shift is useful
8+
# we want
9+
# E + P V - mu N < Emax
10+
# therefore, we modify Emax passed to lammps defining Emax^lammps, with V0 and N0
11+
# defined as the initial volume and species numbers
12+
# E < Emax - P V0 + mu N0 = Emax^lammps
13+
# this is sufficient for position moves, where V and N don't change
14+
#
15+
# for volume changes, we want
16+
# E + P (V0 + dV) - mu N0 < Emax
17+
# where dV is the cumulative difference of the current steps' volume and the step where
18+
# the fix trajectory started
19+
# E < Emax - P (V0 + dV) + mu N0
20+
# E < Emax - P V0 + mu N0 - P dV
21+
# E < Emax^lammps - P dV
22+
# which is equivalent to
23+
# E + P dV < Emax^lammps
24+
725
def set_lammps_from_atoms(ns_atoms):
826
"""set lammps internal configuration data (cell, types, positions, velocities) from
927
ns_atoms object
@@ -184,7 +202,7 @@ def walk_cell(ns_atoms, Emax, rng):
184202
# NOTE: would it be faster to construct more of this command ahead of time?
185203
# would either still have to do step_sizes here, or recreate command
186204
# every time step sizes are changed
187-
fix_cmd = (f"fix NS all ns/cellmc {lammps_seed} {Emax} {ns_atoms.pressure} {move_params_cell['min_aspect_ratio']} "
205+
fix_cmd = (f"fix NS all ns/cellmc {lammps_seed} {Emax} {move_params_cell['min_aspect_ratio']} {ns_atoms.pressure} "
188206
f"{submove_probs['volume']} {step_size_volume} "
189207
f"{submove_probs['stretch']} {step_size_stretch} "
190208
f"{submove_probs['shear']} {step_size_shear} "

0 commit comments

Comments
 (0)