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

Pin MACE calculator version, add missing metadata to AseStructureTaskDoc #1119

Merged
merged 8 commits into from
Feb 11, 2025
8 changes: 5 additions & 3 deletions src/atomate2/ase/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,12 @@ def from_ase_task_doc(
Additional keyword args passed to :obj:`.AseStructureTaskDoc()`.
"""
task_document_kwargs.update(
{k: getattr(ase_task_doc, k) for k in _task_doc_translation_keys}
{k: getattr(ase_task_doc, k) for k in _task_doc_translation_keys},
structure=ase_task_doc.mol_or_struct,
)
return cls.from_structure(
meta_structure=ase_task_doc.mol_or_struct, **task_document_kwargs
)
task_document_kwargs["structure"] = ase_task_doc.mol_or_struct
return cls(**task_document_kwargs)


class AseMoleculeTaskDoc(MoleculeMetadata):
Expand Down
3 changes: 2 additions & 1 deletion src/atomate2/forcefields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
class MLFF(Enum): # TODO inherit from StrEnum when 3.11+
"""Names of ML force fields."""

MACE = "MACE"
MACE = "MACE" # This is MACE-MP-0-medium
MACE_MPA_0 = "MACE_MPA_0"
Copy link
Member

@JaGeo JaGeo Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there are now 3 different MACE MP 0s, should we use 3b? For phonons, it is a lot better than the initial one, for example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 0b3 as well. Avoiding Omat for license reasons. Also added a from_force_field_name method to the phonon and QHA makers to allow easier instantiation of these from a str

GAP = "GAP"
M3GNet = "M3GNet"
CHGNet = "CHGNet"
Expand Down
2 changes: 2 additions & 0 deletions src/atomate2/forcefields/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
MLFF.M3GNet: {"stress_weight": _GPa_to_eV_per_A3},
MLFF.NEP: {"model_filename": "nep.txt"},
MLFF.GAP: {"args_str": "IP GAP", "param_filename": "gap.xml"},
MLFF.MACE: {"model": "medium"},
MLFF.MACE_MPA_0: {"model": "medium-mpa-0"},
}


Expand Down
4 changes: 2 additions & 2 deletions src/atomate2/forcefields/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def ase_calculator(calculator_meta: str | dict, **kwargs: Any) -> Calculator | N
calculator = None

if isinstance(calculator_meta, str | MLFF) and calculator_meta in map(str, MLFF):
calculator_name = MLFF(calculator_meta.split("MLFF.")[-1])
calculator_name = MLFF[calculator_meta.split("MLFF.")[-1]]

if calculator_name == MLFF.CHGNet:
from chgnet.model.dynamics import CHGNetCalculator
Expand All @@ -58,7 +58,7 @@ def ase_calculator(calculator_meta: str | dict, **kwargs: Any) -> Calculator | N
potential = matgl.load_model(path)
calculator = PESCalculator(potential, **kwargs)

elif calculator_name == MLFF.MACE:
elif calculator_name in {MLFF.MACE, MLFF.MACE_MPA_0}:
from mace.calculators import MACECalculator, mace_mp

model = kwargs.get("model")
Expand Down
21 changes: 21 additions & 0 deletions tests/forcefields/test_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,27 @@ def test_mace_relax_maker(
assert output1.output.n_steps == 7


def test_mace_mpa_0_relax_maker(
si_structure: Structure,
):
job = ForceFieldRelaxMaker(
force_field_name="MACE_MPA_0",
steps=25,
relax_kwargs={"fmax": 0.005},
).make(si_structure)
# run the flow or job and ensure that it finished running successfully
responses = run_locally(job, ensure_success=True)

# validating the outputs of the job
output = responses[job.uuid][1].output

assert output.ase_calculator_name == "MLFF.MACE_MPA_0"
assert output.output.energy == pytest.approx(-10.829493522644043)
assert output.output.structure.volume == pytest.approx(40.87471552602735)
assert len(output.output.ionic_steps) == 4
assert output.structure.volume == output.output.structure.volume


def test_gap_static_maker(si_structure: Structure, test_dir):
importorskip("quippy")

Expand Down
Loading