Skip to content

Commit 24a6796

Browse files
committed
init any core restarts
1 parent e61b34c commit 24a6796

40 files changed

+1306
-488
lines changed

pyphare/pyphare/pharein/__init__.py

+8-342
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import os
22
import sys
33
import subprocess
4-
import numpy as np
54

6-
from pyphare.core.phare_utilities import is_scalar
75
from .uniform_model import UniformModel
86
from .maxwellian_fluid_model import MaxwellianFluidModel
97
from .electron_model import ElectronModel
@@ -14,11 +12,7 @@
1412
MetaDiagnostics,
1513
InfoDiagnostics,
1614
)
17-
from .simulation import (
18-
Simulation,
19-
serialize as serialize_sim,
20-
deserialize as deserialize_sim,
21-
)
15+
from .simulation import Simulation
2216
from .load_balancer import LoadBalancer
2317

2418
__all__ = [
@@ -31,6 +25,7 @@
3125
"MetaDiagnostics",
3226
"InfoDiagnostics",
3327
"Simulation",
28+
"LoadBalancer",
3429
]
3530

3631
# This exists to allow a condition variable for when we are running PHARE from C++ via phare-exe
@@ -64,58 +59,6 @@ def NO_GUI():
6459
mpl.use("Agg")
6560

6661

67-
def getSimulation():
68-
from .global_vars import sim
69-
70-
return sim
71-
72-
73-
def _patch_data_ids(restart_file_dir):
74-
"""
75-
for restarts we save samrai patch data ids to the restart files, which we access from here
76-
to tell samrai which patch datas to load from the restart file on restart
77-
"""
78-
from pyphare.cpp import cpp_etc_lib
79-
80-
return cpp_etc_lib().patch_data_ids(restart_file_dir)
81-
82-
83-
def _serialized_simulation_string(restart_file_dir):
84-
from pyphare.cpp import cpp_etc_lib
85-
86-
return cpp_etc_lib().serialized_simulation_string(restart_file_dir)
87-
88-
89-
# converts scalars to array of expected size
90-
# converts lists to arrays
91-
class py_fn_wrapper:
92-
def __init__(self, fn):
93-
self.fn = fn
94-
95-
def __call__(self, *xyz):
96-
args = [np.asarray(arg) for arg in xyz]
97-
ret = self.fn(*args)
98-
if isinstance(ret, list):
99-
ret = np.asarray(ret)
100-
if is_scalar(ret):
101-
ret = np.full(len(args[-1]), ret)
102-
return ret
103-
104-
105-
# Wrap calls to user init functions to turn C++ vectors to ndarrays,
106-
# and returned ndarrays to C++ span
107-
class fn_wrapper(py_fn_wrapper):
108-
def __init__(self, fn):
109-
super().__init__(fn)
110-
111-
def __call__(self, *xyz):
112-
from pyphare.cpp import cpp_etc_lib
113-
114-
# convert numpy array to C++ SubSpan
115-
# couples vector init functions to C++
116-
return cpp_etc_lib().makePyArrayWrapper(super().__call__(*xyz))
117-
118-
11962
def clearDict():
12063
"""
12164
dict may contain dangling references from a previous simulation unless cleared
@@ -126,289 +69,12 @@ def clearDict():
12669

12770

12871
def populateDict():
129-
from .global_vars import sim as simulation
130-
import pybindlibs.dictator as pp
131-
132-
# pybind complains if receiving wrong type
133-
def add_int(path, val):
134-
pp.add_int(path, int(val))
135-
136-
def add_bool(path, val):
137-
pp.add_bool(path, bool(val))
138-
139-
def add_double(path, val):
140-
pp.add_double(path, float(val))
141-
142-
def add_size_t(path, val):
143-
casted = int(val)
144-
if casted < 0:
145-
raise RuntimeError("pyphare.__init__::add_size_t received negative value")
146-
pp.add_size_t(path, casted)
147-
148-
def add_vector_int(path, val):
149-
pp.add_vector_int(path, list(val))
150-
151-
add_string = pp.add_string
152-
addInitFunction = getattr(pp, "addInitFunction{:d}".format(simulation.ndim) + "D")
153-
154-
add_string("simulation/name", "simulation_test")
155-
add_int("simulation/dimension", simulation.ndim)
156-
157-
if simulation.smallest_patch_size is not None:
158-
add_vector_int(
159-
"simulation/AMR/smallest_patch_size", simulation.smallest_patch_size
160-
)
161-
if simulation.largest_patch_size is not None:
162-
add_vector_int(
163-
"simulation/AMR/largest_patch_size", simulation.largest_patch_size
164-
)
165-
166-
add_string("simulation/grid/layout_type", simulation.layout)
167-
add_int("simulation/grid/nbr_cells/x", simulation.cells[0])
168-
add_double("simulation/grid/meshsize/x", simulation.dl[0])
169-
add_double("simulation/grid/origin/x", simulation.origin[0])
170-
add_string("simulation/grid/boundary_type/x", simulation.boundary_types[0])
171-
172-
if simulation.ndim > 1:
173-
add_int("simulation/grid/nbr_cells/y", simulation.cells[1])
174-
add_double("simulation/grid/meshsize/y", simulation.dl[1])
175-
add_double("simulation/grid/origin/y", simulation.origin[1])
176-
add_string("simulation/grid/boundary_type/y", simulation.boundary_types[1])
177-
178-
if simulation.ndim > 2:
179-
add_int("simulation/grid/nbr_cells/z", simulation.cells[2])
180-
add_double("simulation/grid/meshsize/z", simulation.dl[2])
181-
add_double("simulation/grid/origin/z", simulation.origin[2])
182-
add_string("simulation/grid/boundary_type/z", simulation.boundary_types[2])
183-
184-
add_int("simulation/interp_order", simulation.interp_order)
185-
add_int("simulation/refined_particle_nbr", simulation.refined_particle_nbr)
186-
add_double("simulation/time_step", simulation.time_step)
187-
add_int("simulation/time_step_nbr", simulation.time_step_nbr)
188-
189-
add_string("simulation/AMR/clustering", simulation.clustering)
190-
add_int("simulation/AMR/max_nbr_levels", simulation.max_nbr_levels)
191-
add_vector_int("simulation/AMR/nesting_buffer", simulation.nesting_buffer)
192-
193-
add_int("simulation/AMR/tag_buffer", simulation.tag_buffer)
194-
195-
refinement_boxes = simulation.refinement_boxes
196-
197-
def as_paths(rb):
198-
add_int("simulation/AMR/refinement/boxes/nbr_levels/", len(rb.keys()))
199-
for level, boxes in rb.items():
200-
level_path = "simulation/AMR/refinement/boxes/" + level + "/"
201-
add_int(level_path + "nbr_boxes/", int(len(boxes)))
202-
for box_i, box in enumerate(boxes):
203-
box_id = "B" + str(box_i)
204-
lower = box.lower
205-
upper = box.upper
206-
box_lower_path_x = box_id + "/lower/x/"
207-
box_upper_path_x = box_id + "/upper/x/"
208-
add_int(level_path + box_lower_path_x, lower[0])
209-
add_int(level_path + box_upper_path_x, upper[0])
210-
if len(lower) >= 2:
211-
box_lower_path_y = box_id + "/lower/y/"
212-
box_upper_path_y = box_id + "/upper/y/"
213-
add_int(level_path + box_lower_path_y, lower[1])
214-
add_int(level_path + box_upper_path_y, upper[1])
215-
if len(lower) == 3:
216-
box_lower_path_z = box_id + "/lower/z/"
217-
box_upper_path_z = box_id + "/upper/z/"
218-
add_int(level_path + box_lower_path_z, lower[2])
219-
add_int(level_path + box_upper_path_z, upper[2])
220-
221-
if refinement_boxes is not None and simulation.refinement == "boxes":
222-
as_paths(refinement_boxes)
223-
elif simulation.refinement == "tagging":
224-
add_string("simulation/AMR/refinement/tagging/method", "auto")
225-
# the two following params are hard-coded for now
226-
# they will become configurable when we have multi-models or several methods
227-
# per model
228-
add_string("simulation/AMR/refinement/tagging/model", "HybridModel")
229-
add_string("simulation/AMR/refinement/tagging/method", "default")
230-
add_double(
231-
"simulation/AMR/refinement/tagging/threshold", simulation.tagging_threshold
232-
)
233-
else:
234-
add_string(
235-
"simulation/AMR/refinement/tagging/method", "none"
236-
) # integrator.h might want some looking at
237-
238-
add_string("simulation/algo/ion_updater/pusher/name", simulation.particle_pusher)
239-
240-
add_double("simulation/algo/ohm/resistivity", simulation.resistivity)
241-
add_double("simulation/algo/ohm/hyper_resistivity", simulation.hyper_resistivity)
242-
add_string("simulation/algo/ohm/hyper_mode", simulation.hyper_mode)
243-
244-
# load balancer block start
245-
lb = simulation.load_balancer or LoadBalancer(active=False, _register=False)
246-
base = "simulation/AMR/loadbalancing"
247-
add_bool(f"{base}/active", lb.active)
248-
add_string(f"{base}/mode", lb.mode)
249-
add_double(f"{base}/tolerance", lb.tol)
250-
251-
# if mode==nppc, imbalance allowed
252-
add_bool(f"{base}/auto", lb.auto)
253-
add_size_t(f"{base}/next_rebalance", lb.next_rebalance)
254-
add_size_t(f"{base}/max_next_rebalance", lb.max_next_rebalance)
255-
add_size_t(
256-
f"{base}/next_rebalance_backoff_multiplier",
257-
lb.next_rebalance_backoff_multiplier,
258-
)
259-
260-
# cadence based values
261-
add_size_t(f"{base}/every", lb.every)
262-
add_bool(f"{base}/on_init", lb.on_init)
263-
# load balancer block end
264-
265-
init_model = simulation.model
266-
modelDict = init_model.model_dict
267-
268-
if init_model.nbr_populations() < 0:
269-
raise RuntimeError("Number of populations cannot be negative")
270-
add_size_t("simulation/ions/nbrPopulations", init_model.nbr_populations())
271-
272-
partinit = "particle_initializer"
273-
for pop_index, pop in enumerate(init_model.populations):
274-
pop_path = "simulation/ions/pop"
275-
partinit_path = pop_path + "{:d}/".format(pop_index) + partinit + "/"
276-
d = modelDict[pop]
277-
add_string(pop_path + "{:d}/name".format(pop_index), pop)
278-
add_double(pop_path + "{:d}/mass".format(pop_index), d["mass"])
279-
add_string(partinit_path + "name", "maxwellian")
280-
281-
addInitFunction(partinit_path + "density", fn_wrapper(d["density"]))
282-
addInitFunction(partinit_path + "bulk_velocity_x", fn_wrapper(d["vx"]))
283-
addInitFunction(partinit_path + "bulk_velocity_y", fn_wrapper(d["vy"]))
284-
addInitFunction(partinit_path + "bulk_velocity_z", fn_wrapper(d["vz"]))
285-
addInitFunction(partinit_path + "thermal_velocity_x", fn_wrapper(d["vthx"]))
286-
addInitFunction(partinit_path + "thermal_velocity_y", fn_wrapper(d["vthy"]))
287-
addInitFunction(partinit_path + "thermal_velocity_z", fn_wrapper(d["vthz"]))
288-
add_double(partinit_path + "charge", d["charge"])
289-
add_string(partinit_path + "basis", "cartesian")
290-
if "init" in d and "seed" in d["init"]:
291-
pp.add_optional_size_t(partinit_path + "init/seed", d["init"]["seed"])
292-
293-
add_int(partinit_path + "nbr_part_per_cell", d["nbrParticlesPerCell"])
294-
add_double(partinit_path + "density_cut_off", d["density_cut_off"])
295-
296-
add_string("simulation/electromag/name", "EM")
297-
add_string("simulation/electromag/electric/name", "E")
298-
299-
add_string("simulation/electromag/magnetic/name", "B")
300-
maginit_path = "simulation/electromag/magnetic/initializer/"
301-
addInitFunction(maginit_path + "x_component", fn_wrapper(modelDict["bx"]))
302-
addInitFunction(maginit_path + "y_component", fn_wrapper(modelDict["by"]))
303-
addInitFunction(maginit_path + "z_component", fn_wrapper(modelDict["bz"]))
304-
305-
serialized_sim = serialize_sim(simulation)
306-
307-
#### adding diagnostics
308-
309-
diag_path = "simulation/diagnostics/"
310-
for diag in list(simulation.diagnostics.values()):
311-
diag.attributes["serialized_simulation"] = serialized_sim
312-
313-
type_path = diag_path + diag.type + "/"
314-
name_path = type_path + diag.name
315-
add_string(name_path + "/" + "type", diag.type)
316-
add_string(name_path + "/" + "quantity", diag.quantity)
317-
add_size_t(name_path + "/" + "flush_every", diag.flush_every)
318-
pp.add_array_as_vector(
319-
name_path + "/" + "write_timestamps", diag.write_timestamps
320-
)
321-
pp.add_array_as_vector(
322-
name_path + "/" + "compute_timestamps", diag.compute_timestamps
323-
)
324-
325-
add_size_t(name_path + "/" + "n_attributes", len(diag.attributes))
326-
for attr_idx, attr_key in enumerate(diag.attributes):
327-
add_string(name_path + "/" + f"attribute_{attr_idx}_key", attr_key)
328-
add_string(
329-
name_path + "/" + f"attribute_{attr_idx}_value",
330-
diag.attributes[attr_key],
331-
)
332-
333-
if len(simulation.diagnostics) > 0:
334-
if simulation.diag_options is not None and "options" in simulation.diag_options:
335-
add_string(
336-
diag_path + "filePath", simulation.diag_options["options"]["dir"]
337-
)
338-
if "mode" in simulation.diag_options["options"]:
339-
add_string(
340-
diag_path + "mode", simulation.diag_options["options"]["mode"]
341-
)
342-
if "fine_dump_lvl_max" in simulation.diag_options["options"]:
343-
add_int(
344-
diag_path + "fine_dump_lvl_max",
345-
simulation.diag_options["options"]["fine_dump_lvl_max"],
346-
)
347-
else:
348-
add_string(diag_path + "filePath", "phare_output")
349-
#### diagnostics added
350-
351-
#### adding restarts
352-
if simulation.restart_options is not None:
353-
restart_options = simulation.restart_options
354-
restarts_path = "simulation/restarts/"
355-
restart_file_path = "phare_outputs"
356-
357-
if "dir" in restart_options:
358-
restart_file_path = restart_options["dir"]
359-
360-
if "restart_time" in restart_options:
361-
from pyphare.cpp import cpp_etc_lib
362-
363-
restart_time = restart_options["restart_time"]
364-
restart_file_load_path = cpp_etc_lib().restart_path_for_time(
365-
restart_file_path, restart_time
366-
)
367-
368-
if not os.path.exists(restart_file_load_path):
369-
raise ValueError(
370-
f"PHARE restart file not found for time {restart_time}"
371-
)
372-
373-
deserialized_simulation = deserialize_sim(
374-
_serialized_simulation_string(restart_file_load_path)
375-
)
376-
if not simulation.is_restartable_compared_to(deserialized_simulation):
377-
raise ValueError(
378-
"deserialized Restart simulation is incompatible with configured simulation parameters"
379-
)
380-
381-
add_vector_int(
382-
restarts_path + "restart_ids", _patch_data_ids(restart_file_load_path)
383-
)
384-
add_string(restarts_path + "loadPath", restart_file_load_path)
385-
add_double(restarts_path + "restart_time", restart_time)
386-
387-
if "mode" in restart_options:
388-
add_string(restarts_path + "mode", restart_options["mode"])
389-
390-
add_string(restarts_path + "filePath", restart_file_path)
391-
392-
if "elapsed_timestamps" in restart_options:
393-
pp.add_array_as_vector(
394-
restarts_path + "elapsed_timestamps",
395-
restart_options["elapsed_timestamps"],
396-
)
397-
398-
if "timestamps" in restart_options:
399-
pp.add_array_as_vector(
400-
restarts_path + "write_timestamps", restart_options["timestamps"]
401-
)
72+
from .global_vars import sim
73+
from . import initialize
40274

403-
add_string(restarts_path + "serialized_simulation", serialized_sim)
404-
#### restarts added
75+
initialize.general.populateDict(sim)
40576

406-
#### adding electrons
407-
if simulation.electrons is None:
408-
raise RuntimeError("Error - no electrons registered to this Simulation")
77+
if sim.init_options is None:
78+
initialize.user_fns.populateDict(sim)
40979
else:
410-
for item in simulation.electrons.dict_path():
411-
if isinstance(item[1], str):
412-
add_string("simulation/" + item[0], item[1])
413-
else:
414-
add_double("simulation/" + item[0], item[1])
80+
initialize.samrai_hdf5.populateDict(sim)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from . import general
2+
from . import user_fns
3+
from . import samrai_hdf5
4+
5+
__all__ = [
6+
"general",
7+
"user_fns",
8+
"samrai_hdf5",
9+
]

0 commit comments

Comments
 (0)