Skip to content

Commit 199dc7a

Browse files
Prepare Hydra 1.4 compatibility paths
Co-authored-by: frostedoyster <98903385+frostedoyster@users.noreply.github.com>
1 parent ec5a5f3 commit 199dc7a

4 files changed

Lines changed: 125 additions & 4 deletions

File tree

packages/fairchem-core/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dependencies = [
2626
"orjson",
2727
"tqdm",
2828
"submitit>=1.5.4",
29-
"hydra-core",
29+
"hydra-core>=1.3",
3030
"torchtnt",
3131
"pyyaml",
3232
"wandb",

src/fairchem/core/_cli.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import argparse
1111
import logging
1212
import os
13+
import tempfile
1314
from typing import TYPE_CHECKING
1415

1516
import hydra
@@ -69,8 +70,22 @@ def get_hydra_config_from_yaml(
6970
os.environ["HYDRA_FULL_ERROR"] = "1"
7071
config_directory = os.path.dirname(os.path.abspath(config_yml))
7172
config_name = os.path.basename(config_yml)
72-
hydra.initialize_config_dir(config_directory, version_base="1.1")
73-
cfg = hydra.compose(config_name=config_name, overrides=overrides_args)
73+
74+
if config_name.endswith(".yml"):
75+
with tempfile.TemporaryDirectory() as temp_dir:
76+
temp_config_name = f"{os.path.splitext(config_name)[0]}.yaml"
77+
temp_config_path = os.path.join(temp_dir, temp_config_name)
78+
with open(config_yml) as source, open(temp_config_path, "w") as target:
79+
target.write(source.read())
80+
81+
with hydra.initialize_config_dir(temp_dir, version_base="1.3"):
82+
cfg = hydra.compose(
83+
config_name=temp_config_name,
84+
overrides=overrides_args,
85+
)
86+
else:
87+
with hydra.initialize_config_dir(config_directory, version_base="1.3"):
88+
cfg = hydra.compose(config_name=config_name, overrides=overrides_args)
7489
# merge default structured config with initialized job object
7590
cfg = OmegaConf.merge({"job": OmegaConf.structured(JobConfig)}, cfg)
7691
# canonicalize config (remove top level keys that just used replacing variables)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Copyright (c) Meta Platforms, Inc. and affiliates.
3+
4+
This source code is licensed under the MIT license found in the
5+
LICENSE file in the root directory of this source tree.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import textwrap
11+
12+
import hydra
13+
14+
from fairchem.core.scripts.sweep_inference_benchmark import load_config
15+
16+
17+
def test_load_config_hydra_composition_and_defaults(tmp_path):
18+
"""
19+
Test that benchmark config composition works and initializes JobConfig metadata.
20+
"""
21+
hydra.core.global_hydra.GlobalHydra.instance().clear()
22+
config_path = tmp_path / "benchmark_config.yaml"
23+
config_path.write_text(
24+
textwrap.dedent(
25+
"""
26+
benchmark:
27+
base_natoms: 32
28+
"""
29+
)
30+
)
31+
32+
cfg = load_config(
33+
str(config_path),
34+
overrides=["+job.scheduler.ranks_per_node=2"],
35+
)
36+
37+
assert cfg.benchmark.base_natoms == 32
38+
assert cfg.job.scheduler.ranks_per_node == 2
39+
assert cfg.job.metadata is not None
40+
assert cfg.job.run_name is not None

tests/lammps/test_lammps_fc.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88
from __future__ import annotations
99

1010
import os
11+
import sys
1112
import tempfile
1213

14+
import hydra
1315
import numpy as np
1416
import pytest
1517
from ase import Atoms
16-
from fairchem.lammps.lammps_fc import restricted_cell_from_lammps_box
18+
19+
pytest.importorskip("lammps")
20+
21+
from fairchem.lammps import lammps_fc # noqa: E402
22+
from fairchem.lammps.lammps_fc import restricted_cell_from_lammps_box # noqa: E402
1723

1824

1925
def create_lammps_data_file(filepath, positions, cell, atom_types, masses):
@@ -230,3 +236,63 @@ def test_cell_conversion_preserves_volume(box_name, boxlo, boxhi, xy, yz, xz):
230236
f"Volume mismatch for {box_name}: boxlo={boxlo}, boxhi={boxhi}, xy={xy}, yz={yz}, xz={xz}.\n"
231237
f"Expected: {expected_volume}, Actual: {actual_volume}"
232238
)
239+
240+
241+
def test_lammps_hydra_entrypoint_startup(monkeypatch, tmp_path):
242+
"""
243+
Test that the Hydra-decorated LAMMPS entry point composes config and starts.
244+
"""
245+
hydra.core.global_hydra.GlobalHydra.instance().clear()
246+
lammps_state = {}
247+
run_args = {}
248+
249+
def fake_instantiate(_cfg):
250+
return object()
251+
252+
def fake_run_lammps_with_fairchem(
253+
predictor,
254+
lammps_input_path,
255+
task_name,
256+
charge=0,
257+
spin=0,
258+
):
259+
run_args.update(
260+
{
261+
"predictor": predictor,
262+
"lammps_input_path": lammps_input_path,
263+
"task_name": task_name,
264+
"charge": charge,
265+
"spin": spin,
266+
}
267+
)
268+
269+
class DummyLammps:
270+
pass
271+
272+
lmp = DummyLammps()
273+
lmp._predictor = predictor
274+
lammps_state["lmp"] = lmp
275+
return lmp
276+
277+
monkeypatch.setattr(lammps_fc.hydra.utils, "instantiate", fake_instantiate)
278+
monkeypatch.setattr(
279+
lammps_fc, "run_lammps_with_fairchem", fake_run_lammps_with_fairchem
280+
)
281+
282+
old_argv = sys.argv[:]
283+
try:
284+
sys.argv = [
285+
"lammps_fc.py",
286+
f"hydra.run.dir={tmp_path}",
287+
"hydra.output_subdir=null",
288+
]
289+
lammps_fc.main()
290+
finally:
291+
sys.argv = old_argv
292+
hydra.core.global_hydra.GlobalHydra.instance().clear()
293+
294+
assert run_args["lammps_input_path"] == "lammps_in_example.file"
295+
assert run_args["task_name"] == "omol"
296+
assert run_args["charge"] == 0
297+
assert run_args["spin"] == 0
298+
assert not hasattr(lammps_state["lmp"], "_predictor")

0 commit comments

Comments
 (0)