7 templateTouchVertexFirstTime =
"""
9 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary
11 repositories::{{SOLVER_INSTANCE}}.update( fineGridVertex{{SOLVER_NAME}}.getLevel() )
13 logTraceInWith1Argument("TouchVertexFirstTimeBoundary", fineGridVertex{{SOLVER_NAME}}.toString());
14 auto value = fineGridVertex{{SOLVER_NAME}}.getU();
15 repositories::{{SOLVER_INSTANCE}}.setBoundaryConditions(
20 fineGridVertex{{SOLVER_NAME}}.setU(value);
21 logTraceOutWith1Argument("TouchVertexFirstTimeBoundary", fineGridVertex{{SOLVER_NAME}}.toString());
24 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
26 repositories::{{SOLVER_INSTANCE}}.update( fineGridVertex{{SOLVER_NAME}}.getLevel() )
29 logTraceInWith3Arguments("TouchVertexFirstTimeInterior", fineGridVertex{{SOLVER_NAME}}.toString(), marker.x(), marker.h());
31 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
33 // we can pass the whole vector around, but intent is clearer this way
34 fineGridVertex{{SOLVER_NAME}}.setResidual( unknown, 0);
37 fineGridVertex{{SOLVER_NAME}}.setDiag(unknown, 0.0);
40 logTraceOutWith2Arguments("TouchVertexFirstTimeInterior", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
44 templateTouchVertexLastTime =
"""
46 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
48 repositories::{{SOLVER_INSTANCE}}.update( fineGridVertex{{SOLVER_NAME}}.getLevel() )
50 logTraceInWith3Arguments("TouchVertexLastTime", fineGridVertex{{SOLVER_NAME}}.toString(), marker.x(), marker.h());
52 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
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 );
57 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
58 double du = repositories::{{SOLVER_INSTANCE}}.Omega
59 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
61 // only care about solution on finest level...
63 fineGridVertex{{SOLVER_NAME}}.getLevel() == repositories::{{SOLVER_INSTANCE}}.getFinestLevel()
65 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual(r, marker.h());
66 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates(du, marker.h()(0));
69 fineGridVertex{{SOLVER_NAME}}.setU(unknown, fineGridVertex{{SOLVER_NAME}}.getU(unknown) + du);
70 logTraceOutWith1Argument("updateValue", fineGridVertex{{SOLVER_NAME}}.getU(unknown));
72 logTraceOutWith1Argument("TouchVertexLastTime", fineGridVertex{{SOLVER_NAME}}.toString());
76 templateTouchCellFirstTime =
"""
78 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
80 repositories::{{SOLVER_INSTANCE}}.update( fineGridCell{{SOLVER_NAME}}.getLevel() )
82 logTraceInWith3Arguments("Solve::touchCellFirstTime", fineGridCell{{SOLVER_NAME}}.toString(), marker.x(), marker.h());
83 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
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.
90 int startIndex = TwoPowerD * unknown;
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());
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);
108 vertexValues(i) = solColSum;
109 rhsValues(i) = rhsColSum;
110 residualValues(i) = fineGridVertices{{SOLVER_NAME}}(i).getResidual(unknown);
113 // residual = rhs - Ax
114 residualValues += rhsValues;
115 residualValues -= vertexValues;
117 for (int i=0; i<TwoPowerD; i++)
119 logTraceInWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
121 // increment fieldDiag
123 double diagVal = fineGridVertices{{SOLVER_NAME}}(i).getDiag(unknown);
126 fineGridVertices{{SOLVER_NAME}}(i).setDiag(unknown, diagVal);
128 // put new residual values back
129 fineGridVertices{{SOLVER_NAME}}(i).setResidual(unknown, residualValues(i));
131 logTraceOutWith1Argument("puttingValuesBack", fineGridVertices{{SOLVER_NAME}}(i).toString());
135 logTraceOutWith1Argument("Solve::touchCellFirstTime", fineGridCell{{SOLVER_NAME}}.toString());
140 descend_invocation_order=0,
142 super( CollocatedMGSolver, self ).
__init__(
143 descend_invocation_order,
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
153 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
156 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
159 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
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.
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.
182#include "repositories/SolverRepository.h"
183#include "peano4/utils/Loop.h"
184#include "mghype/matrixfree/solvers/CGMultigrid.h"
190 Configure name of generated C++ action set
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
199 return __name__.replace(
".py",
"").replace(
".",
"_") +
"_Solve"
get_action_set_name(self)
Configure name of generated C++ action set.
str templateTouchVertexFirstTime
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
str templateTouchCellFirstTime
str templateTouchVertexLastTime
__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)