11 Evaluate the point-wise refinement criterion and collect the outcome as
12 refine and erase requests
14 The numerical schemes add this action set to the very last task of their
15 time step if the solver has an exahype2.api.RefineErasePointwisely PDE
16 term (@ref exahype2.api.blockstructured.create_dynamic_mesh_refinement_action_set.create_dynamic_mesh_refinement_action_set()). The action set
17 loops over all volumes of each patch and invokes the term per volume
18 centre. It initialises the term's output with Keep. From the outcomes of
19 all the volumes, it derives one command for the whole cell:
21 - If any volume says Refine, the cell asks for a refinement.
22 - If all volumes say Erase, the cell asks to be erased, i.e. coarsened.
23 - Otherwise, the cell is kept and does not issue any command.
25 The action set bounds the mesh size. Refine commands are dropped for
26 cells whose volumes are already smaller than min_volume_size. Erase
27 commands are dropped if the volumes of the coarsened cell would not be
28 smaller than max_volume_size. If a bound is None, the mesh size is not
29 constrained. As the action set drops these commands, it does not issue
30 requests which the mesh cannot realise anyway, and the mesh adaptation
31 phase is only triggered if the mesh actually can change. The numerical
32 schemes take the two bounds as constructor arguments and pass them
35 Peano erases the children of a cell only if they all ask for it. Erase
36 commands therefore carry the cell's position within its parent, and the
37 refinement service keeps them only if all 3^d children of a parent have
38 asked to be erased within the same mesh sweep
39 (@ref exahype2::RefinementControlService::keepOnlyCompleteSiblingEraseEvents()).
40 Incomplete sets of erase requests are dropped right away, so they never
41 trigger the mesh adaptation phase.
43 The action set collects the commands of one tree within a local
44 ::exahype2::RefinementControl, merges it into the rank's
45 ::exahype2::RefinementControlService at the end of the traversal, and
46 commits the new events once per rank in unprepareTraversal(). By
47 default, it does not hand any event over to Peano, i.e. the time step
48 itself never changes the mesh. The mesh adaptation phase consumes the
49 requests (@ref exahype2::isMeshAdaptationRequired()). The setup's mesh
50 adaptation (@ref exahype2.api.fv.SetupSimulationWithUserCodedRefinementCriterion)
51 instead lets the action set hand the events over to Peano right away
52 (hand_events_to_peano). It also vetoes all erase commands (veto_erase):
53 The setup has no restriction which would hand the patches of erased
54 cells over to their parent, i.e. a parent would end up with an
55 uninitialised patch. The mesh adaptation phase of the time stepping
56 always restricts (@ref toolbox.blockstructured.api.InterpolateAndRestrictCells).
58 Subclasses which evaluate a different adaptivity criterion only replace
59 the per-volume evaluation (@ref exahype2.api.blockstructured.DynamicMeshRefinement.DynamicMeshRefinement.get_volume_evaluation()), e.g.
60 exahype2.api.blockstructured.DynamicMeshRefinementWithGradients.
62 The action set works for all block-structured schemes which hold their
63 unknowns as patch_size^d volumes (or grid cells) per mesh cell, i.e. for
64 exahype2.api.fv and exahype2.api.rkfd4.
73 min_volume_size: float =
None,
74 max_volume_size: float =
None,
75 event_lifetime: int = 2,
76 hand_events_to_peano: bool =
False,
77 veto_erase: bool =
False,
81 @param solver: exahype2.api.Solver
82 The solver whose criterion is evaluated.
84 @param patch_size: int
85 Number of volumes per axis within one patch.
88 C++ boolean expression, evaluated per cell, guarding whether the
89 criterion is evaluated for that cell.
91 @param min_volume_size: float
92 A cell asks for a refinement only if its volumes are at least of
93 this size. None does not bound the refinement.
95 @param max_volume_size: float
96 A cell asks to be erased only if the volumes of the coarser cell
97 are strictly smaller than this size. None does not bound the
100 @param event_lifetime: int
101 Number of mesh sweeps a refinement or erase event remains alive
102 within the refinement service (@ref exahype2::RefinementControl::addCommand()).
104 @param hand_events_to_peano: bool
105 Hand the refinement service's committed events over to Peano, so
106 Peano realises them in the subsequent mesh sweeps. The time step
107 leaves this off, the setup's mesh adaptation switches it on.
109 @param veto_erase: bool
110 Drop all erase commands, i.e. only ever refine. The time step
111 leaves this off, the setup's mesh adaptation switches it on.
114 super().
__init__(descend_invocation_order=1, parallel=
False)
125 TemplateEvaluateVolume =
"""
126 const int index = peano4::utils::dLinearised(volume,{{NUMBER_OF_VOLUMES_PER_AXIS}}) * ({{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}});
127 ::exahype2::RefinementCommand command = ::exahype2::RefinementCommand::Keep;
128 repositories::{{SOLVER_INSTANCE}}.refineErasePointwisely(
129 fineGridCell{{UNKNOWN_IDENTIFIER}}.value + index,
130 ::exahype2::fv::getVolumeCentre( marker.x(), marker.h(), {{NUMBER_OF_VOLUMES_PER_AXIS}}, volume),
131 repositories::{{SOLVER_INSTANCE}}.getMinTimeStamp(),
134 anyVolumeWantsToRefine = anyVolumeWantsToRefine or command == ::exahype2::RefinementCommand::Refine;
135 allVolumesWantToErase = allVolumesWantToErase and command == ::exahype2::RefinementCommand::Erase;
141 C++ Jinja2 template evaluating the criterion within one volume
143 The template runs within a loop over the volumes of the patch, i.e.
144 it has access to the volume's index volume. It has to update the
145 two flags anyVolumeWantsToRefine and allVolumesWantToErase.
150 TemplateEvaluateCriterion =
"""
151 logTraceIn( "touchCellFirstTime(...)---DynamicMeshRefinement" );
152 bool anyVolumeWantsToRefine = false;
153 bool allVolumesWantToErase = true;
154 dfor( volume, {{NUMBER_OF_VOLUMES_PER_AXIS}} ) {
158 if ( anyVolumeWantsToRefine {{REFINE_BOUND}}) {
159 _localRefinementControl.addCommand( marker.x(), marker.h(), ::exahype2::RefinementCommand::Refine, {{EVENT_LIFETIME}} );
161{%- if not VETO_ERASE %}
162 else if ( not anyVolumeWantsToRefine and allVolumesWantToErase {{ERASE_BOUND}}) {
163 _localRefinementControl.addCommand( marker.x(), marker.h(), ::exahype2::RefinementCommand::Erase, {{EVENT_LIFETIME}}, marker.getRelativePositionWithinFatherCell() );
166 logTraceOut( "touchCellFirstTime(...)---DynamicMeshRefinement" );
170 if operation_name == ActionSet.OPERATION_BEGIN_TRAVERSAL:
171 return " _localRefinementControl.clear();\n"
172 if operation_name == ActionSet.OPERATION_END_TRAVERSAL:
173 return " ::exahype2::RefinementControlService::getInstance().merge( _localRefinementControl );\n"
174 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
178 refine_bound = f
"and tarch::la::max( marker.h() ) >= {min_cell_size!r} "
183 f
"and 3.0 * tarch::la::max( marker.h() ) < {max_cell_size!r} "
186 "NUMBER_OF_VOLUMES_PER_AXIS": self.
patch_size,
187 "NUMBER_OF_UNKNOWNS": self.
_solver.unknowns,
188 "NUMBER_OF_AUXILIARY_VARIABLES": self.
_solver.auxiliary_variables,
189 "UNKNOWN_IDENTIFIER": self.
_solver._unknown_identifier(),
190 "SOLVER_INSTANCE": self.
_solver.get_name_of_global_instance(),
191 "REFINE_BOUND": refine_bound,
192 "ERASE_BOUND": erase_bound,
199 return jinja2.Template(template).render(**d)
203 if operation_name == ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
210 Commit the new events once per rank and mesh sweep, after all trees
211 have merged their local events into the service
214 return " ::exahype2::RefinementControlService::getInstance().finishStep();\n"
219 return " return ::exahype2::RefinementControlService::getInstance().createGridControlEventsForNextTraversal();\n"
223 ::exahype2::RefinementControl _localRefinementControl;
227 return __name__.replace(
".py",
"").replace(
".",
"_")
235#include "exahype2/RefinementControl.h"
236#include "exahype2/RefinementControlService.h"
237#include "exahype2/fv/PatchUtils.h"
239 + self.
_solver._get_default_includes()
240 + self.
_solver.user_solver_includes
Evaluate the point-wise refinement criterion and collect the outcome as refine and erase requests.
user_should_modify_template(self)
Is the user allowed to modify the output.
str get_volume_evaluation(self)
C++ Jinja2 template evaluating the criterion within one volume.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver, int patch_size, str guard, float min_volume_size=None, float max_volume_size=None, int event_lifetime=2, bool hand_events_to_peano=False, bool veto_erase=False)
get_action_set_name(self)
Return unique action set name.
get_guard_of_operation(self, operation_name)
Return the guard of an operation.
get_body_of_unprepareTraversal(self)
Commit the new events once per rank and mesh sweep, after all trees have merged their local events in...
get_body_of_createGridControlEventsForNextTraversal(self)
Return the grid control events that this action set wants to trigger.
str TemplateEvaluateVolume
Per-volume evaluation of the point-wise criterion.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
get_includes(self)
Return include statements that you need.
str TemplateEvaluateCriterion
Action set (reactions to events)