I am comparing optimization trajectories as obtained via materials.tasks.get_data_by_id (and then looking at ionic steps) vs materials.tasks.get_trajectory. I notice that the second method returns trajectories with constant lattice, rather than the actual lattice evolving during optimization. See the code snippet with comparison between the two approaches.
Code snippet
from mp_api.client import MPRester
from pymatgen.core.trajectory import Trajectory
import numpy as np
np.set_printoptions(suppress=True)
# MP_API_KEY = "..."
with MPRester(api_key=MP_API_KEY) as r:
# Option 1: task doc
tasks_doc = r.materials.tasks.get_data_by_id(
"mp-9588",
fields=["task_id", "orig_inputs", "calcs_reversed", "output", "last_updated"]
)
# Option 2: trajectory
trajectories = [
Trajectory.from_dict(tr_i)
for tr_i in r.materials.tasks.get_trajectory("mp-9588")
]
# Check that both methods give same number of calculations
assert len(tasks_doc.calcs_reversed) == len(trajectories)
# Compare calculations one by one
for i_calc in range(len(tasks_doc.calcs_reversed)):
print("Calc", i_calc)
calc = tasks_doc.calcs_reversed[i_calc]
traj = trajectories[i_calc]
# check that trajectories are of same length
assert len(calc.output.ionic_steps) == len(traj)
# compare trajectories step by step
for i_step in range(len(traj)):
# check that forces, stresses and energies are same
assert np.allclose(calc.output.ionic_steps[i_step].forces, traj.frame_properties[i_step]["forces"])
assert np.allclose(calc.output.ionic_steps[i_step].stress, traj.frame_properties[i_step]["stresses"])
assert np.isclose(calc.output.ionic_steps[i_step].e_wo_entrp, traj.frame_properties[i_step]["e_wo_entrp"])
# check that lattice matrices are same (this often fails, so we catch the exception and print out the matrices)
try:
assert np.allclose(
calc.output.ionic_steps[i_step].structure.lattice.matrix,
traj[i_step].lattice.matrix
)
print(f" step {i_step}: all ok")
except AssertionError:
print(f" step {i_step}: lattices different. Option 1 (left) vs option 2 (right):")
lattice1_str = str(calc.output.ionic_steps[i_step].structure.lattice.matrix)
lattice2_str = str(traj[i_step].lattice.matrix)
print('\n'.join(f" {l1:42} --- {l2}" for l1, l2 in zip(lattice1_str.split('\n'), lattice2_str.split('\n'))))
print()
Email (Optional)
No response
Version
mp-api==0.36.1
Which OS(es) are you using?
What happened?
I am comparing optimization trajectories as obtained via
materials.tasks.get_data_by_id
(and then looking at ionic steps) vsmaterials.tasks.get_trajectory
. I notice that the second method returns trajectories with constant lattice, rather than the actual lattice evolving during optimization. See the code snippet with comparison between the two approaches.Code snippet
Log output
Code of Conduct