Yuan (Cyrus) Chiang commited on
Commit
b7a7786
·
unverified ·
1 Parent(s): 152c1b7

Allow fine grained intermediate cache for optimization in EOS task (#35)

Browse files

* add eos cache

* remove unused import

* add uv into test workflow

* avoid bash inside uv

* disable concurrent eos test due to gh action instability

.github/workflows/test.yaml CHANGED
@@ -6,8 +6,8 @@ on:
6
  pull_request:
7
  branches: [main]
8
 
9
- # env:
10
- # UV_SYSTEM_PYTHON: 1
11
 
12
  jobs:
13
  test:
@@ -23,30 +23,30 @@ jobs:
23
  - name: Checkout repository
24
  uses: actions/checkout@v4
25
 
26
- # - name: Install uv
27
- # uses: astral-sh/setup-uv@v3
28
- # with:
29
- # enable-cache: true
30
- # cache-dependency-glob: "pyproject.toml"
31
-
32
- # - name: Set up Python ${{ matrix.python-version }}
33
- # run: uv python install ${{ matrix.python-version }}
34
 
35
  - name: Set up Python ${{ matrix.python-version }}
36
  uses: actions/setup-python@v5
37
  with:
38
  python-version: ${{ matrix.python-version }}
 
39
  cache: 'pip'
40
 
41
  - name: Install dependencies
42
  run: |
43
- python -m pip install --upgrade pip
44
- pip install torch==2.2.0
45
- bash scripts/install-pyg.sh
46
- bash scripts/install-dgl.sh
47
- pip install -e .[test]
48
- pip install -e .[mace]
49
- pip install -e .[deepmd]
 
 
50
 
51
  - name: List dependencies
52
  run: pip list
 
6
  pull_request:
7
  branches: [main]
8
 
9
+ env:
10
+ UV_SYSTEM_PYTHON: 1
11
 
12
  jobs:
13
  test:
 
23
  - name: Checkout repository
24
  uses: actions/checkout@v4
25
 
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v4
28
+ with:
29
+ enable-cahce: true
30
+ cache-dependency-glob: "pyproject.toml"
 
 
 
31
 
32
  - name: Set up Python ${{ matrix.python-version }}
33
  uses: actions/setup-python@v5
34
  with:
35
  python-version: ${{ matrix.python-version }}
36
+ python-version-file: "pyproject.toml"
37
  cache: 'pip'
38
 
39
  - name: Install dependencies
40
  run: |
41
+ TORCH=2.2
42
+ CUDA=cu121
43
+ uv pip install torch==${TORCH}.0
44
+ uv pip install torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
45
+ uv pip install torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.0+${CUDA}.html
46
+ uv pip install dgl -f https://data.dgl.ai/wheels/torch-${TORCH}/${CUDA}/repo.html
47
+ uv pip install -e .[test]
48
+ uv pip install -e .[mace]
49
+ uv pip install -e .[deepmd]
50
 
51
  - name: List dependencies
52
  run: pip list
mlip_arena/tasks/eos.py CHANGED
@@ -56,6 +56,7 @@ def run(
56
  max_abs_strain: float = 0.1,
57
  npoints: int = 11,
58
  concurrent: bool = True,
 
59
  ) -> dict[str, Any] | State:
60
  """
61
  Compute the equation of state (EOS) for the given atoms and calculator.
@@ -73,11 +74,17 @@ def run(
73
  max_abs_strain: The maximum absolute strain to use.
74
  npoints: The number of points to sample.
75
  concurrent: Whether to relax multiple structures concurrently.
 
76
 
77
  Returns:
78
  A dictionary containing the EOS data, bulk modulus, equilibrium volume, and equilibrium energy if successful. Otherwise, a prefect state object.
79
  """
80
- state = OPT(
 
 
 
 
 
81
  atoms=atoms,
82
  calculator_name=calculator_name,
83
  calculator_kwargs=calculator_kwargs,
@@ -92,8 +99,11 @@ def run(
92
 
93
  if state.is_failed():
94
  return state
95
-
96
- first_relax = state.result(raise_on_failure=False)
 
 
 
97
  assert isinstance(first_relax, dict)
98
  relaxed = first_relax["atoms"]
99
 
@@ -108,7 +118,7 @@ def run(
108
  atoms = relaxed.copy()
109
  atoms.set_cell(c0 * f, scale_atoms=True)
110
 
111
- future = OPT.submit(
112
  atoms=atoms,
113
  calculator_name=calculator_name,
114
  calculator_kwargs=calculator_kwargs,
@@ -134,7 +144,7 @@ def run(
134
  atoms = relaxed.copy()
135
  atoms.set_cell(c0 * f, scale_atoms=True)
136
 
137
- state = OPT(
138
  atoms=atoms,
139
  calculator_name=calculator_name,
140
  calculator_kwargs=calculator_kwargs,
 
56
  max_abs_strain: float = 0.1,
57
  npoints: int = 11,
58
  concurrent: bool = True,
59
+ cache_opt: bool = True,
60
  ) -> dict[str, Any] | State:
61
  """
62
  Compute the equation of state (EOS) for the given atoms and calculator.
 
74
  max_abs_strain: The maximum absolute strain to use.
75
  npoints: The number of points to sample.
76
  concurrent: Whether to relax multiple structures concurrently.
77
+ cache_opt: Whether to cache the intermediate optimization results.
78
 
79
  Returns:
80
  A dictionary containing the EOS data, bulk modulus, equilibrium volume, and equilibrium energy if successful. Otherwise, a prefect state object.
81
  """
82
+
83
+ OPT_ = OPT.with_options(
84
+ refresh_cache=not cache_opt
85
+ )
86
+
87
+ state = OPT_(
88
  atoms=atoms,
89
  calculator_name=calculator_name,
90
  calculator_kwargs=calculator_kwargs,
 
99
 
100
  if state.is_failed():
101
  return state
102
+ elif state.is_completed() and state.name in ["Completed", "Cached"]:
103
+ first_relax = state.result(raise_on_failure=False)
104
+ elif state.is_completed() and state.name in ["Rollback"]:
105
+ first_relax = state.result(raise_on_failure=False)
106
+
107
  assert isinstance(first_relax, dict)
108
  relaxed = first_relax["atoms"]
109
 
 
118
  atoms = relaxed.copy()
119
  atoms.set_cell(c0 * f, scale_atoms=True)
120
 
121
+ future = OPT_.submit(
122
  atoms=atoms,
123
  calculator_name=calculator_name,
124
  calculator_kwargs=calculator_kwargs,
 
144
  atoms = relaxed.copy()
145
  atoms.set_cell(c0 * f, scale_atoms=True)
146
 
147
+ state = OPT_(
148
  atoms=atoms,
149
  calculator_name=calculator_name,
150
  calculator_kwargs=calculator_kwargs,
tests/test_eos.py CHANGED
@@ -10,10 +10,14 @@ from mlip_arena.tasks.eos import run as EOS
10
 
11
 
12
  @flow
13
- def single_eos_flow(calculator_name):
14
  atoms = bulk("Cu", "fcc", a=3.6)
15
 
16
- return EOS(
 
 
 
 
17
  atoms=atoms,
18
  calculator_name=calculator_name,
19
  calculator_kwargs={},
@@ -27,7 +31,8 @@ def single_eos_flow(calculator_name):
27
  ),
28
  max_abs_strain=0.1,
29
  npoints=6,
30
- concurrent=True
 
31
  )
32
 
33
 
@@ -35,8 +40,9 @@ def single_eos_flow(calculator_name):
35
  sys.version_info[:2] != (3, 11),
36
  reason="avoid prefect race condition on concurrent tasks",
37
  )
 
38
  @pytest.mark.parametrize("model", [MLIPEnum["MACE-MP(M)"]])
39
- def test_eos(model: MLIPEnum):
40
  """
41
  Test EOS prefect workflow with a simple cubic lattice.
42
  """
@@ -44,6 +50,19 @@ def test_eos(model: MLIPEnum):
44
  with prefect_test_harness():
45
  result = single_eos_flow(
46
  calculator_name=model.name,
 
 
47
  )
 
 
 
 
 
48
 
49
- assert isinstance(result["b0"], float)
 
 
 
 
 
 
 
10
 
11
 
12
  @flow
13
+ def single_eos_flow(calculator_name, concurrent=True, cache=False):
14
  atoms = bulk("Cu", "fcc", a=3.6)
15
 
16
+ EOS_ = EOS.with_options(
17
+ refresh_cache=not cache,
18
+ )
19
+
20
+ return EOS_(
21
  atoms=atoms,
22
  calculator_name=calculator_name,
23
  calculator_kwargs={},
 
31
  ),
32
  max_abs_strain=0.1,
33
  npoints=6,
34
+ concurrent=concurrent,
35
+ cache_opt=cache
36
  )
37
 
38
 
 
40
  sys.version_info[:2] != (3, 11),
41
  reason="avoid prefect race condition on concurrent tasks",
42
  )
43
+ @pytest.mark.parametrize("concurrent", [False])
44
  @pytest.mark.parametrize("model", [MLIPEnum["MACE-MP(M)"]])
45
+ def test_eos(model: MLIPEnum, concurrent: bool):
46
  """
47
  Test EOS prefect workflow with a simple cubic lattice.
48
  """
 
50
  with prefect_test_harness():
51
  result = single_eos_flow(
52
  calculator_name=model.name,
53
+ concurrent=concurrent,
54
+ cache=False,
55
  )
56
+ assert isinstance(b0_scratch := result["b0"], float)
57
+
58
+ # @pytest.mark.dependency(depends=["test_eos"])
59
+ # @pytest.mark.parametrize("model", [MLIPEnum["MACE-MP(M)"]])
60
+ # def test_eos_cache(model: MLIPEnum):
61
 
62
+ result = single_eos_flow(
63
+ calculator_name=model.name,
64
+ concurrent=concurrent,
65
+ cache=True,
66
+ )
67
+ assert isinstance(b0_cache := result["b0"], float)
68
+ assert b0_scratch == pytest.approx(b0_cache, rel=1e-6)