4from .AbstractRungeKuttaDGActionSet
import AbstractRungeKuttaDGActionSet
5from .ProjectLinearCombinationOfEstimatesOntoFaces
import FaceProjections
6from .ProjectLinearCombinationOfEstimatesOntoFaces
import (
7 compute_number_of_face_projection_quantities,
19 Action set determining the final solution using a linear combination of previous Runge-Kutta guesses
23 @f$ \partial Q = F(Q) @f$
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:
29 @f$ Q^{new} = Q^{old} + a_1 \cdot dt \cdot F_1(Q) + a_2 \cdot dt \cdot F_2(Q) + \dots @f$
31 We observe the following simple facts:
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.
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.
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
57 {{COMPUTE_TIME_STEP_SIZE}}
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 );
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) ];
72 const double timeStamp = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
74 double* newQ = fineGridCell{{UNKNOWN_IDENTIFIER}}.value;
76 {{POSTPROCESS_UPDATED_CELL_AFTER_FINAL_LINEAR_COMBINATION}}
78 {% if COMPUTE_MAX_EIGENVALUE %}
79 ::exahype2::CellData<double, double> cellData( nullptr, marker.x(), marker.h(), timeStamp, timeStepSize, fineGridCell{{UNKNOWN_IDENTIFIER}}.value );
81 ::exahype2::dg::reduceMaxEigenvalue_patchwise_functors(
84 {{NUMBER_OF_UNKNOWNS}},
85 {{NUMBER_OF_AUXILIARY_VARIABLES}},
87 const double * __restrict__ Q,
88 const tarch::la::Vector<Dimensions,double>& x,
94 repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, x, t, dt, normal, maxEigenvalue );
96 repositories::{{SOLVER_INSTANCE}}.QuadraturePoints1d
99 const double maxEigenvalue = cellData.maxEigenvalue[0];
103 // double newTimeStepSize
104 {{COMPUTE_NEW_TIME_STEP_SIZE}}
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) );
111 {% if NUMBER_OF_FACE_PROJECTIONS!=1 %}
112 #error Have to tweak compute final projection
116 ::exahype2::dg::projectVolumetricDataOntoFaces(
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
128 ::exahype2::dg::projectVolumetricDataOntoFaces(
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
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) );
152 ::exahype2::dg::copyOneSideOfFaceProjection(
153 {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}},
155 {{NUMBER_OF_FACE_PROJECTIONS}},
156 marker.getSelectedFaceNumber() % Dimensions,
158 fineGridFace{{UNKNOWN_IDENTIFIER}}EstimateProjection.value,
159 fineGridFace{{UNKNOWN_IDENTIFIER}}OldSolutionProjection.value
166 def __init__(self, solver, guard, face_projections: FaceProjections):
169 guard_project: String (C++ code)
170 Predicate which controls if the solution is actually projected
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
177 super(ComputeFinalLinearCombination, self).
__init__(solver)
186 self.
_solver._init_dictionary_with_default_parameters(d)
187 self.
_solver.add_entries_to_text_replacement_dictionary(d)
188 d[
"PREDICATE"] = self.
guard
190 d[
"NUMBER_OF_FACE_PROJECTIONS"] = compute_number_of_face_projection_quantities(
195 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
201 == peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
208 return __name__.replace(
".py",
"").replace(
".",
"_")
212 super(ComputeFinalLinearCombination, self).
get_includes()
214#include "exahype2/enumerator/AoSLexicographicEnumerator.h"
Action set determining the final solution using a linear combination of previous Runge-Kutta guesses.
get_includes(self)
Return include statements that you need.
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