Peano
Loading...
Searching...
No Matches
ComputeFinalLinearCombination.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 .AbstractRungeKuttaDGActionSet import AbstractRungeKuttaDGActionSet
5from .ProjectLinearCombinationOfEstimatesOntoFaces import FaceProjections
6from .ProjectLinearCombinationOfEstimatesOntoFaces import (
7 compute_number_of_face_projection_quantities,
8)
9
10from exahype2.solvers.ButcherTableau import ButcherTableau
11
12import peano4
13import jinja2
14
15
17 r"""!
18
19 Action set determining the final solution using a linear combination of previous Runge-Kutta guesses
20
21 We solve the ODE
22
23 @f$ \partial Q = F(Q) @f$
24
25 where we have multiple guesses for F according to the Butcher tableau. The final
26 solution can be written down as linear combination over these guesses:
27
28
29 @f$ Q^{new} = Q^{old} + a_1 \cdot dt \cdot F_1(Q) + a_2 \cdot dt \cdot F_2(Q) + \dots @f$
30
31 We observe the following simple facts:
32
33 - The data in fineGridCell{{UNKNOWN_IDENTIFIER}}.value holds @f$ Q^{old} @f$
34 - The data in fineGridCell{{UNKNOWN_IDENTIFIER}}.value shall hold @f$ Q^{new} @f$ eventually.
35 We thus can simply add the scaled estimated to it.
36 - The estimates do not alter the auxiliary variables.
37 - We can thus just keep the previous auxiliary variables implicitly.
38
39
40 ## Face projections
41
42 As I discuss in detail in solvers.rkdg.RungeKuttaDG.create_data_structures(),
43 the field _estimate_projection usually holds the projection of a DG estimate,
44 but not the real solution. At some points, I however need the real solution
45 after a time step. Local time stepping for example depends upon it. So the
46 final combination projects the solution again onto the faces.
47
48 In return, we could skip the projection within the first Runge-Kutta step
49 where we effectively take the data and write it to the faces once again.
50 But this is too much of an optimisation, I just retrigger the projection
51 there agin.
52
53 """
54
55 TemplateProject = """
56 if ({{PREDICATE}}) {
57 {{COMPUTE_TIME_STEP_SIZE}}
58
59 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariables ( 1, {{ORDER}}+1, 0, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
60 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{ORDER}}+1, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
61
62 dfor( dof, {{ORDER}}+1 ) {
63 for (int unknown=0; unknown<{{NUMBER_OF_UNKNOWNS}}; unknown++) {
64 {% for WEIGHT_NO in range(0,WEIGHTS|length) %}
65 fineGridCell{{UNKNOWN_IDENTIFIER}}.value[ enumeratorWithAuxiliaryVariables(0,dof,unknown) ] +=
66 timeStepSize * {{WEIGHTS[WEIGHT_NO]}} * fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},dof,unknown) ];
67 {% endfor %}
68 }
69 }
70
71
72 const double timeStamp = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
73
74 double* newQ = fineGridCell{{UNKNOWN_IDENTIFIER}}.value;
75
76 {{POSTPROCESS_UPDATED_CELL_AFTER_FINAL_LINEAR_COMBINATION}}
77
78 {% if COMPUTE_MAX_EIGENVALUE %}
79 ::exahype2::CellData<double, double> cellData( nullptr, marker.x(), marker.h(), timeStamp, timeStepSize, fineGridCell{{UNKNOWN_IDENTIFIER}}.value );
80
81 ::exahype2::dg::reduceMaxEigenvalue_patchwise_functors(
82 cellData,
83 {{ORDER}},
84 {{NUMBER_OF_UNKNOWNS}},
85 {{NUMBER_OF_AUXILIARY_VARIABLES}},
86 [&](
87 const double * __restrict__ Q,
88 const tarch::la::Vector<Dimensions,double>& x,
89 double t,
90 double dt,
91 int normal
92 )->double {
93 return repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, x, t, dt, normal );
94 },
95 repositories::{{SOLVER_INSTANCE}}.QuadraturePoints1d
96 );
97
98 const double maxEigenvalue = cellData.maxEigenvalue[0];
99 {% endif %}
100
101 // Set the variable
102 // double newTimeStepSize
103 {{COMPUTE_NEW_TIME_STEP_SIZE}}
104
105 fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStamp(timeStamp+timeStepSize);
106 fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStepSize(newTimeStepSize);
107 fineGridCell{{SOLVER_NAME}}CellLabel.setHasUpdated(true);
108 repositories::{{SOLVER_INSTANCE}}.update(newTimeStepSize, timeStamp+timeStepSize, marker.h()(0) );
109
110 {% if NUMBER_OF_FACE_PROJECTIONS!=1 %}
111 #error Have to tweak compute final projection
112 {% endif %}
113
114 #if Dimensions==2
115 ::exahype2::dg::projectVolumetricDataOntoFaces(
116 newQ,
117 {{ORDER}},
118 {{NUMBER_OF_UNKNOWNS}},
119 {{NUMBER_OF_AUXILIARY_VARIABLES}},
120 repositories::{{SOLVER_INSTANCE}}.BasisFunctionValuesLeft1d,
121 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(0).value, //left
122 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(2).value, //right
123 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(1).value, //down
124 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(3).value //up
125 );
126 #elif Dimensions==3
127 ::exahype2::dg::projectVolumetricDataOntoFaces(
128 newQ,
129 {{ORDER}},
130 {{NUMBER_OF_UNKNOWNS}},
131 {{NUMBER_OF_AUXILIARY_VARIABLES}},
132 repositories::{{SOLVER_INSTANCE}}.BasisFunctionValuesLeft1d,
133 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(0).value, //left
134 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(3).value, //right
135 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(1).value, //down
136 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(4).value, //up
137 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(2).value, //front
138 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(5).value //back
139 );
140 #endif
141 }
142"""
143
144 TemplateUpdateFace = """
145 if ( repositories::{{SOLVER_INSTANCE}}.isLastGridSweepOfTimeStep() ) {
146 for (int leftRight=0; leftRight<2; leftRight++) {
147 if ( fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdated(leftRight) ) {
148 fineGridFace{{SOLVER_NAME}}FaceLabel.setOldTimeStamp( leftRight, fineGridFace{{SOLVER_NAME}}FaceLabel.getNewTimeStamp(leftRight) );
149 fineGridFace{{SOLVER_NAME}}FaceLabel.setNewTimeStamp( leftRight, fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdatedTimeStamp(leftRight) );
150
151 ::exahype2::dg::copyOneSideOfFaceProjection(
152 {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}},
153 {{ORDER}},
154 {{NUMBER_OF_FACE_PROJECTIONS}},
155 marker.getSelectedFaceNumber() % Dimensions,
156 leftRight==1,
157 fineGridFace{{UNKNOWN_IDENTIFIER}}EstimateProjection.value,
158 fineGridFace{{UNKNOWN_IDENTIFIER}}OldSolutionProjection.value
159 );
160 }
161 }
162 }
163"""
164
165 def __init__(self, solver, guard, face_projections: FaceProjections):
166 """
167
168 guard_project: String (C++ code)
169 Predicate which controls if the solution is actually projected
170
171 guard_safe_old_time_step: String (C++ code)
172 Predicate which controls if the projection should be copied into
173 the old solution and the time step should also be moved over
174
175 """
176 super(ComputeFinalLinearCombination, self).__init__(solver)
177 self.guard = guard
179 self._face_projections = face_projections
180 assert self._face_projections == FaceProjections.Solution, "not supported"
181
182 def get_body_of_operation(self, operation_name):
183 result = ""
184 d = {}
185 self._solver._init_dictionary_with_default_parameters(d)
186 self._solver.add_entries_to_text_replacement_dictionary(d)
187 d["PREDICATE"] = self.guard
188 d["WEIGHTS"] = self._butcher_tableau.final_estimate_weights()
189 d["NUMBER_OF_FACE_PROJECTIONS"] = compute_number_of_face_projection_quantities(
191 )
192 if (
193 operation_name
194 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
195 ):
196 result = jinja2.Template(self.TemplateProject).render(**d)
197 pass
198 if (
199 operation_name
200 == peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
201 ):
202 result = jinja2.Template(self.TemplateUpdateFace).render(**d)
203 pass
204 return result
205
207 return __name__.replace(".py", "").replace(".", "_")
208
209 def get_includes(self):
210 return (
211 super(ComputeFinalLinearCombination, self).get_includes()
212 + """
213#include "exahype2/enumerator/AoSLexicographicEnumerator.h"
214"""
215 )
Action set determining the final solution using a linear combination of previous Runge-Kutta guesses.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver, guard, FaceProjections face_projections)
guard_project: String (C++ code) Predicate which controls if the solution is actually projected