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

Set initial time window size of the micro simulation in the configuration #112

Merged
merged 8 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## latest

- Set time step of micro simulation in the configuration, and use it in the coupling https://github.com/precice/micro-manager/pull/112
- Add a base class called `MicroManager` with minimal API and member function definitions, rename the existing `MicroManager` class to `MicroManagerCoupling` https://github.com/precice/micro-manager/pull/111
- Handle calling `initialize()` function of micro simulations written in languages other than Python https://github.com/precice/micro-manager/pull/110
- Check if initial data returned from the micro simulation is the data that the adaptivity computation requires https://github.com/precice/micro-manager/pull/109
Expand Down
4 changes: 3 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ The Micro Manager is configured with a JSON file. An example configuration file
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-mesh",
"read_data_names": {"temperature": "scalar", "heat-flux": "vector"},
"write_data_names": {"porosity": "scalar", "conductivity": "vector"}
"write_data_names": {"porosity": "scalar", "conductivity": "vector"},
"micro_time_window_size": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 1.0, 0.0, 1.0, 0.0, 1.0],
Expand All @@ -41,6 +42,7 @@ Parameter | Description
`macro_mesh_name` | Name of the macro mesh as stated in the preCICE configuration.
`read_data_names` | A Python dictionary with the names of the data to be read from preCICE as keys and `"scalar"` or `"vector"` as values depending on the nature of the data.
`write_data_names` | A Python dictionary with the names of the data to be written to preCICE as keys and `"scalar"` or `"vector"` as values depending on the nature of the data.
`micro_dt` | Initial time window size (dt) of the micro simulation.

## Simulation Parameters

Expand Down
3 changes: 2 additions & 1 deletion examples/micro-manager-cpp-adaptivity-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config-adaptivity.xml",
"macro_mesh_name": "macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0],
Expand Down
3 changes: 2 additions & 1 deletion examples/micro-manager-cpp-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0]
Expand Down
3 changes: 2 additions & 1 deletion examples/micro-manager-python-adaptivity-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config-adaptivity.xml",
"macro_mesh_name": "macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0],
Expand Down
3 changes: 2 additions & 1 deletion examples/micro-manager-python-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0]
Expand Down
14 changes: 14 additions & 0 deletions micro_manager/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def __init__(self, logger, config_filename):
self._macro_mesh_name = None
self._read_data_names = dict()
self._write_data_names = dict()
self._micro_dt = None

self._macro_domain_bounds = None
self._ranks_per_axis = None
Expand Down Expand Up @@ -114,6 +115,8 @@ def read_json(self, config_filename):
"No read data names provided. Micro manager will only write data to preCICE."
)

self._micro_dt = data["coupling_params"]["micro_dt"]

self._macro_domain_bounds = data["simulation_params"]["macro_domain_bounds"]

try:
Expand Down Expand Up @@ -431,3 +434,14 @@ def is_adaptivity_required_in_every_implicit_iteration(self):
True if adaptivity needs to be calculated in every time iteration, False otherwise.
"""
return self._adaptivity_every_implicit_iteration

def get_micro_dt(self):
"""
Get the size of the micro time window.

Returns
-------
micro_time_window : float
Size of the micro time window.
"""
return self._micro_dt
51 changes: 28 additions & 23 deletions micro_manager/micro_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ def __init__(self, config_file: str) -> None:
self._crash_threshold = 0.2
self._number_of_nearest_neighbors = 4

self._dt = 0
self._mesh_vertex_ids = None # IDs of macro vertices as set by preCICE
self._micro_n_out = self._config.get_micro_output_n()

Expand Down Expand Up @@ -117,6 +116,8 @@ def solve(self) -> None:
sim_is_associated_to_cp = None
sim_states_cp = [None] * self._local_number_of_sims

dt = min(self._participant.get_max_time_step_size(), self._micro_dt)

if self._is_adaptivity_on:
similarity_dists = np.zeros(
(
Expand All @@ -140,7 +141,7 @@ def solve(self) -> None:
is_sim_active,
sim_is_associated_to,
) = self._adaptivity_controller.compute_adaptivity(
self._dt,
dt,
self._micro_sims,
similarity_dists,
is_sim_active,
Expand All @@ -150,9 +151,7 @@ def solve(self) -> None:

while self._participant.is_coupling_ongoing():

self._dt = (
self._participant.get_max_time_step_size()
) # ask preCICE at beginning of time step for allowed time step size
dt = min(self._participant.get_max_time_step_size(), self._micro_dt)

# Write a checkpoint
if self._participant.requires_writing_checkpoint():
Expand All @@ -168,7 +167,7 @@ def solve(self) -> None:
is_sim_active,
sim_is_associated_to,
) = self._adaptivity_controller.compute_adaptivity(
self._dt,
dt,
self._micro_sims,
similarity_dists,
is_sim_active,
Expand Down Expand Up @@ -197,7 +196,7 @@ def solve(self) -> None:
for active_id in active_sim_ids:
self._micro_sims_active_steps[active_id] += 1

micro_sims_input = self._read_data_from_precice()
micro_sims_input = self._read_data_from_precice(dt)

if self._is_adaptivity_on:
if self._adaptivity_in_every_implicit_step:
Expand All @@ -206,7 +205,7 @@ def solve(self) -> None:
is_sim_active,
sim_is_associated_to,
) = self._adaptivity_controller.compute_adaptivity(
self._dt,
dt,
self._micro_sims,
similarity_dists,
is_sim_active,
Expand All @@ -230,10 +229,10 @@ def solve(self) -> None:
self._micro_sims_active_steps[active_id] += 1

micro_sims_output = self._solve_micro_simulations_with_adaptivity(
micro_sims_input, is_sim_active, sim_is_associated_to
micro_sims_input, is_sim_active, sim_is_associated_to, dt
)
else:
micro_sims_output = self._solve_micro_simulations(micro_sims_input)
micro_sims_output = self._solve_micro_simulations(micro_sims_input, dt)

# Check if more than a certain percentage of the micro simulations have crashed and terminate if threshold is exceeded
crashed_sims_on_all_ranks = np.zeros(self._size, dtype=np.int64)
Expand All @@ -257,11 +256,11 @@ def solve(self) -> None:

self._write_data_to_precice(micro_sims_output)

t += self._dt # increase internal time when time step is done.
t += dt # increase internal time when time step is done.
n += 1 # increase counter
self._participant.advance(
self._dt
) # notify preCICE that time step of size self._dt is complete
dt
) # notify preCICE that time step of size dt is complete

# Revert micro simulations to their last checkpoints if required
if self._participant.requires_reading_checkpoint():
Expand Down Expand Up @@ -427,7 +426,7 @@ def initialize(self) -> None:
self._micro_sims_init = False # DECLARATION

# Read initial data from preCICE, if it is available
initial_data = self._read_data_from_precice()
initial_data = self._read_data_from_precice(dt=0)

if not initial_data:
is_initial_data_available = False
Expand Down Expand Up @@ -556,16 +555,19 @@ def initialize(self) -> None:
):
self._micro_sims_have_output = True

self._dt = self._participant.get_max_time_step_size()

# ***************
# Private methods
# ***************

def _read_data_from_precice(self) -> list:
def _read_data_from_precice(self, dt) -> list:
"""
Read data from preCICE.

Parameters
----------
dt : float
Time step size at which data is to be read from preCICE.

Returns
-------
local_read_data : list
Expand All @@ -579,7 +581,7 @@ def _read_data_from_precice(self) -> list:
read_data.update(
{
name: self._participant.read_data(
self._macro_mesh_name, name, self._mesh_vertex_ids, self._dt
self._macro_mesh_name, name, self._mesh_vertex_ids, dt
)
}
)
Expand Down Expand Up @@ -621,7 +623,7 @@ def _write_data_to_precice(self, data: list) -> None:
self._macro_mesh_name, dname, [], np.array([])
)

def _solve_micro_simulations(self, micro_sims_input: list) -> list:
def _solve_micro_simulations(self, micro_sims_input: list, dt: float) -> list:
"""
Solve all micro simulations and assemble the micro simulations outputs in a list of dicts format.

Expand All @@ -630,6 +632,8 @@ def _solve_micro_simulations(self, micro_sims_input: list) -> list:
micro_sims_input : list
List of dicts in which keys are names of data and the values are the data which are required inputs to
solve a micro simulation.
dt : float
Time step size.

Returns
-------
Expand All @@ -645,9 +649,7 @@ def _solve_micro_simulations(self, micro_sims_input: list) -> list:
# Attempt to solve the micro simulation
try:
start_time = time.time()
micro_sims_output[count] = sim.solve(
micro_sims_input[count], self._dt
)
micro_sims_output[count] = sim.solve(micro_sims_input[count], dt)
end_time = time.time()
# Write solve time of the macro simulation if required and the simulation has not crashed
if self._is_micro_solve_time_required:
Expand Down Expand Up @@ -689,6 +691,7 @@ def _solve_micro_simulations_with_adaptivity(
micro_sims_input: list,
is_sim_active: np.ndarray,
sim_is_associated_to: np.ndarray,
dt: float,
) -> list:
"""
Solve all micro simulations and assemble the micro simulations outputs in a list of dicts format.
Expand All @@ -702,6 +705,8 @@ def _solve_micro_simulations_with_adaptivity(
1D array having state (active or inactive) of each micro simulation
sim_is_associated_to : numpy array
1D array with values of associated simulations of inactive simulations. Active simulations have None
dt : float
Time step size.

Returns
-------
Expand Down Expand Up @@ -741,7 +746,7 @@ def _solve_micro_simulations_with_adaptivity(
try:
start_time = time.time()
micro_sims_output[active_id] = self._micro_sims[active_id].solve(
micro_sims_input[active_id], self._dt
micro_sims_input[active_id], dt
)
end_time = time.time()
# Write solve time of the macro simulation if required and the simulation has not crashed
Expand Down
2 changes: 2 additions & 0 deletions micro_manager/micro_manager_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def __init__(self, config_file):
self._logger.info("Provided configuration file: {}".format(config_file))
self._config = Config(self._logger, config_file)

self._micro_dt = self._config.get_micro_dt()

def initialize(self):
"""
Initialize micro simulations. Not implemented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0, 1, 0, 1, 0, 1],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0, 1, 0, 1, 0, 1],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0, 1, 0, 1, 0, 1],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0, 1, 0, 1, 0, 1],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "precice-config.xml",
"macro_mesh_name": "macro-cube-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0, 1, 0, 1, 0, 1],
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/micro-manager-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "dummy-config.xml",
"macro_mesh_name": "dummy-macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 0.1
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0],
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/micro-manager-config_crash.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"config_file_name": "dummy-config.xml",
"macro_mesh_name": "dummy-macro-mesh",
"read_data_names": {"macro-scalar-data": "scalar", "macro-vector-data": "vector"},
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"}
"write_data_names": {"micro-scalar-data": "scalar", "micro-vector-data": "vector"},
"micro_dt": 1.0
},
"simulation_params": {
"macro_domain_bounds": [0.0, 25.0, 0.0, 25.0, 0.0, 25.0],
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_micro_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_initialization(self):
manager = micro_manager.MicroManagerCoupling("micro-manager-config.json")
manager.initialize()

self.assertEqual(manager._dt, 0.1) # from Interface.initialize
self.assertEqual(manager._micro_dt, 0.1) # from Interface.initialize
self.assertEqual(manager._global_number_of_sims, 4)
self.assertListEqual(manager._macro_bounds, self.macro_bounds)
self.assertListEqual(manager._mesh_vertex_ids.tolist(), [0, 1, 2, 3])
Expand All @@ -85,7 +85,7 @@ def test_read_write_data_from_precice(self):
manager = micro_manager.MicroManagerCoupling("micro-manager-config.json")

manager._write_data_to_precice(self.fake_write_data)
read_data = manager._read_data_from_precice()
read_data = manager._read_data_from_precice(1.0)

for data, fake_data in zip(read_data, self.fake_read_data):
self.assertEqual(data["macro-scalar-data"], 1)
Expand All @@ -105,7 +105,7 @@ def test_solve_micro_sims(self):
manager._micro_sims = [MicroSimulation(i) for i in range(4)]
manager._micro_sims_active_steps = np.zeros(4, dtype=np.int32)

micro_sims_output = manager._solve_micro_simulations(self.fake_read_data)
micro_sims_output = manager._solve_micro_simulations(self.fake_read_data, 1.0)

for data, fake_data in zip(micro_sims_output, self.fake_write_data):
self.assertEqual(data["micro-scalar-data"], 2)
Expand Down
Loading