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* maxEigenvalue
93 )->void {
94 repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, x, t, dt, normal, maxEigenvalue );
95 },
96 repositories::{{SOLVER_INSTANCE}}.QuadraturePoints1d
97 );
98
99 const double maxEigenvalue = cellData.maxEigenvalue[0];
100 {% endif %}
101
102 // Set the variable
103 // double newTimeStepSize
104 {{COMPUTE_NEW_TIME_STEP_SIZE}}
105
106 fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStamp(timeStamp+timeStepSize);
107 fineGridCell{{SOLVER_NAME}}CellLabel.setTimeStepSize(newTimeStepSize);
108 fineGridCell{{SOLVER_NAME}}CellLabel.setHasUpdated(true);
109 repositories::{{SOLVER_INSTANCE}}.update(newTimeStepSize, timeStamp+timeStepSize, marker.h()(0) );
110
111 {% if NUMBER_OF_FACE_PROJECTIONS!=1 %}
112 #error Have to tweak compute final projection
113 {% endif %}
114
115 #if Dimensions==2
116 ::exahype2::dg::projectVolumetricDataOntoFaces(
117 newQ,
118 {{ORDER}},
119 {{NUMBER_OF_UNKNOWNS}},
120 {{NUMBER_OF_AUXILIARY_VARIABLES}},
121 repositories::{{SOLVER_INSTANCE}}.BasisFunctionValuesLeft1d,
122 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(0).value, //left
123 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(2).value, //right
124 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(1).value, //down
125 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(3).value //up
126 );
127 #elif Dimensions==3
128 ::exahype2::dg::projectVolumetricDataOntoFaces(
129 newQ,
130 {{ORDER}},
131 {{NUMBER_OF_UNKNOWNS}},
132 {{NUMBER_OF_AUXILIARY_VARIABLES}},
133 repositories::{{SOLVER_INSTANCE}}.BasisFunctionValuesLeft1d,
134 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(0).value, //left
135 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(3).value, //right
136 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(1).value, //down
137 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(4).value, //up
138 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(2).value, //front
139 fineGridFaces{{UNKNOWN_IDENTIFIER}}EstimateProjection(5).value //back
140 );
141 #endif
142 }
143"""
144
145 TemplateUpdateFace = """
146 if ( repositories::{{SOLVER_INSTANCE}}.isLastGridSweepOfTimeStep() ) {
147 for (int leftRight=0; leftRight<2; leftRight++) {
148 if ( fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdated(leftRight) ) {
149 fineGridFace{{SOLVER_NAME}}FaceLabel.setOldTimeStamp( leftRight, fineGridFace{{SOLVER_NAME}}FaceLabel.getNewTimeStamp(leftRight) );
150 fineGridFace{{SOLVER_NAME}}FaceLabel.setNewTimeStamp( leftRight, fineGridFace{{SOLVER_NAME}}FaceLabel.getUpdatedTimeStamp(leftRight) );
151
152 ::exahype2::dg::copyOneSideOfFaceProjection(
153 {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}},
154 {{ORDER}},
155 {{NUMBER_OF_FACE_PROJECTIONS}},
156 marker.getSelectedFaceNumber() % Dimensions,
157 leftRight==1,
158 fineGridFace{{UNKNOWN_IDENTIFIER}}EstimateProjection.value,
159 fineGridFace{{UNKNOWN_IDENTIFIER}}OldSolutionProjection.value
160 );
161 }
162 }
163 }
164"""
165
166 def __init__(self, solver, guard, face_projections: FaceProjections):
167 """
168
169 guard_project: String (C++ code)
170 Predicate which controls if the solution is actually projected
171
172 guard_safe_old_time_step: String (C++ code)
173 Predicate which controls if the projection should be copied into
174 the old solution and the time step should also be moved over
175
176 """
177 super(ComputeFinalLinearCombination, self).__init__(solver)
178 self.guard = guard
180 self._face_projections = face_projections
181 assert self._face_projections == FaceProjections.Solution, "not supported"
182
183 def get_body_of_operation(self, operation_name):
184 result = ""
185 d = {}
186 self._solver._init_dictionary_with_default_parameters(d)
187 self._solver.add_entries_to_text_replacement_dictionary(d)
188 d["PREDICATE"] = self.guard
189 d["WEIGHTS"] = self._butcher_tableau.final_estimate_weights()
190 d["NUMBER_OF_FACE_PROJECTIONS"] = compute_number_of_face_projection_quantities(
192 )
193 if (
194 operation_name
195 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
196 ):
197 result = jinja2.Template(self.TemplateProject).render(**d)
198 pass
199 if (
200 operation_name
201 == peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
202 ):
203 result = jinja2.Template(self.TemplateUpdateFace).render(**d)
204 pass
205 return result
206
208 return __name__.replace(".py", "").replace(".", "_")
209
210 def get_includes(self):
211 return (
212 super(ComputeFinalLinearCombination, self).get_includes()
213 + """
214#include "exahype2/enumerator/AoSLexicographicEnumerator.h"
215"""
216 )
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