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}}.updateResidual()
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}}.updateResidual()
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 templateTouchCellFirstTime =
"""
62 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
64 repositories::{{SOLVER_INSTANCE}}.updateResidual()
66 logTraceInWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
68 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
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.
75 int startIndex = TwoPowerD * unknown;
77 auto A = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h());
78 auto M = repositories::{{SOLVER_INSTANCE}}.getRhsMatrix(marker.x(), marker.h());
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++){
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);
93 vertexValues(i) = solColSum;
94 rhsValues(i) = rhsColSum;
95 residualValues(i) = fineGridVertices{{SOLVER_NAME}}(i).getResidual(unknown);
98 // residual = rhs - Ax
99 residualValues += rhsValues;
100 residualValues -= vertexValues;
102 for (int i=0; i<TwoPowerD; i++)
104 logTraceInWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
106 // increment fieldDiag
108 double diagVal = fineGridVertices{{SOLVER_NAME}}(i).getDiag(unknown);
111 fineGridVertices{{SOLVER_NAME}}(i).setDiag(unknown, diagVal);
113 // put new residual values back
114 fineGridVertices{{SOLVER_NAME}}(i).setResidual(unknown, residualValues(i));
116 logTraceOutWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
120 logTraceOutWith2Arguments("Solve::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
126 descend_invocation_order=1,
129 super( ResetAndUpdateResidual, self ).
__init__(
130 descend_invocation_order,
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
140 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
143 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
151 Configure name of generated C++ action set
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
160 return __name__.replace(
".py",
"").replace(
".",
"_")
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.
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.
180#include "../repositories/SolverRepository.h"
181#include "peano4/utils/Loop.h"
Action set (reactions to events)
Action set implementing the core of the collocated solver.
str templateTouchCellFirstTime
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=1, parallel=False)
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
str templateTouchVertexFirstTime
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_action_set_name(self)
Configure name of generated C++ action set.