Peano
Loading...
Searching...
No Matches
UpdateFacets.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3from peano4.solversteps.ActionSet import ActionSet
4
5import peano4
6import jinja2
7
8
10 """!
11
12 Action set implementing the facet update of the continuous Galerkin solver
13
14 There are two key elements/events here:
15
16 - When we hit the face, we compute the update due to the Jacobi solver and
17 subsequently clear all the data that is accumulated. We don't need it
18 anymore as we have already determined the face update.
19 - When we hit the cell, we first map the facet update onto the cell. Now we
20 have an updated cell guess. After that, we immediately compute the residual
21 and throw it back onto the facet.
22
23 The latter step might seem to be stupid: After all, we could first update the
24 cell interior and then use the updated solution to determine a residual for
25 the facet. This would be a proper block-Jacobi. However, I prefer a pure
26 Jacobi here, as it allows us to deploy the block update onto a separate task.
27
28 The key properties of the solver that we use here are the following ones:
29
30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31self._degrees_of_freedom_per_cell = unknowns_per_node * ( polynomial_degree + 1) ** dimensions
32self._degrees_of_freedom_per_face = unknowns_per_node * ( polynomial_degree + 1) ** (dimensions-1)
33self._inner_degrees_of_freedom_per_cell = unknowns_per_node * ( polynomial_degree - 1) ** dimensions
34
35self._cell_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "solution", str(self._degrees_of_freedom_per_cell) ))
36self._cell_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "residual", str(self._degrees_of_freedom_per_cell) ))
37self._cell_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "rhs", str(self._degrees_of_freedom_per_cell) ))
38
39self._face_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "residual", str(self._degrees_of_freedom_per_face) ))
40self._face_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "diagonal", str(self._degrees_of_freedom_per_face) ))
41self._face_data.data.add_attribute(peano4.dastgen2.Peano4DoubleArray( "deltaU", str(self._degrees_of_freedom_per_face) ))
42 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43
44 Which map onto the
45
46 """
47 templateTouchFaceFirstTime="""
48 if (
49 fineGridFace{{SOLVER_NAME}}.getType() == facedata::{{SOLVER_NAME}}::Type::Interior
50 and
51 repositories::{{SOLVER_INSTANCE}}.updateFace()
52 ) {
53 logTraceInWith3Arguments( "touchFaceFirstTime", fineGridFace{{SOLVER_NAME}}.getResidual(), fineGridFace{{SOLVER_NAME}}.getDiagonal(), marker.toString() );
54
55 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknowns; i++) {
56 // in the first step, diagonal is zero
57 if ( tarch::la::equals(fineGridFace{{SOLVER_NAME}}.getDiagonal(i),0.0) ) {
58 fineGridFace{{SOLVER_NAME}}.setDeltaU( i, 0.0 );
59 }
60 else {
61 double du = repositories::{{SOLVER_INSTANCE}}.OmegaFace / fineGridFace{{SOLVER_NAME}}.getDiagonal(i) * fineGridFace{{SOLVER_NAME}}.getResidual(i);
62 repositories::{{SOLVER_INSTANCE}}.updateGlobalResidual( fineGridFace{{SOLVER_NAME}}.getResidual(i), marker.h() );
63 repositories::{{SOLVER_INSTANCE}}.updateGlobalSolutionUpdates( du, marker.h() );
64 assertion( du==du );
65 assertion( not std::isnan(du) );
66 fineGridFace{{SOLVER_NAME}}.setDeltaU( i, du );
67 }
68 fineGridFace{{SOLVER_NAME}}.setResidual( i, 0.0 );
69 fineGridFace{{SOLVER_NAME}}.setDiagonal( i, 0.0 );
70 }
71
72 logTraceOutWith1Argument( "touchFaceFirstTime", fineGridFace{{SOLVER_NAME}}.getDeltaU() );
73 }
74 else {
75 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknowns; i++) {
76 fineGridFace{{SOLVER_NAME}}.setDeltaU( i, 0.0 );
77 fineGridFace{{SOLVER_NAME}}.setResidual( i, 0.0 );
78 fineGridFace{{SOLVER_NAME}}.setDiagonal( i, 0.0 );
79 }
80 }
81"""
82
83 templateTouchCellFirstTime = """
84 if (
85 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
86 and
87 repositories::{{SOLVER_INSTANCE}}.updateCell()
88 ) {
89 logTraceInWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
90
91 // ==============================
92 // project updates into the cells
93 // ==============================
94 // @todo Very similar to Alex's matrix calibration discussion on Slack,
95 // there is some scaling missing here.
96 for (int d=0; d<Dimensions; d++) {
97 int unknownInPreimage = 0;
98 dfore(node,repositories::{{SOLVER_INSTANCE}}.PolyDegree+1,d,0) {
99 tarch::la::Vector< Dimensions, int > nodeOnLeftSideOfImage = node;
100 tarch::la::Vector< Dimensions, int > nodeOnRightSideOfImage = node;
101 nodeOnLeftSideOfImage(d) = 0;
102 nodeOnRightSideOfImage(d) = repositories::{{SOLVER_INSTANCE}}.PolyDegree;
103
104 for (int unknown=0; unknown<repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode; unknown++) {
105 int unknownInLeftImage = peano4::utils::dLinearised( nodeOnLeftSideOfImage, repositories::{{SOLVER_INSTANCE}}.PolyDegree+1) * repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode + unknown;
106 int unknownInRightImage = peano4::utils::dLinearised( nodeOnRightSideOfImage, repositories::{{SOLVER_INSTANCE}}.PolyDegree+1) * repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode + unknown;
107
108 double update;
109 update = fineGridFaces{{SOLVER_NAME}}( d ).getDeltaU(unknownInPreimage);
110 assertion( update==update );
111 assertion( not std::isnan(update) );
112 fineGridCell{{SOLVER_NAME}}.setSolution(
113 unknownInLeftImage,
114 fineGridCell{{SOLVER_NAME}}.getSolution(unknownInLeftImage) +
115 update
116 );
117 update = fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).getDeltaU(unknownInPreimage);
118 assertion( not std::isnan(update) );
119 fineGridCell{{SOLVER_NAME}}.setSolution(
120 unknownInRightImage,
121 fineGridCell{{SOLVER_NAME}}.getSolution(unknownInRightImage) +
122 update
123 );
124
125 unknownInPreimage++;
126 }
127 }
128 }
129
130 logTraceOutWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
131 }
132 """
133
134 def __init__(self,
135 solver):
136 super( UpdateFacets, self ).__init__()
137 self.d = {}
138 self.d["SOLVER_INSTANCE"] = solver.instance_name()
139 self.d["SOLVER_NAME"] = solver.typename()
140
141 def get_body_of_operation(self,operation_name):
142 result = ""
143 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
144 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
145 pass
146 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME:
147 result = jinja2.Template(self.templateTouchFaceFirstTime).render(**self.d)
148 pass
149 return result
150
152 """!
153
154 Configure name of generated C++ action set
155
156 This action set will end up in the directory observers with a name that
157 reflects how the observer (initialisation) is mapped onto this action
158 set. The name pattern is ObserverName2ActionSetIdentifier where this
159 routine co-determines the ActionSetIdentifier. We make is reflect the
160 Python class name.
161
162 """
163 return __name__.replace(".py", "").replace(".", "_")
164
166 """!
167
168 The action set that Peano will generate that corresponds to this class
169 should not be modified by users and can safely be overwritten every time
170 we run the Python toolkit.
171
172 """
173 return False
174
175 def get_includes(self):
176 """!
177
178 We need the solver repository in this action set, as we directly access
179 the solver object. We also need access to Peano's d-dimensional loops.
180
181 """
182 return """
183#include "../repositories/SolverRepository.h"
184#include "peano4/utils/Loop.h"
185"""
Action set implementing the facet update of the continuous Galerkin solver.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
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.
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)
Definition ActionSet.py:6