2This test checks that A_CG indeed approximates the continuum operator:
3check A_DG * u_exact == M * b_exact, where u_exact and b_exact are the dof-vectors
4of the functions u_exact(x) and b_exact(x) which satisfy the PDE in the continuum
5 - Laplace u_exact(x) = b_exact(x).
7We use u_exact(x,y) = sin(2*pi*x) * sin(2*pi*y),
8 b_exact(x,y) = 8*pi^2 * sin(2*pi*x) * sin(2*pi*y)
20 In touchVertexFirstTime, we set the type of vertex we see (either Interior, Boundary or Coarse),
21 as well as sending some values to the solver implementation file to be placed into the mesh.
23 In touchCellFirstTime, we just determine the type, as we don't store anything on cells in
27 templateTouchVertexFirstTime =
"""
28 static constexpr double eightPiSquared = 8 * tarch::la::PI * tarch::la::PI;
31 double sinRhs = eightPiSquared;
32 for (int i=0; i<Dimensions; i++){
33 sinValue *= std::sin( 2*tarch::la::PI * marker.x()(i) );
34 sinRhs *= std::sin( 2*tarch::la::PI * marker.x()(i) );
37 // this is done inside getDofType. included here for sanity check
38 auto isOnBoundary = [&]( const tarch::la::Vector< Dimensions, double > & x ) -> bool{
39 bool isOnBoundary = false;
40 for (int d=0; d<Dimensions; d++) {
41 isOnBoundary |= tarch::la::smallerEquals( x(d), DomainOffset(d) );
42 isOnBoundary |= tarch::la::greaterEquals( x(d), DomainOffset(d)+DomainSize(d) );
47 logTraceInWith3Arguments("InitDofs::touchVertexFirstTime", marker.toString(), isOnBoundary(marker.x()), fineGridVertex{{SOLVER_NAME}}.toString());
49 vertexdata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getVertexDoFType(marker.x(),marker.h());
53 case vertexdata::{{SOLVER_NAME}}::Type::Boundary:
55 if ( marker.willBeRefined() )
57 // Coarse grid vertex. Mark it as such for later
58 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Coarse );
62 // we have boundary vertex
63 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Boundary );
66 for (int dof=0; dof<{{VERTEX_CARDINALITY}}; dof++)
68 fineGridVertex{{SOLVER_NAME}}.setU( dof, sinValue);
69 fineGridVertex{{SOLVER_NAME}}.setRhs( dof, sinRhs);
75 case vertexdata::{{SOLVER_NAME}}::Type::Interior:
77 if (isOnBoundary(marker.x()))
79 logWarning( "touchVertexFirstTime(...)", "vertex at " << marker.toString() << " labelled as interior even though it is located at global domain boundary" );
82 if ( marker.willBeRefined() )
84 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Coarse );
89 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Interior );
92 for (int dof=0; dof<{{VERTEX_CARDINALITY}}; dof++)
94 fineGridVertex{{SOLVER_NAME}}.setU(dof, sinValue);
95 fineGridVertex{{SOLVER_NAME}}.setRhs( dof, sinRhs);
101 case vertexdata::{{SOLVER_NAME}}::Type::Coarse:
102 assertionMsg(false, "should not be returned by user" );
105 case vertexdata::{{SOLVER_NAME}}::Type::Undefined:
106 assertionMsg(false, "should not be returned by user" );
111 logTraceOutWith3Arguments("InitDofs::touchVertexFirstTime", marker.toString(), isOnBoundary(marker.x()), fineGridVertex{{SOLVER_NAME}}.toString());
114 templateTouchCellFirstTime =
"""
115 logTraceInWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
117 celldata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
121 case celldata::{{SOLVER_NAME}}::Type::Outside:
123 if ( marker.willBeRefined() ) // make it coarse
125 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
129 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Outside );
134 case celldata::{{SOLVER_NAME}}::Type::Interior:
136 if ( marker.willBeRefined() )
138 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
142 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
143 // perform initialisation proc
144 // this does not work for more than one unknown per vertex
146 tarch::la::Vector<TwoPowerD,double> vu_values;
147 tarch::la::Vector<TwoPowerD,double> vb_values;
150 for (int i=0; i<TwoPowerD; i++){
151 vu_values[i] = fineGridVertices{{SOLVER_NAME}}(i).getU(0);
152 vb_values[i] = fineGridVertices{{SOLVER_NAME}}(i).getRhs(0);
155 // multiply vu by A_cg
156 vu_values = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * vu_values;
158 vb_values = repositories::{{SOLVER_INSTANCE}}.getMassMatrix(marker.x(), marker.h()) * vb_values;
160 // place this into rhs
161 for (int i=0; i<TwoPowerD; i++){
162 fineGridVertices{{SOLVER_NAME}}(i).setVu(
163 fineGridVertices{{SOLVER_NAME}}(i).getVu() + vu_values(i)
166 fineGridVertices{{SOLVER_NAME}}(i).setVb(
167 fineGridVertices{{SOLVER_NAME}}(i).getVb() + vb_values(i)
177 logTraceOutWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
180 templateTouchVertexLastTime=
"""
181 // Set boundary conditions vu = 0 strongly.
182 // This overwrites the result of A_CG * u and M * b at the boundary vertices.
184 if ( fineGridVertex{{SOLVER_NAME}}.getType() == vertexdata::{{SOLVER_NAME}}::Type::Boundary ) {
186 fineGridVertex{{SOLVER_NAME}}.setVu(value);
187 fineGridVertex{{SOLVER_NAME}}.setVb(value);
193 super( InitDofsTest8, self ).
__init__()
195 self.
d[
"SOLVER_INSTANCE"] = solver.instance_name()
196 self.
d[
"SOLVER_NAME"] = solver.typename()
197 self.
d[
"VERTEX_CARDINALITY"] = solver._unknowns_per_vertex_node
201 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
204 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
207 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_LAST_TIME:
214 Configure name of generated C++ action set
216 This action set will end up in the directory observers with a name that
217 reflects how the observer (initialisation) is mapped onto this action
218 set. The name pattern is ObserverName2ActionSetIdentifier where this
219 routine co-determines the ActionSetIdentifier. We make is reflect the
223 return __name__.replace(
".py",
"").replace(
".",
"_")
228 The action set that Peano will generate that corresponds to this class
229 should not be modified by users and can safely be overwritten every time
230 we run the Python toolkit.
238 We need the solver repository in this action set, as we directly access
239 the solver object. We also need access to Peano's d-dimensional loops.
243#include "repositories/SolverRepository.h"
244#include "peano4/utils/Loop.h"
Action set (reactions to events)
In touchVertexFirstTime, we set the type of vertex we see (either Interior, Boundary or Coarse),...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
str templateTouchVertexFirstTime
str templateTouchCellFirstTime
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...
str templateTouchVertexLastTime