12 Action set implementing the facet update of the continuous Galerkin solver
14 There are two key elements/events here:
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.
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.
28 The key properties of the solver that we use here are the following ones:
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
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) ))
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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 templateTouchCellFirstTime =
"""
50 fineGridCell{{SOLVER_NAME}}.getType() == celldata::{{SOLVER_NAME}}::Type::Interior
52 repositories::{{SOLVER_INSTANCE}}.updateCell()
54 logTraceInWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
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();
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;
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;
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(
79 fineGridFaces{{SOLVER_NAME}}( d ).getDiagonal( unknownInPreimage )
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(
88 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).getDiagonal( unknownInPreimage )
93 assertion(r(unknownInLeftImage)==r(unknownInLeftImage));
94 assertion( not std::isnan(r(unknownInLeftImage)) );
95 fineGridFaces{{SOLVER_NAME}}( d ).setResidual(
97 fineGridFaces{{SOLVER_NAME}}( d ).getResidual( unknownInPreimage )
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(
106 fineGridFaces{{SOLVER_NAME}}( d+Dimensions ).getResidual( unknownInPreimage )
108 r(unknownInRightImage)
116 logTraceOutWith2Arguments("touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
122 super( ProjectResidualsAndDiagonalOntoFacets, self ).
__init__()
124 self.
d[
"SOLVER_INSTANCE"] = solver.instance_name()
125 self.
d[
"SOLVER_NAME"] = solver.typename()
129 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
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(
".",
"_")
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.
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.
166#include "../repositories/SolverRepository.h"
167#include "peano4/utils/Loop.h"
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.
str templateTouchCellFirstTime
get_action_set_name(self)
Configure name of generated C++ action set.
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)