Peano
Loading...
Searching...
No Matches
ProjectResidualsAndDiagonalOntoFacets.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
48 templateTouchCellFirstTime = """
49 if (
50 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
51 and
52 repositories::{{SOLVER_INSTANCE}}.updateCell()
53 ) {
54 logTraceInWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
55
56 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > r =
57 repositories::{{SOLVER_INSTANCE}}.getRhsMatrix( marker.x(), marker.h() ) * fineGridCell{{SOLVER_NAME}}.getRhs();
58 r = r - repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * fineGridCell{{SOLVER_NAME}}.getSolution();
59
60 for (int d=0; d<Dimensions; d++) {
61 // names are inverted here, i.e. code works, but variable names are wrong
62 int unknownInPreimage = 0;
63 dfore(node,repositories::{{SOLVER_INSTANCE}}.PolyDegree+1,d,0) {
64 tarch::la::Vector< Dimensions, int > nodeOnLeftSideOfImage = node;
65 tarch::la::Vector< Dimensions, int > nodeOnRightSideOfImage = node;
66 nodeOnLeftSideOfImage(d) = 0;
67 nodeOnRightSideOfImage(d) = repositories::{{SOLVER_INSTANCE}}.PolyDegree;
68
69 for (int unknown=0; unknown<repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode; unknown++) {
70 int unknownInLeftImage = peano4::utils::dLinearised( nodeOnLeftSideOfImage, repositories::{{SOLVER_INSTANCE}}.PolyDegree+1) * repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode + unknown;
71 int unknownInRightImage = peano4::utils::dLinearised( nodeOnRightSideOfImage, repositories::{{SOLVER_INSTANCE}}.PolyDegree+1) * repositories::{{SOLVER_INSTANCE}}.UnknownsPerCellNode + unknown;
72
73 double diagonalUpdate;
74 diagonalUpdate = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h())(unknownInLeftImage,unknownInLeftImage);
75 assertion( diagonalUpdate==diagonalUpdate );
76 assertion2(diagonalUpdate>0.0,repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),unknownInLeftImage);
77 fineGridFaces{{SOLVER_NAME}}( d ).setDiagonal(
78 unknownInPreimage,
79 fineGridFaces{{SOLVER_NAME}}( d ).getDiagonal( unknownInPreimage )
80 +
81 diagonalUpdate
82 );
83 diagonalUpdate = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h())(unknownInRightImage,unknownInRightImage);
84 assertion( diagonalUpdate==diagonalUpdate );
85 assertion2(diagonalUpdate>0.0,repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),unknownInLeftImage);
86 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).setDiagonal(
87 unknownInPreimage,
88 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).getDiagonal( unknownInPreimage )
89 +
90 diagonalUpdate
91 );
92
93 assertion(r(unknownInLeftImage)==r(unknownInLeftImage));
94 assertion( not std::isnan(r(unknownInLeftImage)) );
95 fineGridFaces{{SOLVER_NAME}}( d ).setResidual(
96 unknownInPreimage,
97 fineGridFaces{{SOLVER_NAME}}( d ).getResidual( unknownInPreimage )
98 +
99 r(unknownInLeftImage)
100 );
101 assertion(r(unknownInRightImage)==r(unknownInRightImage));
102 assertion( not std::isnan(r(unknownInRightImage)) );
103 assertion2( r(unknownInRightImage)>-1.0, r(unknownInRightImage), unknownInRightImage );
104 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).setResidual(
105 unknownInPreimage,
106 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).getResidual( unknownInPreimage )
107 +
108 r(unknownInRightImage)
109 );
110
111 unknownInPreimage++;
112 }
113 }
114 }
115
116 logTraceOutWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
117 }
118 """
119
120 def __init__(self,
121 solver):
122 super( ProjectResidualsAndDiagonalOntoFacets, self ).__init__()
123 self.d = {}
124 self.d["SOLVER_INSTANCE"] = solver.instance_name()
125 self.d["SOLVER_NAME"] = solver.typename()
126
127 def get_body_of_operation(self,operation_name):
128 result = ""
129 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
130 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
131 pass
132 return result
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(".", "_")
147
149 """!
150
151 The action set that Peano will generate that corresponds to this class
152 should not be modified by users and can safely be overwritten every time
153 we run the Python toolkit.
154
155 """
156 return False
157
158 def get_includes(self):
159 """!
160
161 We need the solver repository in this action set, as we directly access
162 the solver object. We also need access to Peano's d-dimensional loops.
163
164 """
165 return """
166#include "../repositories/SolverRepository.h"
167#include "peano4/utils/Loop.h"
168"""
Action set implementing the facet update of the continuous Galerkin solver.
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
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)
Definition ActionSet.py:6