12 AMR criterion based upon the particle density
14 Most codes use this criterion in combination with a classic mesh-based criterion
15 which ensures that the mesh is not coarser than a certain maximal mesh sizes.
17 The algorithm relies heavily on the ParticleTreeAnalysis action set which
18 annotates each cell in the tree with the sum of the vertices associated to
19 the 2^d adjacent vertices. If this sum exceeds certain thresholds and, depending
20 on the setup, some search radii of hosted particles are small enough, the code
21 refines the tree. It is then the job of subsequent runs with
22 UpdateParticleGridAssociation to drop the particles into the newly created
26 As we work with cell data to guide the adaptivity yet store the particles
27 within vertices, it is clear that refinement pattern tends to smear out. We
28 get rather regularly refined areas around the particles. For most applications,
29 that's totally fine, as it also ensures that
36 particle_tree_analysis,
37 min_particles_per_cell=1,
38 max_particles_per_cell=65536,
48 particle_set: peano4.toolbox.particles.ParticleSet
49 Instance of the particle set that is to be used as trigger. Each particle in the
50 set has a search radius and this one is used to guide the AMR.
52 particle_tree_analysis: peano4.toolbox.particles.ParticleTreeAnalysis
53 Tree analysis algorithm. Usually is instantiated over particle_set, but you can
54 also impose another analysis algorithm.
56 min_particles_per_cell: Integer (>=0)
57 The tree is not refined if there are less than min_particles_per_cell particles
58 within the cell. By default, this parameter is set to 1 and thus the code refines
59 always if there are more than two particles held in a cell. You can set the value
60 to 0. In this case, we refine whenever there's a particle in a cell and its search
61 radius would allow us to refine further. Set
62 it to a higher number to ensure that there's (approximately) a certain particle
65 max_particles_per_cell: Integer
66 Forces the code to refine if there are more than max_particles_per_cell particles
67 held. Has to be bigger or equal to min_particles_per_cell.
69 Whenever the AMR criterion refines, it can happen that particles do not
70 drop down further, as their search radius is too small.
72 You can also set this argument to zero as well. In this case, the action sets
73 refines all the way down until the mesh size just fits the search radius. It
74 even refines a cell if there's only one particle in it.
77 super(ParticleAMR, self).
__init__(descend_invocation_order=1, parallel=
False)
78 if min_particles_per_cell < 0:
80 "invalid min number of particles pre cell (has to be positive): {}".format(
81 min_particles_per_cell
86 max_particles_per_cell < min_particles_per_cell
87 or max_particles_per_cell < 0
90 "max number of particles ({}) has to be bigger or equal to min number ({}) and it has to be positive".format(
91 max_particles_per_cell, min_particles_per_cell
96 "CELL_DATA_NAME": particle_tree_analysis._cell_data_name,
97 "MIN_PARTICLES_PER_CELL": min_particles_per_cell,
98 "MAX_PARTICLES_PER_CELL": max_particles_per_cell,
101 "PARTICLE_SET": particle_set.name,
102 "PARTICLE": particle_set.particle_model.name,
109 __Template_TouchCellLastTime = jinja2.Template(
116 If we want to erase a cell, we actually make the region that is to be
117 erased slightly bigger. While we can pick this blow-up factor arbitrarily
118 (up to a factor of three might make sense in some cases), but if we make
119 is 2.0, then an erased cell covers half of its neighbour. If we have a
120 cell which hosts a particle, this cell will then maybe not coarsen, but
121 all of its neighbours do, so the cell is eliminated. This triggers a
122 mesh oscillation. So the factor should either be smaller than 2.0, or we
123 have to veto that an area with particles is overwritten. Indeed we go
124 down the latter route and mark cells that we may not erase with a refine
125 event which describes the mesh status quo.
128 This is a tricky part. Our idea is that we mark only examine refined cells
129 one level above the finest mesh. These are cells which will be refined and
130 have been refined, and also carry only few particles such that we could
131 safely erase their children. While we only examine refined cells, we do not
132 examine refined cells which have refined children. To find this out, we
133 look at the flag getParentOfRefinedCell().
137 not marker.willBeRefined()
139 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles() > {{MAX_PARTICLES_PER_CELL}}
141 marker.h()(0)/3.0>{{MIN_H}}
143 const double ScaleMarker = 0.8;
144 peano4::grid::GridControlEvent newEntry;
145 newEntry.setRefinementControl( peano4::grid::GridControlEvent::RefinementControl::Refine );
146 newEntry.setOffset( marker.getOffset() + marker.h() * (1.0-ScaleMarker) / 2.0 );
147 newEntry.setWidth( marker.h() * ScaleMarker );
148 newEntry.setH( marker.h()/3.0 * 1.1 );
149 _localGridControlEvents.push_back(newEntry);
150 logDebug( "touchCellLastTime(...)", "add " << newEntry.toString() );
154 marker.willBeRefined()
156 marker.hasBeenRefined()
158 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles() <= {{MIN_PARTICLES_PER_CELL}}
160 not fineGridCell{{CELL_DATA_NAME}}.getParentOfRefinedCell()
162 marker.h()(0)<{{MAX_H}} // we will remove the suboctants
164 const double ScaleMarker = 1.4;
165 peano4::grid::GridControlEvent newEntry;
166 newEntry.setRefinementControl( peano4::grid::GridControlEvent::RefinementControl::Erase );
167 newEntry.setOffset( marker.getOffset() + marker.h() * (1.0-ScaleMarker) / 2.0 );
168 newEntry.setWidth( marker.h() * ScaleMarker );
169 newEntry.setH( marker.h() * ScaleMarker );
170 _localGridControlEvents.push_back(newEntry);
171 logDebug( "touchCellLastTime(...)", "add " << newEntry.toString() );
176 __Template_EndTraversal = jinja2.Template(
178 static tarch::multicore::BooleanSemaphore semaphore;
179 tarch::multicore::Lock lock(semaphore);
181 // insert and then merge immediately to reduce the
183 _localGridControlEvents = peano4::grid::merge( _localGridControlEvents );
184 _newGridControlEvents.insert( _newGridControlEvents.end(), _localGridControlEvents.begin(), _localGridControlEvents.end() );
185 _newGridControlEvents = peano4::grid::merge( _newGridControlEvents );
191 if operation_name == ActionSet.OPERATION_BEGIN_TRAVERSAL:
193 _localGridControlEvents.clear();
195 if operation_name == ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
197 if operation_name == ActionSet.OPERATION_END_TRAVERSAL:
203 return _oldGridControlEvents;
208 std::vector< peano4::grid::GridControlEvent > _localGridControlEvents;
209 static std::vector< peano4::grid::GridControlEvent > _oldGridControlEvents;
210 static std::vector< peano4::grid::GridControlEvent > _newGridControlEvents;
214 return __name__.replace(
".py",
"").replace(
".",
"_")
219std::vector< peano4::grid::GridControlEvent > """
220 + full_qualified_classname
221 +
"""::_oldGridControlEvents;
222std::vector< peano4::grid::GridControlEvent > """
223 + full_qualified_classname
224 +
"""::_newGridControlEvents;
229 result = jinja2.Template(
231#include "tarch/multicore/Lock.h"
232#include "vertexdata/{{PARTICLE_SET}}.h"
233#include "globaldata/{{PARTICLE}}.h"
234#include "peano4/grid/grid.h"
237 return result.render(**self.
d)
241 #if defined(Parallel)
242 #error not implemented yet
244_oldGridControlEvents.clear();
245_oldGridControlEvents = _newGridControlEvents;
246_newGridControlEvents.clear();
247_oldGridControlEvents = peano4::grid::merge( _oldGridControlEvents );
Action set (reactions to events)
AMR criterion based upon the particle density.
get_body_of_unprepareTraversal(self)
get_static_initialisations(self, full_qualified_classname)
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, particle_set, particle_tree_analysis, min_particles_per_cell=1, max_particles_per_cell=65536, min_h=0.1, max_h=0.01)
:: Arguments
get_attributes(self)
Return attributes as copied and pasted into the generated class.
__Template_TouchCellLastTime
get_includes(self)
Return include statements that you need.
get_action_set_name(self)
Return unique action set name.
user_should_modify_template(self)
Is the user allowed to modify the output.
get_body_of_getGridControlEvents(self)