Peano
Loading...
Searching...
No Matches
InitDG.py
Go to the documentation of this file.
1from peano4.solversteps.ActionSet import ActionSet
2
3import peano4
4import jinja2
5import mghype
6
8 """!
9 Redoing this class for discontinuous galerkin solver.
10
11 This time, we store values only in the cells and just
12 determine the type of vertex we see.
13 """
14 templateTouchVertexFirstTime = """
15
16 //logTraceInWith3Arguments("InitDofsDG::touchVertexFirstTime", marker.toString(), isOnBoundary(marker.x()), fineGridVertex{{SOLVER_NAME}}.toString());
17
18 vertexdata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getVertexDoFType(marker.x(),marker.h());
19
20 switch(dofType)
21 {
22
23 case vertexdata::{{SOLVER_NAME}}::Type::Interior:
24 {
25 if ( marker.willBeRefined() )
26 {
27 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Coarse );
28 }
29
30 else
31 {
32 fineGridVertex{{SOLVER_NAME}}.setType( vertexdata::{{SOLVER_NAME}}::Type::Interior );
33 }
34 }
35 break;
36
37 case vertexdata::{{SOLVER_NAME}}::Type::Coarse:
38 assertionMsg(false, "should not be returned by user" );
39 break;
40
41 case vertexdata::{{SOLVER_NAME}}::Type::Undefined:
42 assertionMsg(false, "should not be returned by user" );
43 break;
44 }
45
46
47 //logTraceOutWith2Arguments("InitDofsDG::touchVertexFirstTime", marker.toString(), fineGridVertex{{SOLVER_NAME}}.toString());
48 """
49
50 templateTouchCellFirstTime = """
51 logTraceInWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
52
53 auto insertIfNotPresent = []( std::vector<int>& v, int i ) {
54 if( std::find( v.begin(), v.end(), i ) == v.end() ) v.push_back(i);
55 };
56
57 // anonymous functions to calculate cell indices which are on the boundary
58 std::vector<int> indicesOnBoundary;
59
60 for (int f=0; f<TwoTimesD; f++) {
61 if( fineGridFaces{{SOLVER_NAME}}(f).getType() == facedata::{{SOLVER_NAME}}::Type::Boundary ) {
62 // this face is on the boundary. Gather the cell dof indices this corresponds to
63
64 switch(f){
65 case 0: {
66 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, (repositories::{{SOLVER_INSTANCE}}.PolyDegree+1 + 1)*i );
67 } break;
68
69 case 1: {
70 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, i );
71 } break;
72
73 case 2: {
74 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, repositories::{{SOLVER_INSTANCE}}.PolyDegree + (repositories::{{SOLVER_INSTANCE}}.PolyDegree+1 + 1)*i );
75 } break;
76
77 case 3: {
78 for (int i=(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1)*repositories::{{SOLVER_INSTANCE}}.PolyDegree; i<(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1)*(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1); i++) insertIfNotPresent( indicesOnBoundary, i );
79 } break;
80
81 }
82
83 }
84 }
85
86 auto indexIsOnBoundary = [&indicesOnBoundary](int i) -> bool { return not( indicesOnBoundary.empty() ) and std::find( indicesOnBoundary.begin(), indicesOnBoundary.end(), i ) != indicesOnBoundary.end() ; };
87
88 celldata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
89
90 /*
91 extremely hacky static random number generator
92 */
93 static std::mt19937 rng(0); // seed with 0 for reproducibility
94 static std::uniform_real_distribution<> dis(0.0, 1.0);
95
96 switch(dofType)
97 {
98 case celldata::{{SOLVER_NAME}}::Type::Outside:
99 {
100 if ( marker.willBeRefined() ) // make it coarse
101 {
102 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
103 }
104 else
105 {
106 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Outside );
107 }
108 }
109 break;
110
111 case celldata::{{SOLVER_NAME}}::Type::Interior:
112 {
113 if ( marker.willBeRefined() )
114 {
115 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
116 }
117 else
118 {
119 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
120
121 // create vectors to send to implementation
122 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > solution;
123 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > rhs;
124 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > residual;
125
126 // first - fill the solution vector with randoms
127 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.CellUnknowns; i++) {
128 if ( indexIsOnBoundary(i) ) {
129 // ...
130 }
131 else {
132 // ...
133 }
134 solution[i] = dis(rng);
135
136 // and residual to 0...
137 residual[i] = 0;
138 }
139
140 // set rhs and update when we have all the projections...
141 rhs = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * solution;
142
143 // send to mesh...
144 fineGridCell{{SOLVER_NAME}}.setSolution( solution );
145 fineGridCell{{SOLVER_NAME}}.setRhs( rhs );
146 fineGridCell{{SOLVER_NAME}}.setResidual( residual );
147 fineGridCell{{SOLVER_NAME}}.setRand( solution );
148
149 // now we need to compute all projections...
150 auto faceProjections = repositories::{{SOLVER_INSTANCE}}. getFaceFromCellMatrix(marker.x(), marker.h()) * solution;
151
152 for (int f=0; f<TwoTimesD; f++) {
153 int startIndexProjection =
154 f < Dimensions ?
155 repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
156 0;
157 for (int p=0; p<repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode; p++) {
158 fineGridFaces{{SOLVER_NAME}}(f).setProjection(
159 p + startIndexProjection,
160 faceProjections( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection + p + startIndexProjection )
161 );
162
163 }
164
165 }
166
167 }
168 }
169 break;
170
171 }
172
173 logTraceOutWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
174 """
175
176 templateTouchFaceFirstTime = """
177 logTraceInWith2Arguments("InitDofs::touchFaceFirstTime", marker.toString(), fineGridFace{{SOLVER_NAME}}.toString());
178
179 facedata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getFaceDoFType(marker.x(),marker.h());
180
181 switch(dofType)
182 {
183 case facedata::{{SOLVER_NAME}}::Type::Outside:
184 {
185 if ( marker.willBeRefined() ) // make it coarse
186 {
187 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Coarse );
188 }
189 else
190 {
191 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Outside );
192 }
193 } break;
194
195 case facedata::{{SOLVER_NAME}}::Type::Interior:
196 {
197 if ( marker.willBeRefined() )
198 {
199 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Coarse );
200 }
201 else
202 {
203 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Interior );
204
205 // vectors to be passed into face
206 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution, double > sol;
207 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection, double > projection;
208
209 // set all of these values to 0
210 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
211 sol[i] = 0;
212
213 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection; i++)
214 projection[i] = 0;
215
216
217 // put into mesh
218 fineGridFace{{SOLVER_NAME}}.setSolution(sol);
219 fineGridFace{{SOLVER_NAME}}.setProjection(projection);
220
221 }
222 } break;
223
224 case facedata::{{SOLVER_NAME}}::Type::Boundary:
225 {
226 if ( marker.willBeRefined() )
227 {
228 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Coarse );
229 }
230 else
231 {
232 fineGridFace{{SOLVER_NAME}}.setType( facedata::{{SOLVER_NAME}}::Type::Boundary );
233
234 // vectors to be passed into face
235 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution, double > sol;
236 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection, double > projection;
237
238 // set all of these values to 0
239 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
240 sol[i] = 0;
241
242 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection; i++)
243 projection[i] = 0;
244
245 // put into mesh
246 fineGridFace{{SOLVER_NAME}}.setSolution(sol);
247 fineGridFace{{SOLVER_NAME}}.setProjection(projection);
248 }
249 } break;
250
251
252 }
253
254 logTraceOutWith2Arguments("InitDofs::touchFaceFirstTime", marker.toString(), fineGridFace{{SOLVER_NAME}}.toString());
255 """
256
257 def __init__(self,
258 solver):
259 super( InitDofsDGTest1, self ).__init__()
260 self.d = {}
261 self.d["SOLVER_INSTANCE"] = solver.instance_name()
262 self.d["SOLVER_NAME"] = solver.typename()
263 # self.d["VERTEX_CARDINALITY"] = solver._unknowns_per_vertex
264
265 def get_body_of_operation(self,operation_name):
266 result = ""
267 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
268 result = jinja2.Template(self.templateTouchVertexFirstTime).render(**self.d)
269 pass
270 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
271 result = jinja2.Template(self.templateTouchCellFirstTime).render(**self.d)
272 pass
273 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME:
274 result = jinja2.Template(self.templateTouchFaceFirstTime).render(**self.d)
275 pass
276 return result
277
279 """!
280
281 Configure name of generated C++ action set
282
283 This action set will end up in the directory observers with a name that
284 reflects how the observer (initialisation) is mapped onto this action
285 set. The name pattern is ObserverName2ActionSetIdentifier where this
286 routine co-determines the ActionSetIdentifier. We make is reflect the
287 Python class name.
288
289 """
290 return __name__.replace(".py", "").replace(".", "_")
291
293 """!
294
295 The action set that Peano will generate that corresponds to this class
296 should not be modified by users and can safely be overwritten every time
297 we run the Python toolkit.
298
299 """
300 return False
301
302 def get_includes(self):
303 """!
304
305 We need the solver repository in this action set, as we directly access
306 the solver object. We also need access to Peano's d-dimensional loops.
307
308 """
309 return """
310#include "repositories/SolverRepository.h"
311#include "peano4/utils/Loop.h"
312#include<numeric> // for std::iota
313#include <random>
314"""
315
317 """!
318 Perform some intermediate actions in test 1, namely:
319 - Fix the face solution, with projections that we get from the init phase
320 - Fix the rhs, using new face solution projected back into cell
321
322 This action set will run first, so we can fix the face solution (perhaps redundantly,
323 as the first TFFT in the solver will do this anyway), and then we fix the rhs during
324 the TCFT of this action set, which will be run first.
325
326 We only want to do this once, so we have a static int to keep count...
327 """
328
329 templateEndTraversal="""
330 Counter++;
331 """
332
333 templateTouchFaceFirstTime="""
334 if (
335 fineGridFace{{SOLVER_NAME}}.getType() == facedata::{{SOLVER_NAME}}::Type::Interior
336 and
337 Counter==0
338 ) {
339 logTraceInWith2Arguments( "updateFaceSolution::Interior", fineGridFace{{SOLVER_NAME}}.getSolution(), marker.toString() );
340
341 // project the u^\pm into a temporary vector
342 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution, double > projection =
343 repositories::{{SOLVER_INSTANCE}}.getRiemannMatrix() * fineGridFace{{SOLVER_NAME}}.getProjection();
344
345 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
346 fineGridFace{{SOLVER_NAME}}.setSolution(
347 i,
348 repositories::{{SOLVER_INSTANCE}}.OmegaFace * projection(i)
349 );
350 logTraceOutWith1Argument( "updateFaceSolution::Interior", fineGridFace{{SOLVER_NAME}}.getSolution() );
351 }
352
353 else if (
354 fineGridFace{{SOLVER_NAME}}.getType() == facedata::{{SOLVER_NAME}}::Type::Boundary
355 and
356 Counter==0
357 ) {
358 logTraceInWith1Argument( "updateFaceSolution::InteriorPenalty", fineGridFace{{SOLVER_NAME}}.getProjection() );
359 // Essentially what we do here is fix the solution on the boundary to be
360 // the inner-side projection.
361
362 // skip halfway along the projection vector if we are on face 0 or 1
363 int startIndexProjection =
364 marker.getSelectedFaceNumber() < Dimensions ?
365 repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
366 0;
367
368 auto boundaryMatrix = repositories::{{SOLVER_INSTANCE}}.getBoundaryConditionMatrix();
369
370 /*
371 Here we do slightly messy matrix multiplication. We would just multiply the boundary matrix
372 by the projection vector, and place that into the solution, but here we only want to capture
373 half of the projection vector; the other half lies outside the computational domain and
374 should be fixed to 0.
375 */
376 for (int row=0; row<boundaryMatrix.rows(); row++)
377 {
378 double rowSolution = 0;
379 for (int col=0; col<boundaryMatrix.cols(); col++)
380 {
381 rowSolution += boundaryMatrix( row, col ) * fineGridFace{{SOLVER_NAME}}.getProjection( col + startIndexProjection );
382 }
383 // place this solution into the face
384 fineGridFace{{SOLVER_NAME}}.setSolution( row, rowSolution );
385 }
386
387 logTraceOut( "updateFaceSolution::InteriorPenalty");
388 }
389
390
391"""
392
393 templateTouchCellFirstTime="""
394 if (
395 fineGridCell{{SOLVER_NAME}}.getType() != celldata::{{SOLVER_NAME}}::Type::Coarse
396 and
397 Counter==0
398 ) {
399 // now let's finish updating rhs
400 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSol;
401 for (int f=0; f<TwoTimesD; f++)
402 for (int s=0; s<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
403 faceSol( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{SOLVER_NAME}}(f).getSolution(s);
404
405 // next, we need to project solution on face onto the cell...
406 auto projection = repositories::{{SOLVER_INSTANCE}}.getCellFromFaceMatrix(marker.x(), marker.h()) * faceSol;
407
408 fineGridCell{{SOLVER_NAME}}.setRhs( fineGridCell{{SOLVER_NAME}}.getRhs( ) + projection );
409
410 }
411 """
412
413 def __init__(self, solver):
414 super(InitDofsIntermediatePhaseTest1, self).__init__(0, False)
415 self.d = {}
416 self.d["SOLVER_INSTANCE"] = solver.instance_name()
417 self.d["SOLVER_NAME"] = solver.typename()
418
419 def get_attributes(self):
420 return """
421 static int Counter;
422 """
423
424 def get_static_initialisations(self, full_qualified_classname):
425 return f"""
426 int {full_qualified_classname}::Counter = 0;
427 """
428
429 def get_body_of_operation(self, operation_name):
430 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
431 return jinja2.Template(self.templateTouchCellFirstTimetemplateTouchCellFirstTime).render(**self.d)
432 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_FIRST_TIME:
433 return jinja2.Template(self.templateTouchFaceFirstTimetemplateTouchFaceFirstTime).render(**self.d)
434 if operation_name==peano4.solversteps.ActionSet.OPERATION_END_TRAVERSAL:
435 return jinja2.Template(self.templateEndTraversaltemplateEndTraversal).render(**self.d)
436 return ""
437
439 """!
440
441 Configure name of generated C++ action set
442
443 This action set will end up in the directory observers with a name that
444 reflects how the observer (initialisation) is mapped onto this action
445 set. The name pattern is ObserverName2ActionSetIdentifier where this
446 routine co-determines the ActionSetIdentifier. We make is reflect the
447 Python class name.
448
449 """
450 return __name__.replace(".py", "").replace(".", "_") + "IntermediateSolve"
451
453 return False
454
455 def get_includes(self):
456 """!
457
458 """
459 return """
460#include "repositories/SolverRepository.h"
461#include "peano4/utils/Loop.h"
462"""
463
464
466 """!
467 Inherit from class above and modify one template.
468 The only difference is that here we set the initial guess to 0.
469 """
470
471 def __init__(self,
472 solver):
473 super( InitDofsDGTest6, self ).__init__(solver)
474
475 templateTouchCellFirstTime = """
476 logTraceInWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
477
478 auto insertIfNotPresent = []( std::vector<int>& v, int i ) {
479 if( std::find( v.begin(), v.end(), i ) == v.end() ) v.push_back(i);
480 };
481
482 // anonymous functions to calculate cell indices which are on the boundary
483 std::vector<int> indicesOnBoundary;
484
485 for (int f=0; f<TwoTimesD; f++) {
486 if( fineGridFaces{{SOLVER_NAME}}(f).getType() == facedata::{{SOLVER_NAME}}::Type::Boundary ) {
487 // this face is on the boundary. Gather the cell dof indices this corresponds to
488
489 switch(f){
490 case 0: {
491 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, (repositories::{{SOLVER_INSTANCE}}.PolyDegree + 1)*i );
492 } break;
493
494 case 1: {
495 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, i );
496 } break;
497
498 case 2: {
499 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.PolyDegree+1; i++) insertIfNotPresent( indicesOnBoundary, repositories::{{SOLVER_INSTANCE}}.PolyDegree + (repositories::{{SOLVER_INSTANCE}}.PolyDegree + 1)*i );
500 } break;
501
502 case 3: {
503 for (int i=(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1)*repositories::{{SOLVER_INSTANCE}}.PolyDegree; i<(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1)*(repositories::{{SOLVER_INSTANCE}}.PolyDegree+1); i++) insertIfNotPresent( indicesOnBoundary, i );
504 } break;
505
506 }
507
508 }
509 }
510
511 auto indexIsOnBoundary = [&indicesOnBoundary](int i) -> bool { return not( indicesOnBoundary.empty() ) and std::find( indicesOnBoundary.begin(), indicesOnBoundary.end(), i ) != indicesOnBoundary.end() ; };
512
513 celldata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
514
515 /*
516 extremely hacky static random number generator
517 */
518 static std::mt19937 rng(0); // seed with 0 for reproducibility
519 static std::uniform_real_distribution<> dis(0.0, 1.0);
520
521 switch(dofType)
522 {
523 case celldata::{{SOLVER_NAME}}::Type::Outside:
524 {
525 if ( marker.willBeRefined() ) // make it coarse
526 {
527 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
528 }
529 else
530 {
531 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Outside );
532 }
533 }
534 break;
535
536 case celldata::{{SOLVER_NAME}}::Type::Interior:
537 {
538 if ( marker.willBeRefined() )
539 {
540 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
541 }
542 else
543 {
544 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
545
546 // create vectors to send to implementation
547 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > solution;
548 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > rhs;
549 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > residual;
550 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > rand;
551
552 // first - fill the solution vector with randoms
553 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.CellUnknowns; i++) {
554 if ( indexIsOnBoundary(i) ) {
555 rand[i] = 0.0; // to satisfy the boundary conditions
556 }
557 else {
558 rand[i] = dis(rng);
559 // rand[i] = std::sin( 2*tarch::la::PI * marker.x()(0) ) * std::sin( 2*tarch::la::PI * marker.x()(1) );
560 }
561
562 // and residual to 0...
563 residual[i] = 0;
564 solution[i] = 0;
565 }
566
567 // save the random field
568 fineGridCell{{SOLVER_NAME}}.setRand( rand );
569
570 // set rhs...
571 rhs = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * rand;
572
573 // now we need to compute all projections...
574 auto faceProjections = repositories::{{SOLVER_INSTANCE}}. getFaceFromCellMatrix(marker.x(), marker.h()) * rand;
575
576 for (int f=0; f<TwoTimesD; f++) {
577 int startIndexProjection =
578 f < Dimensions ?
579 repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
580 0;
581 for (int p=0; p<repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode; p++) {
582 fineGridFaces{{SOLVER_NAME}}(f).setRandProjection(
583 p + startIndexProjection,
584 faceProjections( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsProjection + p + startIndexProjection )
585 );
586 }
587
588 }
589
590 // send to mesh...
591 fineGridCell{{SOLVER_NAME}}.setSolution( solution );
592 fineGridCell{{SOLVER_NAME}}.setRhs( rhs );
593 fineGridCell{{SOLVER_NAME}}.setResidual( residual );
594
595 }
596 }
597 break;
598
599 }
600
601 logTraceOutWith2Arguments("InitDofs::touchCellFirstTime", marker.toString(), fineGridCell{{SOLVER_NAME}}.toString());
602 """
603
605 """
606 Inherit from the class for test1.
607 """
608 templateTouchCellFirstTime="""
609 if (
610 fineGridCell{{SOLVER_NAME}}.getType() != celldata::{{SOLVER_NAME}}::Type::Coarse
611 and
612 Counter==0
613 ) {
614 // now let's finish updating rhs
615 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSol;
616 for (int f=0; f<TwoTimesD; f++)
617 for (int s=0; s<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
618 faceSol( f*repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{SOLVER_NAME}}(f).getRandSolution(s);
619
620 // next, we need to project solution on face onto the cell...
621 auto projection = repositories::{{SOLVER_INSTANCE}}.getCellFromFaceMatrix(marker.x(), marker.h()) * faceSol;
622
623 fineGridCell{{SOLVER_NAME}}.setRhs( fineGridCell{{SOLVER_NAME}}.getRhs( ) + projection );
624 }
625 """
626
627 templateTouchFaceFirstTime="""
628 if (
629 fineGridFace{{SOLVER_NAME}}.getType() == facedata::{{SOLVER_NAME}}::Type::Interior
630 and
631 Counter==0
632 ) {
633
634 // project the u^\pm into a temporary vector
635 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution, double > projection =
636 repositories::{{SOLVER_INSTANCE}}.getRiemannMatrix() * fineGridFace{{SOLVER_NAME}}.getRandProjection();
637
638 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
639 fineGridFace{{SOLVER_NAME}}.setRandSolution(
640 i,
641 repositories::{{SOLVER_INSTANCE}}.OmegaFace * projection(i)
642 );
643 }
644
645 else if (
646 fineGridFace{{SOLVER_NAME}}.getType() == facedata::{{SOLVER_NAME}}::Type::Boundary
647 and
648 Counter==0
649 ) {
650 // Essentially what we do here is fix the solution on the boundary to be
651 // the inner-side projection.
652
653 // skip halfway along the projection vector if we are on face 0 or 1
654 int startIndexProjection =
655 marker.getSelectedFaceNumber() < Dimensions ?
656 repositories::{{SOLVER_INSTANCE}}.NodesPerFace * repositories::{{SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
657 0;
658
659 auto boundaryMatrix = repositories::{{SOLVER_INSTANCE}}.getBoundaryConditionMatrix();
660
661 /*
662 Here we do slightly messy matrix multiplication. We would just multiply the boundary matrix
663 by the projection vector, and place that into the solution, but here we only want to capture
664 half of the projection vector; the other half lies outside the computational domain and
665 should be fixed to 0.
666 */
667 for (int row=0; row<boundaryMatrix.rows(); row++)
668 {
669 double rowSolution = 0;
670 for (int col=0; col<boundaryMatrix.cols(); col++)
671 {
672 rowSolution += boundaryMatrix( row, col ) * fineGridFace{{SOLVER_NAME}}.getRandProjection( col + startIndexProjection );
673 }
674 // place this solution into the face
675 fineGridFace{{SOLVER_NAME}}.setRandSolution( row, rowSolution );
676 }
677
678 }
679
680 """
681
683 def __init__(self,
684 solver):
685 super( InitDofsDGTest4, self ).__init__(solver)
686
687
688 templateTouchCellFirstTime="""
689 celldata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
690
691 /*
692 extremely hacky static random number generator
693 */
694 static std::mt19937 rng(1); // seed with 1 for reproducibility. make sure it's different to the numbers we put in the vertices
695 static std::uniform_real_distribution<> dis(0.0, 1.0);
696
697 switch(dofType)
698 {
699 case celldata::{{SOLVER_NAME}}::Type::Outside:
700 {
701 if ( marker.willBeRefined() ) // make it coarse
702 {
703 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
704 }
705 else
706 {
707 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Outside );
708 }
709 }
710 break;
711
712 case celldata::{{SOLVER_NAME}}::Type::Interior:
713 {
714 if ( marker.willBeRefined() )
715 {
716 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
717 }
718 else
719 {
720 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
721
722 // create vectors to send to implementation
723 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > solution;
724 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > rhs;
725 tarch::la::Vector< repositories::{{SOLVER_INSTANCE}}.CellUnknowns, double > residual;
726
727 // first - fill the solution vector with randoms
728 for (int i=0; i<repositories::{{SOLVER_INSTANCE}}.CellUnknowns; i++) {
729 solution[i] = dis(rng);
730
731 // and residual to 0...
732 residual[i] = 0;
733 }
734
735 // set rhs...
736 rhs = repositories::{{SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * solution;
737
738 // send to mesh...
739 fineGridCell{{SOLVER_NAME}}.setSolution( solution );
740 fineGridCell{{SOLVER_NAME}}.setRhs( rhs );
741 fineGridCell{{SOLVER_NAME}}.setResidual( residual );
742
743 }
744 }
745 break;
746
747 }
748
749 """
750
752
753 templateTouchCellFirstTime="""
754 celldata::{{SOLVER_NAME}}::Type dofType = repositories::{{SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
755
756 switch(dofType)
757 {
758 case celldata::{{SOLVER_NAME}}::Type::Outside:
759 {
760 if ( marker.willBeRefined() ) // make it coarse
761 {
762 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
763 }
764 else
765 {
766 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Outside );
767 }
768 }
769 break;
770
771 case celldata::{{SOLVER_NAME}}::Type::Interior:
772 {
773 if ( marker.willBeRefined() )
774 {
775 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
776 }
777 else
778 {
779 fineGridCell{{SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
780
781 }
782 }
783 break;
784
785 }
786
787 """
788 def __init__(self,
789 solver):
790 super( InitDofsDGTest5, self ).__init__(solver)
791
793
794 templateTouchCellFirstTime="""
795 constexpr int Cols = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
796 constexpr int Rows = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
797
798 static const tarch::la::Matrix< Rows, Cols, double > prolongationMatrix =
799 {
800 {{PROLONGATION_MATRIX[0]| join(", ")}}
801 {% for ROW in PROLONGATION_MATRIX[1:] %}
802 ,{{ROW | join(", ")}}
803 {% endfor %}
804 };
805
806 celldata::{{DG_SOLVER_NAME}}::Type dofType = repositories::{{DG_SOLVER_INSTANCE}}.getCellDoFType(marker.x(),marker.h());
807
808 switch(dofType)
809 {
810 case celldata::{{DG_SOLVER_NAME}}::Type::Outside:
811 {
812 if ( marker.willBeRefined() ) // make it coarse
813 {
814 fineGridCell{{DG_SOLVER_NAME}}.setType( celldata::{{DG_SOLVER_NAME}}::Type::Coarse );
815 }
816 else
817 {
818 fineGridCell{{DG_SOLVER_NAME}}.setType( celldata::{{DG_SOLVER_NAME}}::Type::Outside );
819 }
820 }
821 break;
822
823 case celldata::{{SOLVER_NAME}}::Type::Interior:
824 {
825 if ( marker.willBeRefined() )
826 {
827 fineGridCell{{DG_SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Coarse );
828 }
829 else
830 {
831 fineGridCell{{DG_SOLVER_NAME}}.setType( celldata::{{SOLVER_NAME}}::Type::Interior );
832
833 // also gather the cg values
834 tarch::la::Vector<TwoPowerD, double> u_cg_random;
835 for (int i=0; i<TwoPowerD; i++) u_cg_random(i) = fineGridVertices{{CG_SOLVER_NAME}}(i).getRand(0);
836 auto v_cell = prolongationMatrix * u_cg_random;
837
838 // next, project v_cell onto each of the faces
839 tarch::la::Vector< TwoTimesD * repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsProjection, double > faceProjections = repositories::{{SOLVER_INSTANCE}}. getFaceFromCellMatrix(marker.x(), marker.h()) * v_cell;
840 for (int f=0; f<TwoTimesD; f++) {
841 int startIndexProjection =
842 f < Dimensions ?
843 repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
844 0;
845 for (int p=0; p<repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode; p++) {
846 fineGridFaces{{DG_SOLVER_NAME}}(f).setRandProjections(
847 p + startIndexProjection,
848 faceProjections( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsProjection + p + startIndexProjection )
849 );
850
851 }
852 }
853
854 // also begin to set rhs
855 fineGridCell{{DG_SOLVER_NAME}}.setRhs(
856 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()) * v_cell
857 );
858
859 // set the initial guess to 0
860 fineGridCell{{DG_SOLVER_NAME}}.setSolution(
861 0.0
862 );
863
864 }
865 }
866 break;
867
868 }
869
870 """
871
872 templateTouchFaceLastTime="""
873 // perform averaging on the faces
874 if (
875 fineGridFace{{DG_SOLVER_NAME}}.getType() == facedata::{{DG_SOLVER_NAME}}::Type::Interior
876 ) {
877 // project the u^\pm into a temporary vector
878 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution, double > projection =
879 repositories::{{DG_SOLVER_INSTANCE}}.getRiemannMatrix() * fineGridFace{{DG_SOLVER_NAME}}.getRandProjections();
880
881 for (int i=0; i<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; i++)
882 fineGridFace{{DG_SOLVER_NAME}}.setRandSolutions(
883 i,
884 projection(i)
885 );
886 }
887
888 else if (
889 fineGridFace{{DG_SOLVER_NAME}}.getType() == facedata::{{DG_SOLVER_NAME}}::Type::Boundary
890 ) {
891 // Essentially what we do here is fix the solution on the boundary to be
892 // the inner-side projection.
893
894 // skip halfway along the projection vector if we are on face 0 or 1
895 int startIndexProjection =
896 marker.getSelectedFaceNumber() < Dimensions ?
897 repositories::{{DG_SOLVER_INSTANCE}}.NodesPerFace * repositories::{{DG_SOLVER_INSTANCE}}.ProjectionsPerFaceNode :
898 0;
899
900 auto boundaryMatrix = repositories::{{DG_SOLVER_INSTANCE}}.getBoundaryConditionMatrix();
901
902 /*
903 Here we do slightly messy matrix multiplication. We would just multiply the boundary matrix
904 by the projection vector, and place that into the solution, but here we only want to capture
905 half of the projection vector; the other half lies outside the computational domain and
906 should be fixed to 0.
907 */
908 for (int row=0; row<boundaryMatrix.rows(); row++)
909 {
910 double rowSolution = 0;
911 for (int col=0; col<boundaryMatrix.cols(); col++)
912 {
913 rowSolution += boundaryMatrix( row, col ) * fineGridFace{{DG_SOLVER_NAME}}.getRandProjections( col + startIndexProjection );
914 }
915 // place this solution into the face
916 fineGridFace{{DG_SOLVER_NAME}}.setRandSolutions( row, rowSolution );
917 }
918
919 }
920
921 """
922
925 dim = 2,
926 coarse_order = 1,
927 fine_order = self.dg_solver._poly_degree
928 )
929 return intergrid_operators.prolongation()
930
931 def __init__(self,
932 dg_solver,
933 ):
934 super( InitDofsDGTest7, self ).__init__(dg_solver)
935 self.dg_solver = dg_solver
936 self.dd["DG_SOLVER_INSTANCE"] = dg_solver.instance_name()
937 self.dd["DG_SOLVER_NAME"] = dg_solver.typename()
938 self.dd["CG_SOLVER_INSTANCE"] = "instanceOfCollocatedPoisson"
939 self.dd["CG_SOLVER_NAME"] = "CollocatedPoisson"
940 self.dd["PROLONGATION_MATRIX"] = self.get_prolongation_matrix()
941
942 def get_body_of_operation(self,operation_name):
943 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_FACE_LAST_TIME:
944 return jinja2.Template(self.templateTouchFaceLastTimetemplateTouchFaceLastTime).render(**self.dd)
945 else:
946 return super().get_body_of_operation(operation_name)
Redoing this class for discontinuous galerkin solver.
Definition InitDG.py:7
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Definition InitDG.py:265
__init__(self, solver)
Definition InitDG.py:258
get_action_set_name(self)
Configure name of generated C++ action set.
Definition InitDG.py:278
str templateTouchVertexFirstTime
Definition InitDG.py:14
str templateTouchCellFirstTime
Definition InitDG.py:50
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
Definition InitDG.py:302
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
Definition InitDG.py:292
__init__(self, solver)
Definition InitDG.py:684
__init__(self, solver)
Definition InitDG.py:789
Inherit from class above and modify one template.
Definition InitDG.py:465
__init__(self, solver)
Definition InitDG.py:472
get_prolongation_matrix(self)
Definition InitDG.py:923
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Definition InitDG.py:942
__init__(self, dg_solver)
Definition InitDG.py:933
Perform some intermediate actions in test 1, namely:
Definition InitDG.py:316
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
Definition InitDG.py:429
get_attributes(self)
Return attributes as copied and pasted into the generated class.
Definition InitDG.py:419
get_static_initialisations(self, full_qualified_classname)
Definition InitDG.py:424
user_should_modify_template(self)
Is the user allowed to modify the output.
Definition InitDG.py:452
get_action_set_name(self)
Configure name of generated C++ action set.
Definition InitDG.py:438
get_includes(self)
Return include statements that you need.
Definition InitDG.py:455
Inherit from the class for test1.
Definition InitDG.py:604
Action set (reactions to events)
Definition ActionSet.py:6