Peano
Loading...
Searching...
No Matches
Sequential.py
Go to the documentation of this file.
1# This file is part of the ExaParty project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from exaparty.api.particle.AlgorithmStep import AlgorithmStep
4from exaparty.api.actionsets.UpdateParticleMarker import UpdateParticleMarker
5
6import peano4.api
7import exaparty
8
9
10from .AMRLogic import add_dynamic_mesh_refinement_and_particle_resorting
11from .ParticleSortingAndStorage import (
12 ParticleSortingAndStorage,
13 AddAdditionalDummySweep
14)
15from .SpeciesStepOrdering import concatenate_steps_of_species
16from .Utils import (
17 does_one_species_require_gather,
18 get_species_set,
19 get_observer_prefix,
20 StepType,
21)
22
23
25 step,
26 current_species_set,
27 mesh_traversals,
28 alter_particle_position,
29 use_continuous_particles_sequences,
30 step_type: StepType,
31 verbose,
32):
33 """!
34
35 Translate one step of species into mesh traversal
36
37 Takes one step of the species and adds it to the list of steps. That is,
38 you get one more entry within mesh_traversals. Further to that, the
39 routine also appends a boolean arker to alter_particle_position. It
40 shows if the mesh will change the particle position (or search radius)
41 or not. This is decided from step.effect, i.e. whether it is one of the
42 CHANGE_POSITION_OR_INTERACTION_RADIUS(_AND_MIGHT_RERUN) variants.
43 @see AlgorithmStep.may_trigger_rerun()
44
45 This routine is a helper routine of map_initialisation_steps_onto_separate_mesh_traversals()
46 for example. Note that the returned steps are not fully functionally.
47 If a step alters the particles within the mesh, you still have to resort
48 the particles. That's not done in the step added by this routine, i.e.
49 these steps lack the actual particle sorting. Any sorting has to spread
50 over two steps, so it makes no sense to add it here. Instead, we befill
51 the alter_particle_position, and we expect the calling routine to
52 supplement the actual particle sorting later on in a postprocessing
53 step once all steps are assembled.
54
55
56 @param current_species_set: Particle
57 You get a specific algorithmic step as input. The current_species_set
58 highlights to which this step originally belonged to.
59
60 @param mesh_traversals: [peano4.api.solversteps.Step]
61 Inout parameter. We append a new step to this sequence.
62
63 @param alter_particle_position: [Bool]
64 Inout parameter. We append a new marker to this sequence.
65
66 """
68 "{}{}{}_sweep{}".format(
69 get_observer_prefix(step_type),
70 current_species_set.particle_model.name,
71 step.name,
72 len(mesh_traversals),
73 ),
74 add_user_defined_actions=False,
75 )
76
77 action_set_update_marker = UpdateParticleMarker(particle_set = current_species_set,
78 automatically_set_marker_in_leave_cell=True,
79 make_reset_separate_task=False,
80 )
81
82 action_set_update_marker.descend_invocation_order = (
83 new_step.highest_descend_invocation_order() + 1
84 )
85 action_set_update_marker.parallel = True
86 new_step.add_action_set(action_set_update_marker)
87
88 #
89 # Pick computational kernel
90 # =========================
91 # This is where the actual computation per step is done. We have two
92 # fundamentally different kernels: one keeps track of (multiscale)
93 # neighbours, while the other just updates the particles within the
94 # octant (cell).
95 #
96 if step.dependencies == AlgorithmStep.Dependencies.NEIGHBOURS:
97 if use_continuous_particles_sequences:
98 if verbose:
99 print(
100 "GRAPH COMPILER DEBUG [translate_one_step_of_species_into_mesh_traversal]: step no {} ({}) on particle {} can use the peano4.api.toolbox.particles.UpdateParticle_MultiLevelInteraction_StackOfLists_ContiguousParticles action set and hence optimise aggressively".format(
101 len(mesh_traversals),
102 step.name,
103 current_species_set.particle_model.name,
104 )
105 )
107 particle_set=current_species_set,
108 particle_particle_interaction_kernel=step.cell_kernel,
109 touch_vertex_first_time_compute_particle_update_kernel=step.touch_vertex_first_time_kernel,
110 touch_vertex_last_time_compute_particle_update_kernel=step.touch_vertex_last_time_kernel,
111 prepare_traversal_kernel=step.prepare_traversal_kernel,
112 unprepare_traversal_kernel=step.unprepare_traversal_kernel,
113 additional_includes=step.includes,
114 active_particle_set=step.input_particles,
115 )
116 else:
117 if verbose:
118 print(
119 "GRAPH COMPILER DEBUG [translate_one_step_of_species_into_mesh_traversal]: step no {} ({}) on particle {} uses the peano4.api.toolbox.particles.UpdateParticle_MultiLevelInteraction_Sets".format(
120 len(mesh_traversals),
121 step.name,
122 current_species_set.particle_model.name,
123 )
124 )
125 action_set_particle_particle_interaction = peano4.api.toolbox.particles.UpdateParticle_MultiLevelInteraction_Sets(
126 particle_set=current_species_set,
127 particle_particle_interaction_kernel=step.cell_kernel,
128 touch_vertex_first_time_compute_particle_update_kernel=step.touch_vertex_first_time_kernel,
129 touch_vertex_last_time_compute_particle_update_kernel=step.touch_vertex_last_time_kernel,
130 prepare_traversal_kernel=step.prepare_traversal_kernel,
131 unprepare_traversal_kernel=step.unprepare_traversal_kernel,
132 additional_includes=step.includes,
133 active_particle_set=step.input_particles,
134 )
135 action_set_particle_particle_interaction.descend_invocation_order = (
136 new_step.highest_descend_invocation_order() + 1
137 )
138 action_set_particle_particle_interaction.parallel = True
139 new_step.add_action_set(action_set_particle_particle_interaction)
140 elif step.dependencies == AlgorithmStep.Dependencies.SELF:
141 if use_continuous_particles_sequences:
142 if verbose:
143 print(
144 "GRAPH COMPILER DEBUG [translate_one_step_of_species_into_mesh_traversal]: step no {} ({}) on particle {} uses peano4.api.toolbox.particles.UpdateParticle_SingleLevelInteraction_ContiguousParticles action set".format(
145 len(mesh_traversals),
146 step.name,
147 current_species_set.particle_model.name,
148 )
149 )
150
152 particle_set=current_species_set,
153 particle_cell_update_kernel=step.cell_kernel,
154 touch_vertex_first_time_compute_particle_update_kernel=step.touch_vertex_first_time_kernel,
155 touch_vertex_last_time_compute_particle_update_kernel=step.touch_vertex_last_time_kernel,
156 prepare_traversal_kernel=step.prepare_traversal_kernel,
157 unprepare_traversal_kernel=step.unprepare_traversal_kernel,
158 additional_includes=step.includes,
159 active_particle_set=step.input_particles,
160 )
161 action_set_particle_update.descend_invocation_order = (
162 new_step.highest_descend_invocation_order() + 1
163 )
164 action_set_particle_update.parallel = True
165 new_step.add_action_set(action_set_particle_update)
166 else:
167 if verbose:
168 print(
169 "GRAPH COMPILER DEBUG [translate_one_step_of_species_into_mesh_traversal]: step no {} ({}) on particle {} uses peano4.api.toolbox.particles.UpdateParticle_SingleLevelInteraction action set".format(
170 len(mesh_traversals),
171 step.name,
172 current_species_set.particle_model.name,
173 )
174 )
175
177 particle_set=current_species_set,
178 particle_cell_update_kernel=step.cell_kernel,
179 touch_vertex_first_time_compute_particle_update_kernel=step.touch_vertex_first_time_kernel,
180 touch_vertex_last_time_compute_particle_update_kernel=step.touch_vertex_last_time_kernel,
181 prepare_traversal_kernel=step.prepare_traversal_kernel,
182 unprepare_traversal_kernel=step.unprepare_traversal_kernel,
183 additional_includes=step.includes,
184 active_particle_set=step.input_particles,
185 )
186 action_set_particle_update.descend_invocation_order = (
187 new_step.highest_descend_invocation_order() + 1
188 )
189 action_set_particle_update.parallel = True
190 new_step.add_action_set(action_set_particle_update)
191 else:
192 assert False, "step {} seems to have no action at all".format(step)
193
194 #
195 # As we have a 1:1 mapping, we can directly translate the effect into flags
196 #
197 if (
198 step.effect== AlgorithmStep.Effect.CHANGE_POSITION_OR_INTERACTION_RADIUS_AND_MIGHT_RERUN
199 or
200 step.effect == AlgorithmStep.Effect.CHANGE_POSITION_OR_INTERACTION_RADIUS
201 ):
202 alter_particle_position.append(True)
203 else:
204 alter_particle_position.append(False)
205
206 mesh_traversals.append(new_step)
207
208
209def map_onto_separate_mesh_traversals_with_generic_mapper(
210 sequence_of_steps,
211 particle_sorting_and_storage: ParticleSortingAndStorage,
212 step_type: StepType,
213 verbose,
214 mapper
215):
216 """!
217
218 Generic mapper of separate steps of separate particles onto mesh traversals
219
220 expects a mapper that then defines how to actually map the species plus
221 step combination.
222
223 """
224 mesh_traversals = []
225 alter_particle_position = []
226
227 if verbose:
228 print(
229 "GRAPH COMPILER DEBUG [map_onto_separate_mesh_traversals]: start graph construction with particle sorting {} and step type {}".format(
230 particle_sorting_and_storage, step_type
231 )
232 )
233
234 for current_entry_from_total_sequence_of_steps in sequence_of_steps:
235 current_species_set = current_entry_from_total_sequence_of_steps[0]
236 current_step_of_species = current_entry_from_total_sequence_of_steps[1]
237
238 if (
239 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_ON_THE_FLY_SCATTERED_PARTICLE_STORAGE
240 ):
241 use_continuous_particles_sequences = False
242 add_additional_dummy_sweep = AddAdditionalDummySweep.NO
243 elif (
244 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_ON_THE_FLY_COALESCED_PARTICLE_STORAGE
245 ):
246 use_continuous_particles_sequences = True
247 add_additional_dummy_sweep = AddAdditionalDummySweep.NO
248 elif (
249 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_SCATTERED_PARTICLE_STORAGE
250 and len(alter_particle_position) > 0
251 and alter_particle_position[-1]
252 ):
253 use_continuous_particles_sequences = False
254 add_additional_dummy_sweep = AddAdditionalDummySweep.BEFORE
255 elif (
256 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_SCATTERED_PARTICLE_STORAGE
257 ):
258 use_continuous_particles_sequences = False
259 add_additional_dummy_sweep = AddAdditionalDummySweep.NO
260 elif (
261 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_COALESCED_PARTICLE_STORAGE
262 and len(alter_particle_position) > 0
263 and alter_particle_position[-1]
264 ):
265 use_continuous_particles_sequences = True
266 add_additional_dummy_sweep = AddAdditionalDummySweep.BEFORE
267 elif (
268 particle_sorting_and_storage == ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_COALESCED_PARTICLE_STORAGE
269 ):
270 use_continuous_particles_sequences = True
271 add_additional_dummy_sweep = AddAdditionalDummySweep.NO
272 else:
273 assert False, "variant {} x {} not supported".format(particle_sorting_and_storage,alter_particle_position)
274
275 if add_additional_dummy_sweep == AddAdditionalDummySweep.BEFORE:
276 if verbose:
277 print(
278 "GRAPH COMPILER DEBUG [map_onto_separate_mesh_traversals]: step no {} ({}) on particle {} has to be dummy step to clean up sorting. Will not alter particle position itself".format(
279 len(mesh_traversals),
280 current_step_of_species.name,
281 current_species_set.particle_model.name,
282 )
283 )
285 "DummyStep{}{}_sweep{}".format(
286 current_species_set.particle_model.name,
287 current_step_of_species.name,
288 len(mesh_traversals),
289 ),
290 add_user_defined_actions=False,
291 )
292 new_step.add_action_set(exaparty.api.actionsets.DummyStep())
293 mesh_traversals.append(new_step)
294 alter_particle_position.append(False)
295
296 mapper(
297 step=current_step_of_species,
298 current_species_set=current_species_set,
299 mesh_traversals=mesh_traversals,
300 alter_particle_position=alter_particle_position,
301 use_continuous_particles_sequences=use_continuous_particles_sequences,
302 step_type=step_type,
303 verbose=verbose,
304 )
305
306 if add_additional_dummy_sweep == AddAdditionalDummySweep.AFTER:
307 if verbose:
308 print(
309 "GRAPH COMPILER DEBUG [map_onto_separate_mesh_traversals]: step no {} ({}) on particle {} has to be dummy step to clean up sorting. Will not alter the particle position itself".format(
310 len(mesh_traversals),
311 current_step_of_species.name,
312 current_species_set.particle_model.name,
313 )
314 )
316 "DummyStep{}{}_sweep{}".format(
317 current_species_set.particle_model.name,
318 current_step_of_species.name,
319 len(mesh_traversals),
320 ),
321 add_user_defined_actions=False,
322 )
323 new_step.add_action_set(exaparty.api.actionsets.DummyStep())
324 mesh_traversals.append(new_step)
325 alter_particle_position.append(False)
326
327 if step_type == StepType.INITIALISATION and len(alter_particle_position) > 0:
328 # When we insert particles initially, they will be scattered. So it is
329 # important that we immediately gather them. We cannot flag step -1 as
330 # one that changes teh particle position, but we can present to the
331 # graph compiler that the last step will change the ordering. The graph
332 # compiler does not distinguish initialisation from time stepping and
333 # hence thinks that the sweep prior to the first sweep has changed the
334 # particle order. Which is exactly what we want. We also flag the first
335 # sweep as change, as the initial insertion indeed might be buggy.
336 alter_particle_position[0] = True
337 alter_particle_position[-1] = True
338
339
340 if (
341 particle_sorting_and_storage==ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_SCATTERED_PARTICLE_STORAGE
342 or
343 particle_sorting_and_storage==ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_COALESCED_PARTICLE_STORAGE
344 ):
345 sort_with_lifts_and_drops = True
346 elif (
347 particle_sorting_and_storage==ParticleSortingAndStorage.SORT_ON_THE_FLY_SCATTERED_PARTICLE_STORAGE
348 or
349 particle_sorting_and_storage==ParticleSortingAndStorage.SORT_ON_THE_FLY_COALESCED_PARTICLE_STORAGE
350 ):
351 sort_with_lifts_and_drops = False
352 else:
353 assert False, "variant {} not implemented".format(particle_sorting_and_storage)
354
355
356 add_dynamic_mesh_refinement_and_particle_resorting(
357 mesh_traversals,
358 alter_particle_position,
359 get_species_set(sequence_of_steps),
360 sort_with_lifts_and_drops=sort_with_lifts_and_drops,
361 verbose=verbose,
362 )
363
364 if verbose:
365 print(
366 "GRAPH COMPILER DEBUG [map_onto_separate_mesh_traversals]: finished graph construction"
367 )
368
369 return mesh_traversals
370
371
372
373def map_onto_separate_mesh_traversals(
374 sequence_of_steps,
375 particle_sorting_and_storage: ParticleSortingAndStorage,
376 step_type: StepType,
377 verbose,
378):
379 """!
380
381 Simpest graph compiler mapping each step per particle onto one mesh traversal
382
383 Very simple compiler which takes each individual algorithmic step
384 per species and maps it onto one mesh traversal. We won't get any
385 fancy parallelism besides the core domain decomposition.
386
387 As we work with a strictly synchronised way, we can ignore in and
388 outgoing dependencies which affect the global state. They are
389 implicitly handled.
390
391 It is important to recognise the inter-dependencies between steps:
392
393 We do not have to care about the plotting: It always resorts the
394 particles, and it always re-analyses which particles are local for
395 a tree. Consequently, the plotting will throw away local particle
396 copies if particles have meanwhile left the domain. We may assume
397 that all particles are in the right place after the plotting. We
398 also may assume that the initialisation inserts particles only at
399 the right point. The realisation of this behaviour can be found in
400 Project.generate_Peano4_project().
401
402 Due to the observations above, we can conclude that particles might
403 have moved in the first step of the algorithmic sequence if and
404 only if the last step has changed a position. Otherwise, we know
405 that all is in place. As we run through the species one by one, we
406 also have to make this reasoning one by one.
407
408 ## Initialisation
409
410 The initialisation is no different to the time stepping besides two
411 places:
412
413 1. We have to use the initialisation steps rather than the
414 algorithm steps.
415 2. We have to insert an additional dummy sweep initially. After
416 users have inserted their particles, they are scattered all
417 over the place. If the first initialisation phase then relies
418 on continuous AoS data, it will crash.
419
420 The latter "tweak" obviously can be ignored whenever we work without
421 coalesced memory.
422
423 ## Tree statistics
424
425 We assume that there is a tree marker already. So our analysis
426 will create it, but we assume that it is already out there, so
427 we don't have to add it actually to the project.
428
429 ## Adaptive mesh refinement
430
431 If the mesh changes, we have to resort. In the second step of the
432 sorting, particles might still be dropped. Throughout drops, we may
433 not evaluate particle-particle interactions, as the mesh-particle
434 topology continues to change, so we'll evaluate stuff twice. Therefore,
435 we have to insert dummy steps. This is not a problem when we bucket
436 sort.
437
438
439 @param sequence_of_steps: [(Species,Step)]
440 Sequence of tuples each consisting of one species and one step. Typically
441 constructed through functions within SpeciesStepOrdering.py.
442
443 @param particle_sorting: ParticleSorting
444
445 @param observer_preamble: String
446 Usually people pass in "Init" or "Step" here to distinguish observers for
447 the initialisation from the actual particle update steps.
448
449 @param verbose: {True, False}
450
451 @return mesh_traversals
452
453 """
454 return map_onto_separate_mesh_traversals_with_generic_mapper(
455 sequence_of_steps,
456 particle_sorting_and_storage,
457 step_type,
458 verbose,
459 translate_one_step_of_species_into_mesh_traversal
460 )
461
462
463# ====================================
464# Public API functions
465# ====================================
466#
467# These functions are made available through the __init__.py file. They are all
468# "just" wrappers around the generic map_onto_separate_mesh_traversals()
469# function calls, yet with different arguments.
470#
471
472def initialisation_steps_onto_separate_mesh_traversals_multiscale_sort_scattered_memory(
473 species_sets,
474 verbose,
475):
476 """!
477
478 @see map_onto_separate_mesh_traversals()
479
480 @param concatenate_steps_of_species: [Species]
481 Sequence of particle species to be handled.
482
483 @param verbose: {True, False}
484
485 """
486 return map_onto_separate_mesh_traversals(
487 sequence_of_steps=concatenate_steps_of_species(species_sets, True),
488 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_SCATTERED_PARTICLE_STORAGE,
489 step_type=StepType.INITIALISATION,
490 verbose=verbose,
491 )
492
493
494def initialisation_steps_onto_separate_mesh_traversals_bucket_sort_scattered_memory(
495 species_sets,
496 verbose,
497):
498 """!
499
500 @see map_onto_separate_mesh_traversals()
501
502 @param concatenate_steps_of_species: [Species]
503 Sequence of particle species to be handled.
504
505 @param verbose: {True, False}
506
507 """
508 return map_onto_separate_mesh_traversals(
509 sequence_of_steps=concatenate_steps_of_species(species_sets, True),
510 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_ON_THE_FLY_SCATTERED_PARTICLE_STORAGE,
511 step_type=StepType.INITIALISATION,
512 verbose=verbose,
513 )
514
515
516def initialisation_steps_onto_separate_mesh_traversals_multiscale_sort_coalesced_memory(
517 species_sets,
518 verbose,
519):
520 """!
521
522 @see map_onto_separate_mesh_traversals()
523
524 @param concatenate_steps_of_species: [Species]
525 Sequence of particle species to be handled.
526
527 @param verbose: {True, False}
528
529 """
530 return map_onto_separate_mesh_traversals(
531 sequence_of_steps=concatenate_steps_of_species(species_sets, True),
532 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_COALESCED_PARTICLE_STORAGE,
533 step_type=StepType.INITIALISATION,
534 verbose=verbose,
535 )
536
537
538def initialisation_steps_onto_separate_mesh_traversals_bucket_sort_coalesced_memory(
539 species_sets,
540 verbose,
541):
542 """!
543
544 @see map_onto_separate_mesh_traversals()
545
546 @param concatenate_steps_of_species: [Species]
547 Sequence of particle species to be handled.
548
549 @param verbose: {True, False}
550
551 """
552 return map_onto_separate_mesh_traversals(
553 sequence_of_steps=concatenate_steps_of_species(species_sets, True),
554 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_ON_THE_FLY_COALESCED_PARTICLE_STORAGE,
555 step_type=StepType.INITIALISATION,
556 verbose=verbose,
557 )
558
559
560def particle_steps_onto_separate_mesh_traversals_multiscale_sort_scattered_memory(
561 species_sets,
562 verbose,
563):
564 """!
565
566 For a sequential ordering, i.e. 1:1 mapping of steps per species onto
567 traversals, it makes no real difference how we order the progress through
568 the individual steps. So I just concatenate the steps per species.
569
570 @see map_onto_separate_mesh_traversals()
571
572 @param concatenate_steps_of_species: [Species]
573 Sequence of particle species to be handled.
574
575 @param verbose: {True, False}
576
577 """
578 return map_onto_separate_mesh_traversals(
579 sequence_of_steps=concatenate_steps_of_species(species_sets, False),
580 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_SCATTERED_PARTICLE_STORAGE,
581 step_type=StepType.TIME_STEP,
582 verbose=verbose,
583 )
584
585
586def particle_steps_onto_separate_mesh_traversals_bucket_sort_scattered_memory(
587 species_sets,
588 verbose,
589):
590 """!
591
592 For a sequential ordering, i.e. 1:1 mapping of steps per species onto
593 traversals, it makes no real difference how we order the progress through
594 the individual steps. So I just concatenate the steps per species.
595
596 @see map_onto_separate_mesh_traversals()
597
598 @param concatenate_steps_of_species: [Species]
599 Sequence of particle species to be handled.
600
601 @param verbose: {True, False}
602
603 """
604 return map_onto_separate_mesh_traversals(
605 sequence_of_steps=concatenate_steps_of_species(species_sets, False),
606 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_ON_THE_FLY_SCATTERED_PARTICLE_STORAGE,
607 step_type=StepType.TIME_STEP,
608 verbose=verbose,
609 )
610
611
612
613def particle_steps_onto_separate_mesh_traversals_multiscale_sort_coalesced_memory(
614 species_sets,
615 verbose,
616):
617 """!
618
619 For a sequential ordering, i.e. 1:1 mapping of steps per species onto
620 traversals, it makes no real difference how we order the progress through
621 the individual steps. So I just concatenate the steps per species.
622
623 @see map_onto_separate_mesh_traversals()
624
625 @param concatenate_steps_of_species: [Species]
626 Sequence of particle species to be handled.
627
628 @param verbose: {True, False}
629
630 """
631 return map_onto_separate_mesh_traversals(
632 sequence_of_steps=concatenate_steps_of_species(species_sets, False),
633 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_WITH_LIFTS_AND_DROPS_COALESCED_PARTICLE_STORAGE,
634 step_type=StepType.TIME_STEP,
635 verbose=verbose,
636 )
637
638
639def particle_steps_onto_separate_mesh_traversals_bucket_sort_coalesced_memory(
640 species_sets,
641 verbose,
642):
643 """!
644
645 For a sequential ordering, i.e. 1:1 mapping of steps per species onto
646 traversals, it makes no real difference how we order the progress through
647 the individual steps. So I just concatenate the steps per species.
648
649 @see map_onto_separate_mesh_traversals()
650
651 @param concatenate_steps_of_species: [Species]
652 Sequence of particle species to be handled.
653
654 @param verbose: {True, False}
655
656 """
657 return map_onto_separate_mesh_traversals(
658 sequence_of_steps=concatenate_steps_of_species(species_sets, False),
659 particle_sorting_and_storage=ParticleSortingAndStorage.SORT_ON_THE_FLY_COALESCED_PARTICLE_STORAGE,
660 step_type=StepType.TIME_STEP,
661 verbose=verbose,
662 )
663
translate_one_step_of_species_into_mesh_traversal(step, current_species_set, mesh_traversals, alter_particle_position, use_continuous_particles_sequences, StepType step_type, verbose)
Translate one step of species into mesh traversal.
Definition Sequential.py:32