Peano
Loading...
Searching...
No Matches
UpdateSolution.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import peano4
4import jinja2
5
7 """!
8 We use this action set to apply the residual and solution updates to the vertices
9
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.
16
17
18 The idea is then to perform the following:
19
20 During Solve stage:
21 - updateSolution (but not on the first stage)
22 - ResetAndUpdateResidual
23 - New sweep
24
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.
28
29 Solving gets its own sweep, and we lump in Restriction and Prolongation together,
30 which should be able to run in parallel.
31
32 We can then have two bool functions - updateResidual() and updateSolution().
33
34 updateResidual() should return true if we are on the active level and in the
35 smoothing state either PreSmoothing or PostSmoothing.
36
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.
46
47 Since we need to synchronise the solution/rhs data after restriction and prolongation, we
48 separate these out into separate sweeps.
49 """
50
51 templateTouchVertexFirstTime="""
52 if (
53 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
54 and
55 repositories::{{SOLVER_INSTANCE}}.updateSolution( fineGridVertex{{SOLVER_NAME}}.getLevel() )
56 ) {
57 logTraceInWith3Arguments("TouchVertexLastTime", fineGridVertex{{SOLVER_NAME}}.toString(), marker.x(), marker.h());
58
59 for (int unknown=0; unknown<{{VERTEX_CARDINALITY}}; unknown++)
60 {
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 );
63
64 double r = fineGridVertex{{SOLVER_NAME}}.getResidual(unknown);
65 double du = repositories::{{SOLVER_INSTANCE}}.Omega
66 * 1.0 / fineGridVertex{{SOLVER_NAME}}.getDiag(unknown) * r;
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 // only care about solution on finest level...
75 if (
76 fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Interior
77 and
78 repositories::{{SOLVER_INSTANCE}}.reportSolutionUpdates( fineGridVertex{{SOLVER_NAME}}.getLevel() )
79 ) {
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;
84
85 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual(r, marker.h());
86 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates(du, marker.h()(0));
87 }
88 }
89 """
90
91 def __init__(self,
92 solver,
93 descend_invocation_order=0,
94 parallel=False):
95 super( UpdateSolution, self ).__init__(
96 descend_invocation_order,
97 parallel
98 )
99 self.d = {}
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
103
104 def get_body_of_operation(self,operation_name):
105 result = ""
106 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
107 result = jinja2.Template(self.templateTouchVertexFirstTime).render(**self.d)
108 pass
109 return result
110
112 """!
113
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.
117
118 """
119 return False
120
121 def get_includes(self):
122 """!
123
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.
126
127 """
128 return """
129#include "repositories/SolverRepository.h"
130#include "peano4/utils/Loop.h"
131#include "mghype/matrixfree/solvers/CGMultigrid.h"
132"""
133
135 """!
136
137 Configure name of generated C++ action set
138
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
143 Python class name.
144
145 """
146 return __name__.replace(".py", "").replace(".", "_")
Action set (reactions to events)
Definition ActionSet.py:6
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.