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