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