Peano
Loading...
Searching...
No Matches
AdaptivityCriterion.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3
4from .AbstractFVActionSet import AbstractFVActionSet
5
6import peano4
7import jinja2
8
10 """!
11
12 The action set to realise AMR
13
14 AMR is a multistep process in ExaHyPE. Most of the relevant documentation
15 on it is documented in the class exahype2::RefinementControl.
16
17 There are different phases in ExaHyPE: grid generation (either with
18 refinement or without), initialisation, plotting and time stepping. It
19 depends on your solver in which time stepping to use AMR, but the there
20 are some things to take into account that are in common for all schemes:
21
22 - The grid creation does not use any actual solver data, so we should not
23 evalutae the adaptivity criterion here.
24 - InitGrid has volumetric data and might want to evaluate the criterion.
25 This is implicitly done by the t=0 check below.
26 - The plotting does not alter the solution. It thus makes no sense to
27 evaluate the criterion here.
28
29 Please consult EnclaveTasking.create_action_sets for details regarding
30 the handling of AMR within the enclave tasking concept.
31
32 """
33
34
35 TemplateAMR = """
36 logTraceInWith2Arguments( "touchCellFirstTime(...)", marker.willBeRefined(), marker.hasBeenRefined() );
37
38 ::exahype2::RefinementCommand refinementCriterion = ::exahype2::getDefaultRefinementCommand();
39
40 {% if GRID_CONSTRUCTION %}
41 if (
42 not marker.willBeRefined()
43 and
44 tarch::la::greater( tarch::la::max( marker.h() ), repositories::{{SOLVER_INSTANCE}}.MaxAdmissiblePatchH)
45 ) {
46 refinementCriterion = ::exahype2::RefinementCommand::Refine;
47 }
48 else if (
49 not marker.willBeRefined()
50 and
51 tarch::la::greaterEquals( tarch::la::max( marker.h() ), repositories::{{SOLVER_INSTANCE}}.MinAdmissiblePatchH )
52 and
53 not fineGridCell{{CELL_LABEL_NAME}}.getAMDCriterionEvaluatedThroughoutGridConstruction()
54 ) {
55 dfor( volume, {{NUMBER_OF_VOLUMES_PER_AXIS}} ) {
56 refinementCriterion = refinementCriterion and repositories::{{SOLVER_INSTANCE}}.refinementCriterion(
57 nullptr,
58 ::exahype2::fv::getVolumeCentre( marker.x(), marker.h(), {{NUMBER_OF_VOLUMES_PER_AXIS}}, volume),
59 ::exahype2::fv::getVolumeSize( marker.h(), {{NUMBER_OF_VOLUMES_PER_AXIS}} ),
60 0.0
61 );
62 }
63 fineGridCell{{CELL_LABEL_NAME}}.setAMDCriterionEvaluatedThroughoutGridConstruction(true);
64 }
65 else {
66 refinementCriterion = ::exahype2::RefinementCommand::Keep;
67 }
68 {% else %}
69 if (
70 {{PREDICATE}}
71 and
72 not marker.willBeRefined()
73 and
74 tarch::la::greater( tarch::la::max( marker.h() ), repositories::{{SOLVER_INSTANCE}}.MaxAdmissiblePatchH)
75 ) {
76 refinementCriterion = ::exahype2::RefinementCommand::Refine;
77 }
78 else if (
79 {{PREDICATE}}
80 and
81 fineGridCell{{CELL_LABEL_NAME}}.getHasUpdated()
82 ) {
83 int index = 0;
84 dfor( volume, {{NUMBER_OF_VOLUMES_PER_AXIS}} ) {
85 refinementCriterion = refinementCriterion and repositories::{{SOLVER_INSTANCE}}.refinementCriterion(
86 fineGridCell{{UNKNOWN_IDENTIFIER}}.value + index,
87 ::exahype2::fv::getVolumeCentre( marker.x(), marker.h(), {{NUMBER_OF_VOLUMES_PER_AXIS}}, volume),
88 ::exahype2::fv::getVolumeSize( marker.h(), {{NUMBER_OF_VOLUMES_PER_AXIS}} ),
89 repositories::{{SOLVER_INSTANCE}}.getMinTimeStamp()
90 );
91 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
92 }
93
94 if (
95 refinementCriterion==::exahype2::RefinementCommand::Refine
96 and
97 tarch::la::smallerEquals( tarch::la::max( marker.h() ), repositories::{{SOLVER_INSTANCE}}.MinAdmissiblePatchH )
98 ) {
99 logDebug( "touchCellFirstTime(...)", "drop refine instructions, as mesh would be too small" );
100 refinementCriterion = ::exahype2::RefinementCommand::Keep;
101 }
102 else if (refinementCriterion==::exahype2::RefinementCommand::Erase and 3.0* tarch::la::max( marker.h() ) > repositories::{{SOLVER_INSTANCE}}.MaxAdmissiblePatchH ) {
103 refinementCriterion = ::exahype2::RefinementCommand::Keep;
104 }
105 }
106 else {
107 refinementCriterion = ::exahype2::RefinementCommand::Keep;
108 }
109 {% endif %}
110
111 _localRefinementControl.addCommand( marker.x(), marker.h(), refinementCriterion, {{EVENT_LIFETIME}} );
112 logTraceOutWith1Argument( "touchCellFirstTime(...)", toString(refinementCriterion) );
113 """
114
115
116 def __init__(self,
117 solver,
118 guard,
119 build_up_new_refinement_instructions,
120 implement_previous_refinement_instructions,
121 called_by_grid_construction,
122 event_lifetime=2,
123 ):
124 """
125
126 :: Attributes
127
128 _implement_previous_refinement_instructions: Boolean
129 This name might be misleading. Consult exahype2::RefinementControl for
130 a description of the control flow. This flag controls if instructions
131 are picked up from the RefinementControl database.
132
133
134 :: Arguments
135
136 guard: C++ expression which evaluates to true or false
137 A per cell decision whether we should study a cell or not.
138
139 build_up_new_refinement_instructions: Boolean
140 See remarks on multistep realisation of AMR in C++ class
141 exahype2::RefinementControl.
142
143 implement_previous_refinement_instructions: Boolean
144 See remarks on multistep realisation of AMR in C++ class
145 exahype2::RefinementControl.
146
147 event_lifetime: Int
148 See setter below
149
150 """
151 AbstractFVActionSet.__init__(self,solver)
152 self.guard = guard
153 self._build_up_new_refinement_instructions = build_up_new_refinement_instructions
154 self._implement_previous_refinement_instructions = implement_previous_refinement_instructions
155 self._event_lifetime = event_lifetime
156 self._called_by_grid_construction = called_by_grid_construction
157
158
161 return """
162 return ::exahype2::RefinementControlService::getInstance().getGridControlEvents();
163"""
164 else:
165 return """
166 return std::vector< peano4::grid::GridControlEvent >();
167"""
168
169
170 def get_body_of_operation(self,operation_name):
171 result = ""
172 if self._build_up_new_refinement_instructions and operation_name==peano4.solversteps.ActionSet.OPERATION_BEGIN_TRAVERSAL:
173 result = """
174 _localRefinementControl.clear();
175"""
176
177 if self._build_up_new_refinement_instructions and operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
178 result = """
179 ::exahype2::RefinementControlService::getInstance().merge( _localRefinementControl );
180"""
181
182 if self._build_up_new_refinement_instructions and operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
183 d = {}
184 if self._solver._patch.dim[0] != self._solver._patch.dim[1]:
185 raise Exception( "Error: Can only handle square patches." )
186
187 d[ "CELL_LABEL_NAME" ] = self._solver._cell_label.name
188 d[ "UNKNOWNS" ] = str(self._solver._patch.no_of_unknowns)
189 d[ "DOFS_PER_AXIS" ] = str(self._solver._patch.dim[0])
190 d[ "NUMBER_OF_DOUBLE_VALUES_IN_ORIGINAL_PATCH_2D" ] = str(self._solver._patch.no_of_unknowns * self._solver._patch.dim[0] * self._solver._patch.dim[0])
191 d[ "NUMBER_OF_DOUBLE_VALUES_IN_ORIGINAL_PATCH_3D" ] = str(self._solver._patch.no_of_unknowns * self._solver._patch.dim[0] * self._solver._patch.dim[0] * self._solver._patch.dim[0])
192 d[ "CELL_ACCESSOR" ] = "fineGridCell" + self._solver._patch.name
193 d[ "PREDICATE" ] = "not marker.willBeRefined() and not marker.hasBeenRefined() and " + self.guard
194 d[ "EVENT_LIFETIME"] = self._event_lifetime
195 d[ "GRID_CONSTRUCTION" ] = self._called_by_grid_construction
196 self._solver._init_dictionary_with_default_parameters(d)
197 self._solver.add_entries_to_text_replacement_dictionary(d)
198 result = jinja2.Template( self.TemplateAMR ).render(**d)
199
200 return result
201
202
203 @property
204 def event_lifetime(self):
205 return self._event_lifetime
206
207
208 @event_lifetime.setter
209 def event_lifetime(self,value):
210 """
211
212 By default, a refinement/coarsening event is only alive for one grid sweep.
213 After that one, the set of refine/coarsen commands is reset and we start
214 again. If you work with local time stepping, subcycling, multiphysics codes,
215 you might want to keep an event for more steps. In this case, you have to
216 invoke this setter.
217
218 """
219 self._event_lifetime = value
220
221
222 def get_attributes(self):
223 return """
224 ::exahype2::RefinementControl _localRefinementControl;
225"""
226
227
229 return __name__.replace(".py", "").replace(".", "_")
230
231
232 def get_includes(self):
233 return super( AdaptivityCriterion, self ).get_includes() + """
234#include "exahype2/RefinementControlService.h"
235"""
get_attributes(self)
Return attributes as copied and pasted into the generated class.
__init__(self, solver, guard, build_up_new_refinement_instructions, implement_previous_refinement_instructions, called_by_grid_construction, event_lifetime=2)
:: Attributes
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...