Peano
Loading...
Searching...
No Matches
ProjectIntoCellAndUpdateCellSolutionWithTasks.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import peano4
4import jinja2
5
6
8 templateTouchCellFirstTime="""
9 if (
10 fineGridCell{{SOLVER_NAME}}.getType() != celldata::{{SOLVER_NAME}}::Type::Coarse
11 and
12 repositories::{{SOLVER_INSTANCE}}.projectOntoCells()
13 ) {
14 logTraceInWith2Arguments( "ProjectOntoCells", fineGridCell{{SOLVER_NAME}}.getResidual(), fineGridCell{{SOLVER_NAME}}.getSolution() );
15
16 /**
17 * Collect the face data into a face vector and determine the projection
18 * into the cell.
19 */
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);
25 }
26
27 auto projection = repositories::{{SOLVER_INSTANCE}}.applyCellFromFaceMatrix(marker.x(), marker.h(), faceSol);
28
29
30 /**
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.
33 */
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" );
37
38
39 /**
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.
43 */
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)
49 );
50 }
51
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());
56 }
57
58
59 /**
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.
62 */
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() );
66
67 fineGridCell{{SOLVER_NAME}}.setResidual(
68 tarch::la::multiply( invertedApproxSystemMatrix, residual )
69 );
70
71
72 /**
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.
76 */
77 if ( not repositories::{{SOLVER_INSTANCE}}.updateResidual() ) {
78 tarch::freeMemory(
79 fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix(),
80 tarch::MemoryLocation::Heap
81 );
82 fineGridCell{{SOLVER_NAME}}.setInverseOfSystemMatrix( nullptr );
83 }
84
85 /**
86 * Finally update the solution
87 */
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
95 );
96 _solverStatistics.updateGlobalSolutionUpdates(du, marker.h()(0));
97 _solverStatistics.updateMinMaxMeshSize( marker.h() );
98 }
99
100 logTraceOutWith2Arguments( "ProjectOntoCells", fineGridCell{{SOLVER_NAME}}.getResidual(), fineGridCell{{SOLVER_NAME}}.getSolution() );
101 }
102
103 """
104 def __init__(self,
105 solver,
106 descend_invocation_order=0,
107 parallel=True):
108 super( ProjectIntoCellAndUpdateCellSolutionWithTasks, self ).__init__(
109 descend_invocation_order,
110 parallel
111 )
112 self.d = {}
113 self.d["SOLVER_INSTANCE"] = solver.instance_name()
114 self.d["SOLVER_NAME"] = solver.typename()
115 self.d["TASK_MARKER"] = solver._task_name + "MeshNumber"
116
117 def get_body_of_operation(self,operation_name):
118 result = ""
119 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
120 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
121 pass
122 # This is now done within the abstract solver
123# if operation_name==peano4.solversteps.ActionSet.OPERATION_BEGIN_TRAVERSAL:
124# result = jinja2.Template("""
125# _solverStatistics.clearGlobalPrecondResidualUpdate();
126# _solverStatistics.clearGlobalResidualAndSolutionUpdate();
127#""").render(**self.d)
128 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
129 result = jinja2.Template("""
130 repositories::{{SOLVER_INSTANCE}}.merge( _solverStatistics );
131""").render(**self.d)
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
148
150 """!
151
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.
155
156 """
157 return False
158
159 def get_includes(self):
160 """!
161
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.
164
165 """
166 return """
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"
172"""
173
174 def get_attributes(self):
175 """!
176
177 Return attributes as copied and pasted into the generated class.
178
179 Please note that action sets are not persistent, i.e. there is one
180 object creation per grid sweep per tree.
181
182 """
183 return """
184 ::mghype::matrixfree::solvers::SolverStatistics _solverStatistics;
185"""
186
Action set (reactions to events)
Definition ActionSet.py:6
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...