10 Action set implementing the core of the collocated solver
12 The implementation is relatively straightforward:
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.
20 @TODO The boundary conditions are manually pinned to 0 during touchVertexLastTime.
21 This isn't good, and should be moved to implementation files.
24 templateTouchVertexFirstTime =
"""
26 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary
28 repositories::{{SOLVER_INSTANCE}}.update()
30 logTraceInWith2Arguments("TouchVertexFirstTime", marker.x(), fineGridVertex{{SOLVER_NAME}}.toString());
31 auto value = fineGridVertex{{SOLVER_NAME}}.getU();
32 repositories::{{SOLVER_INSTANCE}}.setBoundaryConditions(
37 fineGridVertex{{SOLVER_NAME}}.setU(value);
38 logTraceOutWith2Arguments("TouchVertexFirstTime", marker.x(), fineGridVertex{{SOLVER_NAME}}.toString());
41 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
43 repositories::{{SOLVER_INSTANCE}}.update()
45 logTraceInWith2Arguments("TouchVertexFirstTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
47 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
49 // we can pass the whole vector around, but intent is clearer this way
50 fineGridVertex{{SOLVER_NAME}}.setResidual( unknown, 0);
53 fineGridVertex{{SOLVER_NAME}}.setDiag(unknown, 0.0);
56 logTraceOutWith2Arguments("TouchVertexFirstTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
60 templateTouchVertexLastTime =
"""
62 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
64 repositories::{{SOLVER_INSTANCE}}.update()
66 logTraceInWith2Arguments("TouchVertexLastTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
68 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
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 );
73 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
74 double du = repositories::{{SOLVER_INSTANCE}}.Omega
75 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
77 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual(
80 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates(
83 repositories::{{SOLVER_INSTANCE}}.updateMinMaxMeshSize( marker.h() );
85 fineGridVertex{{SOLVER_NAME}}.setU(unknown, fineGridVertex{{SOLVER_NAME}}.getU(unknown) + du );
86 logTraceOutWith1Argument("updateValue", fineGridVertex{{SOLVER_NAME}}.getU(unknown));
88 logTraceOutWith2Arguments("TouchVertexLastTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
91 if ( fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary ) {
93 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
94 fineGridVertex{{SOLVER_NAME}}.setU(unknown, value);
99 templateTouchCellFirstTime =
"""
101 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
103 repositories::{{SOLVER_INSTANCE}}.update()
105 logTraceInWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
107 repositories::{{SOLVER_INSTANCE}}.updateMinMaxMeshSize(
111 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
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;
120 auto A = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h());
121 auto M = repositories::{{SOLVER_INSTANCE}}.getMassMatrix(marker.x(), marker.h());
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);
136 vertexValues(i) = solColSum;
137 rhsValues(i) = rhsColSum;
138 residualValues(i) = fineGridVertices{{SOLVER_NAME}}(i).getResidual(unknown);
141 // residual = rhs - Ax
142 residualValues += rhsValues;
143 residualValues -= vertexValues;
145 for (int i=0; i<TwoPowerD; i++)
147 logTraceInWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
149 // increment fieldDiag
151 double diagVal = fineGridVertices{{SOLVER_NAME}}(i).getDiag(unknown);
154 fineGridVertices{{SOLVER_NAME}}(i).setDiag(unknown, diagVal);
156 // put new residual values back
157 fineGridVertices{{SOLVER_NAME}}(i).setResidual(unknown, residualValues(i));
159 logTraceOutWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
163 logTraceOutWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
169 super( CollocatedSolver, self ).
__init__()
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
177 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
180 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
183 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
191 Configure name of generated C++ action set
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
200 return __name__.replace(
".py",
"").replace(
".",
"_")
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.
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.
220#include "../repositories/SolverRepository.h"
221#include "peano4/utils/Loop.h"
Action set implementing the core of the collocated solver.
str templateTouchVertexFirstTime
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...
str templateTouchCellFirstTime
get_action_set_name(self)
Configure name of generated C++ action set.
str templateTouchVertexLastTime
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Action set (reactions to events)