materialsproject / api

New API client for the Materials Project
https://materialsproject.github.io/api/
Other
105 stars 33 forks source link

[Bug]: `materials.tasks.get_trajectory` ignores cell optimization (constant cell returned) #846

Open SiLiKhon opened 9 months ago

SiLiKhon commented 9 months ago

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) 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()

Log output

Calc 0
  step 0: all ok
  step 1: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97038519  0.          0.        ]        ---    [[ 4.97009308  0.          0.        ]
       [ 0.          5.57474616 -0.46217408]        ---     [ 0.          5.57486854 -0.46228058]
       [ 0.         -0.00758389  9.06941488]]       ---     [ 0.         -0.0077896   9.06902486]]

Calc 1
  step 0: all ok
  step 1: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.96091213  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.58143317 -0.46043936]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.0024992   9.09681218]]       ---     [ 0.          0.          9.07254016]]

  step 2: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.9574325   0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57840014 -0.45998062]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00208335  9.09277348]]       ---     [ 0.          0.          9.07254016]]

  step 3: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.96117516  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57741918 -0.46009706]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00261877  9.08857696]]       ---     [ 0.          0.          9.07254016]]

  step 4: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97225675  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57451465 -0.46044181]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00420411  9.07615155]]       ---     [ 0.          0.          9.07254016]]

  step 5: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97302679  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57429884 -0.46277011]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00834577  9.07190273]]       ---     [ 0.          0.          9.07254016]]

  step 6: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97321148  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57424707 -0.46332856]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00933916  9.07088364]]       ---     [ 0.          0.          9.07254016]]

  step 7: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97154227  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57328397 -0.46350287]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00971155  9.06979745]]       ---     [ 0.          0.          9.07254016]]

  step 8: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.96959382  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57215976 -0.46370633]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.01014624  9.06852956]]       ---     [ 0.          0.          9.07254016]]

  step 9: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.96978754  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57380555 -0.46270985]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00851069  9.06873143]]       ---     [ 0.          0.          9.07254016]]

  step 10: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.96992024  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57493292 -0.46202725]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00739033  9.06886971]]       ---     [ 0.          0.          9.07254016]]

  step 11: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97011434  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57486062 -0.46231174]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.00783871  9.06904395]]       ---     [ 0.          0.          9.07254016]]

  step 12: lattices different. Option 1 (left) vs option 2 (right):
      [[ 4.97009308  0.          0.        ]        ---    [[ 4.94        0.          0.        ]
       [ 0.          5.57486854 -0.46228058]        ---     [ 0.          5.56320508 -0.45768241]
       [ 0.         -0.0077896   9.06902486]]       ---     [ 0.          0.          9.07254016]]

Code of Conduct

munrojm commented 9 months ago

@SiLiKhon, thanks for bringing this up. I will take a closer look.