8 templateTouchCellFirstTime=
"""
10 fineGridCell{{SOLVER_NAME}}.getType() != celldata::{{SOLVER_NAME}}::Type::Coarse
12 repositories::{{SOLVER_INSTANCE}}.projectOntoCells()
14 logTraceInWith2Arguments( "ProjectOntoCells", fineGridCell{{SOLVER_NAME}}.getResidual(), fineGridCell{{SOLVER_NAME}}.getSolution() );
17 * Collect the face data into a face vector and determine the projection
20 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSol;
21 for (int f=0; f<TwoTimesD; f++)
22 for (int s=0; s<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; s++) {
23 assertion2( fineGridFaces{{SOLVER_NAME}}(f).getSolution(s)<1e10, fineGridFaces{{SOLVER_NAME}}(f).getSolution(s), fineGridFaces{{SOLVER_NAME}}(f).getSolution() );
24 faceSol( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{SOLVER_NAME}}(f).getSolution(s);
27 auto projection = repositories::{{SOLVER_INSTANCE}}.applyCellFromFaceMatrix(marker.x(), marker.h(), faceSol);
31 * Take the cell residual and substract the projected values. Before we do
32 * this, we have to wait for the residual calculation to complete.
34 int taskNumber = fineGridCell{{TASK_MARKER}}.getNumber() * 2;
35 tarch::multicore::waitForTasks({taskNumber+0,taskNumber+1}, tarch::multicore::TaskWaitType::ExclusivelyFusedTasks);
36 logDebug( "touchCellFirstTime(...)", "tasks " << (taskNumber+0) << " and " << (taskNumber+1) << " completed" );
40 * Now that the volumetric kernel is used, we know that noone is accessing
41 * the residual anymore, so we can safely substract the projected value
42 * and compute the residual norm.
44 for (int f=0; f<repositories::{{SOLVER_INSTANCE}}.CellUnknowns; f++) {
45 assertion1( fineGridCell{{SOLVER_NAME}}.getResidual(f)<1e10, marker.toString() );
46 assertion1( projection(f)<1e10, marker.toString() );
47 fineGridCell{{SOLVER_NAME}}.setResidual(f,
48 fineGridCell{{SOLVER_NAME}}.getResidual(f)- projection(f)
52 // update global residual before multiplying by the preconditioner
53 for (int i=0; i<fineGridCell{{SOLVER_NAME}}.getSolution().size(); i++) {
54 double res = fineGridCell{{SOLVER_NAME}}.getResidual( i );
55 _solverStatistics.updateGlobalResidual(res, marker.h());
60 * Take inverted cell operator and then apply it. We already have the
61 * residual as a smart pointer, so we can apply the inverse in-situ.
63 tarch::la::ShallowMatrix< {{SOLVER_NAME}}::CellUnknowns, {{SOLVER_NAME}}::CellUnknowns, double > invertedApproxSystemMatrix
64 = fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix();
65 tarch::la::SmartPointerVector<{{SOLVER_NAME}}::CellUnknowns, double> residual( fineGridCell{{SOLVER_NAME}}.getResidualSmartPointer() );
67 fineGridCell{{SOLVER_NAME}}.setResidual(
68 tarch::la::multiply( invertedApproxSystemMatrix, residual )
73 * Free memory. If we immediately run the next iteration sweep, it is
74 * better to recycle the memory, i.e. to omit any free here. However, the
75 * free is robust, i.e. it does not affect the semantics.
77 if ( not repositories::{{SOLVER_INSTANCE}}.updateResidual() ) {
79 fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix(),
80 tarch::MemoryLocation::Heap
82 fineGridCell{{SOLVER_NAME}}.setInverseOfSystemMatrix( nullptr );
86 * Finally update the solution
88 for (int i=0; i<fineGridCell{{SOLVER_NAME}}.getSolution().size(); i++) {
89 const double res = fineGridCell{{SOLVER_NAME}}.getResidual( i );
90 const double du = repositories::{{SOLVER_INSTANCE}}.OmegaCell * res;
91 assertion6( res<1e10, du, res, marker.toString(), fineGridCell{{SOLVER_NAME}}.getResidual(), repositories::{{SOLVER_INSTANCE}}.OmegaCell, i );
92 assertion7( du<1e10, du, res, marker.toString(), fineGridCell{{SOLVER_NAME}}.getResidual(), repositories::{{SOLVER_INSTANCE}}.OmegaCell, i, fineGridCell{{SOLVER_NAME}}.getResidual( i ) );
93 fineGridCell{{SOLVER_NAME}}.setSolution( i,
94 fineGridCell{{SOLVER_NAME}}.getSolution( i ) + du
96 _solverStatistics.updateGlobalSolutionUpdates(du, marker.h()(0));
97 _solverStatistics.updateMinMaxMeshSize( marker.h() );
100 logTraceOutWith2Arguments( "ProjectOntoCells", fineGridCell{{SOLVER_NAME}}.getResidual(), fineGridCell{{SOLVER_NAME}}.getSolution() );
106 descend_invocation_order=0,
108 super( ProjectIntoCellAndUpdateCellSolutionWithTasks, self ).
__init__(
109 descend_invocation_order,
113 self.
d[
"SOLVER_INSTANCE"] = solver.instance_name()
114 self.
d[
"SOLVER_NAME"] = solver.typename()
115 self.
d[
"TASK_MARKER"] = solver._task_name +
"MeshNumber"
119 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
128 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
129 result = jinja2.Template(
"""
130 repositories::{{SOLVER_INSTANCE}}.merge( _solverStatistics );
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(
".",
"_")
152 The action set that Peano will generate that corresponds to this class
153 should not be modified by users and can safely be overwritten every time
154 we run the Python toolkit.
162 We need the solver repository in this action set, as we directly access
163 the solver object. We also need access to Peano's d-dimensional loops.
167#include "../repositories/SolverRepository.h"
168#include "peano4/utils/Loop.h"
169#include "tarch/multicore/Task.h"
170#include "tarch/multicore/multicore.h"
171#include "tarch/la/ShallowMatrix.h"
177 Return attributes as copied and pasted into the generated class.
179 Please note that action sets are not persistent, i.e. there is one
180 object creation per grid sweep per tree.
184 ::mghype::matrixfree::solvers::SolverStatistics _solverStatistics;
Action set (reactions to events)
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
get_action_set_name(self)
Configure name of generated C++ action set.
str templateTouchCellFirstTime
__init__(self, solver, descend_invocation_order=0, parallel=True)
get_attributes(self)
Return attributes as copied and pasted into the generated class.