Peano
Loading...
Searching...
No Matches
SpawnTaskToUpdateCellInterior.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 .AbstractFVActionSet import AbstractFVActionSet
4from .UpdateCellInterior import UpdateCellInterior
5
6import peano4.api
7
8
10 """!
11
12 Update the patch interior with a damped time step size
13
14 The action set takes the admissible time step size of the current time
15 step, i.e. the fourth entry of solver._max_eigenvalue_and_time_step_sizes
16 (@see exahype2.api.fv.actionsets.ReadjustTimeStepSizeForOptimisticGlobalTimestepping),
17 multiplies it with damp_time_step_size, and stores the result as
18 estimated time step size in the second entry. Afterwards, it updates the
19 patch interior with this damped time step size (@see
20 exahype2.api.fv.actionsets.UpdateCellInterior and
21 exahype2.api.fv.RusanovWithOptimisticExplicitEuler). As the admissible
22 time step size is never damped itself, the estimates do not shrink from
23 time step to time step.
24
25 The action set has to run before
26 exahype2.api.fv.actionsets.ComputeGlobalCFLCondition, which is why
27 exahype2.api.fv.RusanovWithOptimisticExplicitEuler makes the CFL
28 condition's task depend on the spawn's task. This way, the order in
29 which the tasks are added to the task graph does not matter. The CFL
30 condition advances the solver's time stamp and time step size
31 straightaway. Before it runs, the solver still holds the time stamp
32 and time step size of the current time step. The patch, however, has
33 already been advanced by the current time step. The patch interior
34 update hence starts from the solver's time stamp plus its time step
35 size.
36
37 If the admissible time step size is zero, i.e. in the very first time
38 step, there is nothing to estimate from. The action set then does not
39 update the patch interior. It sets the maximum eigenvalue of the patch
40 interior (third entry) to zero and the estimated time step size
41 (second entry) to the maximum double value, so the next time step
42 takes the traditional route.
43
44 ## Spawning the update as a task
45
46 If the action set is given the cell data holding a task number, it does
47 not update the patch interior straightaway. Instead, it takes a new task
48 number, stores it in the cell data, and spawns the update as a task
49 with this number. exahype2.api.fv.actionsets.InsertPatchInterior and
50 exahype2.api.fv.actionsets.DiscardPatchInterior wait for this task.
51 If there is nothing to update, the action set stores
52 tarch::multicore::TaskEnumerator::NoNumber instead.
53
54 The task captures the cell data by value. As the patch interior and the
55 eigenvalue data are managed via smart pointers, the task writes into the
56 cell's data. The patch, however, is handed to the task as a private copy,
57 as the next time step updates the patch's shell, which the task reads,
58 while the task might still be running. The time stamp and the time step
59 size are evaluated before the task is spawned, as the CFL condition
60 changes the solver's values afterwards.
61
62 """
63
64 def __init__(self, solver, damp_time_step_size, guard, task_number=None):
65 """!
66
67 @param solver: exahype2.api.Solver
68 Has to have solver._patch, solver._patch_interior,
69 solver._max_eigenvalue_and_time_step_sizes and
70 solver.compute_kernel_call_on_patch_interior set - @see
71 exahype2.api.fv.RusanovWithOptimisticExplicitEuler.
72
73 @param damp_time_step_size: float
74 Factor the solver's current time step size is scaled with to
75 obtain the estimated time step size of the patch interior update.
76
77 @param guard: str
78 C++ boolean expression, evaluated per cell in touchCellFirstTime,
79 guarding whether the patch interior of that cell is updated.
80
81 @param task_number: peano4.api.datamodel.DaStGen2
82 Cell data holding the number of the task updating the patch
83 interior. If None, the update runs straightaway.
84
85 """
86 AbstractFVActionSet.__init__(self, solver)
87 self.damp_time_step_size = damp_time_step_size
88 self.guard = guard
89 self.task_number = task_number
90 if task_number is None:
92 solver,
93 guard,
94 time_step_size="dampedTimeStepSize",
95 time_stamp=f"repositories::{solver.get_name_of_global_instance()}.getMinTimeStamp() + "
96 f"repositories::{solver.get_name_of_global_instance()}.getMinTimeStepSize()",
97 )
98 else:
100 solver,
101 guard,
102 time_step_size="dampedTimeStepSize",
103 time_stamp="timeStampOfPatchInteriorUpdate",
104 input="patchCopy->data()",
105 )
106
107 def get_body_of_operation(self, operation_name):
108 result = ""
109 if operation_name == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
110 solver = f"repositories::{self._solver.get_name_of_global_instance()}"
111 data = f"fineGridCell{self._solver._max_eigenvalue_and_time_step_sizes.name}"
112 update = self._update_cell_interior.get_body_of_operation(operation_name)
113 if self.task_number is None:
114 result = f"""
115 if ( tarch::la::equals({data}.getMaxEigenvalue(3), 0.0) ) {{
116 {data}.setMaxEigenvalue( 1, std::numeric_limits<double>::max() );
117 {data}.setMaxEigenvalue( 2, 0.0 );
118 }}
119 else {{
120 double dampedTimeStepSize = {self.damp_time_step_size} * {data}.getMaxEigenvalue(3);
121 {data}.setMaxEigenvalue( 1, dampedTimeStepSize );
122""" + update + """
123 }
124"""
125 else:
126 task_number = f"fineGridCell{self.task_number.name}"
127 patch = f"fineGridCell{self._solver._patch.name}"
128 result = f"""
129 if ( tarch::la::equals({data}.getMaxEigenvalue(3), 0.0) ) {{
130 {data}.setMaxEigenvalue( 1, std::numeric_limits<double>::max() );
131 {data}.setMaxEigenvalue( 2, 0.0 );
132 {task_number}.setTaskNumber( tarch::multicore::TaskEnumerator::NoNumber );
133 }}
134 else {{
135 const double dampedTimeStepSize = {self.damp_time_step_size} * {data}.getMaxEigenvalue(3);
136 const double timeStampOfPatchInteriorUpdate = {solver}.getMinTimeStamp() + {solver}.getMinTimeStepSize();
137 {data}.setMaxEigenvalue( 1, dampedTimeStepSize );
138
139 // The next time step updates the patch's shell while the task might still run
140 auto patchCopy = std::make_shared< std::vector<double> >( {patch}.Cardinality );
141 for (int i=0; i<{patch}.Cardinality; i++) {{
142 (*patchCopy)[i] = {patch}.value[i];
143 }}
144
145 const int taskNumber = {task_number}.getTaskEnumerator().getNumber();
146 {task_number}.setTaskNumber( taskNumber );
147 tarch::multicore::spawnTask(
148 new tarch::multicore::TaskWithCopyOfFunctor(
149 tarch::multicore::Task::DontFuse,
150 tarch::multicore::Task::DefaultPriority,
151 [=]() mutable {{
152""" + update + f"""
153 }}
154 ),
155 tarch::multicore::NoInDependencies,
156 taskNumber
157 );
158 }}
159"""
160 return result
161
162 def get_guard_of_operation(self, operation_name):
163 if operation_name == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
164 return self.guard
165 return "true"
166
167 def get_includes(self):
168 result = super().get_includes() + """
169#include <limits>
170#include "tarch/la/ScalarOperations.h"
171"""
172 if self.task_number is not None:
173 result += """
174#include <memory>
175#include <vector>
176#include "tarch/multicore/multicore.h"
177#include "tarch/multicore/Task.h"
178#include "tarch/multicore/TaskEnumerator.h"
179"""
180 return result
181
183 return __name__.replace(".py", "").replace(".", "_")
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...
Update the patch interior of a Finite Volume patch.