Skip to content

Commit 01daef4

Browse files
authored
Fix bug in adaptivity computation when an active simulation with associations is deactivated (#171)
* Fix bug when adaptivity is computed in every implicit iteration * Calculate association after deactivating simulations * Only delete simulation objects AFTER the inactive update is completed * Add changelog entry
1 parent 169d3ec commit 01daef4

File tree

4 files changed

+31
-36
lines changed

4 files changed

+31
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## latest
44

5+
- Fix bug in adaptivity computation when an active simulation with associations is deactivated https://github.com/precice/micro-manager/pull/171
56
- Properly handle micro simulation initialization for lazy initialization https://github.com/precice/micro-manager/pull/169
67
- Delete the simulation object when the simulation is deactivated https://github.com/precice/micro-manager/pull/167
78
- Remove float32 data type restriction for adaptivity data [commit](https://github.com/precice/micro-manager/commit/bfa44ff4d3432c6ac0f3b1311274308d2ec9c2a4)

micro_manager/adaptivity/global_adaptivity.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
Note: All ID variables used in the methods of this class are global IDs, unless they have *local* in their name.
77
"""
88
import hashlib
9-
import importlib
109
from copy import deepcopy
1110
from typing import Dict
1211

@@ -307,12 +306,6 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
307306

308307
self._just_deactivated.clear() # Clear the list of sims deactivated in this step
309308

310-
# Delete the micro simulation object if it is inactive
311-
for i in self._global_ids:
312-
if not self._is_sim_active[i]:
313-
local_id = self._global_ids.index(i)
314-
micro_sims[local_id] = 0
315-
316309
local_sim_is_associated_to = self._sim_is_associated_to[
317310
self._global_ids[0] : self._global_ids[-1] + 1
318311
]
@@ -369,8 +362,13 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
369362
)
370363
micro_sims[local_id].set_state(state)
371364

372-
self._sim_is_associated_to = _sim_is_associated_to_updated
373-
del _sim_is_associated_to_updated
365+
# Delete the micro simulation object if it is inactive
366+
for i in self._global_ids:
367+
if not self._is_sim_active[i]:
368+
local_id = self._global_ids.index(i)
369+
micro_sims[local_id] = 0
370+
371+
self._sim_is_associated_to = np.copy(_sim_is_associated_to_updated)
374372

375373
def _create_tag(self, sim_id: int, src_rank: int, dest_rank: int) -> int:
376374
"""

micro_manager/adaptivity/local_adaptivity.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,6 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
203203

204204
self._just_deactivated.clear() # Clear the list of sims deactivated in this step
205205

206-
# Delete the inactive micro simulations which have not been activated
207-
for i in range(self._is_sim_active.size):
208-
if not self._is_sim_active[i]:
209-
micro_sims[i] = 0
210-
211206
# Update the set of inactive micro sims
212207
for i in to_be_activated_ids:
213208
associated_active_id = self._sim_is_associated_to[i]
@@ -216,3 +211,8 @@ def _update_inactive_sims(self, micro_sims: list) -> None:
216211
self._sim_is_associated_to[
217212
i
218213
] = -2 # Active sim cannot have an associated sim
214+
215+
# Delete the inactive micro simulations which have not been activated
216+
for i in range(self._is_sim_active.size):
217+
if not self._is_sim_active[i]:
218+
micro_sims[i] = 0

micro_manager/micro_manager.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ def solve(self) -> None:
150150
- If adaptivity is on, compute micro simulations adaptively.
151151
"""
152152
t, n = 0, 0
153-
t_checkpoint, n_checkpoint = 0, 0
154153
sim_states_cp = [None] * self._local_number_of_sims
155154
mem_usage: list = []
156155

@@ -161,23 +160,11 @@ def solve(self) -> None:
161160
dt = min(self._participant.get_max_time_step_size(), self._micro_dt)
162161

163162
first_iteration = True
164-
checkpoints_saved = False
165163

166164
while self._participant.is_coupling_ongoing():
167165

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

170-
# Write a checkpoint
171-
if self._participant.requires_writing_checkpoint():
172-
for i in range(self._local_number_of_sims):
173-
sim_states_cp[i] = (
174-
self._micro_sims[i].get_state() if self._micro_sims[i] else None
175-
)
176-
t_checkpoint = t
177-
n_checkpoint = n
178-
first_iteration = True
179-
checkpoints_saved = True
180-
181168
if self._is_adaptivity_on:
182169
if (self._adaptivity_in_every_implicit_step or first_iteration) and (
183170
n % self._adaptivity_n == 0
@@ -188,15 +175,23 @@ def solve(self) -> None:
188175
self._data_for_adaptivity,
189176
)
190177

178+
# Write a checkpoint if a simulation is just activated.
179+
# This checkpoint will be asynchronous to the checkpoints written at the start of the time window.
180+
for i in range(self._local_number_of_sims):
181+
if sim_states_cp[i] is None and self._micro_sims[i]:
182+
sim_states_cp[i] = self._micro_sims[i].get_state()
183+
191184
active_sim_ids = self._adaptivity_controller.get_active_sim_ids()
192185

193186
for active_id in active_sim_ids:
194187
self._micro_sims_active_steps[active_id] += 1
195188

196-
if sim_states_cp[active_id] == None and checkpoints_saved:
197-
sim_states_cp[active_id] = self._micro_sims[
198-
active_id
199-
].get_state()
189+
# Write a checkpoint
190+
if self._participant.requires_writing_checkpoint():
191+
for i in range(self._local_number_of_sims):
192+
sim_states_cp[i] = (
193+
self._micro_sims[i].get_state() if self._micro_sims[i] else None
194+
)
200195

201196
micro_sims_input = self._read_data_from_precice(dt)
202197

@@ -227,23 +222,21 @@ def solve(self) -> None:
227222

228223
self._write_data_to_precice(micro_sims_output)
229224

230-
t += dt
231-
n += 1
232-
233225
self._participant.advance(dt)
234226

235227
# Revert micro simulations to their last checkpoints if required
236228
if self._participant.requires_reading_checkpoint():
237229
for i in range(self._local_number_of_sims):
238230
if self._micro_sims[i]:
239231
self._micro_sims[i].set_state(sim_states_cp[i])
240-
n = n_checkpoint
241-
t = t_checkpoint
242232
first_iteration = False
243233

244234
if (
245235
self._participant.is_time_window_complete()
246236
): # Time window has converged, now micro output can be generated
237+
t += dt # Update time to the end of the time window
238+
n += 1 # Update time step to the end of the time window
239+
247240
if self._micro_sims_have_output:
248241
if n % self._micro_n_out == 0:
249242
for sim in self._micro_sims:
@@ -260,6 +253,9 @@ def solve(self) -> None:
260253

261254
self._logger.log_info_rank_zero("Time window {} converged.".format(n))
262255

256+
# Reset first iteration flag for the next time window
257+
first_iteration = True
258+
263259
if self._is_adaptivity_on and n % self._adaptivity_output_n != 0:
264260
self._adaptivity_controller.log_metrics(n)
265261

0 commit comments

Comments
 (0)