Skip to content

Commit cac8f46

Browse files
committed
ase_md enhancements, write_atoms, minor cleanup
1 parent 52572a3 commit cac8f46

File tree

10 files changed

+114
-15
lines changed

10 files changed

+114
-15
lines changed

asimtools/asimmodules/ase_md/ase_md.py

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
1919
from ase.md.langevin import Langevin
2020
from ase.md.npt import NPT
21+
from ase.md import MDLogger
2122
from asimtools.calculators import load_calc
2223
from asimtools.utils import (
2324
get_atoms,
@@ -31,6 +32,9 @@ def langevin_nvt(
3132
traj_file: str = None,
3233
friction: float = 1e-2,
3334
timestep: float = 1*fs,
35+
properties: Optional[Sequence] = ('energy', 'forces', 'stress'),
36+
log_interval: int = 1,
37+
traj_interval: Optional[int] = 1,
3438
):
3539
"""Does Langevin dynamics
3640
@@ -64,7 +68,19 @@ def langevin_nvt(
6468
mode='w',
6569
properties=['energy', 'forces']
6670
)
67-
dyn.attach(traj.write)
71+
dyn.attach(traj.write, interval=traj_interval)
72+
stress = False
73+
if 'stress' in properties:
74+
stress = True
75+
dyn.attach(MDLogger(
76+
dyn,
77+
atoms,
78+
'md.log',
79+
header=True,
80+
stress=stress,
81+
peratom=True,
82+
mode="a"
83+
), interval=log_interval)
6884
dyn.run(nsteps)
6985
return atoms, traj
7086

@@ -78,6 +94,8 @@ def npt(
7894
ttime: float = 25*fs,
7995
pfactor: Optional[float] = None, # (75*fs)**2 * 14*GPa, #Replace 14 with bulk modulus of material
8096
properties: Optional[Sequence] = ('energy', 'forces', 'stress'),
97+
log_interval: int = 1,
98+
traj_interval: Optional[int] = 1,
8199
):
82100
"""Does NPT dynamics
83101
@@ -116,7 +134,20 @@ def npt(
116134
mode='w',
117135
properties=properties,
118136
)
119-
dyn.attach(traj.write)
137+
dyn.attach(traj.write, interval=traj_interval)
138+
139+
stress = False
140+
if 'stress' in properties:
141+
stress = True
142+
dyn.attach(MDLogger(
143+
dyn,
144+
atoms,
145+
'md.log',
146+
header=True,
147+
stress=stress,
148+
peratom=True,
149+
mode="a"
150+
), interval=log_interval)
120151
dyn.run(nsteps)
121152
traj = Trajectory(traj_file, 'r')
122153
return atoms, traj
@@ -176,6 +207,9 @@ def ase_md(
176207
plot: Optional[bool] = True,
177208
time_unit: Optional[str] = 'ase',
178209
plot_args: Optional[dict] = None,
210+
properties: Optional[Sequence] = ('energy', 'forces', 'stress'),
211+
log_interval: Optional[int] = 1,
212+
traj_interval: Optional[int] = 1,
179213
) -> Dict:
180214
"""Runs ASE MD simulations. This is only recommended for small systems and
181215
for testing. For larger systems, use LAMMPS or more purpose-built code
@@ -209,7 +243,7 @@ def ase_md(
209243

210244
calc = load_calc(**calc_spec)
211245
atoms = get_atoms(**image)
212-
atoms.set_calculator(calc)
246+
atoms.calc = calc
213247

214248
if time_unit == 'fs':
215249
timestep *= fs
@@ -224,6 +258,8 @@ def ase_md(
224258
traj_file='output.traj',
225259
timestep=timestep,
226260
friction=friction,
261+
log_interval=log_interval,
262+
traj_interval=traj_interval,
227263
)
228264
elif dynamics == 'npt':
229265
atoms, _ = npt(
@@ -235,6 +271,9 @@ def ase_md(
235271
pfactor=pfactor,
236272
externalstress=externalstress,
237273
ttime=ttime,
274+
properties=properties,
275+
log_interval=log_interval,
276+
traj_interval=traj_interval,
238277
)
239278
elif dynamics == 'nvt':
240279
atoms, _ = npt(
@@ -245,7 +284,9 @@ def ase_md(
245284
timestep=timestep,
246285
pfactor=None,
247286
ttime=ttime,
248-
properties=['energy', 'forces'],
287+
properties=properties,
288+
log_interval=log_interval,
289+
traj_interval=traj_interval,
249290
)
250291

251292

asimtools/asimmodules/elastic_constants/cubic_energy_expansion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def cubic_energy_expansion(
101101
"""
102102
calc = load_calc(calc_id)
103103
atoms = get_atoms(**image)
104-
atoms.set_calculator(calc)
104+
atoms.calc = calc
105105

106106
# Start by getting the Bulk modulus and optimized cell from the EOS
107107
logging.info('Calculating EOS')

asimtools/asimmodules/geometry_optimization/atom_relax.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def atom_relax(
4040
"""
4141
calc = load_calc(calc_id)
4242
atoms = get_atoms(**image)
43-
atoms.set_calculator(calc)
43+
atoms.calc = calc
4444
logger = get_logger()
4545

4646
if prefix is not None:

asimtools/asimmodules/geometry_optimization/cell_relax.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def cell_relax(
4646
"""
4747
calc = load_calc(calc_id)
4848
atoms = get_atoms(**image)
49-
atoms.set_calculator(calc)
49+
atoms.calc = calc
5050

5151
if prefix is not None:
5252
prefix = prefix + '_'

asimtools/asimmodules/geometry_optimization/optimize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def optimize(
4646

4747
calc = load_calc(calc_id)
4848
atoms = get_atoms(**image)
49-
atoms.set_calculator(calc)
49+
atoms.calc = calc
5050

5151
ecf = ExpCellFilter(atoms, **expcellfilter_args)
5252

asimtools/asimmodules/geometry_optimization/symmetric_cell_relax.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def symmetric_cell_relax(
4747

4848
calc = load_calc(calc_id)
4949
atoms = get_atoms(**image)
50-
atoms.set_calculator(calc)
50+
atoms.calc = calc
5151

5252
atoms.set_constraint(FixSymmetry(atoms, **fixsymmetry_args))
5353
ecf = ExpCellFilter(atoms, **expcellfilter_args)

asimtools/asimmodules/vacancy_formation_energy/vacancy_formation_energy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def vacancy_formation_energy(
4949

5050
calc = load_calc(calc_id)
5151
bulk = get_atoms(**image).repeat(repeat)
52-
bulk.set_calculator(calc)
52+
bulk.calc = calc
5353

5454
vacant = bulk.copy()
5555
del vacant[vacancy_index]

asimtools/job.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from asimtools.utils import (
2222
read_yaml,
2323
write_yaml,
24+
write_atoms,
2425
join_names,
2526
get_atoms,
2627
get_images,
@@ -396,9 +397,9 @@ def gen_input_files(
396397
if image and write_image:
397398
atoms = get_atoms(**image)
398399
input_image_file = 'image_input.xyz' # Relative to workdir
399-
atoms.write(
400+
write_atoms(
400401
self.workdir / input_image_file,
401-
format='extxyz'
402+
atoms,
402403
)
403404
sim_input['args']['image'] = {
404405
'image_file': str(input_image_file),

asimtools/utils.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import numpy as np
1717
import matplotlib.pyplot as plt
1818
import pandas as pd
19-
from ase.io import read
19+
from ase.io import read, write
2020
from ase.parallel import paropen
2121
import ase.db
2222
import ase.build
@@ -149,6 +149,52 @@ def join_names(substrs: Sequence[str]) -> str:
149149
name = '__'.join(final_substrs) + '__'
150150
return name
151151

152+
def write_atoms(
153+
image_file: str,
154+
atoms: Atoms,
155+
fmt: str = 'extxyz',
156+
write_info: bool = True,
157+
columns: Optional[Sequence] = None,
158+
**kwargs
159+
):
160+
"""
161+
162+
"""
163+
if kwargs.get('format', False):
164+
fmt = kwargs.pop('format')
165+
166+
if fmt in ['extxyz']:
167+
if kwargs.get('write_info', False):
168+
write_info = kwargs.pop('write_info')
169+
if kwargs.get('columns', False):
170+
write_info = kwargs.pop('columns')
171+
else:
172+
reserved_ks = ['symbols', 'positions', 'numbers', 'species', 'pos']
173+
columns = ['symbols', 'positions'] + kwargs.get(
174+
'columns',
175+
[k for k in atoms.arrays.keys() if k not in reserved_ks]
176+
)
177+
178+
if len(atoms.constraints) > 0:
179+
columns.append('move_mask')
180+
181+
write(
182+
image_file,
183+
atoms,
184+
format=fmt,
185+
write_info=write_info,
186+
columns=columns,
187+
**kwargs
188+
)
189+
else:
190+
write(
191+
image_file,
192+
atoms,
193+
format=fmt,
194+
**kwargs
195+
)
196+
197+
152198
def get_atoms(
153199
image_file: Optional[str] = None,
154200
interface: str = 'ase',
@@ -742,11 +788,21 @@ def get_str_btn(
742788
s = s[start_index:stop_index]
743789
while occurence - j >= 0:
744790
if s1 is not None:
745-
i1 = s.index(s1) + len(s1)
791+
try:
792+
i1 = s.index(s1) + len(s1)
793+
except:
794+
raise ValueError(
795+
f'substring {s1} not found in {s}'
796+
)
746797
else:
747798
i1 = 0
748799
if s2 is not None:
749-
i2 = s[i1:].index(s2) + i1
800+
try:
801+
i2 = s[i1:].index(s2) + i1
802+
except:
803+
raise ValueError(
804+
f'substring {s2} not found in {s}'
805+
)
750806
else:
751807
i2 = len(s)
752808

tests/unit/test_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
get_nth_label,
2121
get_str_btn,
2222
expand_wildcards,
23+
write_atoms,
2324
)
2425
import ase.build
2526

0 commit comments

Comments
 (0)