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 faceSol( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{SOLVER_NAME}}(f).getSolution(s);
24
25 auto projection = repositories::{{SOLVER_INSTANCE}}.applyCellFromFaceMatrix(marker.x(), marker.h(), faceSol);
26
27
28 /**
29 * Take the cell residual and substract the projected values. Before we do
30 * this, we have to wait for the residual calculation to complete.
31 */
32 int taskNumber = fineGridCell{{TASK_MARKER}}.getNumber() * 2;
33 tarch::multicore::waitForTasks({taskNumber+0,taskNumber+1}, tarch::multicore::TaskWaitType::ExclusivelyFusedTasks);
34
35
36 /**
37 * Now that the volumetric kernel is used, we know that noone is accessing
38 * the residual anymore, so we can safely substract the projected value
39 * and compute the residual norm.
40 */
41 for (int f=0; f<repositories::{{SOLVER_INSTANCE}}.CellUnknowns; f++) {
42 fineGridCell{{SOLVER_NAME}}.setResidual(f,
43 fineGridCell{{SOLVER_NAME}}.getResidual(f)- projection(f));
44 }
45
46 // update global residual before multiplying by the preconditioner
47 for (int i=0; i<fineGridCell{{SOLVER_NAME}}.getSolution().size(); i++) {
48 double res = fineGridCell{{SOLVER_NAME}}.getResidual( i );
49 _solverStatistics.updateGlobalResidual(res, marker.h());
50 }
51
52
53 /**
54 * Take inverted cell operator and then apply it. We already have the
55 * residual as a smart pointer, so we can apply the inverse in-situ.
56 */
57 tarch::la::ShallowMatrix< {{SOLVER_NAME}}::CellUnknowns, {{SOLVER_NAME}}::CellUnknowns, double > invertedApproxSystemMatrix
58 = fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix();
59 tarch::la::SmartPointerVector<{{SOLVER_NAME}}::CellUnknowns, double> residual( fineGridCell{{SOLVER_NAME}}.getResidualSmartPointer() );
60
61 fineGridCell{{SOLVER_NAME}}.setResidual(
62 tarch::la::multiply( invertedApproxSystemMatrix, residual )
63 );
64
65
66
67 /**
68 * Free memory. If we immediately run the next iteration sweep, it is
69 * better to recycle the memory, i.e. to omit any free here. However, the
70 * free is robust, i.e. it does not affect the semantics.
71 */
72 if ( not repositories::{{SOLVER_INSTANCE}}.updateResidual() ) {
73 tarch::freeMemory(
74 fineGridCell{{SOLVER_NAME}}.getInverseOfSystemMatrix(),
75 tarch::MemoryLocation::Heap
76 );
77 fineGridCell{{SOLVER_NAME}}.setInverseOfSystemMatrix( nullptr );
78 }
79
80 /**
81 * Finally update the solution
82 */
83 for (int i=0; i<fineGridCell{{SOLVER_NAME}}.getSolution().size(); i++) {
84 double res = fineGridCell{{SOLVER_NAME}}.getResidual( i );
85 double du = repositories::{{SOLVER_INSTANCE}}.OmegaCell * res;
86 fineGridCell{{SOLVER_NAME}}.setSolution( i,
87 fineGridCell{{SOLVER_NAME}}.getSolution( i ) + du
88 );
89 _solverStatistics.updateGlobalSolutionUpdates(du, marker.h()(0));
90 _solverStatistics.updateMinMaxMeshSize( marker.h() );
91 }
92
93 logTraceOutWith2Arguments( "ProjectOntoCells", fineGridCell{{SOLVER_NAME}}.getResidual(), fineGridCell{{SOLVER_NAME}}.getSolution() );
94 }
95
96 """
97 def __init__(self,
98 solver,
99 descend_invocation_order=0,
100 parallel=True):
101 super( ProjectIntoCellAndUpdateCellSolutionWithTasks, self ).__init__(
102 descend_invocation_order,
103 parallel
104 )
105 self.d = {}
106 self.d["SOLVER_INSTANCE"] = solver.instance_name()
107 self.d["SOLVER_NAME"] = solver.typename()
108 self.d["TASK_MARKER"] = solver._task_name + "MeshNumber"
109
110 def get_body_of_operation(self,operation_name):
111 result = ""
112 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
113 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
114 pass
115 if operation_name==peano4.solversteps.ActionSet.OPERATION_BEGIN_TRAVERSAL:
116 result = jinja2.Template("""
117 _solverStatistics.clearGlobalPrecondResidualUpdate();
118 _solverStatistics.clearGlobalResidualAndSolutionUpdate();
119""").render(**self.d)
120 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
121 result = jinja2.Template("""
122 repositories::{{SOLVER_INSTANCE}}.merge( _solverStatistics );
123""").render(**self.d)
124 return result
125
127 """!
128
129 Configure name of generated C++ action set
130
131 This action set will end up in the directory observers with a name that
132 reflects how the observer (initialisation) is mapped onto this action
133 set. The name pattern is ObserverName2ActionSetIdentifier where this
134 routine co-determines the ActionSetIdentifier. We make is reflect the
135 Python class name.
136
137 """
138 return __name__.replace(".py", "").replace(".", "_")
139
140
142 """!
143
144 The action set that Peano will generate that corresponds to this class
145 should not be modified by users and can safely be overwritten every time
146 we run the Python toolkit.
147
148 """
149 return False
150
151 def get_includes(self):
152 """!
153
154 We need the solver repository in this action set, as we directly access
155 the solver object. We also need access to Peano's d-dimensional loops.
156
157 """
158 return """
159#include "../repositories/SolverRepository.h"
160#include "peano4/utils/Loop.h"
161#include "tarch/multicore/Task.h"
162#include "tarch/multicore/multicore.h"
163#include "tarch/la/ShallowMatrix.h"
164"""
165
166 def get_attributes(self):
167 """!
168
169 Return attributes as copied and pasted into the generated class.
170
171 Please note that action sets are not persistent, i.e. there is one
172 object creation per grid sweep per tree.
173
174 """
175 return """
176 ::mghype::matrixfree::solvers::SolverStatistics _solverStatistics;
177"""
178
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...