Peano
Loading...
Searching...
No Matches
UpdateParticleMarker.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
6import peano4
7
8
10 def __init__(self,
11 particle_set,
12 automatically_set_marker_in_leave_cell,
13 make_reset_separate_task,
14 ):
15 """!
16
17 Update particles marker
18
19 Particles do not uniquely belong to one cell or the other. If they sit
20 exactly on the face in-between two cells, they belong to both. If they
21 sit on a vertex location, they can belong to up to 2^d cells. We cannot
22 avoid such an ambivalency, as we work with floating point numbers, and
23 as particles are stored within the vertices. If they were stored within
24 cells, the association would be unique by definition.
25
26 Therefore, we introduce a boolean per particle which indicates if a
27 particle has been updated by a cell already. That is, we do not make
28 the association unique artificially, but we realise a "whoever grabs it
29 first"-policy.
30
31 The realisation of this marker is straightforward: The
32 swift2.particle.Particle base class defines the marker, which is a simple
33 bool. When we touch a vertex for the first time, we implicitly also touch
34 all particles associated with this vertex for the first time. So we set
35 the marker to false.
36
37 When we leave a cell, we set all the flags to true. We can be sure that
38 this routine is called before we store the vertices and we can be sure that
39 it is called before we enter any adjacent cell. This statement implies that
40 you shall not change a vertex position prior to touchVertexLastTime().
41
42 For a task-based version, we cannot set the flags to true in
43 touchCellLastTime(). At this point, the cell's task might not have run yet,
44 so if we reset the particle state, we run risk that we break the code
45 semantics of the task functor, as they typically check for the update
46 flag. So if we use tasks, it has to be the task itself which sets the
47 "have updated" flag to true. This is realised within the tasks created by
48 TaskGraphKernelWrapper.
49
50 We note that the marker's name is unfortunate: It is not really that we
51 have updated a particle necessary. But we keep track that we have at least
52 studied one.
53
54 """
55 self._particle_set = particle_set
56 self.d = {}
57 self.d[ "PARTICLE" ] = particle_set.particle_model.name
58 self.d[ "PARTICLES_CONTAINER" ] = particle_set.name
60 particle_set.name
61 )
62 self._automatically_set_marker_in_leave_cell = automatically_set_marker_in_leave_cell
63 self._make_reset_separate_task = make_reset_separate_task
64
65
66
67
68 __Template_TouchVertexFirstTime = jinja2.Template("""
69 auto& particles = fineGridVertex{{PARTICLES_CONTAINER}};
70
71 for (auto* particle: particles) {
72 particle->setCellHasUpdatedParticle(false);
73 }
74""")
75
76
77 __Template_TouchVertexFirstTimeAsTask = jinja2.Template("""
78 auto& particles = fineGridVertex{{PARTICLES_CONTAINER}};
79
80 const ::swift2::TaskNumber taskNumberToBeUsed{
81 fineGridVertex{{MARKER_NAME}}.getNumber(),
82 ::swift2::TaskNumber::TaskAssociation::TouchVertexFirstTime
83 };
84
85 tarch::multicore::Task* newTask = new tarch::multicore::TaskWithCopyOfFunctor (
86 tarch::multicore::Task::DontFuse,
87 tarch::multicore::Task::DefaultPriority,
88 [=,this]()->bool {
89 for (auto* particle: particles) {
90 particle->setCellHasUpdatedParticle(false);
91 }
92 return false;
93 }
94 #if PeanoDebug>0
95 , "update-particle-marker"
96 #endif
97 );
98
99 tarch::multicore::spawnTask( newTask, std::set<int>{::swift2::flatten(taskNumberToBeUsed)}, ::swift2::flatten(taskNumberToBeUsed) );
100""")
101
102
103 __Template_TouchCellLastTime = jinja2.Template("""
104 for (int i=0; i<TwoPowerD; i++) {
105 ::swift2::markAllParticlesAsUpdatedWithinCell( fineGridVertices{{PARTICLES_CONTAINER}}(i), marker );
106 }
107""")
108
109
110 def get_body_of_operation(self,operation_name):
111 result = "\n"
112 if self._automatically_set_marker_in_leave_cell and operation_name==ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
113 result = self.__Template_TouchCellLastTime.render(**self.d)
114 if operation_name==ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME and not self._make_reset_separate_task:
115 result = self.__Template_TouchVertexFirstTime.render(**self.d)
116 if operation_name==ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME and self._make_reset_separate_task:
117 result = self.__Template_TouchVertexFirstTimeAsTask.render(**self.d)
118 return result
119
120
122 return " return std::vector< peano4::grid::GridControlEvent >();\n"
123
124
125 #def get_body_of_prepareTraversal(self):
126 # return self.d[ "PREPARE_TRAVERSAL_KERNEL" ]
127
128
129 #def get_body_of_unprepareTraversal(self):
130 # return self.d[ "UNPREPARE_TRAVERSAL_KERNEL" ]
131
132
134 return __name__.replace(".py", "").replace(".", "_")
135
136
138 return False
139
140
141 def get_includes(self):
142 return jinja2.Template( """
143#include "vertexdata/{{PARTICLES_CONTAINER}}.h"
144#include "globaldata/{{PARTICLE}}.h"
145#include "swift2/swift2.h"
146#include "swift2/TaskNumber.h"
147""" ).render( **self.d )
148
Action set (reactions to events)
Definition ActionSet.py:6
__init__(self, particle_set, automatically_set_marker_in_leave_cell, make_reset_separate_task)
Update particles marker.
get_includes(self)
Return include statements that you need.
user_should_modify_template(self)
Is the user allowed to modify the output.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.