16
16
from ase .constraints import FixSymmetry
17
17
from ase .filters import FrechetCellFilter
18
18
from ase .io import Trajectory as AseTrajectory
19
- from ase .io import write
19
+ from ase .io import write as ase_write
20
20
from ase .optimize import BFGS , FIRE , LBFGS , BFGSLineSearch , LBFGSLineSearch , MDMin
21
21
from ase .optimize .sciopt import SciPyFminBFGS , SciPyFminCG
22
22
from monty .serialization import dumpfn
@@ -329,15 +329,18 @@ def relax(
329
329
fmax : float = 0.1 ,
330
330
steps : int = 500 ,
331
331
traj_file : str = None ,
332
- final_atoms_object_file : str = "final_atoms_object.xyz" ,
332
+ final_atoms_object_file : str | os . PathLike [ str ] = "final_atoms_object.xyz" ,
333
333
interval : int = 1 ,
334
334
verbose : bool = False ,
335
335
cell_filter : Filter = FrechetCellFilter ,
336
+ filter_kwargs : dict | None = None ,
336
337
** kwargs ,
337
338
) -> AseResult :
338
339
"""
339
340
Relax the molecule or structure.
340
341
342
+ If steps <= 1, this will perform a single-point calculation.
343
+
341
344
Parameters
342
345
----------
343
346
atoms : ASE Atoms, pymatgen Structure, or pymatgen Molecule
@@ -348,7 +351,7 @@ def relax(
348
351
Max number of steps for relaxation.
349
352
traj_file : str
350
353
The trajectory file for saving.
351
- final_atoms_object_file: str
354
+ final_atoms_object_file: str | os.PathLike
352
355
The final atoms object file for saving.
353
356
interval : int
354
357
The step interval for saving the trajectories.
@@ -374,14 +377,16 @@ def relax(
374
377
atoms .calc = self .calculator
375
378
with contextlib .redirect_stdout (sys .stdout if verbose else io .StringIO ()):
376
379
obs = TrajectoryObserver (atoms )
377
- if self .relax_cell and (not is_mol ):
378
- atoms = cell_filter (atoms )
379
- optimizer = self .opt_class (atoms , ** kwargs )
380
- optimizer .attach (obs , interval = interval )
381
380
t_i = time .perf_counter ()
382
- optimizer .run (fmax = fmax , steps = steps )
383
- t_f = time .perf_counter ()
381
+ if steps > 1 :
382
+ if self .relax_cell and (not is_mol ):
383
+ atoms = cell_filter (atoms , ** (filter_kwargs or {}))
384
+ optimizer = self .opt_class (atoms , ** kwargs )
385
+ optimizer .attach (obs , interval = interval )
386
+ optimizer .run (fmax = fmax , steps = steps )
384
387
obs ()
388
+ t_f = time .perf_counter ()
389
+
385
390
if traj_file is not None :
386
391
obs .save (traj_file )
387
392
if isinstance (atoms , cell_filter ):
@@ -402,7 +407,9 @@ def relax(
402
407
write_atoms .calc = self .calculator
403
408
else :
404
409
write_atoms = atoms
405
- write (final_atoms_object_file , write_atoms , format = "extxyz" , append = True )
410
+ ase_write (
411
+ final_atoms_object_file , write_atoms , format = "extxyz" , append = True
412
+ )
406
413
407
414
return AseResult (
408
415
final_mol_or_struct = struct ,
0 commit comments