Peano
Loading...
Searching...
No Matches
DGCGCoupling.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import dastgen2
4import peano4
5import jinja2
6import mghype
7
9 """!
10 Using this action set isn't strictly necessary. But it's the easiest way
11 to pipe in the prolongation / restriction matrices.
12
13 During tcft we:
14 - Set the auxiliary cell data by prolongating the aux vertex values
15 - Set the auxiliary vertex data by restricting the aux cell values
16 """
17
18 templateEndTraversal="""
19 Counter++;
20 """
21
22 templateTouchCellFirstTime="""
23 if (
24 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
25 and
26 Counter==0
27 ) {
28 constexpr int Cols = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
29 constexpr int Rows = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
30
31 // gather vertex values to interpolate upwards:
32 tarch::la::Vector< Cols, double > vertexValues;
33 for (int i=0; i<TwoPowerD; i++) vertexValues[i] = fineGridVertices{{CG_SOLVER_NAME}}(i).getU( 0 );
34
35 static std::vector< tarch::la::Matrix< Rows, Cols, double > > matrices = {
36 {% for MATRIX in PROLONGATION_MATRIX %}
37 {
38 {{MATRIX[0]| join(", ")}}
39 {% for ROW in MATRIX[1:] %}
40 ,{{ROW | join(", ")}}
41 {% endfor %}
42 },
43 {% endfor %}
44 };
45
46 {% if PROLONGATION_MATRIX_SCALING is not defined %}
47 #error No scaling for prolongation matrix available.
48 {% endif %}
49
50 static std::vector<int> scaleFactors = {
51 {% for el in PROLONGATION_MATRIX_SCALING %}
52 {{el}},
53 {% endfor %}
54 };
55
56 static tarch::la::Matrix< Rows, Cols, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( matrices, scaleFactors, marker.h() );
57
58 // interpolate
59 auto newDgVector1 = composedProlongationMatrix * vertexValues;
60 fineGridCell{{DG_SOLVER_NAME}}.setVector1( newDgVector1 );
61
62 // NEXT - do the same thing for the vertices...
63 // forget about solution injection!!
64
65 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
66 {% for MATRIX in RESTRICTION_MATRIX %}
67 {
68 {{MATRIX[0]| join(", ")}}
69 {% for ROW in MATRIX[1:] %}
70 ,{{ROW | join(", ")}}
71 {% endfor %}
72 },
73 {% endfor %}
74 };
75
76 {% if RESTRICTION_MATRIX_SCALING is not defined %}
77 #error No scaling for injection matrix available.
78 {% endif %}
79
80 static std::vector<int> restrictionMatricesScaleFactors = {
81 {% for el in INJECTION_MATRIX_SCALING %}
82 {{el}},
83 {% endfor %}
84 };
85
86 static tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
87
88 auto valuesToPutIntoVertex = composedRestrictionMatrix * fineGridCell{{DG_SOLVER_NAME}}.getSolution();
89 for (int v=0; v<TwoPowerD; v++)
90 fineGridVertices{{CG_SOLVER_NAME}}(v).setVector2(
91 0, // assume only one value, so we ask for index 0
92 fineGridVertices{{CG_SOLVER_NAME}}(v).getVector2(0) + valuesToPutIntoVertex(v)
93 );
94
95 }
96 """
97
99 self,
100 dg_solver,
101 cg_solver,
102 prolongation_matrix,
103 prolongation_matrix_scaling,
104 restriction_matrix,
105 restriction_matrix_scaling,
106 injection_matrix,
107 injection_matrix_scaling
108 ):
109
110 super( Test4Coupling, self ).__init__(
111 0, #descend_invocation_order -> will be ignored
112 False # parallel
113 )
114
115 dg_solver._basic_descend_order = cg_solver._basic_descend_order - 1
116
117 self.d = {}
118 self.d["DG_SOLVER_INSTANCE"] = dg_solver.instance_name()
119 self.d["DG_SOLVER_NAME"] = dg_solver.typename()
120 self.d["CG_SOLVER_INSTANCE"] = cg_solver.instance_name()
121 self.d["CG_SOLVER_NAME"] = cg_solver.typename()
122
123 self.d["INJECTION_MATRIX"] = injection_matrix
124 self.d["INJECTION_MATRIX_SCALING"] = injection_matrix_scaling
125 self.d["PROLONGATION_MATRIX"] = prolongation_matrix
126 self.d["PROLONGATION_MATRIX_SCALING"] = prolongation_matrix_scaling
127 self.d["RESTRICTION_MATRIX"] = restriction_matrix
128 self.d["RESTRICTION_MATRIX_SCALING"] = restriction_matrix_scaling
129
130 def get_body_of_operation(self,operation_name):
131 result = ""
132 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
133 return jinja2.Template(self.templateTouchCellFirstTimetemplateTouchCellFirstTime).render(**self.d)
134 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
135 return jinja2.Template(self.templateEndTraversaltemplateEndTraversal).render(**self.d)
136 return result
137
139 """!
140
141 Configure name of generated C++ action set
142
143 This action set will end up in the directory observers with a name that
144 reflects how the observer (initialisation) is mapped onto this action
145 set. The name pattern is ObserverName2ActionSetIdentifier where this
146 routine co-determines the ActionSetIdentifier. We make is reflect the
147 Python class name.
148
149 """
150 return __name__.replace(".py", "").replace(".", "_")
151
153 """!
154
155 The action set that Peano will generate that corresponds to this class
156 should not be modified by users and can safely be overwritten every time
157 we run the Python toolkit.
158
159 """
160 return False
161
162 def get_includes(self):
163 """!
164
165 We need the solver repository in this action set, as we directly access
166 the solver object. We also need access to Peano's d-dimensional loops.
167
168 """
169 return """
170#include "repositories/SolverRepository.h"
171#include <random>
172#include "peano4/utils/Loop.h"
173#include "mghype/mghype.h"
174"""
175
176 def get_attributes(self):
177 return """
178 static int Counter;
179 """
180
181 def get_static_initialisations(self, full_qualified_classname):
182 return f"""
183 int {full_qualified_classname}::Counter = 0;
184 """
185
186
188
189 templateTouchCellFirstTime="""
190 constexpr int Cols = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
191 constexpr int Rows = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
192
193 static std::vector< tarch::la::Matrix< Rows, Cols, double > > matrices = {
194 {% for MATRIX in PROLONGATION_MATRIX %}
195 {
196 {{MATRIX[0]| join(", ")}}
197 {% for ROW in MATRIX[1:] %}
198 ,{{ROW | join(", ")}}
199 {% endfor %}
200 },
201 {% endfor %}
202 };
203
204 {% if PROLONGATION_MATRIX_SCALING is not defined %}
205 #error No scaling for prolongation matrix available.
206 {% endif %}
207
208 static std::vector<int> scaleFactors = {
209 {% for el in PROLONGATION_MATRIX_SCALING %}
210 {{el}},
211 {% endfor %}
212 };
213
214 static tarch::la::Matrix< Rows, Cols, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( matrices, scaleFactors, marker.h() );
215
216 // restriction matrix
217 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
218 {% for MATRIX in RESTRICTION_MATRIX %}
219 {
220 {{MATRIX[0]| join(", ")}}
221 {% for ROW in MATRIX[1:] %}
222 ,{{ROW | join(", ")}}
223 {% endfor %}
224 },
225 {% endfor %}
226 };
227
228 {% if RESTRICTION_MATRIX_SCALING is not defined %}
229 #error No scaling for injection matrix available.
230 {% endif %}
231
232 static std::vector<int> restrictionMatricesScaleFactors = {
233 {% for el in INJECTION_MATRIX_SCALING %}
234 {{el}},
235 {% endfor %}
236 };
237
238 static tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
239
240 if (
241 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
242 and
243 Counter==0
244 ) {
245 // fetch the cg stuff
246 tarch::la::Vector<TwoPowerD, double> u_cg_random;
247
248 for (int i=0; i<TwoPowerD; i++) u_cg_random(i) = fineGridVertices{{CG_SOLVER_NAME}}(i).getRand(0);
249
250 auto v_cell = composedProlongationMatrix * u_cg_random;
251
252 fineGridCell{{DG_SOLVER_NAME}}.setVcell(
253 v_cell
254 );
255
256 // and now project that onto the faces
257 auto faceProjections = repositories::{{DG_SOLVER_INSTANCE}}.getFaceFromCellMatrix( marker.x(), marker.h() ) * v_cell;
258
259 for (int f=0; f<TwoTimesD; f++) {
260 int startIndexProjection =
261 f < Dimensions ?
262 repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
263 0;
264 for (int p=0; p<repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode; p++) {
265 fineGridFaces{{DG_SOLVER_NAME}}(f).setProjectionTest(
266 p + startIndexProjection,
267 faceProjections( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsProjection + p + startIndexProjection )
268 );
269
270 }
271 }
272
273 }
274
275 else if (
276 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
277 and
278 Counter==1
279 ) {
280
281 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSol;
282 for (int f=0; f<TwoTimesD; f++)
283 for (int s=0; s<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
284 faceSol( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{DG_SOLVER_NAME}}(f).getSolutionTest(s);
285
286 fineGridCell{{DG_SOLVER_NAME}}.setAdgp(
287 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * fineGridCell{{DG_SOLVER_NAME}}.getVcell()
288 +
289 repositories::{{DG_SOLVER_INSTANCE}}.getCellFromFaceMatrix(marker.x(), marker.h()) * faceSol
290 );
291
292 // now that's done, set v_restrict_ADG
293 auto v_restrict_ADG = composedRestrictionMatrix * fineGridCell{{DG_SOLVER_NAME}}.getAdgp();
294
295 for (int v=0; v<TwoPowerD; v++)
296 fineGridVertices{{CG_SOLVER_NAME}}(v).setVrestrictADG( fineGridVertices{{CG_SOLVER_NAME}}(v).getVrestrictADG(0) + v_restrict_ADG(v) );
297
298 // finally, steps 9 and 10
299 auto mdg_p = repositories::{{DG_SOLVER_INSTANCE}}.getMassMatrix(marker.x(), marker.h()) * fineGridCell{{DG_SOLVER_NAME}}.getVcell();
300
301 fineGridCell{{DG_SOLVER_NAME}}.setMdgp(
302 mdg_p
303 );
304
305 auto v_restrict_mdg = composedRestrictionMatrix * mdg_p;
306 for (int v=0; v<TwoPowerD; v++)
307 fineGridVertices{{CG_SOLVER_NAME}}(v).setVrestrictMDG( 0, fineGridVertices{{CG_SOLVER_NAME}}(v).getVrestrictMDG(0) + v_restrict_mdg(v) );
308
309 }
310 """
311
312 templateTouchFaceLastTime="""
313 // perform averaging on the faces
314 if (
315 fineGridFace{{DG_SOLVER_NAME}}.getType() == facedata::{{DG_SOLVER_NAME}}::Type::Interior
316 and
317 Counter == 0
318 ) {
319 // project the u^\pm into a temporary vector
320 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution, double > projection =
321 repositories::{{DG_SOLVER_INSTANCE}}.getRiemannMatrix() * fineGridFace{{DG_SOLVER_NAME}}.getProjectionTest();
322
323 for (int i=0; i<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
324 fineGridFace{{DG_SOLVER_NAME}}.setSolutionTest(
325 i,
326 projection(i)
327 );
328 }
329
330 else if (
331 fineGridFace{{DG_SOLVER_NAME}}.getType() == facedata::{{DG_SOLVER_NAME}}::Type::Boundary
332 and
333 Counter==0
334 ) {
335 // Essentially what we do here is fix the solution on the boundary to be
336 // the inner-side projection.
337
338 // skip halfway along the projection vector if we are on face 0 or 1
339 int startIndexProjection =
340 marker.getSelectedFaceNumber() < Dimensions ?
341 repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
342 0;
343
344 auto boundaryMatrix = repositories::{{DG_SOLVER_INSTANCE}}.getBoundaryConditionMatrix();
345
346 /*
347 Here we do slightly messy matrix multiplication. We would just multiply the boundary matrix
348 by the projection vector, and place that into the solution, but here we only want to capture
349 half of the projection vector; the other half lies outside the computational domain and
350 should be fixed to 0.
351 */
352 for (int row=0; row<boundaryMatrix.rows(); row++)
353 {
354 double rowSolution = 0;
355 for (int col=0; col<boundaryMatrix.cols(); col++)
356 {
357 rowSolution += boundaryMatrix( row, col ) * fineGridFace{{DG_SOLVER_NAME}}.getProjection( col + startIndexProjection );
358 }
359 // place this solution into the face
360 fineGridFace{{DG_SOLVER_NAME}}.setSolutionTest( row, rowSolution );
361 }
362
363 }
364
365 """
366
368 self,
369 dg_solver,
370 cg_solver,
371 prolongation_matrix,
372 prolongation_matrix_scaling,
373 restriction_matrix,
374 restriction_matrix_scaling,
375 injection_matrix,
376 injection_matrix_scaling
377 ):
378
379 super( Test5Coupling, self ).__init__(
380 dg_solver,
381 cg_solver,
382 prolongation_matrix,
383 prolongation_matrix_scaling,
384 restriction_matrix,
385 restriction_matrix_scaling,
386 injection_matrix,
387 injection_matrix_scaling
388 )
389 dg_solver._basic_descend_order = cg_solver._basic_descend_order - 1
390
391 self.dd = {}
392 self.dd["DG_SOLVER_INSTANCE"] = dg_solver.instance_name()
393 self.dd["DG_SOLVER_NAME"] = dg_solver.typename()
394 self.dd["CG_SOLVER_INSTANCE"] = cg_solver.instance_name()
395 self.dd["CG_SOLVER_NAME"] = cg_solver.typename()
396
397 self.dd["INJECTION_MATRIX"] = injection_matrix
398 self.dd["INJECTION_MATRIX_SCALING"] = injection_matrix_scaling
399 self.dd["PROLONGATION_MATRIX"] = prolongation_matrix
400 self.dd["PROLONGATION_MATRIX_SCALING"] = prolongation_matrix_scaling
401 self.dd["RESTRICTION_MATRIX"] = restriction_matrix
402 self.dd["RESTRICTION_MATRIX_SCALING"] = restriction_matrix_scaling
403
404 def get_body_of_operation(self,operation_name):
405 result = ""
406 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
408 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME:
409 return jinja2.Template(self.templateTouchFaceLastTimetemplateTouchFaceLastTime).render(**self.dd)
410 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
411 return jinja2.Template(self.templateEndTraversaltemplateEndTraversaltemplateEndTraversal).render(**self.dd)
412 return result
413
414
415class Test7Coupling(mghype.matrixfree.solvers.api.actionsets.MultiplicativeDGCGCoupling):
416 templateTouchCellFirstTime="""
417 if (
418 firstCycleCounter==0
419 and
420 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
421 ){
422 // finish updating rhs
423 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.CellUnknowns, double > rhs;
424
425 // fetch the faces
426 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSol;
427 for (int f=0; f<TwoTimesD; f++)
428 for (int s=0; s<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
429 faceSol( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{DG_SOLVER_NAME}}(f).getRandSolutions(s);
430
431 fineGridCell{{DG_SOLVER_NAME}}.setRhs(
432 fineGridCell{{DG_SOLVER_NAME}}.getRhs()
433 +
434 repositories::{{DG_SOLVER_INSTANCE}}.getCellFromFaceMatrix(marker.x(), marker.h()) * faceSol
435 );
436 }
437 """ + mghype.matrixfree.solvers.api.actionsets.MultiplicativeDGCGCoupling.templateTouchCellFirstTime
438
439 templateEndTraversal = """
440 firstCycleCounter++;
441 """
442
443 def get_includes(self):
444 """!
445
446 We need the solver repository in this action set, as we directly access
447 the solver object. We also need access to Peano's d-dimensional loops.
448
449 """
450 return """
451#include "repositories/SolverRepository.h"
452#include <random>
453#include "peano4/utils/Loop.h"
454#include "mghype/mghype.h"
455#include "mghype/matrixfree/solvers/DGCGCoupling.h"
456"""
457
458 def get_attributes(self):
459 return super().get_attributes() + """
460 static int firstCycleCounter;
461"""
462
463 def get_static_initialisations(self, full_qualified_classname):
464 return super().get_static_initialisations(full_qualified_classname) + f"""
465int {full_qualified_classname}::firstCycleCounter = 0;
466"""
467 def get_body_of_operation(self,operation_name):
468 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
469 return jinja2.Template(self.templateEndTraversaltemplateEndTraversal).render(**self.d)
470 else:
471 return super().get_body_of_operation(operation_name)
Using this action set isn't strictly necessary.
__init__(self, dg_solver, cg_solver, prolongation_matrix, prolongation_matrix_scaling, restriction_matrix, restriction_matrix_scaling, injection_matrix, injection_matrix_scaling)
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
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...
get_action_set_name(self)
Configure name of generated C++ action set.
get_static_initialisations(self, full_qualified_classname)
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, dg_solver, cg_solver, prolongation_matrix, prolongation_matrix_scaling, restriction_matrix, restriction_matrix_scaling, injection_matrix, injection_matrix_scaling)
get_body_of_operation(self, operation_name)
get_static_initialisations(self, full_qualified_classname)
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
Action set (reactions to events)
Definition ActionSet.py:6