Peano
Loading...
Searching...
No Matches
CollocatedSolver.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}}.update()
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}}.update()
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 templateTouchVertexLastTime = """
61 if (
62 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
63 and
64 repositories::{{SOLVER_INSTANCE}}.update()
65 ) {
66 logTraceInWith2Arguments("TouchVertexLastTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
67
68 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
69 {
70 logTraceInWith3Arguments("updateValue", fineGridVertex{{SOLVER_NAME}}.getU(unknown), fineGridVertex{{SOLVER_NAME}}.getDiag(unknown), fineGridVertex{{SOLVER_NAME}}.getResidual(unknown));
71 assertion( fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) > 0 );
72
73 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
74 double du = repositories::{{SOLVER_INSTANCE}}.Omega
75 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
76
77 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual(
78 r, marker.h()
79 );
80 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates(
81 du, marker.h()(0)
82 );
83 repositories::{{SOLVER_INSTANCE}}.updateMinMaxMeshSize( marker.h() );
84
85 fineGridVertex{{SOLVER_NAME}}.setU(unknown, fineGridVertex{{SOLVER_NAME}}.getU(unknown) + du );
86 logTraceOutWith1Argument("updateValue", fineGridVertex{{SOLVER_NAME}}.getU(unknown));
87 }
88 logTraceOutWith2Arguments("TouchVertexLastTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
89 }
90
91 if ( fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary ) {
92 auto value = 0.0;
93 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
94 fineGridVertex{{SOLVER_NAME}}.setU(unknown, value);
95 }
96 }
97 """
98
99 templateTouchCellFirstTime = """
100 if (
101 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
102 and
103 repositories::{{SOLVER_INSTANCE}}.update()
104 ) {
105 logTraceInWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
106
107 repositories::{{SOLVER_INSTANCE}}.updateMinMaxMeshSize(
108 marker.h()
109 );
110
111 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
112 {
113 // Mass and assembly matrix should be block diagonal,
114 // depending on which unknown we are currently dealing with.
115 // We will collect the rhs & solution values from the
116 // vertices, and apply the correct matrix as we go.
117 // Define the offset:
118 int startIndex = TwoPowerD * unknown;
119
120 auto A = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h());
121 auto M = repositories::{{SOLVER_INSTANCE}}.getMassMatrix(marker.x(), marker.h());
122
123 // collect all of the vertex values into one vector - apply the appropriate
124 // part of the matrix as we go.
125 tarch::la::Vector<TwoPowerD, double> vertexValues;
126 tarch::la::Vector<TwoPowerD, double> rhsValues;
127 tarch::la::Vector<TwoPowerD, double> residualValues;
128 for (int i=0; i<TwoPowerD; i++){
129 double solColSum = 0;
130 double rhsColSum = 0;
131 for (int j=0; j<TwoPowerD; j++){
132 solColSum += A(startIndex+i, startIndex+j) * fineGridVertices{{SOLVER_NAME}}(j).getU(unknown);
133 rhsColSum += M(startIndex+i, startIndex+j) * fineGridVertices{{SOLVER_NAME}}(j).getRhs(unknown);
134 }
135
136 vertexValues(i) = solColSum;
137 rhsValues(i) = rhsColSum;
138 residualValues(i) = fineGridVertices{{SOLVER_NAME}}(i).getResidual(unknown);
139 }
140
141 // residual = rhs - Ax
142 residualValues += rhsValues;
143 residualValues -= vertexValues;
144
145 for (int i=0; i<TwoPowerD; i++)
146 {
147 logTraceInWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
148
149 // increment fieldDiag
150 // get current val
151 double diagVal = fineGridVertices{{SOLVER_NAME}}(i).getDiag(unknown);
152 // increment it
153 diagVal += A(i,i);
154 fineGridVertices{{SOLVER_NAME}}(i).setDiag(unknown, diagVal);
155
156 // put new residual values back
157 fineGridVertices{{SOLVER_NAME}}(i).setResidual(unknown, residualValues(i));
158
159 logTraceOutWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
160 }
161
162 }
163 logTraceOutWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
164 }
165 """
166
167 def __init__(self,
168 solver):
169 super( CollocatedSolver, self ).__init__()
170 self.d = {}
171 self.d["SOLVER_INSTANCE"] = solver.instance_name()
172 self.d["SOLVER_NAME"] = solver.typename()
173 self.d["VERTEX_CARDINALITY"] = solver._unknowns_per_vertex_node
174
175 def get_body_of_operation(self,operation_name):
176 result = ""
177 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
178 result = jinja2.Template(self.templateTouchVertexFirstTime).render(**self.d)
179 pass
180 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
181 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
182 pass
183 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
184 result = jinja2.Template(self.templateTouchVertexLastTime).render(**self.d)
185 pass
186 return result
187
189 """!
190
191 Configure name of generated C++ action set
192
193 This action set will end up in the directory observers with a name that
194 reflects how the observer (initialisation) is mapped onto this action
195 set. The name pattern is ObserverName2ActionSetIdentifier where this
196 routine co-determines the ActionSetIdentifier. We make is reflect the
197 Python class name.
198
199 """
200 return __name__.replace(".py", "").replace(".", "_")
201
203 """!
204
205 The action set that Peano will generate that corresponds to this class
206 should not be modified by users and can safely be overwritten every time
207 we run the Python toolkit.
208
209 """
210 return False
211
212 def get_includes(self):
213 """!
214
215 We need the solver repository in this action set, as we directly access
216 the solver object. We also need access to Peano's d-dimensional loops.
217
218 """
219 return """
220#include "../repositories/SolverRepository.h"
221#include "peano4/utils/Loop.h"
222"""
Action set implementing the core of the collocated solver.
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_action_set_name(self)
Configure name of generated C++ action set.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Action set (reactions to events)
Definition ActionSet.py:6