From b446f60de7645d48515d69bd9fb1747356800725 Mon Sep 17 00:00:00 2001 From: Noam Bernstein Date: Wed, 10 Jan 2024 14:31:40 -0500 Subject: [PATCH] Clean up minimahopping tests Don't adjust cell in optimize FixSymmetry because it breaks calculation caching in PreconLBFGS --- complete_pytest.tin | 2 +- tests/test_minimahopping.py | 8 ++++---- wfl/autoparallelize/pool.py | 12 ++++++++++++ wfl/generate/minimahopping.py | 26 ++++++++++++++++++-------- wfl/generate/optimize.py | 2 +- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/complete_pytest.tin b/complete_pytest.tin index 63138350..7b1855cb 100755 --- a/complete_pytest.tin +++ b/complete_pytest.tin @@ -57,7 +57,7 @@ echo "summary line $l" # ===== 152 passed, 17 skipped, 3 xpassed, 78 warnings in 4430.81s (1:13:50) ===== lp=$( echo $l | sed -E -e 's/ in .*//' -e 's/\s*,\s*/\n/g' ) -declare -A expected_n=( ["passed"]="152" ["skipped"]="17" ["warnings"]=78 ["xpassed"]=3 ) +declare -A expected_n=( ["passed"]="160" ["skipped"]="21" ["warnings"]=828 ["xfailed"]=2 ["xpassed"]=1 ) IFS=$'\n' for out in $lp; do out_n=$(echo $out | sed -e 's/^=* //' -e 's/ .*//' -e 's/,//') diff --git a/tests/test_minimahopping.py b/tests/test_minimahopping.py index 06c94849..ccd9b50a 100644 --- a/tests/test_minimahopping.py +++ b/tests/test_minimahopping.py @@ -28,7 +28,7 @@ def test_return_md_traj(cu_slab, tmp_path): inputs = ConfigSet(input_configs) outputs = OutputSpec() - atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=1, totalsteps=5, save_tmpdir=True, return_all_traj=True) + atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=1, totalsteps=5, save_tmpdir=True, return_all_traj=True, workdir=tmp_path) assert any(["minima" in at.info["config_type"] for at in atoms_opt]) assert any(["traj" in at.info["config_type"] for at in atoms_opt]) @@ -43,7 +43,7 @@ def test_mult_files(cu_slab, tmp_path): calc = EMT() - atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=1, totalsteps=3) + atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=1, totalsteps=3, workdir=tmp_path) n1 = len(ase.io.read(tmp_path / infiles[0].replace('.xyz', '.out.xyz'), ':')) n2 = len(ase.io.read(tmp_path / infiles[1].replace('.xyz', '.out.xyz'), ':')) @@ -51,7 +51,7 @@ def test_mult_files(cu_slab, tmp_path): assert n1 == n2 * 2 -def test_relax(cu_slab): +def test_relax(cu_slab, tmp_path): calc = EMT() @@ -67,7 +67,7 @@ def test_relax(cu_slab): # where are trajectories fail is excluded. Thus, let's give it some trials to avoid this situation. trial = 0 while trial < 10: - atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=fmax, totalsteps=totalsteps) + atoms_opt = minimahopping.minimahopping(inputs, outputs, calc, fmax=fmax, totalsteps=totalsteps, workdir=tmp_path) if len(list(atoms_opt)) > 0: break trial += 1 diff --git a/wfl/autoparallelize/pool.py b/wfl/autoparallelize/pool.py index 5c66bd59..b18056f5 100644 --- a/wfl/autoparallelize/pool.py +++ b/wfl/autoparallelize/pool.py @@ -4,6 +4,18 @@ import inspect import functools + +# seems to conflict with torch's own multiprocessing +# try: +# # make multiprocessing use dill instead of pickle, mainly to support lambdas. See +# # https://stackoverflow.com/questions/19984152/what-can-multiprocessing-and-dill-do-together +# import dill, multiprocessing +# dill.Pickler.dumps, dill.Pickler.loads = dill.dumps, dill.loads +# multiprocessing.reduction.ForkingPickler = dill.Pickler +# multiprocessing.reduction.dump = dill.dump +# except ModuleNotFoundError: +# pass + from multiprocessing.pool import Pool from wfl.configset import ConfigSet diff --git a/wfl/generate/minimahopping.py b/wfl/generate/minimahopping.py index 4c3885d2..51068ae4 100644 --- a/wfl/generate/minimahopping.py +++ b/wfl/generate/minimahopping.py @@ -30,10 +30,14 @@ def _get_MD_trajectory(rundir): # perform MinimaHopping on one ASE.atoms object def _atom_opt_hopping(atom, calculator, Ediff0, T0, minima_threshold, mdmin, - fmax, timestep, totalsteps, skip_failures, **opt_kwargs): + fmax, timestep, totalsteps, skip_failures, workdir=None, **opt_kwargs): save_tmpdir = opt_kwargs.pop("save_tmpdir", False) return_all_traj = opt_kwargs.pop("return_all_traj", False) - workdir = os.getcwd() + origdir = Path.cwd() + if workdir is None: + workdir = Path.cwd() + else: + workdir = Path(workdir) rundir = tempfile.mkdtemp(dir=workdir, prefix='Opt_hopping_') @@ -50,6 +54,7 @@ def _atom_opt_hopping(atom, calculator, Ediff0, T0, minima_threshold, mdmin, sys.stderr.flush() os.chdir(workdir) shutil.rmtree(rundir) + os.chdir(origdir) return None else: raise @@ -61,14 +66,17 @@ def _atom_opt_hopping(atom, calculator, Ediff0, T0, minima_threshold, mdmin, for hop_traj in Trajectory('minima.traj'): config_type_append(hop_traj, 'minima') traj.append(hop_traj) - os.chdir(workdir) if not save_tmpdir: + os.chdir(workdir) shutil.rmtree(rundir) + os.chdir(origdir) return traj + os.chdir(origdir) + def _run_autopara_wrappable(atoms, calculator, Ediff0=1, T0=1000, minima_threshold=0.5, mdmin=2, - fmax=1, timestep=1, totalsteps=10, skip_failures=True, + fmax=1, timestep=1, totalsteps=10, skip_failures=True, workdir=None, autopara_rng_seed=None, autopara_per_item_info=None, **opt_kwargs): """runs a structure optimization @@ -82,12 +90,12 @@ def _run_autopara_wrappable(atoms, calculator, Ediff0=1, T0=1000, minima_thresho Ediff0: float, default 1 (eV) initial energy acceptance threshold T0: float, default 1000 (K) - initial MD ‘temperature’ - minima_threshold: float, default 0.5 (Å) + initial MD temperature + minima_threshold: float, default 0.5 (A) threshold for identical configs mdmin: int, default 2 criteria to stop MD simulation (number of minima) - fmax: float, default 1 (eV/Å) + fmax: float, default 1 (eV/A) max force for optimizations timestep: float, default 1 (fs) timestep for MD simulations @@ -95,6 +103,8 @@ def _run_autopara_wrappable(atoms, calculator, Ediff0=1, T0=1000, minima_thresho number of steps skip_failures: bool, default True just skip optimizations that raise an exception + workdir: str/Path default None + workdir for saving files opt_kwargs keyword arguments for MinimaHopping autopara_rng_seed: int, default None @@ -115,7 +125,7 @@ def _run_autopara_wrappable(atoms, calculator, Ediff0=1, T0=1000, minima_thresho traj = _atom_opt_hopping(atom=at, calculator=calculator, Ediff0=Ediff0, T0=T0, minima_threshold=minima_threshold, mdmin=mdmin, fmax=fmax, timestep=timestep, totalsteps=totalsteps, - skip_failures=skip_failures, **opt_kwargs) + skip_failures=skip_failures, workdir=workdir, **opt_kwargs) all_trajs.append(traj) return all_trajs diff --git a/wfl/generate/optimize.py b/wfl/generate/optimize.py index 199652cd..73a40f92 100644 --- a/wfl/generate/optimize.py +++ b/wfl/generate/optimize.py @@ -103,7 +103,7 @@ def _run_autopara_wrappable(atoms, calculator, fmax=1.0e-3, smax=None, steps=100 org_constraints = at.constraints if keep_symmetry: - sym = FixSymmetry(at) + sym = FixSymmetry(at, adjust_cell=False) # Append rather than overwrite constraints at.set_constraint([*at.constraints, sym])