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 .AbstractADERDGActionSet import AbstractADERDGActionSet
4
5import jinja2
6import peano4.solversteps
7
8
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 evaluate 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 _Template_AMR = """
33 logTraceInWith2Arguments("touchCellFirstTime(...)", marker.willBeRefined(), marker.hasBeenRefined());
34
35 ::exahype2::RefinementCommand refinementCriterion = ::exahype2::getDefaultRefinementCommand();
36
37 {% if GRID_CONSTRUCTION %}
38 if (
39 not marker.willBeRefined()
40 and
41 tarch::la::greater(tarch::la::max(marker.h()), repositories::{{SOLVER_INSTANCE}}.MaxAdmissibleCellH)
42 ) {
43 refinementCriterion = ::exahype2::RefinementCommand::Refine;
44 } else if (
45 not marker.willBeRefined()
46 and
47 tarch::la::greaterEquals(tarch::la::max(marker.h()), repositories::{{SOLVER_INSTANCE}}.MinAdmissibleCellH)
48 and
49 not fineGridCell{{CELL_LABEL_NAME}}.getAMDCriterionEvaluatedThroughoutGridConstruction()
50 ) {
51 refinementCriterion = repositories::{{SOLVER_INSTANCE}}.refinementCriterion(
52 nullptr,
53 marker.x(),
54 marker.h(),
55 repositories::{{SOLVER_INSTANCE}}.getMinTimeStamp()
56 );
57 fineGridCell{{CELL_LABEL_NAME}}.setAMDCriterionEvaluatedThroughoutGridConstruction(true);
58 } else {
59 refinementCriterion = ::exahype2::RefinementCommand::Keep;
60 }
61 {% else %}
62 if (
63 {{PREDICATE}}
64 and
65 not marker.willBeRefined()
66 and
67 tarch::la::greater(tarch::la::max(marker.h()), repositories::{{SOLVER_INSTANCE}}.MaxAdmissibleCellH)
68 ) {
69 refinementCriterion = ::exahype2::RefinementCommand::Refine;
70 } else if (
71 {{PREDICATE}}
72 and
73 fineGridCell{{CELL_LABEL_NAME}}.getHasUpdated()
74 ) {
75 refinementCriterion = repositories::{{SOLVER_INSTANCE}}.refinementCriterion(
76 fineGridCell{{UNKNOWN_IDENTIFIER}}.value,
77 marker.x(),
78 marker.h(),
79 repositories::{{SOLVER_INSTANCE}}.getMinTimeStamp()
80 );
81
82 if (
83 refinementCriterion == ::exahype2::RefinementCommand::Refine
84 and
85 tarch::la::smallerEquals(tarch::la::max(marker.h()), 3.0 * repositories::{{SOLVER_INSTANCE}}.MinAdmissibleCellH)
86 ) {
87 logDebug("touchCellFirstTime(...)", "drop refine instructions, as mesh would be too small");
88 refinementCriterion = ::exahype2::RefinementCommand::Keep;
89 } else if (
90 refinementCriterion == ::exahype2::RefinementCommand::Erase
91 and
92 3.0 * tarch::la::max(marker.h()) > repositories::{{SOLVER_INSTANCE}}.MaxAdmissibleCellH
93 ) {
94 refinementCriterion = ::exahype2::RefinementCommand::Keep;
95 }
96 } else {
97 refinementCriterion = ::exahype2::RefinementCommand::Keep;
98 }
99 {% endif %}
100
101 _localRefinementControl.addCommand(marker.x(), marker.h(), refinementCriterion, {{EVENT_LIFETIME}});
102 logTraceOutWith1Argument("touchCellFirstTime(...)", toString(refinementCriterion));
103"""
104
106 self,
107 solver,
108 guard,
109 build_up_new_refinement_instructions,
110 implement_previous_refinement_instructions,
111 called_by_grid_construction,
112 event_lifetime=2,
113 ):
114 """
115 :: Attributes
116
117 _implement_previous_refinement_instructions: Boolean
118 This name might be misleading. Consult exahype2::RefinementControl for
119 a description of the control flow. This flag controls if instructions
120 are picked up from the RefinementControl database.
121
122
123 :: Arguments
124
125 guard: C++ expression which evaluates to true or false
126 A per cell decision whether we should study a cell or not.
127
128 build_up_new_refinement_instructions: Boolean
129 See remarks on multistep realisation of AMR in C++ class
130 exahype2::RefinementControl.
131
132 implement_previous_refinement_instructions: Boolean
133 See remarks on multistep realisation of AMR in C++ class
134 exahype2::RefinementControl.
135
136 event_lifetime: Int
137 See setter below
138 """
139 super(AdaptivityCriterion, self).__init__(solver)
140 self._guard = guard
142 build_up_new_refinement_instructions
143 )
145 implement_previous_refinement_instructions
146 )
147 self._event_lifetime = event_lifetime
148 self._called_by_grid_construction = called_by_grid_construction
149
152 return """
153 return ::exahype2::RefinementControlService::getInstance().getGridControlEvents();
154"""
155 else:
156 return """
157 return std::vector<peano4::grid::GridControlEvent>();
158"""
159
160 def get_body_of_operation(self, operation_name):
161 result = ""
162 if (
164 and operation_name == peano4.solversteps.ActionSet.OPERATION_BEGIN_TRAVERSAL
165 ):
166 result = """
167 _localRefinementControl.clear();
168"""
169
170 if (
172 and operation_name == peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL
173 ):
174 result = """
175 ::exahype2::RefinementControlService::getInstance().merge(_localRefinementControl);
176"""
177
178 if (
180 and operation_name
181 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME
182 ):
183 d = {}
184
185 d["CELL_LABEL_NAME"] = self._solver._cell_label.name
186 d["UNKNOWNS"] = str(self._solver._current_time_step.no_of_unknowns)
187 # d["DOFS_PER_AXIS"] = str(self._solver._patch.dim[0])
188 # 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])
189 # 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])
190 d["CELL_ACCESSOR"] = "fineGridCell" + self._solver._current_time_step.name
191 d["PREDICATE"] = (
192 "not marker.willBeRefined() and not marker.hasBeenRefined() and "
193 + self._guard
194 )
195 # TODO: Falsch: Auch nur im letzten Schritt oder so evaluieren bei RK
196 d["EVENT_LIFETIME"] = self._event_lifetime
197 d["GRID_CONSTRUCTION"] = self._called_by_grid_construction
198 self._solver._init_dictionary_with_default_parameters(d)
199 self._solver.add_entries_to_text_replacement_dictionary(d)
200 result = jinja2.Template(self._Template_AMR).render(**d)
201
202 return result
203
204 def set_event_lifetime(self, value):
205 """
206 By default, a refinement/coarsening event is only alive for one grid sweep.
207 After that one, the set of refine/coarsen commands is reset and we start
208 again. If you work with local time stepping, subcycling, multiphysics codes,
209 you might want to keep an event for more steps. In this case, you have to
210 invoke this setter.
211 """
212 self._event_lifetime = value
213
214 def get_attributes(self):
215 return """
216 ::exahype2::RefinementControl _localRefinementControl;
217"""
218
220 return __name__.replace(".py", "").replace(".", "_")
221
222 def get_includes(self):
223 return (
224 super(AdaptivityCriterion, self).get_includes()
225 + """
226#include "exahype2/RefinementControlService.h"
227 """
228 )
get_attributes(self)
Return attributes as copied and pasted into the generated class.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
set_event_lifetime(self, value)
By default, a refinement/coarsening event is only alive for one grid sweep.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver, guard, build_up_new_refinement_instructions, implement_previous_refinement_instructions, called_by_grid_construction, event_lifetime=2)
:: Attributes