Peano
Loading...
Searching...
No Matches
UpdateParticle_SingleLevelInteraction_ContiguousParticles.py
Go to the documentation of this file.
1# This file is part of the Peano project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from peano4.solversteps.ActionSet import ActionSet
4
5import jinja2
6
7
10 self,
11 particle_set,
12 particle_cell_update_kernel=None,
13 touch_vertex_first_time_compute_particle_update_kernel=None,
14 touch_vertex_last_time_compute_particle_update_kernel=None,
15 prepare_traversal_kernel="",
16 unprepare_traversal_kernel="",
17 additional_includes="",
18 active_particle_set=None,
19 ):
20 """!
21
22 Update particles without non-local interaction
23
24 This action set is very similar to UpdateParticle_SingleLevelInteraction,
25 but it assumes that data are stored @ref toolbox_particles_memorypool "continuously in memory".
26 Therefore, we can provide meta information how many particles we have per
27 vertex stored en bloc.
28
29 Per cell, there's a @f$ 2^d @f$ vector over integers called
30 numberOfActiveParticles. It encodes how many particles are contributed
31 towards the active set from each vertex. If you employ contiguous particle
32 storage schemes, you can loop over this integer range rather than the
33 particle set, and you can exploit the fact that data within the index set
34 is contigous.
35
36 A cell update then resembles
37
38 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 auto localParticlesIterator = activeParticles.begin();
40 // There is some parallelism here if you wanna exploit it
41 for (int vertex=0; vertex<TwoPowerD; vertex++) {
42 auto* firstParticle = *localParticlesIterator;
43 std::advance( localParticlesIterator, numberOfActiveParticles[vertex] );
44 // This loop encodes vector-level parallelism (SIMD)
45 for (int currentParticleNo = 0; currentParticleNo < numberOfActiveParticles[vertex]; currentParticleNo++) {
46 doSomethingFancy( firstParticle+currentParticleNo );
47 }
48 }
49 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50
51
52 A vertex update resembles
53 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 auto* firstParticle = *localParticles.begin();
55 // This loop encodes vector-level parallelism (SIMD)
56 for (int currentParticleNo = 0; currentParticleNo < numberOfActiveParticles; currentParticleNo++) {
57 doSomethingFancy( firstParticle+currentParticleNo );
58 }
59 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60
61 ## Validity if particles change their position of cut-off radius
62
63 If particles change their position or cut-off radius, you have to resort
64 them. See also UpdateParticle_MultiLevelInteraction_StackOfLists_ContiguousParticles
65 for a discussion of the data validity.
66
67
68 """
69 super(UpdateParticle_SingleLevelInteraction_ContiguousParticles, self).__init__(
70 descend_invocation_order=1, parallel=False
71 )
72
73 self._particle_set = particle_set
74 self.d = {}
75 self.d["LOCAL_PARTICLE"] = particle_set.particle_model.name
76 self.d["LOCAL_PARTICLES_CONTAINER"] = particle_set.name
77 if active_particle_set == None:
78 self.d["ACTIVE_PARTICLE"] = particle_set.particle_model.name
79 self.d["ACTIVE_PARTICLES_CONTAINER"] = particle_set.name
80 else:
81 self.d["ACTIVE_PARTICLE"] = active_particle_set.particle_model.name
82 self.d["ACTIVE_PARTICLES_CONTAINER"] = active_particle_set.name
83 self.d["PARTICLE_CELL_UPDATE_KERNEL"] = particle_cell_update_kernel
84 self.d[
85 "TOUCH_VERTEX_FIRST_COMPUTE_KERNEL"
86 ] = touch_vertex_first_time_compute_particle_update_kernel
87 self.d[
88 "TOUCH_VERTEX_LAST_COMPUTE_KERNEL"
89 ] = touch_vertex_last_time_compute_particle_update_kernel
90 self.d["ADDITIONAL_INCLUDES"] = additional_includes
91 self.d["PREPARE_TRAVERSAL_KERNEL"] = prepare_traversal_kernel
92 self.d["UNPREPARE_TRAVERSAL_KERNEL"] = unprepare_traversal_kernel
93
94 __Template_TouchVertexFirstTime = jinja2.Template(
95 """
96 {% if TOUCH_VERTEX_FIRST_COMPUTE_KERNEL!=None %}
97 auto& assignedParticles = fineGridVertex{{LOCAL_PARTICLES_CONTAINER}};
98 const int numberOfCoalescedAssignedParticles = fineGridVertex{{LOCAL_PARTICLES_CONTAINER}}.isGathered() ? fineGridVertex{{LOCAL_PARTICLES_CONTAINER}}.size() : -1;
99
100 {{TOUCH_VERTEX_FIRST_COMPUTE_KERNEL}}
101 {% endif %}
102"""
103 )
104
105 __Template_TouchVertexLastTime = jinja2.Template(
106 """
107 {% if TOUCH_VERTEX_LAST_COMPUTE_KERNEL!=None %}
108 auto& assignedParticles = fineGridVertex{{LOCAL_PARTICLES_CONTAINER}};
109 const int numberOfCoalescedAssignedParticles = fineGridVertex{{LOCAL_PARTICLES_CONTAINER}}.isGathered() ? fineGridVertex{{LOCAL_PARTICLES_CONTAINER}}.size() : -1;
110
111 {{TOUCH_VERTEX_LAST_COMPUTE_KERNEL}}
112 {% endif %}
113"""
114 )
115
116 __Template_TouchCellFirstTime = jinja2.Template(
117 """
118 {% if PARTICLE_CELL_UPDATE_KERNEL!=None %}
119 std::list< globaldata::{{LOCAL_PARTICLE}}* > localParticles;
120 std::list< globaldata::{{ACTIVE_PARTICLE}}* > _activeParticles;
121 std::vector< int > numberOfCoalescedLocalParticlesPerVertex( TwoPowerD );
122 std::vector< int > _numberOfActiveParticlesPerVertex( TwoPowerD ); // stay compatible with coalesced version
123 auto& numberOfCoalescedActiveParticlesPerVertex = _numberOfActiveParticlesPerVertex;
124 auto& activeParticles = _activeParticles;
125
126 for (int i=0; i<TwoPowerD; i++) {
127 numberOfCoalescedActiveParticlesPerVertex[i] = fineGridVertices{{ACTIVE_PARTICLES_CONTAINER}}(i).size();
128 for (auto* p: fineGridVertices{{ACTIVE_PARTICLES_CONTAINER}}(i) ) {
129 activeParticles.push_front( p );
130 }
131 numberOfCoalescedLocalParticlesPerVertex[i] = fineGridVertices{{LOCAL_PARTICLES_CONTAINER}}(i).size();
132 for (auto* p: fineGridVertices{{LOCAL_PARTICLES_CONTAINER}}(i) ) {
133 localParticles.push_front( p );
134 }
135 }
136
137 {{PARTICLE_CELL_UPDATE_KERNEL}}
138 {% endif %}
139"""
140 )
141
142 def get_body_of_operation(self, operation_name):
143 result = "\n"
144 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
145 result = self.__Template_TouchCellFirstTime.render(**self.d)
146 if operation_name == ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
147 result = self.__Template_TouchVertexFirstTime.render(**self.d)
148 if operation_name == ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
149 result = self.__Template_TouchVertexLastTime.render(**self.d)
150 return result
151
153 return " return std::vector< peano4::grid::GridControlEvent >();\n"
154
156 return self.d["PREPARE_TRAVERSAL_KERNEL"]
157
159 return self.d["UNPREPARE_TRAVERSAL_KERNEL"]
160
162 return __name__.replace(".py", "").replace(".", "_")
163
165 return False
166
167 def get_includes(self):
168 result = jinja2.Template(
169 """
170#include "toolbox/particles/particles.h"
171#include "vertexdata/{{LOCAL_PARTICLES_CONTAINER}}.h"
172#include "globaldata/{{LOCAL_PARTICLE}}.h"
173#include "vertexdata/{{ACTIVE_PARTICLES_CONTAINER}}.h"
174#include "globaldata/{{ACTIVE_PARTICLE}}.h"
175
176{{ADDITIONAL_INCLUDES}}
177
178#include <list>
179"""
180 )
181 return result.render(**self.d)
182
183 def get_attributes(self):
184 return """
185 int _spacetreeId;
186"""
187
189 return """
190 _spacetreeId = treeNumber;
191 """
Action set (reactions to events)
Definition ActionSet.py:6
__init__(self, particle_set, particle_cell_update_kernel=None, touch_vertex_first_time_compute_particle_update_kernel=None, touch_vertex_last_time_compute_particle_update_kernel=None, prepare_traversal_kernel="", unprepare_traversal_kernel="", additional_includes="", active_particle_set=None)
Update particles without non-local interaction.