3from .CellCenteredFiniteDifferences
import CellCenteredFiniteDifferences
12 ReconstructPatchAndApplyFunctor,
21 Update one cell, i.e. compute Runge-Kutta step on it
23 This routine is very similar to the Finite Volume step. The big difference in
24 the context of Runge-Kutta is that we always have to construct a linear
25 combination of the input data and then write the new estimate for the
26 right-hand side into the large estimate field.
28 So we operate in two steps: First, we let the default block-structured code
29 reconstruct the old time step data. After that, we add the rhs estimates
30 onto this reconstructed data. The latter can be read as a correction step
31 to the reconstructed values. It is correct if and only if the haloes are
32 properly initialised with a corrected value, as we cannot correct the halo
36 # Correction terms with Runge-Kutta trials
38 We current the values with a linear combination of all of the estimates according to the
41 The linear combination is a volumetric representation which includes both
42 the degrees of freedom and the auxiliary variables. However, the auxiliary
43 variables are not developing over time. In Runge-Kutta, I have estimates
44 for the right-hand side, i.e. for the derivatives
46 @f$ \partial _t Q = F(Q) @f$
48 This is the stuff stored in RhsEstimates. It does not comprise any auxiliary
49 variables. So I have to copy the auxiliary variables from the last valid
50 time step every time I reconstruct a new guess.
56 SolveRiemannProblemsOverPatch = jinja2.Template(
58 double timeStamp = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
61 // double timeStepSize
62 {{COMPUTE_TIME_STEP_SIZE}}
64 {% for PREDICATE_NO in range(0,PREDICATES|length) %}
65 if ({{PREDICATES[PREDICATE_NO]}}) {
66 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariablesOnReconstructedPatch( 1, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, {{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
67 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
68 {% if RECONSTRUCTION_STAGES != 0 %}
69 {{PRIMARY_VARS_INDICES}}
70 {{AUXILIARY_VARS_INDICES}}
73 dfor( dof, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} ) {
74 {% if RECONSTRUCTION_STAGES==0 %}
75 for (int unknown=0; unknown<{{NUMBER_OF_UNKNOWNS}}; unknown++) {
76 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
77 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
78 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] +=
79 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
80 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},dof,unknown) ];
85 for (int unknown : primaryVarsIndices) {
86 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
87 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
88 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] +=
89 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
90 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},dof,unknown) ];
94 for (int unknown : auxiliaryVarsIndices) {
95 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] = //abuse of RHS, auxiliary variables are stored there.
96 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},dof,unknown) ];
102 newQ = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},0,0);
106 {% for PREDICATE_NO in range(0,PREDICATES_RECONSTRUCTION|length) %}
107 if ({{PREDICATES_RECONSTRUCTION[PREDICATE_NO]}}) {
108 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithAuxiliaryVariablesOnReconstructedPatch( 1, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, {{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}});
109 ::exahype2::enumerator::AoSLexicographicEnumerator enumeratorWithoutAuxiliaryVariables( {{RK_STEPS}}, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}}, 0, {{NUMBER_OF_UNKNOWNS}}, 0 );
110 {% if RECONSTRUCTION_STAGES != 0 %}
111 {{PRIMARY_VARS_INDICES}}
112 {{AUXILIARY_VARS_INDICES}}
115 dfor( dof, {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} ) {
116 for (int unknown : primaryVarsIndices) {
117 {% for WEIGHT_NO in range(0,BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO]|length) %}
118 {% if BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]!=0 %}
119 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] +=
120 timeStepSize * {{BUTCHER_TABLEAU_WEIGHTS[PREDICATE_NO][WEIGHT_NO]}} *
121 fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value[ enumeratorWithoutAuxiliaryVariables({{WEIGHT_NO}},dof,unknown) ];
125 for (int unknown : auxiliaryVarsIndices) {
126 oldQWithHalo[ enumeratorWithAuxiliaryVariablesOnReconstructedPatch(0,dof,unknown) ] = 0;
127 // actually no need for this initialization as we do overwritten in reconstruction, but we keep it for safety.
132 newQ = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + enumeratorWithoutAuxiliaryVariables({{PREDICATE_NO}},0,0);
137 {{PREPROCESS_RECONSTRUCTED_PATCH}}
139 assertion2( tarch::la::greaterEquals( timeStamp, 0.0 ), timeStamp, timeStepSize );
140 assertion2( tarch::la::greaterEquals( timeStepSize, 0.0 ), timeStamp, timeStepSize );
142 ::exahype2::fd::validatePatch(
144 {{NUMBER_OF_UNKNOWNS}},
145 {{NUMBER_OF_AUXILIARY_VARIABLES}},
146 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
147 {{HALO_SIZE}}, // halo
148 std::string(__FILE__) + "(" + std::to_string(__LINE__) + "): " + marker.toString()
149 ); // previous time step has to be valid
151 double subTimeStamp=timeStamp;
152 {% for PREDICATE_NO in range(0,PREDICATES|length) %}
153 if ({{PREDICATES[PREDICATE_NO]}}) {
154 subTimeStamp += {{BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES[PREDICATE_NO]}}*timeStepSize;
158 ::exahype2::CellData patchData( oldQWithHalo, marker.x(), marker.h(), subTimeStamp, timeStepSize, newQ );
160 {% if RECONSTRUCTION_STAGES==0 %}
161 ::exahype2::fd::{{KERNEL_NAMESPACE}}::{{COMPUTE_KERNEL_CALL}}
163 if ({{IS_UNDER_RECONSTRUCTION}}) {
164 ::exahype2::fd::{{KERNEL_NAMESPACE}}::{{RECONSTRUCTION_KERNEL_CALL}}
165 } else if ({{IS_UNDER_RKSTEP}}) {
166 ::exahype2::fd::{{KERNEL_NAMESPACE}}::{{COMPUTE_KERNEL_CALL}}
170 ::exahype2::fd::validatePatch(
172 {{NUMBER_OF_UNKNOWNS}},
173 {{NUMBER_OF_AUXILIARY_VARIABLES}},
174 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
176 std::string(__FILE__) + "(" + std::to_string(__LINE__) + "): " + marker.toString()
177 ); // outcome has to be valid
183 ReconstructPatchAndApplyFunctor.__init__(
186 patch_overlap=solver._patch_overlap_new,
187 functor_implementation=
"""
188#error please switch to your Riemann solver of choice
190 reconstructed_array_memory_location=solver._reconstructed_array_memory_location,
191 guard=
"not marker.willBeRefined() and not marker.hasBeenRefined()",
192 add_assertions_to_halo_exchange=
False,
200 +
"""CellLabel.setHasUpdated(false);
210 This is our plug-in point to alter the underlying dictionary
215 self.
_solver._init_dictionary_with_default_parameters(d)
216 self.
_solver.add_entries_to_text_replacement_dictionary(d)
219 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep{}".format(
220 self.
_solver._store_cell_data_default_guard(),
221 self.
_solver.get_name_of_global_instance(),
225 for step
in range(0, self.
_solver.number_of_Runge_Kutta_steps())
227 if self.
_solver._reconstruction_stages != 0 :
228 d[
"PREDICATES_RECONSTRUCTION"] = [
229 "{} and repositories::{}.getSolverState()=={}::SolverState::ReconstructionSubStep{}".format(
230 self.
_solver._store_cell_data_default_guard(),
231 self.
_solver.get_name_of_global_instance(),
235 for step
in range(0, self.
_solver._reconstruction_stages)
238 re_condition_text=
"repositories::{}.getSolverState()=={}::SolverState::ReconstructionSubStep{}".format(
239 self.
_solver.get_name_of_global_instance(),
243 for step
in range(1,self.
_solver._reconstruction_stages):
244 re_condition_text +=
" or repositories::{}.getSolverState()=={}::SolverState::ReconstructionSubStep{}".format(
245 self.
_solver.get_name_of_global_instance(),
249 rk_condition_text=
"repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep{}".format(
250 self.
_solver.get_name_of_global_instance(),
254 for step
in range(1,self.
_solver.number_of_Runge_Kutta_steps()):
255 rk_condition_text +=
" or repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep{}".format(
256 self.
_solver.get_name_of_global_instance(),
260 d[
"IS_UNDER_RECONSTRUCTION"] = re_condition_text
261 d[
"IS_UNDER_RKSTEP"] = rk_condition_text
266 "BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES"
278#include "exahype2/enumerator/enumerator.h"
279#include "exahype2/fd/PatchUtils.h"
280#include "tarch/NonCriticalAssertions.h"
282 + self.
_solver._get_default_includes()
283 + self.
_solver.user_action_set_includes
289 You should replicate this function in each subclass, so you get
290 meaningful action set names (otherwise, it will be
291 AbstractRKFDActionSet0,1,2,...).
294 return __name__.replace(
".py",
"").replace(
".",
"_") +
"_UpdateCell"
299 Probably the simplest solver you could think off.
301 This particular variant works only for Runge-Kutta order greater or equal
305 :: Write your own specialisation ::
307 self._preprocess_reconstructed_patch
308 Has to hold any preprocessing, but it also has to set the doubles
309 timeStepSize and timeStamp to valid data.
311 self._postprocess_updated_patch
312 You don't have to redefine this one, but if you want to alter the
313 time step size, then this is the right place to do so. If you don't
314 alter timeStepSize, the code will automatically continue with
315 the current one subject to a preprocessing in the next step.
329 plot_grid_properties,
334 Instantiate a generic FV scheme with an overlap of 1.
339 super(SeparateSweeps, self).
__init__(
348 plot_grid_properties,
354 "Runge-Kutta order has to be at least 1 but was {}".format(rk_order)
367 Call the superclass' create_data_structures() to ensure that all the data
368 structures are in place, i.e. each cell can host a patch, that each face hosts
369 patch overlaps, and so forth. These quantities are all set to defaults. See
370 FV.create_data_structures().
372 After that, take the patch overlap (that's the data stored within the faces)
373 and ensure that these are sent and received via MPI whenever they are also
374 stored persistently. The default in FV is that no domain boundary data exchange
375 is active. Finally, ensure that the old data is only exchanged between the
376 initialisation sweep and the first first grid run-through.
381 initialisation_sweep_guard =
"""(
382 repositories::{}.getSolverState()=={}::SolverState::GridInitialisation
386 first_iteration_after_initialisation_guard =
"""(
387 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep0AfterGridInitialisation or
388 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation
401 first_iteration_after_initialisation_guard
405 first_sweep_of_time_step_or_plotting_guard =
"""(
406 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep0AfterGridInitialisation or
407 repositories::{}.getSolverState()=={}::SolverState::ReconstructionSubStep0 or
408 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
409 repositories::{}.getSolverState()=={}::SolverState::Plotting or
410 repositories::{}.getSolverState()=={}::SolverState::Suspended
419 first_sweep_of_time_step_or_plotting_guard =
"""(
420 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep0AfterGridInitialisation or
421 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep0 or
422 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
423 repositories::{}.getSolverState()=={}::SolverState::Plotting or
424 repositories::{}.getSolverState()=={}::SolverState::Suspended
434 last_sweep_of_time_step_or_plotting_initialisation =
"""(
435 repositories::{}.getSolverState()=={}::SolverState::GridInitialisation or
436 repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep{} or
437 repositories::{}.getSolverState()=={}::SolverState::PlottingAfterGridInitialisation or
438 repositories::{}.getSolverState()=={}::SolverState::Plotting or
439 repositories::{}.getSolverState()=={}::SolverState::Suspended
448 self.
_patch_estimates.generator.load_store_compute_flag =
"::peano4::grid::constructLoadStoreComputeFlag({},{},{})".format(
453 + first_sweep_of_time_step_or_plotting_guard
458 + last_sweep_of_time_step_or_plotting_initialisation
465 Call superclass routine and then reconfigure the update cell call.
466 Only the UpdateCell action set is specific to a single sweep.
468 This operation is implicity called via the superconstructor.
470 Each guard here should combine the storage predicate with the
483 "{} and repositories::{}.getSolverState()=={}::SolverState::RungeKuttaSubStep{}".format(
491 "{} and repositories::{}.getSolverState()=={}::SolverState::GridInitialisation".format(
500 "{} and repositories::{}.getSolverState()=={}::SolverState::ReconstructionSubStep{}".format(
513#include "exahype2/CellData.h"
515 + super(SeparateSweeps, self).user_action_set_includes
525 refinement_criterion,
528 additional_action_set_includes,
529 additional_user_includes,
532 If you pass in User_Defined, then the generator will create C++ stubs
533 that you have to befill manually. If you pass in None_Implementation, it
534 will create nop, i.e. no implementation or defaults. Any other string
535 is copied 1:1 into the implementation. If you pass in None, then the
536 set value so far won't be overwritten.
538 if boundary_conditions
is not None:
540 if refinement_criterion
is not None:
542 if initial_conditions
is not None:
544 if memory_location
is not None:
547 if refinement_criterion == exahype2.solvers.PDETerms.None_Implementation:
548 assert False,
"refinement criterion cannot be none"
549 if initial_conditions == exahype2.solvers.PDETerms.None_Implementation:
550 assert False,
"initial conditions cannot be none"
556 if eigenvalues
is not None:
558 if source_term
is not None:
563 == peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.HeapThroughTarchWithoutDelete
565 == peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.HeapWithoutDelete
567 == peano4.toolbox.blockstructured.ReconstructedArrayMemoryLocation.ManagedSharedAcceleratorDeviceMemoryThroughTarchWithoutDelete
570 "memory mode without appropriate delete chosen, i.e. this will lead to a memory leak"
580 d: Dictionary of string to string
Abstract solver for patch-based finite diffences.
_provide_cell_data_to_compute_kernels_default_guard(self)
_action_set_project_patch_onto_faces
_user_action_set_includes
_store_cell_data_default_guard(self)
Extend the guard via ands only.
_load_cell_data_default_guard(self)
Extend the guard via ands only.
get_name_of_global_instance(self)
number_of_Runge_Kutta_steps(self)
Return number of steps required to realise the Runge-Kutta scheme.
_solver_template_file_class_name
_baseline_action_set_descend_invocation_order
_boundary_conditions_implementation
_reconstructed_array_memory_location
create_action_sets(self)
Create required action sets.
_action_set_compute_final_linear_combination
_initial_conditions_implementation
_refinement_criterion_implementation
Probably the simplest solver you could think off.
add_entries_to_text_replacement_dictionary(self, d)
d: Dictionary of string to string in/out argument
_initial_conditions_implementation
__init__(self, name, patch_size, overlap, rk_order, unknowns, auxiliary_variables, min_meshcell_h, max_meshcell_h, plot_grid_properties, kernel_namespace)
Instantiate a generic FV scheme with an overlap of 1.
_reconstructed_array_memory_location
set_implementation(self, flux, ncp, source_term, eigenvalues, boundary_conditions, refinement_criterion, initial_conditions, memory_location, additional_action_set_includes, additional_user_includes)
If you pass in User_Defined, then the generator will create C++ stubs that you have to befill manuall...
_eigenvalues_implementation
user_action_set_includes(self)
Add further includes to this property, if your action sets require some additional routines from othe...
_refinement_criterion_implementation
_boundary_conditions_implementation
create_data_structures(self)
Call the superclass' create_data_structures() to ensure that all the data structures are in place,...
create_action_sets(self)
Call superclass routine and then reconfigure the update cell call.
_source_term_implementation
_solver_template_file_class_name
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
_add_action_set_entries_to_dictionary(self, d)
This is our plug-in point to alter the underlying dictionary.
get_includes(self)
Return include statements that you need.
_Template_TouchCellFirstTime_Preamble
SolveRiemannProblemsOverPatch
__init__(self, solver)
patch: peano4.datamodel.Patch Patch which is to be used