Skip to content

Commit cc88ac8

Browse files
Merge branch 'develop' into abstract-micro-sim-class
2 parents 6ec6462 + 5dc8f4f commit cc88ac8

25 files changed

Lines changed: 1618 additions & 131 deletions

.github/workflows/run-unit-tests.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,40 @@ jobs:
2020
run: |
2121
apt-get -qq update
2222
apt-get -qq install python3-dev python3-venv git pkg-config
23+
apt-get -qq install wget build-essential
24+
25+
- name: Load Cache OpenMPI 5
26+
id: ompi-cache-load
27+
uses: actions/cache/restore@v5
28+
with:
29+
path: ~/openmpi
30+
key: openmpi-v5-${{ runner.os }}-build
31+
32+
- name: Build OpenMPI 5
33+
if: steps.ompi-cache-load.outputs.cache-hit != 'true'
34+
run: |
35+
wget https://download.open-mpi.org/release/open-mpi/v5.0/openmpi-5.0.5.tar.gz
36+
tar -xzf openmpi-5.0.5.tar.gz
37+
cd openmpi-5.0.5
38+
mkdir -p ~/openmpi
39+
./configure --prefix=$HOME/openmpi
40+
make -j$(nproc)
41+
make install
42+
43+
- name: Save OpenMPI 5 to cache
44+
if: steps.ompi-cache.outputs.cache-hit != 'true'
45+
id: ompi-cache-store
46+
uses: actions/cache/save@v5
47+
with:
48+
path: ~/openmpi
49+
key: openmpi-v5-${{ runner.os }}-build
50+
51+
- name: Configure OpenMPI
52+
run: |
53+
cp -r ~/openmpi/* /usr/local/
54+
ldconfig
55+
which mpiexec
56+
mpiexec --version
2357
2458
- name: Create a virtual environment and install Micro Manager in it
2559
timeout-minutes: 6
@@ -37,6 +71,16 @@ jobs:
3771
cd tests/unit
3872
python3 -m unittest test_micro_manager.py
3973
74+
- name: Install Micro Manager and run tasking unit test
75+
working-directory: micro-manager
76+
env:
77+
OMPI_ALLOW_RUN_AS_ROOT: "1"
78+
OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: "1"
79+
run: |
80+
. .venv/bin/activate
81+
cd tests/unit
82+
python3 -m unittest test_tasking.py
83+
4084
- name: Install Micro Manager and run interpolation unit test
4185
working-directory: micro-manager
4286
run: |

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## latest
44

5+
- Added option to use compute instances to reduce memory consumption [#226](https://github.com/precice/micro-manager/pull/226)
6+
- Added support to run micro simulations in separate processes with workers [#219](https://github.com/precice/micro-manager/pull/219)
57
- Added abstraction layers to micro simulations to support more features [#218](https://github.com/precice/micro-manager/pull/218)
68

79
## v0.8.0

docs/configuration.md

Lines changed: 50 additions & 47 deletions
Large diffs are not rendered by default.

docs/model-adaptivity.md

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ class MicroSimulation: # Name is fixed
115115
It will be called with frequency set by configuration option `simulation_params: micro_output_n`
116116
This function is *optional*.
117117
"""
118+
119+
def get_global_id(self):
120+
"""
121+
Return the assigned global id.
122+
"""
118123
```
119124

120125
For this the default MicroSimulation still serves as the model interface, while the `(set)|(get)_state()` methods
@@ -124,40 +129,43 @@ is likely to be the full order model, while subsequent ones are ROMs.
124129

125130
```python
126131
def switching_function(
127-
resolutions: np.ndarray,
128-
locations: np.ndarray,
132+
resolution: int,
133+
location: np.ndarray,
129134
t: float,
130-
inputs: list[dict],
135+
input: dict,
131136
prev_output: dict,
132-
active: np.ndarray,
133-
) -> np.ndarray:
137+
) -> int:
134138
"""
135139
Switching interface function, use as reference
136140
137141
Parameters
138142
----------
139-
resolutions : np.array - shape(N,)
140-
Array with resolution information as get_sim_class_resolution would return for a sim obj.
141-
locations : np.array - shape(N,D)
142-
Array with gaussian points for all sims. D is the mesh dimension.
143+
resolution : int
144+
Current resolution as get_sim_class_resolution would return for the respective sim obj.
145+
location : np.array - shape(D,)
146+
Array with gaussian points.
143147
t : float
144148
Current time in simulation.
145-
inputs : list[dict]
146-
List of input objects.
147-
prev_output : [None, dict-like]
149+
input : dict
150+
Input object.
151+
prev_output : [None, dict]
148152
Contains the outputs of the previous model evaluation.
149-
active : np.array - shape(N,)
150-
Bool array indicating whether the model is active or not.
151153
154+
Returns
155+
-------
156+
switch_direction: int
157+
0 if resolution should not change
158+
-1 if resolution should increase
159+
1 if resolution should decrease
152160
"""
153-
return np.zeros_like(resolutions)
161+
return 0
154162
```
155163

156-
The switching of models is governed by the `switching_function`.
157-
The output is expected to be a np.ndarray of shape (N,) and is interpreted in the following manner:
164+
The switching of models is governed by the `switching_function`, which is evaluated for each micro simulation.
165+
The output is expected to be an integer and is interpreted in the following manner:
158166

159-
Value | Action
160-
--- | ---
161-
0 | No resolution change
162-
-1 | Increase model fidelity by one (go back one in list)
163-
1 | Decrease model fidelity by one (go one ahead in list)
167+
| Value | Action |
168+
|-------|-------------------------------------------------------|
169+
| 0 | No resolution change |
170+
| -1 | Increase model fidelity by one (go back one in list) |
171+
| 1 | Decrease model fidelity by one (go one ahead in list) |

micro_manager/adaptivity/adaptivity.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from micro_manager.tools.logging_wrapper import Logger
88
from micro_manager.config import Config
99
from micro_manager.micro_simulation import MicroSimulationClass
10+
from micro_manager.model_manager import ModelManager
1011

1112
import numpy as np
1213

@@ -17,6 +18,7 @@ def __init__(
1718
configurator: Config,
1819
nsims: int,
1920
micro_problem_cls: MicroSimulationClass,
21+
model_manager: ModelManager,
2022
base_logger: Logger,
2123
rank: int,
2224
) -> None:
@@ -31,6 +33,8 @@ def __init__(
3133
Number of micro simulations.
3234
micro_problem_cls : callable
3335
Class of micro problem.
36+
model_manager : object
37+
Handles instantiation of micro simulation.
3438
base_logger : object of class Logger
3539
Logger object to log messages.
3640
rank : int
@@ -44,6 +48,7 @@ def __init__(
4448
self._adaptivity_output_type = configurator.get_adaptivity_output_type()
4549

4650
self._micro_problem_cls = micro_problem_cls
51+
self._model_manager = model_manager
4752

4853
self._coarse_tol = 0.0
4954
self._ref_tol = 0.0
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from .global_adaptivity import GlobalAdaptivityCalculator
2+
from .global_adaptivity_lb import GlobalAdaptivityLBCalculator
3+
from .local_adaptivity import LocalAdaptivityCalculator
4+
from .adaptivity import AdaptivityCalculator
5+
6+
7+
def create_adaptivity_calculator(
8+
config,
9+
local_number_of_sims,
10+
global_number_of_sims,
11+
global_ids_of_local_sims,
12+
participant,
13+
logger,
14+
rank,
15+
comm,
16+
micro_problem_cls,
17+
model_manager,
18+
use_lb,
19+
) -> AdaptivityCalculator:
20+
adaptivity_type = config.get_adaptivity_type()
21+
22+
if adaptivity_type == "local":
23+
return LocalAdaptivityCalculator(
24+
config,
25+
local_number_of_sims,
26+
logger,
27+
rank,
28+
comm,
29+
micro_problem_cls,
30+
model_manager,
31+
)
32+
33+
if adaptivity_type == "global":
34+
cls = GlobalAdaptivityCalculator
35+
if use_lb:
36+
cls = GlobalAdaptivityLBCalculator
37+
38+
return cls(
39+
config,
40+
global_number_of_sims,
41+
global_ids_of_local_sims,
42+
participant,
43+
logger,
44+
rank,
45+
comm,
46+
micro_problem_cls,
47+
model_manager,
48+
)
49+
50+
raise ValueError("Unknown adaptivity type")

micro_manager/adaptivity/global_adaptivity.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from micro_manager.config import Config
1717
from micro_manager.tools.logging_wrapper import Logger
1818
from micro_manager.micro_simulation import MicroSimulationClass
19+
from micro_manager.model_manager import ModelManager
1920

2021

2122
class GlobalAdaptivityCalculator(AdaptivityCalculator):
@@ -29,6 +30,7 @@ def __init__(
2930
rank: int,
3031
comm: MPI.Comm,
3132
micro_problem_cls: MicroSimulationClass,
33+
model_manager: ModelManager,
3234
) -> None:
3335
"""
3436
Class constructor.
@@ -51,9 +53,16 @@ def __init__(
5153
Communicator for MPI.
5254
micro_problem_cls : callable
5355
Class of micro problem.
56+
model_manager : object of class ModelManager
57+
Handles instantiation of the micro simulation.
5458
"""
5559
super().__init__(
56-
configurator, global_number_of_sims, micro_problem_cls, base_logger, rank
60+
configurator,
61+
global_number_of_sims,
62+
micro_problem_cls,
63+
model_manager,
64+
base_logger,
65+
rank,
5766
)
5867
self._global_number_of_sims = global_number_of_sims
5968
self._global_ids = global_ids
@@ -462,7 +471,9 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
462471
# Only handle activation of simulations on this rank
463472
for gid in to_be_activated_gids:
464473
to_be_activated_lid = self._global_ids.index(gid)
465-
micro_sims[to_be_activated_lid] = self._micro_problem_cls(gid)
474+
micro_sims[to_be_activated_lid] = self._model_manager.get_instance(
475+
gid, self._micro_problem_cls
476+
)
466477
assoc_active_gid = self._sim_is_associated_to[gid]
467478

468479
if self._is_sim_on_this_rank[
@@ -499,7 +510,9 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
499510
local_ids = to_be_activated_map[gid]
500511
for lid in local_ids:
501512
# Create the micro simulation object and set its state
502-
micro_sims[lid] = self._micro_problem_cls(self._global_ids[lid])
513+
micro_sims[lid] = self._model_manager.get_instance(
514+
self._global_ids[lid], self._micro_problem_cls
515+
)
503516
micro_sims[lid].set_state(state)
504517

505518
# Delete the micro simulation object if it is inactive

micro_manager/adaptivity/global_adaptivity_lb.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from micro_manager.config import Config
1414
from micro_manager.micro_simulation import MicroSimulationClass
1515
from micro_manager.tools.logging_wrapper import Logger
16+
from micro_manager.model_manager import ModelManager
1617

1718

1819
class GlobalAdaptivityLBCalculator(GlobalAdaptivityCalculator):
@@ -26,6 +27,7 @@ def __init__(
2627
rank: int,
2728
comm: MPI.Comm,
2829
micro_problem_cls: MicroSimulationClass,
30+
model_manager: ModelManager,
2931
) -> None:
3032
"""
3133
Class constructor.
@@ -48,6 +50,8 @@ def __init__(
4850
Communicator for MPI.
4951
micro_problem_cls : callable
5052
Class of micro problem.
53+
model_manager : object of class ModelManager
54+
Handles instantiation of the micro simulation.
5155
"""
5256
super().__init__(
5357
configurator,
@@ -58,6 +62,7 @@ def __init__(
5862
rank,
5963
comm,
6064
micro_problem_cls,
65+
model_manager,
6166
)
6267

6368
self._base_logger = base_logger
@@ -370,7 +375,9 @@ def _move_active_sims(
370375
# Create simulations and set them to the received states
371376
for req in recv_reqs:
372377
output, gid = req.wait()
373-
micro_sims.append(self._micro_problem_cls(gid))
378+
micro_sims.append(
379+
self._model_manager.get_instance(gid, self._micro_problem_cls)
380+
)
374381
micro_sims[-1].set_state(output)
375382
self._global_ids.append(gid)
376383
self._is_sim_on_this_rank[gid] = True

micro_manager/adaptivity/local_adaptivity.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from micro_manager.config import Config
1313
from micro_manager.micro_simulation import MicroSimulationClass
1414
from micro_manager.tools.logging_wrapper import Logger
15+
from micro_manager.model_manager import ModelManager
1516

1617

1718
class LocalAdaptivityCalculator(AdaptivityCalculator):
@@ -23,6 +24,7 @@ def __init__(
2324
rank: int,
2425
comm: MPI.Comm,
2526
micro_problem_cls: MicroSimulationClass,
27+
model_manager: ModelManager,
2628
) -> None:
2729
"""
2830
Class constructor.
@@ -41,8 +43,12 @@ def __init__(
4143
Communicator for MPI.
4244
micro_problem_cls : callable
4345
Class of micro problem.
46+
model_manager : object of class ModelManager
47+
Handles instantiation of micro simulation.
4448
"""
45-
super().__init__(configurator, num_sims, micro_problem_cls, base_logger, rank)
49+
super().__init__(
50+
configurator, num_sims, micro_problem_cls, model_manager, base_logger, rank
51+
)
4652
self._comm = comm
4753

4854
# similarity_dists: 2D array having similarity distances between each micro simulation pair
@@ -295,7 +301,7 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
295301
# Update the set of inactive micro sims
296302
for i in to_be_activated_ids:
297303
associated_active_id = self._sim_is_associated_to[i]
298-
micro_sims[i] = self._micro_problem_cls(i)
304+
micro_sims[i] = self._model_manager.get_instance(i, self._micro_problem_cls)
299305
micro_sims[i].set_state(micro_sims[associated_active_id].get_state())
300306
self._sim_is_associated_to[
301307
i

0 commit comments

Comments
 (0)