Peano
Loading...
Searching...
No Matches
AdaptiveSubcyclingTimeSteppingCodeSnippets.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
3from .SolverCodeSnippets import SolverCodeSnippets
4
5
7 """
8
9 Code snippet generator for all subcycling solvers
10
11 """
12
14 return """
15protected:
16 double _maxEigenvalue;
17 double _admissibleTimeStepSize;
18public:
19 void setMaxEigenvalue( double eigenvalue );
20 /**
21 * @return Admissible time step size for the current sweep, i.e.
22 * return _admissibleTimeStepSize. This value always refers
23 * to the minimum mesh volume size. If you use subcycling,
24 * you have to scale it for cells that are not on the finest
25 * mesh resolution.
26 */
27 virtual double getAdmissibleTimeStepSize() const;
28 """
29
30
32 return """
33void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::setMaxEigenvalue( double eigenvalue ) {
34 if ( tarch::la::greater( eigenvalue, 0.0 ) ) {
35 tarch::multicore::Lock lock(_semaphore);
36 _maxEigenvalue = std::max(_maxEigenvalue,eigenvalue);
37 }
38}
39
40
41double {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::getAdmissibleTimeStepSize() const {
42 return _admissibleTimeStepSize;
43}
44 """
45
46
48 return "_admissibleTimeStepSize = 0.0;"
49
50
52 if remove_accumulation_errors:
53 return """
54 // The fixed solver's _timeStepSize scales with min volume h, i.e. it is
55 // always chosen such that the finest grid does something meaningful.
56 const double originalStepSize = repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false)>0.0 ?
57 repositories::{{SOLVER_INSTANCE}}.getTimeStepSize() * marker.h()(0) / repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false) :
58 0.0;
59 double timeStepSize = ::exahype2::removeTimeStepAccumulationErrorsFromCell( fineGridCell""" + solver_name + """CellLabel, fineGridFaces""" + solver_name + """FaceLabel, originalStepSize);
60"""
61 else:
62 return """
63 // The fixed solver's _timeStepSize scales with min volume h, i.e. it is
64 // always chosen such that the finest grid does something meaningful.
65 double timeStepSize = repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false)>0.0 ?
66 repositories::{{SOLVER_INSTANCE}}.getTimeStepSize() * marker.h()(0) / repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false) :
67 0.0;
68"""
69
70 if remove_accumulation_errors:
71 return """
72 // The fixed solver's _timeStepSize scales with min volume h, i.e. it is
73 // always chosen such that the finest grid does something meaningful.
74 const double originalTimeStepSize = repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false)>0.0 ?
75 repositories::{{SOLVER_INSTANCE}}.getAdmissibleTimeStepSize() * marker.h()(0) / repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false) :
76 0.0;
77 double timeStepSize = ::exahype2::removeTimeStepAccumulationErrorsFromCell( fineGridCell""" + solver_name + """CellLabel, fineGridFaces""" + solver_name + """FaceLabel, originalTimeStepSize);
78"""
79 else:
80 return """
81 // The fixed solver's _timeStepSize scales with min volume h, i.e. it is
82 // always chosen such that the finest grid does something meaningful.
83 double timeStepSize = repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false)>0.0 ?
84 repositories::{{SOLVER_INSTANCE}}.getAdmissibleTimeStepSize() * marker.h()(0) / repositories::{{SOLVER_INSTANCE}}.getMinPatchSize(false) :
85 0.0;
86"""
87
88
90 """
91
92 This is global, fixed time stepping, i.e. the new time step size will likely
93 be the same as the previous one, unless the mesh changes, as we work with
94 normalised time step sizes, i.e. in this case the time step size might change.
95 Anyway, the new time step size is only for stats anyway, as we'll pick a
96 global one when we determine timeStepSize the next time step.
97
98 """
99 return """
100 repositories::{{SOLVER_INSTANCE}}.setMaxEigenvalue( maxEigenvalue );
101
102 // This is a value set for stats reasons. We'll ignore it later as we
103 // ask for a new valid time step size from getAdmissibleTimeStepSize().
104 const double newTimeStepSize = repositories::{{SOLVER_INSTANCE}}.getAdmissibleTimeStepSize();
105"""
106
107
109 """
110
111 This routine is inserted after we have reduced all global quantities. These
112 are the quantities with the postfix ThisTimeStep.
113
114 """
115 return """
116 if ( isLastGridSweepOfTimeStep() ) {
117 #ifdef Parallel
118 double newMaxEigenvalue = _maxEigenvalue;
119 tarch::mpi::Rank::getInstance().allReduce(
120 &newMaxEigenvalue,
121 &_maxEigenvalue,
122 1,
123 MPI_DOUBLE,
124 MPI_MAX,
125 [&]() -> void { tarch::services::ServiceRepository::getInstance().receiveDanglingMessages(); }
126 );
127 #endif
128
129 if ( tarch::la::smaller(_maxEigenvalue, 0.0 ) ) {
130 ::tarch::triggerNonCriticalAssertion( __FILE__, __LINE__, "_maxEigenvalue>=0", "invalid max eigenvalue: " + std::to_string(_maxEigenvalue) );
131 // keep time step size invariant
132 // _admissibleTimeStepSize = _admissibleTimeStepSize;
133 }
134 else if ( tarch::la::equals(_maxEigenvalue, 0.0 ) ) {
135 logWarning( "finishTimeStep(...)", "maximum eigenvalue approaches 0.0. For nonlinear PDEs, this often means the PDE becomes stationary. It could also be a bug however" );
136 _admissibleTimeStepSize = 0.0;
137 }
138 }
139"""
create_finish_time_step_implementation(self)
This routine is inserted after we have reduced all global quantities.
Interface for all solvers' code snippets.
create_compute_time_step_size()
Within the actual compute kernels, the kernels ask the solver variant how to determine a new field.
create_compute_new_time_step_size()
Very similar to create_compute_time_step_size(), this routine should return a code snippet which crea...