Peano
Loading...
Searching...
No Matches
ResetAndUpdateResidual.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import peano4
4import jinja2
5
6
8 """!
9
10 Action set implementing the core of the collocated solver
11
12 The implementation is relatively straightforward:
13
14 - We clear diag and the residual when we hit a vertex for the first time.
15 - In each cell, we accumulate the residual. This is the contribution from
16 @f$ Ax = Mb @f$ as it stems from the current cell.
17 - In touchVertexFirstTime(), we can update the unknown.
18 - Eventually, we dump the total residual and the updates.
19
20 @TODO The boundary conditions are manually pinned to 0 during touchVertexLastTime.
21 This isn't good, and should be moved to implementation files.
22
23 """
24 templateTouchVertexFirstTime = """
25 if (
26 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary
27 and
28 repositories::{{SOLVER_INSTANCE}}.updateResidual()
29 ) {
30 logTraceInWith2Arguments("TouchVertexFirstTime", marker.x(), fineGridVertex{{SOLVER_NAME}}.toString());
31 auto value = fineGridVertex{{SOLVER_NAME}}.getU();
32 repositories::{{SOLVER_INSTANCE}}.setBoundaryConditions(
33 marker.x(),
34 marker.h(),
35 value
36 );
37 fineGridVertex{{SOLVER_NAME}}.setU(value);
38 logTraceOutWith2Arguments("TouchVertexFirstTime", marker.x(), fineGridVertex{{SOLVER_NAME}}.toString());
39 }
40 else if (
41 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
42 and
43 repositories::{{SOLVER_INSTANCE}}.updateResidual()
44 ) {
45 logTraceInWith2Arguments("TouchVertexFirstTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
46
47 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
48 // set residual to 0
49 // we can pass the whole vector around, but intent is clearer this way
50 fineGridVertex{{SOLVER_NAME}}.setResidual( unknown, 0);
51
52 // set diag to 0
53 fineGridVertex{{SOLVER_NAME}}.setDiag(unknown, 0.0);
54 }
55
56 logTraceOutWith2Arguments("TouchVertexFirstTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
57 }
58 """
59
60 templateTouchCellFirstTime = """
61 if (
62 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
63 and
64 repositories::{{SOLVER_INSTANCE}}.updateResidual()
65 ) {
66 logTraceInWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
67
68 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
69 {
70 // Mass and assembly matrix should be block diagonal,
71 // depending on which unknown we are currently dealing with.
72 // We will collect the rhs & solution values from the
73 // vertices, and apply the correct matrix as we go.
74 // Define the offset:
75 int startIndex = TwoPowerD * unknown;
76
77 auto A = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h());
78 auto M = repositories::{{SOLVER_INSTANCE}}.getRhsMatrix(marker.x(), marker.h());
79
80 // collect all of the vertex values into one vector - apply the appropriate
81 // part of the matrix as we go.
82 tarch::la::Vector<TwoPowerD, double> vertexValues;
83 tarch::la::Vector<TwoPowerD, double> rhsValues;
84 tarch::la::Vector<TwoPowerD, double> residualValues;
85 for (int i=0; i<TwoPowerD; i++){
86 double solColSum = 0;
87 double rhsColSum = 0;
88 for (int j=0; j<TwoPowerD; j++){
89 solColSum += A(startIndex+i, startIndex+j) * fineGridVertices{{SOLVER_NAME}}(j).getU(unknown);
90 rhsColSum += M(startIndex+i, startIndex+j) * fineGridVertices{{SOLVER_NAME}}(j).getRhs(unknown);
91 }
92
93 vertexValues(i) = solColSum;
94 rhsValues(i) = rhsColSum;
95 residualValues(i) = fineGridVertices{{SOLVER_NAME}}(i).getResidual(unknown);
96 }
97
98 // residual = rhs - Ax
99 residualValues += rhsValues;
100 residualValues -= vertexValues;
101
102 for (int i=0; i<TwoPowerD; i++)
103 {
104 logTraceInWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
105
106 // increment fieldDiag
107 // get current val
108 double diagVal = fineGridVertices{{SOLVER_NAME}}(i).getDiag(unknown);
109 // increment it
110 diagVal += A(i,i);
111 fineGridVertices{{SOLVER_NAME}}(i).setDiag(unknown, diagVal);
112
113 // put new residual values back
114 fineGridVertices{{SOLVER_NAME}}(i).setResidual(unknown, residualValues(i));
115
116 logTraceOutWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
117 }
118
119 }
120 logTraceOutWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
121 }
122 """
123
124 def __init__(self,
125 solver,
126 descend_invocation_order=1,
127 parallel=False
128 ):
129 super( ResetAndUpdateResidual, self ).__init__(
130 descend_invocation_order,
131 parallel
132 )
133 self.d = {}
134 self.d["SOLVER_INSTANCE"] = solver.instance_name()
135 self.d["SOLVER_NAME"] = solver.typename()
136 self.d["VERTEX_CARDINALITY"] = solver._unknowns_per_vertex_node
137
138 def get_body_of_operation(self,operation_name):
139 result = ""
140 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
141 result = jinja2.Template(self.templateTouchVertexFirstTime).render(**self.d)
142 pass
143 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
144 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
145 pass
146 return result
147
149 """!
150
151 Configure name of generated C++ action set
152
153 This action set will end up in the directory observers with a name that
154 reflects how the observer (initialisation) is mapped onto this action
155 set. The name pattern is ObserverName2ActionSetIdentifier where this
156 routine co-determines the ActionSetIdentifier. We make is reflect the
157 Python class name.
158
159 """
160 return __name__.replace(".py", "").replace(".", "_")
161
163 """!
164
165 The action set that Peano will generate that corresponds to this class
166 should not be modified by users and can safely be overwritten every time
167 we run the Python toolkit.
168
169 """
170 return False
171
172 def get_includes(self):
173 """!
174
175 We need the solver repository in this action set, as we directly access
176 the solver object. We also need access to Peano's d-dimensional loops.
177
178 """
179 return """
180#include "../repositories/SolverRepository.h"
181#include "peano4/utils/Loop.h"
182"""
Action set (reactions to events)
Definition ActionSet.py:6
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.