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

DFT calculator convergence test #292

Merged
merged 5 commits into from
Feb 8, 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 complete_pytest.tin
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,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"]="163" ["skipped"]="21" ["warnings"]=803 ["xfailed"]=2 ["xpassed"]=1 )
declare -A expected_n=( ["passed"]="164" ["skipped"]="21" ["warnings"]=803 ["xfailed"]=2 ["xpassed"]=1 )
IFS=$'\n'
for out in $lp; do
out_n=$(echo $out | sed -e 's/^=* //' -e 's/ .*//' -e 's/,//')
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setuptools.setup(
name="wfl",
version="0.2.1",
version="0.2.2",
packages=setuptools.find_packages(exclude=["tests"]),
install_requires=["click>=7.0", "numpy", "ase>=3.21", "pyyaml", "spglib", "docstring_parser",
"expyre-wfl @ https://github.com/libAtoms/ExPyRe/tarball/main",
Expand Down
37 changes: 37 additions & 0 deletions tests/calculators/test_vasp.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,40 @@ def test_vasp_multi_calc(tmp_path):

assert np.abs(e_GGA - e_test) < 1.0e-4
assert n_loop_test < n_loop_GGA - 2


def test_vasp_unconverged(tmp_path):
ase.io.write(tmp_path / 'vasp_in.xyz', Atoms('Si', cell=(2, 2, 2), pbc=[True] * 3), format='extxyz')

configs_eval = generic.calculate(
inputs=ConfigSet(tmp_path / 'vasp_in.xyz'),
outputs=OutputSpec('vasp_out.regular.xyz', file_root=tmp_path),
calculator=Vasp(workdir=tmp_path, encut=200, kspacing=1.0, pp=os.environ['PYTEST_VASP_POTCAR_DIR'],
keep_files=True),
output_prefix='TEST_')

run_dir = list(tmp_path.glob('run_VASP_*'))
nfiles = len(list(os.scandir(run_dir[0])))

assert nfiles == 18

ats = list(configs_eval)
print("initial run converged?", ats[0].info["TEST_converged"])
assert ats[0].info["TEST_converged"]


configs_eval = generic.calculate(
inputs=ConfigSet(tmp_path / 'vasp_in.xyz'),
outputs=OutputSpec('vasp_out.unconverged.xyz', file_root=tmp_path),
calculator=Vasp(workdir=tmp_path, encut=200, nelm=6, kspacing=1.0, pp=os.environ['PYTEST_VASP_POTCAR_DIR'],
keep_files=True),
output_prefix='TEST_')

run_dir = list(tmp_path.glob('run_VASP_*'))
nfiles = len(list(os.scandir(run_dir[0])))

assert nfiles == 18

ats = list(configs_eval)
print("second run converged?", ats[0].info["TEST_converged"])
assert not ats[0].info["TEST_converged"]
2 changes: 1 addition & 1 deletion tests/test_optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def test_relax_fixed_vol(cu_slab):

def test_subselect_from_traj(cu_slab):

calc = EMT()
calc = (EMT, [], {})

cu_slab_optimised = cu_slab.copy()
cu_slab_optimised.set_positions(expected_relaxed_positions_constant_pressure)
Expand Down
15 changes: 6 additions & 9 deletions tests/test_remote_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def do_generic_calc(tmp_path, sys_name, monkeypatch, remoteinfo_env):
monkeypatch.setenv('WFL_EXPYRE_NO_MARK_PROCESSED', '1')

t0 = time.time()
results = generic.calculate(inputs=ci, outputs=co, calculator=calc, properties=["energy", "forces"],
results = generic.calculate(inputs=ci, outputs=co, calculator=(EMT, [], {}), properties=["energy", "forces"],
autopara_info={"remote_info": ri})
dt = time.time() - t0
print('remote parallel calc_time', dt)
Expand All @@ -161,7 +161,7 @@ def do_generic_calc(tmp_path, sys_name, monkeypatch, remoteinfo_env):
co = OutputSpec(tmp_path / f'ats_o_{sys_name}.xyz')

t0 = time.time()
results = generic.calculate(inputs=ci, outputs=co, calculator=calc, properties=["energy", "forces"],
results = generic.calculate(inputs=ci, outputs=co, calculator=(EMT, [], {}), properties=["energy", "forces"],
autopara_info={"remote_info": ri})
dt_rerun = time.time() - t0
print('remote parallel calc_time', dt_rerun)
Expand Down Expand Up @@ -293,18 +293,18 @@ def test_resubmit_killed_jobs(tmp_path, expyre_systems, monkeypatch, remoteinfo_
def do_resubmit_killed_jobs(tmp_path, sys_name, monkeypatch, remoteinfo_env):
# make sure that jobs that time out can be resubmitted automatically
ri = {'sys_name': sys_name, 'job_name': 'pytest_'+sys_name,
'resources': {'max_time': '1m', 'num_nodes': 1},
'resources': {'max_time': '10s', 'num_nodes': 1},
'num_inputs_per_queued_job': 1, 'check_interval': 10}
remoteinfo_env(ri)

print("RemoteInfo", ri)

ats = [Atoms('C') for _ in range(3)]
n = 20
n = 40
ats[1] = Atoms(f'C{n**3}', positions=np.asarray(np.meshgrid(range(n), range(n), range(n))).reshape((3, -1)).T,
cell=[n]*3, pbc=[True]*3)

calc = EMT()
calc = (EMT, [], {})

# first just ignore failures
ri['ignore_failed_jobs'] = True
Expand All @@ -324,12 +324,9 @@ def do_resubmit_killed_jobs(tmp_path, sys_name, monkeypatch, remoteinfo_env):
ri['resubmit_killed_jobs'] = True
monkeypatch.setenv('WFL_EXPYRE_INFO', json.dumps({"test_resubmit_killed_jobs": ri}))
print("BOB ######### second run, should time out")
try:
with pytest.raises(ExPyReJobDiedError):
results = generic.calculate(inputs=ConfigSet(ats), outputs=OutputSpec(), calculator=calc, properties=["energy", "forces"],
raise_calc_exceptions=True, autopara_info=AutoparaInfo(remote_label="test_resubmit_killed_jobs"))
except ExPyReJobDiedError:
# ignore timeout in initial call
pass

# now resubmit with longer time
ri['resources']['max_time'] = '5m'
Expand Down
8 changes: 7 additions & 1 deletion wfl/calculators/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ def _run_autopara_wrappable(atoms, calculator, properties=None, output_prefix='_
calculator_default = None

if output_prefix == '_auto_':
output_prefix = calculator.__class__.__name__ + '_'
if isinstance(calculator, tuple):
# constructor, get name directly
calc_class = calculator[0].__name__
else:
# calculator object, get name from class
calc_class = calculator.__class__.__name__
output_prefix = calc_class + '_'

at_out = []
for at in atoms_to_list(atoms):
Expand Down
7 changes: 5 additions & 2 deletions wfl/calculators/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ def save_results(atoms, properties, results_prefix=None):
config_results['dipole'] = atoms.get_dipole_moment()
if 'magmom' in properties:
config_results['magmom'] = atoms.get_magnetic_moment()
try:
if results_prefix is not None:
config_results['converged'] = atoms.calc.converged
except AttributeError as exc:
pass

# copy per-atom results
if 'forces' in properties:
Expand All @@ -78,8 +83,6 @@ def save_results(atoms, properties, results_prefix=None):
atoms_results['magmoms'] = atoms.get_magnetic_moments()
if 'energies' in properties:
atoms_results['energies'] = atoms.get_potential_energies()
if 'converged' in properties and results_prefix is not None:
config_results['converged'] = atoms.get_calculator().read_convergence()

if "extra_results" in dir(atoms.calc):
if results_prefix is None and (len(atoms.calc.extra_results.get("config", {})) > 0 or
Expand Down
Loading