Peano
Loading...
Searching...
No Matches
SolveVolumeIntegral.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
5
6from exahype2.solvers.ButcherTableau import ButcherTableau
7
8import peano4
9import exahype2
10import jinja2
11
12
14 """
15 Solve volume integral
16
17 Solve the volumetric part of the DG method. This includes the evaluation of the
18 volume integral of the operator multiplied with a trial function, plus the
19 subsequent multiplication with an inverted (lumped) mass matrix. So, eventually,
20 we do an explicit Euler step subject to a relaxed time step size from the Butcher
21 tableau. The input is already properly computed (see LinearCombinationOfEstimates()).
22
23 The volume integral definition is an underdetermined action set, i.e., you still
24 have to ensure that a number of macros are actually defined when you use it:
25
26 - {{COMPUTE_TIME_STEP_SIZE}} has to specify a double timeStepSize. It may be const if
27 you want. I don't alter it.
28
29 In return, the following variables will be set by the action set:
30
31 - timeStampOldSolution: double This is the time stamp of the original
32 solution, i.e. not the one we are currently evaluating due to the
33 Runge-Kutta scheme.
34 - timeStamp: double This is the time stamp of the current Runge Kutta
35 guess. It is timeStampOldSolution plus the weight of the Butcher scheme
36 times the time step size.
37 - QIn: double* A pointer to the actual linear combination of previous
38 guesses according to the Butcher tableau.
39 - QOut: For Runge-Kutta, we ahve to store all guesses of the future solution,
40 so we can eventually combine them into one final outcome. QOut points to
41 that segment/guess that's to be computed in this step.
42
43 """
44
45 TemplateCellKernel = """
46 {% for PREDICATE_NO in range(0,PREDICATES|length) %}
47 if ({{PREDICATES[PREDICATE_NO]}}) {
48 const double timeStampOldSolution = fineGridCell{{SOLVER_NAME}}CellLabel.getTimeStamp();
49
50 // Set the variable
51 // double timeStepSize
52 {{COMPUTE_TIME_STEP_SIZE}}
53
54 const double timeStamp = timeStampOldSolution + {{BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES[PREDICATE_NO]}} * timeStepSize;
55
56 assertion3( tarch::la::greaterEquals( timeStepSize, 0.0 ), timeStamp, timeStepSize, timeStampOldSolution );
57 assertion3( tarch::la::greaterEquals( timeStamp, 0.0 ), timeStamp, timeStepSize, timeStampOldSolution );
58
59 double* QIn = fineGridCell{{UNKNOWN_IDENTIFIER}}LinearCombination.value;
60 #if Dimensions==2
61 double* QOut = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + {{PREDICATE_NO}} * {{NUMBER_OF_DOFS_PER_CELL_2D}} * {{NUMBER_OF_UNKNOWNS}};
62 #elif Dimensions==3
63 double* QOut = fineGridCell{{UNKNOWN_IDENTIFIER}}RhsEstimates.value + {{PREDICATE_NO}} * {{NUMBER_OF_DOFS_PER_CELL_3D}} * {{NUMBER_OF_UNKNOWNS}};
64 #endif
65
66 {% if SPAWN_VOLUME_KERNEL_AS_TASK %}
67 if (marker.willBeSkeletonCell()) {
68 ::exahype2::CellData cellData(
69 QIn,
70 marker.x(),
71 marker.h(),
72 timeStamp,
73 timeStepSize,
74 QOut
75 );
76
77 tasks::{{SOLVER_NAME}}_VolumetricSolverEnclaveTask::applyKernelToCell(
78 marker,
79 timeStamp,
80 timeStepSize,
81 QIn,
82 QOut
83 );
84 } else {
85 assertion(marker.willBeEnclaveCell());
86 assertion(not marker.willBeRefined());
87 auto newEnclaveTask = new tasks::{{SOLVER_NAME}}_VolumetricSolverEnclaveTask(
88 marker,
89 timeStamp,
90 timeStepSize,
91 {% if MAKE_COPY_OF_ENCLAVE_TASK_DATA %}
92 QIn
93 {% else %}
94 fineGridCell{{UNKNOWN_IDENTIFIER}}LinearCombination.getSmartPointer(),
95 QOut
96 {% endif %}
97 );
98
99 int predecessorEnclaveTaskNumber = fineGridCell{{SEMAPHORE_LABEL}}.getSemaphoreNumber();
100
101 tarch::multicore::spawnTask(
102 newEnclaveTask,
103 predecessorEnclaveTaskNumber>=0 ? std::set<int>{predecessorEnclaveTaskNumber} : tarch::multicore::NoInDependencies,
104 newEnclaveTask->getTaskId()
105 );
106
107 if (predecessorEnclaveTaskNumber>=0) {
108 ::exahype2::EnclaveTask::releaseTaskNumber(predecessorEnclaveTaskNumber);
109 }
110
111 fineGridCell{{SEMAPHORE_LABEL}}.setSemaphoreNumber(newEnclaveTask->getTaskId());
112 }
113 {% else %}
114 ::exahype2::CellData cellData(
115 QIn,
116 marker.x(),
117 marker.h(),
118 timeStamp,
119 timeStepSize,
120 QOut
121 );
122
123 {% if STATELESS_PDE_TERMS %}
124 if (repositories::{{SOLVER_INSTANCE}}.cellCanUseStatelessPDETerms(
125 marker.x(),
126 marker.h(),
127 timeStamp,
128 timeStepSize
129 )) {
130 ::exahype2::dg::{{KERNEL_NAMESPACE}}::{{VOLUMETRIC_COMPUTE_KERNEL_CALL_STATELESS}}
131 } else
132 {% endif %}
133
134 ::exahype2::dg::{{KERNEL_NAMESPACE}}::{{VOLUMETRIC_COMPUTE_KERNEL_CALL}}
135 {% endif %}
136 }
137 {% endfor %}
138"""
139
140
141 def __init__(self,solver,spawn_volume_kernel_as_task = False):
142 """
143 guard_project: String (C++ code)
144 Predicate which controls if the solution is actually projected.
145
146 guard_safe_old_time_step: String (C++ code)
147 Predicate which controls if the projection should be copied into
148 the old solution and the time step should also be moved over.
149 """
150 super(SolveVolumeIntegral,self).__init__(solver)
153 self.spawn_volume_kernel_as_task = spawn_volume_kernel_as_task
154
155
156 @property
157 def guards(self):
158 if self._guards==[]:
159 raise Exception("Guards are not initialised")
160 return self._guards
161
162
163 @guards.setter
164 def guards(self,new_guards):
165 if new_guards!=[] and len(new_guards)!=self._solver.number_of_Runge_Kutta_steps():
166 raise Exception( "Expect one guard per Runge Kutta step. Have {} steps but got guards {}".format(solver.number_of_Runge_Kutta_steps(),guards) )
167 self._guards = new_guards
168
169
170 def get_body_of_operation(self,operation_name):
171 result = ""
172 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
173 d = {}
174 self._solver._init_dictionary_with_default_parameters(d)
175 self._solver.add_entries_to_text_replacement_dictionary(d)
176 d[ "PREDICATES" ] = self.guardsguardsguards
177 d[ "BUTCHER_TABLEAU_RELATIVE_TIME_STEP_SIZES" ] = self._butcher_tableau.time_step_sizes()
178 d[ "SPAWN_VOLUME_KERNEL_AS_TASK"] = self.spawn_volume_kernel_as_task
179 d[ "SEMAPHORE_LABEL" ] = exahype2.grid.UpdateCellLabel.get_attribute_name(self._solver._name)
180 result = jinja2.Template(self.TemplateCellKernel).render(**d)
181 pass
182 return result
183
184
186 return __name__.replace(".py", "").replace(".", "_")
187
188
189 def get_includes(self):
191 return super( SolveVolumeIntegral, self ).get_includes() + """
192#include "tasks/""" + self._solver._name + """_VolumetricSolverEnclaveTask.h"
193"""
194 else:
195 return super( SolveVolumeIntegral, self ).get_includes()
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
__init__(self, solver, spawn_volume_kernel_as_task=False)
guard_project: String (C++ code) Predicate which controls if the solution is actually projected.