Peano
Loading...
Searching...
No Matches
UpdateResidualWithTasks.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import peano4
4import jinja2
5
6
8 """!
9
10 This is for DG solver
11
12 @todo Documntation missing
13
14 """
15 templateTouchCellFirstTime="""
16 if (
17 fineGridCell{{SOLVER_NAME}}.getType() != celldata::{{SOLVER_NAME}}::Type::Coarse
18 and
19 // only one condition here - ensures that we don't do this when restricting the residual
20 repositories::{{SOLVER_INSTANCE}}.updateResidual()
21 ) {
22 logTraceInWith4Arguments("touchCellFirstTime(...)",
23 fineGridCell{{SOLVER_NAME}}.getSolution(),
24 fineGridCell{{SOLVER_NAME}}.getRhs(),
25 marker.toString(),
26 repositories::{{SOLVER_INSTANCE}}.getRhsMatrix( marker.x(), marker.h() )
27 );
28
29 const int OperatorSize = {{SOLVER_NAME}}::CellUnknowns * {{SOLVER_NAME}}::CellUnknowns;
30
31 /**
32 * Lazy allocation of memory. In this particular realisation, it is never
33 * released. In principle, that's a reasonable strategy, although we might
34 * want to re-evaluate it later.
35 */
36 if (fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix()==nullptr) {
37 fineGridCell{{SOLVER_NAME}}.setInverseOfSystemMatrix(
38 tarch::allocateMemory<double>( OperatorSize, tarch::MemoryLocation::Heap )
39 );
40 }
41
42 auto rhsPointer = fineGridCell{{SOLVER_NAME}}.getRhsSmartPointer();
43 auto solutionPointer = fineGridCell{{SOLVER_NAME}}.getSolutionSmartPointer();
44 auto residualPointer = fineGridCell{{SOLVER_NAME}}.getResidualSmartPointer();
45 double* inverseOperator = fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix();
46
47 /**
48 * Without the mutable keyword, the copied four arguments will stay const.
49 * C++ then complains as any assignment to a const copy becomes invalid.
50 *
51 * @todo There might be a lot of scope for optimisation
52 *
53 * It remains an open question to which degree these implementations can be
54 * optimised if we avoid copying forth and back into tarch vectors. We
55 * could set residualPointer to zero and then accumulate the outcome
56 * directly into this smart pointer.
57 */
58 auto updateResidualFunctor = [rhsPointer, solutionPointer, residualPointer, marker]() mutable -> void {
59 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > r =
60 repositories::{{SOLVER_INSTANCE}}.applyRhsMatrix( marker.x(), marker.h(), rhsPointer.toVector() );
61
62 r = r - repositories::{{SOLVER_INSTANCE}}.applyLocalAssemblyMatrix(marker.x(), marker.h(), solutionPointer.toVector() );
63
64 residualPointer = r;
65 };
66
67
68 /**
69 * Issue the calculation of the inverse of the system matrix
70 */
71 auto invertMatrixFunctor = [inverseOperator, marker, OperatorSize]() mutable -> void {
72 std::memcpy(
73 inverseOperator,
74 repositories::{{SOLVER_INSTANCE}}.getInvertedApproxSystemMatrix(
75 marker.x(),
76 marker.h()
77 ).data(),
78 sizeof(double)*OperatorSize
79 );
80 };
81
82
83 static int residualTaskType = peano4::parallel::getTaskType("{{SOLVER_INSTANCE}}::UpdateResidualTask");
84 static int invertMatrixTaskType = peano4::parallel::getTaskType("{{SOLVER_INSTANCE}}::InvertTask");
85 tarch::multicore::TaskWithCopyOfFunctor* updateResidualTask = new tarch::multicore::TaskWithCopyOfFunctor(
86 residualTaskType,
87 tarch::multicore::Task::DefaultPriority,
88 updateResidualFunctor
89 );
90 tarch::multicore::TaskWithCopyOfFunctor* invertMatrixTask = new tarch::multicore::TaskWithCopyOfFunctor(
91 invertMatrixTaskType,
92 tarch::multicore::Task::DefaultPriority,
93 invertMatrixFunctor
94 );
95
96
97 int taskNumber = fineGridCell{{TASK_MARKER}}.getNumber() * 2;
98 tarch::multicore::spawnTask(
99 updateResidualTask,
100 tarch::multicore::NoInDependencies,
101 taskNumber+0
102 );
103 tarch::multicore::spawnTask(
104 invertMatrixTask,
105 tarch::multicore::NoInDependencies,
106 taskNumber+1
107 );
108
109 logTraceOut("touchCellFirstTime(...)");
110 }
111 """
112
113
114 def __init__(self,
115 solver,
116 descend_invocation_order=0,
117 parallel=True):
118 super( UpdateResidualWithTasks, self ).__init__(
119 descend_invocation_order,
120 parallel
121 )
122 self.d = {}
123 self.d["SOLVER_INSTANCE"] = solver.instance_name()
124 self.d["SOLVER_NAME"] = solver.typename()
125 self.d["TASK_MARKER"] = solver._task_name + "MeshNumber"
126
127 def get_body_of_operation(self,operation_name):
128 result = ""
129 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
130 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
131 pass
132 return result
133
135 """!
136
137 Configure name of generated C++ action set
138
139 This action set will end up in the directory observers with a name that
140 reflects how the observer (initialisation) is mapped onto this action
141 set. The name pattern is ObserverName2ActionSetIdentifier where this
142 routine co-determines the ActionSetIdentifier. We make is reflect the
143 Python class name.
144
145 """
146 return __name__.replace(".py", "").replace(".", "_")
147
149 """!
150
151 The action set that Peano will generate that corresponds to this class
152 should not be modified by users and can safely be overwritten every time
153 we run the Python toolkit.
154
155 """
156 return False
157
158 def get_includes(self):
159 """!
160
161 We need the solver repository in this action set, as we directly access
162 the solver object. We also need access to Peano's d-dimensional loops.
163
164 """
165 return """
166#include "../repositories/SolverRepository.h"
167
168#include "peano4/utils/Loop.h"
169#include "tarch/multicore/Task.h"
170#include "tarch/multicore/multicore.h"
171
172#include <cstring>
173"""
Action set (reactions to events)
Definition ActionSet.py:6
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.