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,
93 return repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, x, t, dt, normal );
95 repositories::{{SOLVER_INSTANCE}}.QuadraturePoints1d
98 const double maxEigenvalue = cellData.maxEigenvalue[0];
102 // double newTimeStepSize
103 {{COMPUTE_NEW_TIME_STEP_SIZE}}
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) );
110 {% if NUMBER_OF_FACE_PROJECTIONS!=1 %}
111 #error Have to tweak compute final projection
115 ::exahype2::dg::projectVolumetricDataOntoFaces(
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
127 ::exahype2::dg::projectVolumetricDataOntoFaces(
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
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) );
151 ::exahype2::dg::copyOneSideOfFaceProjection(
152 {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}},
154 {{NUMBER_OF_FACE_PROJECTIONS}},
155 marker.getSelectedFaceNumber() % Dimensions,
157 fineGridFace{{UNKNOWN_IDENTIFIER}}EstimateProjection.value,
158 fineGridFace{{UNKNOWN_IDENTIFIER}}OldSolutionProjection.value
165 def __init__(self, solver, guard, face_projections: FaceProjections):
168 guard_project: String (C++ code)
169 Predicate which controls if the solution is actually projected
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
176 super(ComputeFinalLinearCombination, self).
__init__(solver)
185 self.
_solver._init_dictionary_with_default_parameters(d)
186 self.
_solver.add_entries_to_text_replacement_dictionary(d)
187 d[
"PREDICATE"] = self.
guard
189 d[
"NUMBER_OF_FACE_PROJECTIONS"] = compute_number_of_face_projection_quantities(
194 == peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
200 == peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME
207 return __name__.replace(
".py",
"").replace(
".",
"_")
211 super(ComputeFinalLinearCombination, self).
get_includes()
213#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