Peano
Loading...
Searching...
No Matches
SPHParticle.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
10import abc
11import copy
12
13
14from enum import Enum
15
16
18 """!
19
20 The SPH particle base class. Contains the bare minimum of data
21 required for the base algorithm, in particular the neighboursearch/
22 smoothing length computation, to work. Actual SPH implementations
23 should inherit these properties from this class.
24 Note that this base class contains no algorithm steps. The derived
25 classes will have to implement that individually.
26
27 The data contained in this super class are:
28
29 General simulation data:
30 - CFL factor
31 - initial time step size
32 - hydro dimension
33
34 Smoothing length related global simulation parameters:
35 - eta factor (resolution eta, which determines number of neighbours)
36 - max h iterations
37 - h_min
38 - h_max
39 - h_tolerance: Convergence criterion for smoothing length iteration
40
41 Implementation specifics:
42 - particle interaction kernel realisation
43 - swift project namespace
44
45 Particle Data:
46 - mass
47 - velocity
48 - acceleration
49 - density
50 - pressure
51 - smoothing length
52 - specific internal energy u
53 - time derivative of specific internal energy uDot
54
55 Smoothing lenght related particle fields:
56 - wcount : Neighbour weight number
57 - wcount_dh : derivative of eighbour weight number w.r.t smoothing length
58 - hDot: derivative of smoothing length w.r.t. time
59 - f: a collected factor required for sml computation
60 - sml_iteration_count
61
62 Additional Particle fields
63 - hasNoNeighbours: Flag whether particle has no neighbours
64
65
66 ## Attributes
67
68 name: String
69 To be in line with other conventions, I recommend you start with an
70 uppercase letter. This has to be a valid C++ identifier, i.e. don't
71 use any special symbols besides an underscore.
72
73 ## Vectorisation
74
75 This type can be used with aggressively optimised kernels if you follow
76 @ref page_swift_performance_optimisation Performance optimisation and use
77 the map_particle_steps_onto_separate_mesh_traversals_insert_dummy_sweeps_for_coalesced_memory_access
78 graph compiler from the Sequential suite; or literally any other
79 flavour which yields coalesced memory.
80
81
82 @see peano4::datamanagement::CellMarker
83 @see peano4::datamanagement::VertexMarker
84
85 """
86
88 self,
89 name,
90 dimensions_hydro=2,
91 cfl_factor=0.1,
92 initial_time_step_size=1e-4,
93 constant_time_step_size=True,
94 swift_project_namespace="SPH",
95 particles_per_cell=0, # makes no sense, and should likely be forbidden
96 min_h=0.3,
97 max_h=0.3,
98 ):
99 super(SPHParticle, self).__init__(
100 name,
101 particles_per_cell,
102 min_h,
103 max_h,
104 )
105
106 # Initialize default parameters.
107 # ---------------------------------------
108
109 self._sph_flavour = "none"
110
111 # Simulation properties
112 self._cfl_factor = cfl_factor
113 self._initial_time_step_size = initial_time_step_size
114 self._constant_time_step_size = constant_time_step_size
115
116 # SPH parameters (default values)
117 self._hydro_dimensions = dimensions_hydro
118
119 # resolution eta. Determines the number of neighbours considered
120 self._eta_factor = 1.2348
121
122 # Maximal number of smoothing length iterations
124
125 # TODO: these values should probably not be hardcoded like this.
126 # But it's good enough for the elementary tests and benchmarks
127 # we have for now.
128 self._h_hydro_min = 1e-6
130 1.0 / 3.0 / 2.0
131 ) # Approximated value for coarsest grid level
132 self._h_tolerance = 1e-4
133
134 # Project namespace to have consistent use of exported Constants in kernels
135 # Not used right now.
136 self._swift_project_namespace = swift_project_namespace
137
138 # now set these parameters as dastgen attributes
139 # self.set_parameters()
140 # NOTE: derived classes should do this at this point. But not this
141 # super class - the reason being that when instantiated as an object
142 # of the subclass type, this line will call the subclass' set_parameters()
143 # method, which will try to set parameters that aren't set yet.
144 # So don't call this here, but make sure to include a super class' invocation
145 # of set_parameters() in your subclass' set_parameters() definition.
146
147 # Construct particle properties
148 # --------------------------------
149
150 # Baseline particle properties -------------------------------------------------
154 self.data.add_attribute(self.mass)
155 self.data.add_attribute(self.velocity)
156 self.data.add_attribute(self.acceleration)
157
158 # Basic SPH properties
161 # Make sure to initialize SML to zero, not possibly some random value.
162 # Will be checked to see whether ICs have modified it.
163 self.smoothL = dastgen2.attributes.Double("smoothingLength", initval=0.0)
166 self.data.add_attribute(self.density)
167 self.data.add_attribute(self.pressure)
168 self.data.add_attribute(self.smoothL)
169 self.data.add_attribute(self.u)
170 self.data.add_attribute(self.uDot)
171
172 # Extended arrays for time integration consistency
173 self.v_full = peano4.dastgen2.Peano4DoubleArray("v_full", "Dimensions")
175 self.data.add_attribute(self.v_full)
176 self.data.add_attribute(self.u_full)
177
178 # Variable smoothing length scheme ---------------------------------------------
185 "smoothingLengthIterCount"
186 )
189 self.data.add_attribute(self.wcount)
190 self.data.add_attribute(self.wcount_dh)
191 self.data.add_attribute(self.f)
192 self.data.add_attribute(self.hDot)
193 self.data.add_attribute(self.rho_dh)
194 self.data.add_attribute(self.sml_iteration_count)
195 self.data.add_attribute(self.sml_iter_left_bound)
196 self.data.add_attribute(self.sml_iter_right_bound)
197
198 # Extra ------------------------------------------------------------------------
201 "smoothingLengthConverged", initval="false"
202 )
204 "densityNeighbourCount", ifdefs=["PeanoDebug > 0"]
205 )
207 "forceNeighbourCount", ifdefs=["PeanoDebug > 0"]
208 )
209 self.data.add_attribute(self.has_no_neighbours)
210 self.data.add_attribute(self.sml_converged)
211 self.data.add_attribute(self.density_neighbourcount)
212 self.data.add_attribute(self.force_neighbourcount)
213
214 return
215
216 def set_parameters(self):
217 """!
218 This function translates "global" particle parameters which are
219 constant throughout the simulation (like CFL factor, minimal time step
220 size, viscosity parameters...) into dastgen attributes of the C++
221 particle class.
222 If you modify any of the attributes manually outside of the particle
223 initialisation, e.g. by invoking
224
225 ```
226 particle = SPHParticle(initial_time_step_size=ABC, ...)
227 particle.initial_time_step_size = XYZ
228 ```
229
230 you need to call this function manually so your changes propagate
231 into the generated C++ files.
232 """
233
234 const_static = dastgen2.attributes.Attribute.Qualifier.CONST_STATIC
235
237 "cfl", qualifier=const_static, initval=self._cfl_factor
238 )
239 self.data.add_or_replace_attribute(cfl_attr)
240
241 initial_time_step_size_attr = dastgen2.attributes.Double(
242 "initialTimeStepSize",
243 qualifier=const_static,
244 initval=self._initial_time_step_size,
245 )
246 self.data.add_or_replace_attribute(initial_time_step_size_attr)
247
249 adjustTimeStepSize = "false"
250 else:
251 adjustTimeStepSize = "true"
252 adjust_time_step_size_attr = dastgen2.attributes.Boolean(
253 "adjustTimeStepSize", qualifier=const_static, initval=adjustTimeStepSize
254 )
255 self.data.add_or_replace_attribute(adjust_time_step_size_attr)
256
257 hydro_dimensions_attr = dastgen2.attributes.Double(
258 "hydroDimensions", qualifier=const_static, initval=self._hydro_dimensions
259 )
260 self.data.add_or_replace_attribute(hydro_dimensions_attr)
261
262 eta_factor_attr = dastgen2.attributes.Double(
263 "etaFactor", qualifier=const_static, initval=self._eta_factor
264 )
265 self.data.add_or_replace_attribute(eta_factor_attr)
266
267 h_hydro_min_attr = dastgen2.attributes.Double(
268 "smlMin", qualifier=const_static, initval=self._h_hydro_min
269 )
270 self.data.add_or_replace_attribute(h_hydro_min_attr)
271
272 h_hydro_max_attr = dastgen2.attributes.Double(
273 "smlMax", qualifier=const_static, initval=self._h_hydro_max
274 )
275 self.data.add_or_replace_attribute(h_hydro_max_attr)
276
277 h_tolerance_attr = dastgen2.attributes.Double(
278 "smlTolerance", qualifier=const_static, initval=self._h_tolerance
279 )
280 self.data.add_or_replace_attribute(h_tolerance_attr)
281
282 h_max_iterations_attr = dastgen2.attributes.Integer(
283 "smlMaxIterations", qualifier=const_static, initval=self._h_max_iterations
284 )
285 self.data.add_or_replace_attribute(h_max_iterations_attr)
286
287 return
288
289 @abc.abstractmethod
291 """!
292 Set up the internal list of algorithm steps for this particle.
293 We need to maintain an individual instance of this list for cases
294 where we modify the algorithm steps later on. This can happen for
295 example when adding debugging/dependency checks later on.
296
297
298 The algorithm steps shall be a list of AlgorithmStep objects to be
299 executed in that order.
300
301 Definitions of the algorithm steps stored in the algorithm_steps_dict are
302 placed in get_algorithm_steps_dict(self). The dict is set up during
303 instantiation of this class, and reads in all available algorithm steps
304 defined in AlgorithmStepLibrary.py.
305 """
306 return
307
309 """!
310
311 Return algorithm steps: A list of AlgorithmStep objects to be executed in
312 that order for this particle.
313
314 Make sure that self._setup_algorithm_steps_dict() and
315 self._setup_algorithm_steps() have been called before using this function.
316
317 """
318
319 return self._algorithm_steps
320
321 @abc.abstractmethod
323 """
324 Define the algorithm steps to be taken during initialization here.
325 This follows the same logic as _setup_algorithm_steps. See documentation
326 there for more info.
327
328 Make sure self._setup_algorithm_steps_dict() has been called before.
329
330 Every derived class must implement this function depending on its own
331 requirements.
332 """
333 return
334
336 """
337 Return the list of algorithm steps to be executed during initialisation.
338 Make sure self._setup_algorithm_steps_dict() and self._setup_initialisation_steps() have been called before.
339
340 Every derived class must implement this function depending on its own
341 requirements.
342 """
343 return self._initialisation_steps
344
345 @property
347 """!
348 Forbid users to modify hydro dimensions on-the-fly.
349 """
350 return self._hydro_dimensions
351
352 @hydro_dimensions.setter
353 def hydro_dimensions(self, hydro_dimensions):
354 raise ValueError(
355 "Can't change hydro_dimensions now. Modify it while instantiating the class."
356 )
357
358 @property
359 def eta_factor(self):
360 """!
361
362 Set the eta factor used by the SPH kernel to target a certain number of
363 neighbour particles.
364 The default value is eta = 1.2348.
365
366 """
367 return self._eta_factor
368
369 @eta_factor.setter
370 def eta_factor(self, eta_factor):
371 if eta_factor <= 0:
372 raise ValueError("SPH eta factor value not valid.")
373 self._eta_factor = eta_factor
374
375 @property
376 def h_hydro_min(self):
377 """
378
379 Set the limits allowed for the SPH smoothing length. Notice that the max value
380 is bounded by Peano's search radius as h_max = R_search_max = max_grid_size /
381 gamma_k, where gamma_k is the SPH kernel factor that relates h and H.
382 Typically gamma_k = 2, so h_max = max_grid_size / 2.
383
384 """
385 return self._h_hydro_min
386
387 @h_hydro_min.setter
388 def h_hydro_min(self, h_hydro_min):
389 if h_hydro_min > self._h_hydro_max:
390 raise ValueError("Min value of smoothing length larger than max allowed.")
391 self._h_hydro_min = h_hydro_min
392
393 @property
394 def h_hydro_max(self):
395 return self._h_hydro_max
396
397 @h_hydro_max.setter
398 def h_hydro_max(self, h_hydro_max):
399 if h_hydro_max < self._h_hydro_min:
400 raise ValueError("max value of smoothing length smaller than min allowed.")
401 self._h_hydro_max = h_hydro_max
402
403 @property
404 def h_tolerance(self):
405 """
406
407 Tolerance for Newton-Raphson convergence criterion.
408
409 """
410 return self._h_tolerance
411
412 @h_tolerance.setter
413 def h_tolerance(self, h_tolerance):
414 if h_tolerance > 1:
415 raise ValueError("Value of h_tolerance cannot be larger than 1.")
416 self._h_tolerance = h_tolerance
417
418 @property
420 """
421 Max number of iterations to adapt the SPH smoothing length
422 """
423 return self._h_max_iterations
424
425 @h_max_iterations.setter
426 def h_max_iterations(self, h_max_iterations):
427 if h_max_iterations > 50:
428 raise ValueError("Value of h_max_iterations is too large.")
429 self._h_max_iterations = h_max_iterations
430
431 @property
432 def mantissa_size(self):
433 """
434
435 Set the mantissa size of doubles and Peano double arrays if
436 we want to use reduced precission via Clang annotations. As a reference,
437 floats have mantissa size = 23.
438
439 """
440 return self._mantissa_size
441
442 @mantissa_size.setter
443 def mantissa_size(self, mantissa_size):
444 if mantissa_size < 0:
445 raise ValueError("Mantissa size has to be larger than 0.")
446 self._mantissa_size = mantissa_size
447
449 """
450
451 Transform namespace into cpp format. Could be used to append namespace to
452 constants in kernels (not used currently).
453
454 """
455 namespace = "::".join(self._swift_project_namespace) + "::"
456
457 print(namespace)
458
459 @property
460 @abc.abstractmethod
462 return super(SPHParticle, self).readme_descriptor
463
464
466 new_namespace,
467 old_namespace = "::swift2::kernels::"
468 ):
469 """!
470
471 Switch the prefix (namespace) of all particle iterators
472
473 Run through all iterators/kernels and replace the iterator namespaces. This
474 is a simple text replacement and should be used with care. Usually, we may
475 assume that an algorithm step does already pick a proper realisation by
476 default, but you might want to change this default behaviour. The problem
477 is that you will overwrite any bespoke choice, i.e. if a particle species
478 developer has carefully ported some kernels to the GPU but others not, you
479 overwrite these decisions maybe and switch to a different implementation.
480
481 The realisation is very simple: We run over all algorithm steps and replace
482 all "forAll" function calls with the leading namespace old_namespace with
483 a new namespace.
484
485 @param new_namespace: String
486 Please ensure that it starts with :: (to avoid namespace confusion) and
487 ends with ::, too.
488
489 """
490 for algorithm_step in self._algorithm_steps:
491 algorithm_step.cell_kernel = algorithm_step.cell_kernel.replace( old_namespace + "forAll", new_namespace + "forAll" )
492 algorithm_step.touch_vertex_first_time_kernel = algorithm_step.touch_vertex_first_time_kernel.replace( old_namespace + "forAll", new_namespace + "forAll" )
493 algorithm_step.touch_vertex_last_time_kernel = algorithm_step.touch_vertex_last_time_kernel.replace( old_namespace + "forAll", new_namespace + "forAll" )
494
495
496
cardinality is a string (you can thus use symbols as well as long as they will be defined at compile ...
Definition Double.py:6
Specialisation of dastgen2.attributes.DoubleArray which relies on Peano's tarch.
Base class for any particle in the project.
Definition Particle.py:10
The SPH particle base class.
h_max_iterations(self)
Max number of iterations to adapt the SPH smoothing length.
_setup_initialisation_steps(self)
Define the algorithm steps to be taken during initialization here.
h_hydro_min(self)
Set the limits allowed for the SPH smoothing length.
__init__(self, name, dimensions_hydro=2, cfl_factor=0.1, initial_time_step_size=1e-4, constant_time_step_size=True, swift_project_namespace="SPH", particles_per_cell=0, min_h=0.3, max_h=0.3)
Initialise the particle.
eta_factor(self)
Set the eta factor used by the SPH kernel to target a certain number of neighbour particles.
get_cpp_namespace_from_project_namespace(self)
Transform namespace into cpp format.
h_tolerance(self)
Tolerance for Newton-Raphson convergence criterion.
algorithm_steps(self)
Return algorithm steps: A list of AlgorithmStep objects to be executed in that order for this particl...
_setup_algorithm_steps(self)
Set up the internal list of algorithm steps for this particle.
mantissa_size(self)
Set the mantissa size of doubles and Peano double arrays if we want to use reduced precission via Cla...
initialisation_steps(self)
Return the list of algorithm steps to be executed during initialisation.
hydro_dimensions(self)
Forbid users to modify hydro dimensions on-the-fly.
set_parameters(self)
This function translates "global" particle parameters which are constant throughout the simulation (l...
switch_namespace_of_all_particle_iterators(self, new_namespace, old_namespace="::swift2::kernels::")
Switch the prefix (namespace) of all particle iterators.