Peano
Loading...
Searching...
No Matches
LeapfrogFixedSearchRadius.py
Go to the documentation of this file.
1# This file is part of the SWIFT2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from swift2.particle.Particle import Particle
4from swift2.particle.AlgorithmStep import AlgorithmStep
5
6import peano4
7import dastgen2
9
10from abc import ABC
11import copy
12
13
15 """
16
17 Leapfrog ODE integrator
18
19 Simple particle with a fixed interaction radius h which moves according
20 to leapfrog KDK scheme.
21 By default, it uses global time stepping,
22 i.e. the combination of maximum velocity and minimal mesh size determines
23 the time step size of the subsequent time step. Besides the default
24 variables x and h, the particle has the following properties:
25
26 - a vector a which is the acceleration;
27 - a vector v which is the velocity.
28
29 You can add further properties via
30
31 myparticle.data.add_attribute( peano4.dastgen2.Peano4DoubleArray("myFancyArray","Dimensions") )
32
33 in your code. Or you can create a subclass which adds additional fields
34 after it has called the baseline constructor.
35
36 You will need to add further properties for any SPH project.
37
38 Study swift2.particle.ExplicitEulerFixedSearchRadius for further
39 information including all parameter documentation.
40
41 @param add_partid: Whether to add a particle ID.
42 Normally, that is done in the Particle super class if PeanoDebug > 0.
43 For certain tests however, a particle ID is required even in release mode.
44 So switch this on if you need it and are building release mode.
45
46 """
47
49 self,
50 name,
51 cfl_factor,
52 initial_time_step_size,
53 enter_cell_kernel="",
54 touch_particles_of_set_first_time_kernel="",
55 touch_particles_of_set_last_time_kernel="",
56 particles_per_cell=0,
57 min_h=0.005,
58 max_h=0.3,
59 add_partid=False,
60 ):
61 super(LeapfrogFixedSearchRadius, self).__init__(
62 name,
63 particles_per_cell,
64 min_h,
65 max_h,
66 )
67
68 self.cfl_factor = cfl_factor
69 self.initial_time_step_size = initial_time_step_size
70
71 # Particle attributes
74 self.data.add_attribute(self.velocity)
75 self.data.add_attribute(self.accelerator)
76
77 if add_partid:
78 self.partidpartid = dastgen2.attributes.Integer("partid", initval="0")
79 self.data.add_or_replace_attribute(self.partidpartid)
80
84
85 self.enter_cell_kernel = enter_cell_kernel
87 touch_particles_of_set_first_time_kernel
88 )
90 touch_particles_of_set_last_time_kernel
91 )
92
93 # Raises errors for 1D periodic BC test... leave it for now.
94 # self._add_dependency_checks()
95
96 return
97
98 @property
100 return self._algorithm_steps_dict[
101 "ForceCalculation"
102 ].touch_vertex_first_time_kernel
103
104 @touch_particles_of_set_first_time_kernel.setter
107 "ForceCalculation"
108 ].touch_vertex_first_time_kernel = value
109
110 @property
112 return self._algorithm_steps_dict[
113 "ForceCalculation"
114 ].touch_vertex_last_time_kernel
115
116 @touch_particles_of_set_last_time_kernel.setter
119 "ForceCalculation"
120 ].touch_vertex_last_time_kernel = value
121
122 @property
123 def cell_kernel(self):
124 return self._algorithm_steps_dict["ForceCalculation"].cell_kernel
125
126 @cell_kernel.setter
127 def cell_kernel(self, value):
128 self._algorithm_steps_dict["ForceCalculation"].cell_kernel = value
129
130 def add_to_reduction(self, value):
132 "ReduceGlobalQuantities"
133 ].unprepare_traversal_kernel += value
134
136 # function needs to exist for parent class
138
140 # function needs to exist for parent class
142
144 """!
145
146 Create a repository of algorithmic steps which are then
147 ordered into the actual time stepping sequence.
148
149 """
150
151 PARTICLE = self.namenamename
152 CFL_FACTOR = self.cfl_factor
153 TIME_STEP_SIZE = self.initial_time_step_size
154
156 "ForceCalculation": AlgorithmStep(
157 name="ForceCalculation",
158 dependencies=AlgorithmStep.Dependencies.NEIGHBOURS,
159 effect=AlgorithmStep.Effect.ALTER_LOCAL_STATE,
160 touch_vertex_first_time_kernel="",
161 cell_kernel="",
162 touch_vertex_last_time_kernel="",
163 ),
164 "Kick1": AlgorithmStep(
165 name="Kick1",
166 dependencies=AlgorithmStep.Dependencies.SELF,
167 effect=AlgorithmStep.Effect.ALTER_LOCAL_STATE,
168 touch_vertex_first_time_kernel=f"""
169 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
170 ::swift2::kernels::forAllParticles(marker,
171 assignedParticles,
172 numberOfCoalescedAssignedParticles,
173 ::swift2::timestepping::leapfrogKickWithGlobalTimeStepSize<globaldata::{PARTICLE}>,
174 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>);
175 // end template
176 """,
177 includes="""
178 #include "swift2/timestepping/Leapfrog.h"
179 #include "swift2/timestepping/GlobalTimeStepping.h"
180 #include "swift2/timestepping/TimeStepping.h"
181 """,
182 ),
183 "Drift": AlgorithmStep(
184 name="Drift",
185 dependencies=AlgorithmStep.Dependencies.SELF,
186 effect=AlgorithmStep.Effect.CHANGE_POSITION_OR_INTERACTION_RADIUS,
187 touch_vertex_first_time_kernel=f"""
188 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
189 ::swift2::kernels::forAllParticles(
190 marker,
191 assignedParticles,
192 numberOfCoalescedAssignedParticles,
193 ::swift2::timestepping::resetMovedParticleMarker<globaldata::{PARTICLE}>,
194 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>);
195 // end template
196 """,
197 touch_vertex_last_time_kernel=f"""
198 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
199 auto oldParticlePositions = ::toolbox::particles::assignmentchecks::recordParticlePositions(assignedParticles);
200
201 ::swift2::kernels::forAllParticles(
202 marker,
203 assignedParticles,
204 numberOfCoalescedAssignedParticles,
205 ::swift2::timestepping::leapfrogDriftWithGlobalTimeStepSize<globaldata::{PARTICLE}>,
206 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>
207 );
208
209 ::toolbox::particles::assignmentchecks::traceParticleMovements(assignedParticles, oldParticlePositions, marker.x(), marker.h(), _spacetreeId);
210 // end template
211 """,
212 includes="""
213 #include "swift2/timestepping/Leapfrog.h"
214 #include "swift2/timestepping/GlobalTimeStepping.h"
215 #include "swift2/timestepping/TimeStepping.h"
216 """,
217 cell_kernel_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_MayOverwritePreviousCellUpdatesFromSameSweep_FutureStagesMayUpdate",
218 touch_vertex_first_time_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_FutureStagesMayUpdate",
219 touch_vertex_last_time_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce",
220 ),
221 "Kick2": AlgorithmStep(
222 name="Kick2",
223 dependencies=AlgorithmStep.Dependencies.SELF,
224 effect=AlgorithmStep.Effect.ALTER_LOCAL_STATE,
225 touch_vertex_first_time_kernel=f"""
226 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
227 ::swift2::kernels::forAllParticles(
228 marker,
229 assignedParticles,
230 numberOfCoalescedAssignedParticles,
231 ::swift2::timestepping::resetMovedParticleMarker<globaldata::{PARTICLE}>,
232 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>);
233
234 ::swift2::kernels::forAllParticles(marker,
235 assignedParticles,
236 numberOfCoalescedAssignedParticles,
237 ::swift2::timestepping::leapfrogKickWithGlobalTimeStepSize<globaldata::{PARTICLE}>,
238 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>);
239 // end template
240 """,
241 includes="""
242 #include "swift2/timestepping/Leapfrog.h"
243 #include "swift2/timestepping/GlobalTimeStepping.h"
244 #include "swift2/timestepping/TimeStepping.h"
245 """,
246 touch_vertex_first_time_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_MayOverwritePreviousCellUpdatesFromSameSweep",
247 cell_kernel_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_MayOverwritePreviousCellUpdatesFromSameSweep",
248 ),
249 "ReduceVelocityAndDetermineTimeStepSize": AlgorithmStep(
250 name="ReduceVelocityAndDetermineTimeStepSize",
251 dependencies=AlgorithmStep.Dependencies.SELF,
252 effect=AlgorithmStep.Effect.ALTER_GLOBAL_STATE,
253 prepare_traversal_kernel=f"""
254 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
255 ::swift2::timestepping::computeAdmissibleTimeStepSizeFromGlobalMeshSizeAndMaximumVelocity<globaldata::{PARTICLE}>({CFL_FACTOR},{TIME_STEP_SIZE});
256 // end template
257 """,
258 includes="""
259 #include "swift2/timestepping/Euler.h"
260 #include "swift2/timestepping/GlobalTimeStepping.h"
261 #include "swift2/timestepping/TimeStepping.h"
262 """,
263 ),
264 "ReduceGlobalQuantities": AlgorithmStep(
265 name="ReduceGlobalQuantities",
266 dependencies=AlgorithmStep.Dependencies.SELF,
267 effect=AlgorithmStep.Effect.ALTER_GLOBAL_STATE,
268 touch_vertex_first_time_kernel=f"""
269 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
270 ::swift2::kernels::forAllParticles(
271 marker,
272 assignedParticles,
273 numberOfCoalescedAssignedParticles,
274 ::swift2::statistics::reduceVelocityAndSearchRadius<globaldata::{PARTICLE}>,
275 ::swift2::kernels::alwaysUpdateInVertexKernel<globaldata::{PARTICLE}>);
276 // end template
277 """,
278 prepare_traversal_kernel=f"""
279 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
280 globaldata::{PARTICLE}::getSpecies().clearSearchRadius();
281 globaldata::{PARTICLE}::getSpecies().clearVelocity();
282 // end template
283 """,
284 unprepare_traversal_kernel=f"""
285 // Template in python/swift2/particle/LeapfrogFixedSearchRadius.py
286 globaldata::{PARTICLE}::getSpecies().allReduce();
287 globaldata::{PARTICLE}::getSpecies().setTimeStamp( globaldata::{PARTICLE}::getSpecies().getMinTimeStamp() + globaldata::{PARTICLE}::getSpecies().getMinTimeStepSize(), false );
288 ::swift2::statistics::reportSearchRadiusVTDt<globaldata::{PARTICLE}>( "{PARTICLE}" );
289 // end template
290 """,
291 includes="""
292 #include "swift2/statistics/Reports.h"
293 #include "swift2/statistics/Statistics.h"
294 """,
295 ),
296 "FirstInitParticle": AlgorithmStep(
297 name="FirstInitParticle",
298 dependencies=AlgorithmStep.Dependencies.SELF,
299 effect=AlgorithmStep.Effect.CHANGE_POSITION_OR_INTERACTION_RADIUS,
300 touch_vertex_last_time_kernel="",
301 includes="",
302 cell_kernel_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_MayOverwritePreviousCellUpdatesFromSameSweep_FutureStagesMayUpdate",
303 touch_vertex_first_time_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce_FutureStagesMayUpdate",
304 touch_vertex_last_time_dependency_policy="TouchAtLeastOnce_AllPreviousStepsUpdateAtLeastOnce",
305 ),
306 }
307
309 """!
310
311 Create algorithm steps behind leapfrog
312
313 Leapfrog consists basically of four steps per particle. We first
314 determine the force. Then we update the velocity by half a timestep and move
315 the particle by a full timestep. Then the force is re-computed and the
316 second half of the velocity update is done.
317 Some variations of this KDK form re-arrange the steps executed per timestep
318 to avoid a second force loop.
319
320 """
321
322 steps = [
323 self._algorithm_steps_dict["ForceCalculation"],
324 self._algorithm_steps_dict["ReduceVelocityAndDetermineTimeStepSize"],
325 self._algorithm_steps_dict["Kick1"],
326 self._algorithm_steps_dict["Drift"],
327 self._algorithm_steps_dict["Kick2"],
328 self._algorithm_steps_dict["ReduceGlobalQuantities"],
329 ]
330 # make a copy of the steps, so if you modify them later (e.g. by
331 # adding dependency checks), it won't modify the steps in the dict.
332 self._algorithm_steps_algorithm_steps = [copy.deepcopy(i) for i in steps]
333 return
334
336 """!
337
338 Technically nothing really required, but
339
340 """
341
342 steps = [self._algorithm_steps_dict["FirstInitParticle"]]
343 self._initialisation_steps_initialisation_steps = [copy.deepcopy(i) for i in steps]
344
345 @property
347 return (
348 super(LeapfrogFixedSearchRadius, self).readme_descriptor
349 + """
350
351 Time integrator: Leapfrog
352
353 - search radius: fixed
354 - CFL factor: """
355 + str(self.cfl_factor)
356 + """
357 - dt_initial: """
358 + str(self.initial_time_step_size)
359 + """
360
361 """
362 )
Specialisation of array using Peano's tarch.
Defines the meta data around one algorithmic step per particle.
algorithm_steps(self)
Return sequence of algorithm steps that have to be called per time step.
_setup_algorithm_steps_dict(self)
Create a repository of algorithmic steps which are then ordered into the actual time stepping sequenc...
__init__(self, name, cfl_factor, initial_time_step_size, enter_cell_kernel="", touch_particles_of_set_first_time_kernel="", touch_particles_of_set_last_time_kernel="", particles_per_cell=0, min_h=0.005, max_h=0.3, add_partid=False)
Initialise the particle.
initialisation_steps(self)
Return sequence of algorithm steps that have to be performed throughout initialisation.
_setup_initialisation_steps(self)
Technically nothing really required, but.
Base class for any particle in the project.
Definition Particle.py:10