14 AMR criterion based upon the particle density
16 This implementation is almsot exactly the same as the toolbox variant,
17 but it does not work with a static field, but instead pipes all the
18 refinement events a global variable. Actually, it fuses two different
19 action sets of the toolbox: The actual stats over the markers which
20 count the particles and the translation fo this info into mesh refinement
21 and coarsening commands.
23 Different to the default toolbox variant, Swift's marker doesn't need to
24 distinguish a new and an old marker and we use the marker information
25 straightaway throughout the steps up.
27 Please consult the constructor, i.e. __init__(), for some information
28 on algorithm variants and the implementation.
30 To understand the code's behaviour, it is resonable to read through
31 @ref peano_amr_tex "Peano's generic AMR description".
36 return name +
"CellStatistics"
41 Create the cell marker that is used by the analysis
47 DynamicMeshRefinementAnalysis.marker_name(name)
51 cell_marker.data.add_attribute(
54 cell_marker.peano4_mpi_and_storage_aspect.store_predicate =
"false"
55 cell_marker.peano4_mpi_and_storage_aspect.load_predicate =
"false"
62 min_particles_per_cell=1,
63 max_particles_per_cell=65536,
70 Construct the action set
74 particle_set: peano4.toolbox.particles.ParticleSet
75 Instance of the particle set that is to be used as trigger. Each particle in the
76 set has a search radius and this one is used to guide the AMR.
78 min_particles_per_cell: Integer (>=0)
79 The tree is not refined if there are less than min_particles_per_cell particles
80 within the cell. By default, this parameter is set to 1 and thus the code refines
81 always if there are more than two particles held in a cell. You can set the value
82 to 0. In this case, we refine whenever there's a particle in a cell and its search
83 radius would allow us to refine further. Set
84 it to a higher number to ensure that there's (approximately) a certain particle
87 max_particles_per_cell: Integer
88 Forces the code to refine if there are more than max_particles_per_cell
89 particles held. Has to be bigger or equal to min_particles_per_cell.
91 Whenever the AMR criterion refines, it can happen that particles do not
92 drop down further, as their search radius is too small.
94 You can also set this argument to zero as well. In this case, the action
95 sets refines all the way down until the mesh size just fits the search
96 radius. It even refines a cell if there's only one particle in it.
99 In principle, many particle codes create a mesh that is by magnitudes
100 too fine. Therefore, it makes sense to make the refinement events a
101 little bit smaller than the actual underlying cell. However, if they are
102 small, the ::peano4::grid::merge() operation might not be able to fuse
103 them, i.e. you have to be careful that you increase the tolerance there
107 if min_particles_per_cell < 0:
109 "invalid min number of particles pre cell (has to be positive): {}".format(
110 min_particles_per_cell
115 max_particles_per_cell < min_particles_per_cell
116 or max_particles_per_cell < 0
119 "max number of particles ({}) has to be bigger or equal to min number ({}) and it has to be positive".format(
120 max_particles_per_cell, min_particles_per_cell
125 "CELL_DATA_NAME": DynamicMeshRefinementAnalysis.marker_name(
128 "MIN_PARTICLES_PER_CELL": min_particles_per_cell,
129 "MAX_PARTICLES_PER_CELL": max_particles_per_cell,
132 "PARTICLE_SET": particle_set.name,
133 "PARTICLE": particle_set.particle_model.name,
134 "SCALE_MARKER": scale_marker,
141 __Template_TouchCellFirstTime = jinja2.Template(
143 fineGridCell{{CELL_DATA_NAME}}.setNumberOfParticles(0);
144 fineGridCell{{CELL_DATA_NAME}}.setParentOfRefinedCell( false );
148 __Template_CreateCell = jinja2.Template(
150 fineGridCell{{CELL_DATA_NAME}}.setNumberOfParticles( std::numeric_limits<int>::max() );
151 fineGridCell{{CELL_DATA_NAME}}.setParentOfRefinedCell( true );
155 __Template_TouchCellLastTime = jinja2.Template(
162 Determine local number of particles associated with the adjacent
167 for (int i=0; i<TwoPowerD; i++) {
168 count += fineGridVertices{{PARTICLE_SET}}(i).size();
174 Determine local counter
175 =======================
177 We might already have received data from finer cells (if we are
178 in a refined cell), so we add the data. We might also be in a
179 newly generated cell, where adding new particles might cause an
180 overflow. So I protect the accumulation.
183 if ( fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles() < std::numeric_limits<int>::max() ) {
184 fineGridCell{{CELL_DATA_NAME}}.setNumberOfParticles(
185 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles()
193 Restrict the particle count to the next coarser level
194 =====================================================
197 coarseGridCell{{CELL_DATA_NAME}}.setNumberOfParticles(
198 coarseGridCell{{CELL_DATA_NAME}}.getNumberOfParticles()
200 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles()
203 if ( marker.willBeRefined() ) {
204 coarseGridCell{{CELL_DATA_NAME}}.setParentOfRefinedCell( true );
209 To understand the code's behaviour, it is resonable to read through
210 @ref peano_amr_tex "Peano's generic AMR description".
215 Refine if we have not yet reached the finest mesh resolution and violate
216 the max particle count. This implies that we actually get a mesh which is
217 slightly finer then min_h or this species.
222 If we want to erase a cell, we actually make the region that is to be
223 erased slightly bigger. This is in line with @ref peano_amr_tex "Peano's generic AMR description".
224 Furthermore, we mark only refined cells
225 one level above the finest mesh. These are cells which will be refined and
226 have been refined, and also carry only few particles such that we could
227 safely erase their children plus have no refined children. To find out if
228 this holds for a cell, we look at the flag getParentOfRefinedCell().
232 not marker.willBeRefined()
234 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles() > {{MAX_PARTICLES_PER_CELL}}
236 const double ScaleMarker = {{SCALE_MARKER}};
237 peano4::grid::GridControlEvent newEntry;
238 newEntry.setRefinementControl( peano4::grid::GridControlEvent::RefinementControl::Refine );
239 newEntry.setOffset( marker.getOffset() + marker.h() * (1.0-ScaleMarker) / 2.0 );
240 newEntry.setWidth( marker.h() * ScaleMarker );
242 tarch::la::greater( marker.h()(0), {{MIN_H}} ) ? marker.h()/3.0 * 1.1 : marker.h() * 1.1
244 _localGridControlEvents.push_back(newEntry);
245 logDebug( "touchCellLastTime(...)", "add " << newEntry.toString() );
249 marker.willBeRefined()
251 marker.hasBeenRefined()
253 fineGridCell{{CELL_DATA_NAME}}.getNumberOfParticles() <= {{MIN_PARTICLES_PER_CELL}}
255 not fineGridCell{{CELL_DATA_NAME}}.getParentOfRefinedCell()
257 marker.h()(0)<{{MAX_H}} // we will remove the suboctants
259 const double ScaleMarker = 3.0 * (1.0+{{SCALE_MARKER}});
260 peano4::grid::GridControlEvent newEntry;
261 newEntry.setRefinementControl( peano4::grid::GridControlEvent::RefinementControl::Erase );
262 newEntry.setOffset( marker.getOffset() + marker.h() * (1.0-ScaleMarker) / 2.0 );
263 newEntry.setWidth( marker.h() * ScaleMarker );
264 newEntry.setH( marker.h() * ScaleMarker );
265 _localGridControlEvents.push_back(newEntry);
266 logDebug( "touchCellLastTime(...)", "add " << newEntry.toString() );
271 __Template_EndTraversal = jinja2.Template(
273 static tarch::multicore::BooleanSemaphore semaphore;
274 tarch::multicore::Lock lock(semaphore);
276 _newGridControlEvents.insert( _newGridControlEvents.end(), _localGridControlEvents.begin(), _localGridControlEvents.end() );
282 if operation_name == ActionSet.OPERATION_BEGIN_TRAVERSAL:
284 _localGridControlEvents.clear();
286 if operation_name == ActionSet.OPERATION_CREATE_CELL:
288 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
290 if operation_name == ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
292 if operation_name == ActionSet.OPERATION_END_TRAVERSAL:
303 std::list< peano4::grid::GridControlEvent > _localGridControlEvents;
304 static std::list< peano4::grid::GridControlEvent > _newGridControlEvents;
308 return __name__.replace(
".py",
"").replace(
".",
"_")
313std::list< peano4::grid::GridControlEvent > """
314 + full_qualified_classname
315 +
"""::_newGridControlEvents;
320 result = jinja2.Template(
322#include "tarch/multicore/Lock.h"
323#include "vertexdata/{{PARTICLE_SET}}.h"
324#include "globaldata/{{PARTICLE}}.h"
325#include "peano4/grid/grid.h"
326#include "swift2/GridControlEvents.h"
331 return result.render(**self.
d)
335::swift2::commitGridControlEvents( _newGridControlEvents );
336_newGridControlEvents.clear();
Default superclass for any data model in Peano which is stored within the grid.
Action set (reactions to events)
AMR criterion based upon the particle density.
get_static_initialisations(self, full_qualified_classname)
get_attributes(self)
Return attributes as copied and pasted into the generated class.
__Template_TouchCellFirstTime
user_should_modify_template(self)
Is the user allowed to modify the output.
get_action_set_name(self)
Return unique action set name.
create_cell_marker(name)
Create the cell marker that is used by the analysis.
get_includes(self)
Return include statements that you need.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_body_of_unprepareTraversal(self)
__init__(self, particle_set, min_particles_per_cell=1, max_particles_per_cell=65536, min_h=0.1, max_h=0.01, scale_marker=0.95)
Construct the action set.
__Template_TouchCellLastTime