1
1
import os
2
2
import sys
3
3
import subprocess
4
- import numpy as np
5
4
6
- from pyphare .core .phare_utilities import is_scalar
7
5
from .uniform_model import UniformModel
8
6
from .maxwellian_fluid_model import MaxwellianFluidModel
9
7
from .electron_model import ElectronModel
14
12
MetaDiagnostics ,
15
13
InfoDiagnostics ,
16
14
)
17
- from .simulation import (
18
- Simulation ,
19
- serialize as serialize_sim ,
20
- deserialize as deserialize_sim ,
21
- )
15
+ from .simulation import Simulation
22
16
from .load_balancer import LoadBalancer
23
17
24
18
__all__ = [
31
25
"MetaDiagnostics" ,
32
26
"InfoDiagnostics" ,
33
27
"Simulation" ,
28
+ "LoadBalancer" ,
34
29
]
35
30
36
31
# 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():
64
59
mpl .use ("Agg" )
65
60
66
61
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
-
119
62
def clearDict ():
120
63
"""
121
64
dict may contain dangling references from a previous simulation unless cleared
@@ -126,289 +69,12 @@ def clearDict():
126
69
127
70
128
71
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
402
74
403
- add_string (restarts_path + "serialized_simulation" , serialized_sim )
404
- #### restarts added
75
+ initialize .general .populateDict (sim )
405
76
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 )
409
79
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 )
0 commit comments