8 We use this action set to apply the residual and solution updates to the vertices
10 Logically, this should be the final step in a sweep whilst we are solving, but due
11 to the fact that we need to perform synchronisation between vertices on parallel
12 boundaries before continuing to update, restrict or prolongate, we move the
13 residual/solution updates into its own action set. We push this action set into
14 the following sweep, since vertex synchronisation happens after the traversal has
15 begun, but before any action sets are invoked.
18 The idea is then to perform the following:
21 - updateSolution (but not on the first stage)
22 - ResetAndUpdateResidual
25 To facilitate this, we add in a new bool function to the abstract solver class (and
26 rename the existing one). Previously we would update if we are on the active level
27 and in any of the solver states. We should now change this.
29 Solving gets its own sweep, and we lump in Restriction and Prolongation together,
30 which should be able to run in parallel.
32 We can then have two bool functions - updateResidual() and updateSolution().
34 updateResidual() should return true if we are on the active level and in the
35 smoothing state either PreSmoothing or PostSmoothing.
37 updateSolution() should return true if:
38 - We are on the active level, the smoothing state is either PreSmoothing or PostSmoothing
39 and the relevant counter is at least 1 (prevents division by 0 error with diag == 0)
40 - We are in phase Restriction, and we are on the active level. Note that moving to the
41 restriction phase does not(!) move the activeLevel. We then finish updating
42 the solution to be restricted during touchVertexFirstTime. Since we are setting quantities
43 on the level above (ie coarser), we then do restriction during touchVertexLastTime
44 - We are in the phase prolongation, and we are one above the active level. Prolongation
45 grabs data from the level above during touchVertexFirstTime.
47 Since we need to synchronise the solution/rhs data after restriction and prolongation, we
48 separate these out into separate sweeps.
51 templateTouchVertexFirstTime=
"""
53 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
55 repositories::{{SOLVER_INSTANCE}}.updateSolution( fineGridVertex{{SOLVER_NAME}}.getLevel() )
57 logTraceInWith3Arguments("TouchVertexLastTime", fineGridVertex{{SOLVER_NAME}}.toString(), marker.x(), marker.h());
59 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
61 logTraceInWith3Arguments("updateValue", fineGridVertex{{SOLVER_NAME}}.getU(unknown), fineGridVertex{{SOLVER_NAME}}.getDiag(unknown), fineGridVertex{{SOLVER_NAME}}.getResidual(unknown));
62 assertion( fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) > 0 );
64 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
65 double du = repositories::{{SOLVER_INSTANCE}}.Omega
66 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
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());
74 // only care about solution on finest level...
76 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
78 repositories::{{SOLVER_INSTANCE}}.reportSolutionUpdates( fineGridVertex{{SOLVER_NAME}}.getLevel() )
80 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++) {
81 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
82 double du = repositories::{{SOLVER_INSTANCE}}.Omega
83 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
85 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual(r, marker.h());
86 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates(du, marker.h()(0));
93 descend_invocation_order=0,
95 super( UpdateSolution, self ).
__init__(
96 descend_invocation_order,
100 self.
d[
"SOLVER_INSTANCE"] = solver.instance_name()
101 self.
d[
"SOLVER_NAME"] = solver.typename()
102 self.
d[
"VERTEX_CARDINALITY"] = solver._unknowns_per_vertex_node
106 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
114 The action set that Peano will generate that corresponds to this class
115 should not be modified by users and can safely be overwritten every time
116 we run the Python toolkit.
124 We need the solver repository in this action set, as we directly access
125 the solver object. We also need access to Peano's d-dimensional loops.
129#include "repositories/SolverRepository.h"
130#include "peano4/utils/Loop.h"
131#include "mghype/matrixfree/solvers/CGMultigrid.h"
137 Configure name of generated C++ action set
139 This action set will end up in the directory observers with a name that
140 reflects how the observer (initialisation) is mapped onto this action
141 set. The name pattern is ObserverName2ActionSetIdentifier where this
142 routine co-determines the ActionSetIdentifier. We make is reflect the
146 return __name__.replace(
".py",
"").replace(
".",
"_")
Action set (reactions to events)
We use this action set to apply the residual and solution updates to the vertices.
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...
__init__(self, solver, descend_invocation_order=0, parallel=False)
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
get_action_set_name(self)
Configure name of generated C++ action set.
str templateTouchVertexFirstTime