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 std::vector< bool > localParticleIsContainedInCell;
124 auto& numberOfCoalescedActiveParticlesPerVertex = _numberOfActiveParticlesPerVertex;
125 auto& activeParticles = _activeParticles;
126
127 for (int i=0; i<TwoPowerD; i++) {
128 numberOfCoalescedActiveParticlesPerVertex[i] = fineGridVertices{{ACTIVE_PARTICLES_CONTAINER}}(i).size();
129 for (auto* p: fineGridVertices{{ACTIVE_PARTICLES_CONTAINER}}(i) ) {
130 activeParticles.push_front( p );
131 }
132 numberOfCoalescedLocalParticlesPerVertex[i] = fineGridVertices{{LOCAL_PARTICLES_CONTAINER}}(i).size();
133 for (auto* p: fineGridVertices{{LOCAL_PARTICLES_CONTAINER}}(i) ) {
134 std::bitset<TwoPowerD> mask = 0;
135 mask.set(TwoPowerD-i-1);
136 bool isLocal = (mask & p->getContainedInAdjacentCell()).any();
137 assertionEquals4(
138 isLocal,
139 marker.isContained( p->getX(), toolbox::particles::internal::relativeGrabOwnershipSpatialSortingTolerance( marker.h() ) * tarch::la::NUMERICAL_ZERO_DIFFERENCE ),
140 marker.toString(), p->toString(), i, mask
141 );
142 localParticleIsContainedInCell.push_back( isLocal );
143 localParticles.push_front( p );
144 }
145 }
146
147 {{PARTICLE_CELL_UPDATE_KERNEL}}
148 {% endif %}
149"""
150 )
151
152 def get_body_of_operation(self, operation_name):
153 result = "\n"
154 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
155 result = self.__Template_TouchCellFirstTime.render(**self.d)
156 if operation_name == ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
157 result = self.__Template_TouchVertexFirstTime.render(**self.d)
158 if operation_name == ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
159 result = self.__Template_TouchVertexLastTime.render(**self.d)
160 return result
161
163 return " return std::vector< peano4::grid::GridControlEvent >();\n"
164
166 return self.d["PREPARE_TRAVERSAL_KERNEL"]
167
169 return self.d["UNPREPARE_TRAVERSAL_KERNEL"]
170
172 return __name__.replace(".py", "").replace(".", "_")
173
175 return False
176
177 def get_includes(self):
178 result = jinja2.Template(
179 """
180#include "toolbox/particles/particles.h"
181#include "vertexdata/{{LOCAL_PARTICLES_CONTAINER}}.h"
182#include "globaldata/{{LOCAL_PARTICLE}}.h"
183#include "vertexdata/{{ACTIVE_PARTICLES_CONTAINER}}.h"
184#include "globaldata/{{ACTIVE_PARTICLE}}.h"
185
186{{ADDITIONAL_INCLUDES}}
187
188#include <list>
189"""
190 )
191 return result.render(**self.d)
192
193 def get_attributes(self):
194 return """
195 int _spacetreeId;
196"""
197
199 return """
200 _spacetreeId = treeNumber;
201 """
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.