Skip to content

Commit a645804

Browse files
authored
Merge pull request #27 from libAtoms/cell_step_param_scaling
Cell step param scaling
2 parents 669e06a + 9070a8a commit a645804

File tree

7 files changed

+48
-35
lines changed

7 files changed

+48
-35
lines changed

README_input_parameters.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@
5050
- cell_proportion = 0.0
5151
- type_proportion = 0.0
5252
- [max_step_size]
53-
- pos_gmc_each_atom = -1.0
54-
- cell_volume_per_atom = -1.0
55-
- cell_shear = 0.2
53+
- pos_gmc_each_atom = -0.1
54+
- cell_volume_per_atom = -0.05
55+
- cell_shear_per_rt3_atom = -1.0
5656
- cell_stretch = 0.2
5757
- [step_size]
5858
- pos_gmc_each_atom = -1.0
5959
- cell_volume_per_atom = -1.0
60-
- cell_shear = -1.0
60+
- cell_shear_per_rt3_atom = -1.0
6161
- cell_stretch = -1.0
6262
- [cell]
6363
- min_aspect_ratio = 0.8

README_usage.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,21 @@ Hopefully section and key names are self explanatory.
111111

112112
### Additional notes on run parameters
113113

114-
- all intervals are in NS iterations, except `stdout_report_interval_s` which is in seconds
114+
- All intervals are in NS iterations, except `stdout_report_interval_s` which is in seconds
115115
- `configs.calculator.type` can be `"ASE"` or `"LAMMPS"`
116116
- if `"LAMMPS"`, `args` consists of `cmds`, with LAMMPS commands, and `types` dict (one key for each species)
117117
- if `"ASE"`, `args` consists of `module` key with module that defines a `calc` symbol containing an `ase.calculators.Calculator` object
118118
- `configs.walk.*_traj_len` controls the number of steps in a walk block of that type
119119
- `configs.walk.*_proportion` controls the fraction of steps overall that are used for that type of move
120-
- if `config.walk.type.sGC = true`, a dict of `mu` values, one per species, is required.
120+
- If `config.walk.type.sGC = true`, a dict of `mu` values, one per species, is required.
121+
- There are position, cell, and atom-type walks, with associated step size parameters that are auto-tuned. Default values depends on
122+
an overall volume scale given by `initial_rand_vol_per_atom` and corresponding length scale given by its cube root.
123+
- Maxima are in `[configs.walk.max_step_size]` section. Defaults for first three are negative.
124+
- `pos_gmc_each_atom`: distance (typically A) that each atom should typically make in GMC step. If negative, used as multiplier for
125+
length scale.
126+
- `cell_volume_per_atom`: change in volume (typically A^3), will also be scaled by number of atoms. If negative, used as multiplier
127+
for volume scale.
128+
- `cell_shear_per_rt3_atom`: cell shear magnitude (typically A) which multiplies _normalized_ cell vectors, will also be scaled by
129+
cube root of number of atoms. If negative used as multiplier for length scale.
130+
- `cell_stretch`: cell stretch, fractional (i.e. strain)
131+
- Initial values with same key names are in `[configs.walk.step_size]` section. Any negative values are replaced with half the corresponding maximum.

pymatnext/ns_configs/ase_atoms/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class NSConfig_ASE_Atoms():
6262
filename_suffix = ".extxyz"
6363
n_quantities = -1
6464

65-
_step_size_params = ["pos_gmc_each_atom", "cell_volume_per_atom", "cell_shear", "cell_stretch"]
65+
_step_size_params = ["pos_gmc_each_atom", "cell_volume_per_atom", "cell_shear_per_rt3_atom", "cell_stretch"]
6666
_max_E_hist = collections.deque(maxlen=1000)
6767
_walk_moves = ["gmc", "cell", "type"]
6868
_Zs = []
@@ -432,9 +432,11 @@ def _prep_walk(self, params, vol_per_atom=None):
432432
assert set(list(self.max_step_size.keys())) == set(self._step_size_params)
433433
# max step size for position GMC and cell volume defaults are scaled to volume per atom
434434
if self.max_step_size["pos_gmc_each_atom"] < 0.0:
435-
self.max_step_size["pos_gmc_each_atom"] = (vol_per_atom ** (1.0/3.0)) / 10.0
435+
self.max_step_size["pos_gmc_each_atom"] = (vol_per_atom ** (1.0/3.0)) * np.abs(self.max_step_size["pos_gmc_each_atom"])
436436
if self.max_step_size["cell_volume_per_atom"] < 0.0:
437-
self.max_step_size["cell_volume_per_atom"] = vol_per_atom / 20.0
437+
self.max_step_size["cell_volume_per_atom"] = vol_per_atom * np.abs(self.max_step_size["cell_volume_per_atom"])
438+
if self.max_step_size["cell_shear_per_rt3_atom"] < 0.0:
439+
self.max_step_size["cell_shear_per_rt3_atom"] = (vol_per_atom ** (1.0/3.0)) * np.abs(self.max_step_size["cell_shear_per_rt3_atom"])
438440

439441
# actual step sizes
440442
self.step_size = params["step_size"].copy()

pymatnext/ns_configs/ase_atoms/ase_atoms_params.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@
2727
"type_proportion": 0.0,
2828

2929
"max_step_size": {
30-
"pos_gmc_each_atom": -1.0,
31-
"cell_volume_per_atom": -1.0,
32-
"cell_shear": 0.2,
30+
"pos_gmc_each_atom": -0.1,
31+
"cell_volume_per_atom": -0.05,
32+
"cell_shear_per_rt3_atom": -1.0,
3333
"cell_stretch": 0.2
3434
},
3535

3636
"step_size": {
3737
"pos_gmc_each_atom": -1.0,
3838
"cell_volume_per_atom": -1.0,
39-
"cell_shear": -1.0,
39+
"cell_shear_per_rt3_atom": -1.0,
4040
"cell_stretch": -1.0
4141
},
4242

pymatnext/ns_configs/ase_atoms/walks_ase_calc.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,15 @@ def walk_cell(ns_atoms, Emax, rng):
126126
127127
Returns
128128
-------
129-
[("cell_volume_per_atom", int n_attempt, int n_success), ("cell_shear", ...), ("cell_stretch", ...)] info on move params and attempts/successes
129+
[("cell_volume_per_atom", int n_attempt, int n_success),
130+
("cell_shear_per_rt3_atom", int n_attempt, n_success),
131+
("cell_stretch", int n_attempt, n_success)] with n_att and n_acc number of attempted and accepted
132+
move for each submove type
130133
"""
131134
atoms = ns_atoms.atoms
132135
N_atoms = len(atoms)
133-
step_size_volume = N_atoms * ns_atoms.step_size["cell_volume_per_atom"]
134-
step_size_shear = ns_atoms.step_size["cell_shear"]
136+
step_size_volume = ns_atoms.step_size["cell_volume_per_atom"] * N_atoms
137+
step_size_shear = ns_atoms.step_size["cell_shear_per_rt3_atom"] * (N_atoms ** (1.0 / 3.0))
135138
step_size_stretch = ns_atoms.step_size["cell_stretch"]
136139
min_aspect_ratio = ns_atoms.move_params["cell"]["min_aspect_ratio"]
137140
flat_V_prior = ns_atoms.move_params["cell"]["flat_V_prior"]
@@ -197,7 +200,7 @@ def walk_cell(ns_atoms, Emax, rng):
197200
n_acc[move] += 1
198201

199202
return [("cell_volume_per_atom", n_att["volume"], n_acc["volume"]),
200-
("cell_shear", n_att["shear"], n_acc["shear"]),
203+
("cell_shear_per_rt3_atom", n_att["shear"], n_acc["shear"]),
201204
("cell_stretch", n_att["stretch"], n_acc["stretch"])]
202205

203206

pymatnext/ns_configs/ase_atoms/walks_lammps.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,18 +187,19 @@ def walk_cell(ns_atoms, Emax, rng):
187187
188188
Returns
189189
-------
190-
[("cell_volume_per_atom", n_att, n_acc),
191-
("cell_shear", n_att, n_acc),
192-
("cell_stretch", n_att, n_acc)] with n_att and n_acc number of attempted and accepted
190+
[("cell_volume_per_atom", int n_attempt, int n_success),
191+
("cell_shear_per_rt3_atom", int n_attempt, n_success),
192+
("cell_stretch", int n_attempt, n_success)] with n_att and n_acc number of attempted and accepted
193193
move for each submove type
194194
"""
195195
ns_atoms.calc.command("unfix NS")
196196
atoms = ns_atoms.atoms
197197
# for LAMMPS RanMars RNG
198198
lammps_seed = rng.integers(1, 900000000)
199199

200-
step_size_volume = len(atoms) * ns_atoms.step_size["cell_volume_per_atom"]
201-
step_size_shear = ns_atoms.step_size["cell_shear"]
200+
N_atoms = len(atoms)
201+
step_size_volume = ns_atoms.step_size["cell_volume_per_atom"] * N_atoms
202+
step_size_shear = ns_atoms.step_size["cell_shear_per_rt3_atom"] * (N_atoms ** (1.0 / 3.0))
202203
step_size_stretch = ns_atoms.step_size["cell_stretch"]
203204

204205
types, pos, vel = set_lammps_from_atoms(ns_atoms)
@@ -256,7 +257,7 @@ def walk_cell(ns_atoms, Emax, rng):
256257
n_acc[submove_type] = 0
257258

258259
return [("cell_volume_per_atom", n_att["volume"], n_acc["volume"]),
259-
("cell_shear", n_att["shear"], n_acc["shear"]),
260+
("cell_shear_per_rt3_atom", n_att["shear"], n_acc["shear"]),
260261
("cell_stretch", n_att["stretch"], n_acc["stretch"])]
261262

262263
def walk_type(ns_atoms, Emax, rng):

tests/test_sample.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def do_Morse_ASE(tmp_path, monkeypatch, using_mpi, max_iter=None):
158158
assert len(list(tmp_path.glob('Morse_ASE.test.traj.*xyz'))) == 1
159159
assert len(list(ase.io.read(tmp_path / 'Morse_ASE.test.traj.extxyz', ':'))) == int(np.ceil(max_iter_use / traj_interval))
160160

161-
# from test run 6/13/2025, when max iter was extended to 110 to catch deadlock in old buggy snapshot step_size writing
161+
# from test run 6/20/2025, when cell_shear_per_rt3_atom default was increased
162162
if using_mpi:
163163
samples_fields_ref = np.asarray([1.09000000e+02, 8.02719236e+00, 1.28609799e+04, 1.60000000e+01])
164164
else:
@@ -172,9 +172,7 @@ def do_Morse_ASE(tmp_path, monkeypatch, using_mpi, max_iter=None):
172172
# tolerance loosened so that restart, which isn't perfect due to finite precision in
173173
# saved cofig file, still passes
174174
if not np.allclose(samples_fields, samples_fields_ref, rtol=0.02):
175-
print("final samples line test", samples_fields)
176-
print("final samples line ref ", samples_fields_ref)
177-
assert False
175+
assert False, f"test {samples_fields} ref {samples_fields_ref}"
178176

179177
# this will fail if number of steps is not divisible by N_samples interval, because
180178
# clone_hist always saves every line. Also, clone_hist is a hack that's truncated by
@@ -243,21 +241,19 @@ def do_EAM_LAMMPS(tmp_path, monkeypatch, using_mpi, max_iter=None):
243241
assert len(list(tmp_path.glob('EAM_LAMMPS.test.traj.*xyz'))) == 1
244242
assert len(list(ase.io.read(tmp_path / 'EAM_LAMMPS.test.traj.extxyz', ':'))) == max_iter_use // traj_interval
245243

246-
# from test run 12/8/2022
244+
# from test run 6/20/2025 when cell shear default was increased
247245
if using_mpi:
248-
fields_ref = np.asarray([2.99000000e+02, -3.91163426e+02, 1.08674253e+04, 1.60000000e+01, 1.87500000e-01, 8.12500000e-01])
246+
fields_ref = np.asarray([2.99000000e+02, -3.90328931e+02, 1.99365520e+04, 1.60000000e+01, 1.87500000e-01, 8.12500000e-01])
249247
else:
250-
fields_ref = np.asarray([299, -366.1823642208, 6004.3693892916, 16.0000000000, 0.2500000000, 0.7500000000])
248+
fields_ref = np.asarray([2.99000000e+02, -3.90994404e+02, 1.45640509e+04, 1.60000000e+01, 1.87500000e-01, 8.12500000e-01])
251249

252250
with open(tmp_path / 'EAM_LAMMPS.test.NS_samples') as fin:
253251
for l in fin:
254252
pass
255253
fields = np.asarray([float(f) for f in l.strip().split()])
256254

257255
if not np.allclose(fields, fields_ref):
258-
print("final line test", fields)
259-
print("final line ref ", fields_ref)
260-
assert False
256+
assert False, f"test {fields} ref {fields_ref}"
261257

262258

263259
def do_pressure(tmp_path, monkeypatch, using_mpi):
@@ -308,7 +304,7 @@ def do_pressure(tmp_path, monkeypatch, using_mpi):
308304

309305
Vfirst = float(lfirst.strip().split()[2])
310306
Vlast = float(llast.strip().split()[2])
311-
assert Vfirst / Vlast > 20
307+
assert Vfirst / Vlast > 10
312308

313309

314310
def do_sGC(tmp_path, monkeypatch, using_mpi):
@@ -366,4 +362,4 @@ def do_sGC(tmp_path, monkeypatch, using_mpi):
366362
f_13_last, f_29_last = [float(f) for f in llast.strip().split()[4:6]]
367363

368364
assert f_29_first / f_13_first == 1.0
369-
assert f_29_last / f_13_last > 5
365+
assert f_29_last / f_13_last > 4

0 commit comments

Comments
 (0)