Peano
Loading...
Searching...
No Matches
SBH.py
Go to the documentation of this file.
1# This file is part of the Peano project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3import os
4import argparse
5
6import peano4
7import exahype2
8import dastgen2
9
10import peano4.toolbox.particles
11import numpy as np
12
13import jinja2
14
15
16import exahype2.solvers.fv.rusanov.kernels
17
18from enum import Enum
19
20# See comments in README.dox
21# export PYTHONPATH=../../../../python
22# export PYTHONPATH=$PYTHONPATH:../../../../applications/ccz4
23from CCZ4Solver import CCZ4Solver_FV_GlobalAdaptiveTimeStepWithEnclaveTasking
24from CCZ4Solver import CCZ4Solver_FD4_GlobalAdaptiveTimeStepWithEnclaveTasking
25from CCZ4Solver import (
26 CCZ4Solver_FD4_SecondOrderFormulation_GlobalAdaptiveTimeStepWithEnclaveTasking,
27)
28
29from CCZ4Solver import CCZ4Solver_FV_GlobalAdaptiveTimeStep
30from CCZ4Solver import CCZ4Solver_FD4_GlobalAdaptiveTimeStep
31
32
33# for the coupling
34from exahype2.solvers.fv.actionsets.AbstractFVActionSet import AbstractFVActionSet
35
36BlackHoleRegion = 0.1
37
38
40 NONE = "::peano4::utils::LoopPlacement::Serial"
41 PARALLEL_FOR = "::peano4::utils::LoopPlacement::Nested"
42 SUBTASKS = "::peano4::utils::LoopPlacement::SpreadOut"
43
44
46 """!
47
48 Construct the Finite Volume (limiter) scheme
49
50 We assume that the underlying Finite Differences scheme has a patch
51 size of 6x6x6. To make the Finite Volume scheme's time stepping (and
52 accuracy) match this patch size, we have to employ a 16 times finer
53 mesh.
54
55 It is interesting to see that the limiter does not really have a min
56 and max mesh size. The point is that the higher order solver dictates
57 the mesh structure, and we then follow this structure with the
58 Finite Volume scheme.
59
60 """
61
63 self,
64 name,
65 patch_size,
66 amend_priorities: bool,
67 parallelisation_of_kernels: KernelParallelisation,
68 ):
69 """!
70
71 Construct the limiter
72
73 patch_size: Integer
74 Pass in the patch size of the FD4 scheme or, if you are using RKDG,
75 hand in the number 1. The Finite Volume patch then will be 16 times
76 finer.
77
78 """
79 SubPatchSize = int(patch_size * 4 * 4)
80
81 super(Limiter, self).__init__(
82 name=name + "_FV",
83 patch_size=SubPatchSize,
84 min_volume_h=1.0 / 65536,
85 max_volume_h=65536,
86 pde_terms_without_state=True,
87 )
88 self.double_constants["BlackHoleFVRegion"] = BlackHoleRegion
89
90 self._user_action_set_includes += """
91#include "toolbox/blockstructured/Restriction.h"
92#include "toolbox/blockstructured/Interpolation.h"
93"""
94
95 if amend_priorities:
96 self.enclave_task_priority = "tarch::multicore::Task::DefaultPriority+1"
97
98 # self._fused_compute_kernel_call_gpu = exahype2.solvers.fv.rusanov.kernels.create_compute_Riemann_kernel_for_Rusanov(
99 # self._flux_implementation, self._ncp_implementation, self._source_term_implementation,
100 # compute_max_eigenvalue_of_next_time_step=True,
101 # solver_variant = exahype2.solvers.fv.rusanov.kernels.SolverVariant.Accelerator,
102 # kernel_variant = exahype2.solvers.fv.rusanov.kernels.KernelVariant.GenericAoS
103 # )
104
105 self.set_implementation(
106 initial_conditions=exahype2.solvers.PDETerms.User_Defined_Implementation,
107 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
108 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
109 )
110
111 if parallelisation_of_kernels == KernelParallelisation.SUBTASKS:
112 # self._compute_kernel_call = exahype2.solvers.fv.rusanov.kernels.create_compute_Riemann_kernel_for_Rusanov(
113 # self._flux_implementation, self._ncp_implementation, self._source_term_implementation,
114 # compute_max_eigenvalue_of_next_time_step=True,
115 # solver_variant = exahype2.solvers.fv.rusanov.kernels.SolverVariant.WithVirtualFunctions,
116 # kernel_variant = exahype2.solvers.fv.rusanov.kernels.KernelVariant.PatchWiseAoSHeap
117 # )
118
119 self._fused_compute_kernel_call_cpu = exahype2.solvers.fv.rusanov.kernels.create_compute_Riemann_kernel_for_Rusanov(
123 compute_max_eigenvalue_of_next_time_step=True,
124 solver_variant=exahype2.solvers.fv.rusanov.kernels.SolverVariant.Multicore,
125 kernel_variant=exahype2.solvers.fv.rusanov.kernels.KernelVariant.PatchWiseAoSHeap,
126 )
127
130
132 """!
133
134 Mask out exterior cells
135
136 """
137 return (
138 """("""
139 + super(Limiter, self)._store_cell_data_default_guard()
140 + " and repositories::instanceOf"
141 + self._name
142 + ".isCellOverlappingWithBHImpactArea(marker) )"
143 )
144
146 return (
147 """("""
148 + super(Limiter, self)._load_cell_data_default_guard()
149 + " and repositories::instanceOf"
150 + self._name
151 + ".isCellOverlappingWithBHImpactArea(marker) )"
152 )
153
155 return (
156 """("""
158 + " and repositories::instanceOf"
159 + self._name
160 + ".isCellOverlappingWithBHImpactArea(marker) )"
161 )
162
164 return "{} and repositories::instanceOf{}.isOneAdjacentCellOverlappingWithBHImpactArea(marker)".format(
166 self._name,
167 )
168
170 return "({} and repositories::instanceOf{}.areBothAdjacentCellsOverlappingWithBHImpactArea(marker))".format(
171 super(Limiter, self)._store_face_data_default_guard(), self._name
172 )
173
175 return "({} and repositories::instanceOf{}.areBothAdjacentCellsOverlappingWithBHImpactArea(marker))".format(
176 super(Limiter, self)._load_face_data_default_guard(), self._name
177 )
178
180 """!
181
182 Not really a lot of things to do here. The only exception that is
183 really important is that we have to ensure that we only solve stuff
184 inside the local domain of the FV. By default, ExaHyPE 2 solves the
185 PDE everywhere. If data is not stored persistently or loaded from
186 the persistent stacks, it still solves, as it then would assume that
187 such data arises from dynamic AMR. In this particular case, we have
188 to really mask out certain subdomains.
189
190 It is not just a nice optimisation to do so. It is absolutely key,
191 as the application of the compute kernel on garbage would mean that
192 we end up with invalid eigenvalues.
193
194 """
195 super(Limiter, self).create_action_sets()
196
197 self._action_set_update_cell.guard = "({} and repositories::instanceOf{}.isCellOverlappingWithBHImpactArea(marker))".format(
198 self._action_set_update_cell.guard, self._name
199 )
200 self._action_set_merge_enclave_task_outcome.guard = "({} and repositories::instanceOf{}.isCellOverlappingWithBHImpactArea(marker))".format(
201 self._action_set_merge_enclave_task_outcome.guard, self._name
202 )
203
204
206 """!
207
208 4th order Finite Differences solver with a limiter
209
210 The FD scheme is our primary solver, i.e. the one we wanna use (almost)
211 everywhere. Hence, we have to be sure that we use the right boundary
212 conditions. In our case, that should be Sommerfeld ones. As we work
213 with a limited FD4 solver, we have to ensure that we get the
214 @ref benchmarks_exahype2_ccz4_single_black_hole "solver coupling" right.
215
216 The primary solver is a plain CCZ4 FD4 solver with enclave tasking. There
217 are some modification though:
218
219 1. We ensure that we use Sommerfeld boundary conditions. This means that
220 we have to replace the whole generic boundary treatment with a bespoke
221 action set.
222 2. The coupling has to be injected. We model the coupling as separate
223 (enclave) tasks to avoid that we totally serialise the solver steps
224 whenever we encounter a coupling.
225
226 """
227
229 self,
230 name,
231 patch_size,
232 min_cell_size,
233 max_cell_size,
234 parallelisation_of_interpolation: KernelParallelisation,
235 parallelisation_of_kernels: KernelParallelisation,
236 interpolation_method,
237 ):
239 self._parallelisation_of_interpolation = parallelisation_of_interpolation
240 self.interpolation_method = interpolation_method
241
242 CCZ4Solver_FD4_GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
243 self,
244 name=name + "_FD4",
245 patch_size=patch_size,
246 rk_order=1,
247 min_meshcell_h=min_cell_size / patch_size,
248 max_meshcell_h=max_cell_size / patch_size,
249 pde_terms_without_state=False,
250 )
251
252 self._user_action_set_includes += """
253#include "toolbox/blockstructured/Projection.h"
254#include "toolbox/blockstructured/Restriction.h"
255#include "toolbox/blockstructured/Interpolation.h"
256#include "toolbox/blockstructured/Copy.h"
257"""
258 if self.interpolation_method == "matrix":
259 self._user_action_set_includes += (
260 """
261#include "matrixdata/Interpolator_"""
262 + str(patch_size)
263 + """_"""
264 + str(patch_size * 16)
265 + """.h"
266"""
267 )
268 self.double_constants["BlackHoleFVRegion"] = BlackHoleRegion
269
270 self.set_implementation(
271 initial_conditions=exahype2.solvers.PDETerms.User_Defined_Implementation,
272 refinement_criterion=exahype2.solvers.PDETerms.User_Defined_Implementation,
273 boundary_conditions=exahype2.solvers.PDETerms.None_Implementation,
274 )
276
277 if parallelisation_of_kernels == KernelParallelisation.SUBTASKS:
278 print(
279 "WARNING: Unfortunately, we have not yet written parallelised kernels for FD4"
280 )
281 pass
282
284
285 if self.interpolation_method == "matrix":
286 solver_matrix_interpolator = exahype2.solvers.SolverMatrixInterpolator(
287 patch_size, patch_size * 16, 3, 1
288 )
289 solver_matrix_interpolator.generateData()
290
292 """!
293
294 Tailor action set behaviour
295
296 We first make a few additional cells skeleton cells. The rationale
297 behind additional skeletons is given in the @ref benchmarks_exahype2_ccz4_single_black_hole "generic overview".
298 Given the first remark there on FD4-FV coupling, one would be tempted
299 to use the predicate
300
301 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302 self._action_set_update_cell.additional_skeleton_guard = " " "(
303 repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.isCellOverlappingWithBHImpactArea(marker)
304 and
305 not repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.areAllFaceConnectedCellsOverlappingWithBHImpactArea(marker)
306 )
307 " " "
308 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
309
310 Once we study the other items (notably the fourth), we see that it is
311 reasonable to make all the overlap region a skeleton within the FD4
312 solver.
313
314 """
315 super(FD4SolverWithLimiter, self).create_action_sets()
316
317 self._action_set_handle_boundary.TemplateHandleBoundary_KernelCalls = (
318 """
319 double Qinf[59]={1.0, 0.0, 0.0, 1.0, 0.0, 1.0, //q0-5
320 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q6-11
321 0.0, 0.0, 0.0, 0.0, //q12-15
322 1.0, 0.0, 0.0, 0.0, //q16-19
323 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q20-25
324 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q26-34
325 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
326 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q35-52
327 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 //q53-58
328 }; //approximate background solution at infinity
329 ::exahype2::fd::applySommerfeldConditions(
330 [&](
331 const double * NOALIAS Q,
332 const tarch::la::Vector<DIMENSIONS,double>& faceCentre,
333 const tarch::la::Vector<DIMENSIONS,double>& gridCellH,
334 double t,
335 double dt,
336 int normal
337 ) -> double {
338 return repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, faceCentre, gridCellH, t, dt, normal );
339 },
340 [&](
341 double * NOALIAS Q,
342 const tarch::la::Vector<DIMENSIONS,double>& faceCentre,
343 const tarch::la::Vector<DIMENSIONS,double>& gridCellH
344 ) -> void {
345 for (int i=0; i<"""
346 + str(self._unknowns + self._auxiliary_variables)
347 + """; i++) {
348 Q[i] = 0.0;
349 }
350 Q[0] = 1.0; Q[3] = 1.0; Q[5] = 1.0;
351 Q[16] = 0.95; Q[54] = 0.95;
352 },
353 marker.getX(),
354 marker.getH(),
355 {{FACE_METADATA_ACCESSOR}}.getOldTimeStamp(marker.getSelectedFaceNumber()<DIMENSIONS ? 1 : 0),
356 repositories::{{SOLVER_INSTANCE}}.getMinTimeStepSize(),
357 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
358 {{OVERLAP}},
359 {{NUMBER_OF_UNKNOWNS}},
360 {{NUMBER_OF_AUXILIARY_VARIABLES}},
361 marker.getSelectedFaceNumber(),
362 {0.0, 0.0, 0.0},
363 fineGridFace{{UNKNOWN_IDENTIFIER}}Old.data(),
364 fineGridFace{{UNKNOWN_IDENTIFIER}}New.data(),
365 -1 //not use checkpoint yet
366 );
367 """
368 )
369
370 self._action_set_preprocess_solution = exahype2.solvers.rkfd.actionsets.PreprocessReconstructedSolutionWithHalo(
371 solver=self,
372 enclave_task_cell_label="fineGridCell"
374 + "_FVCellLabel",
375 compute_kernel_implementation="""
376const int sizeOfPatch = (repositories::instanceOf"""
378 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch+2)
379 * (repositories::instanceOf"""
381 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch+2)
382 * (repositories::instanceOf"""
384 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch+2)
385 * (repositories::instanceOf"""
387 + """_FV.NumberOfUnknowns + repositories::instanceOf"""
389 + """_FV.NumberOfAuxiliaryVariables);
390const int sizeOfFace = 2
391 * (repositories::instanceOf"""
393 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch+2)
394 * (repositories::instanceOf"""
396 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch+2)
397 * (repositories::instanceOf"""
399 + """_FV.NumberOfUnknowns + repositories::instanceOf"""
401 + """_FV.NumberOfAuxiliaryVariables);
402
403double* interpolatedFVDataWithHalo = ::tarch::allocateMemory<double>(sizeOfPatch, ::tarch::MemoryLocation::Heap);
404
405bool faceIsReal0 = repositories::instanceOf"""
407 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,0);
408bool faceIsReal1 = repositories::instanceOf"""
410 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,1);
411bool faceIsReal2 = repositories::instanceOf"""
413 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,2);
414bool faceIsReal3 = repositories::instanceOf"""
416 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,3);
417bool faceIsReal4 = repositories::instanceOf"""
419 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,4);
420bool faceIsReal5 = repositories::instanceOf"""
422 + """_FV.areBothAdjacentCellsOverlappingWithBHImpactArea(marker,5);
423
424double* realFace0 = faceIsReal0 ? fineGridFaces"""
426 + """_FVQNew(0).data() : nullptr;
427double* realFace1 = faceIsReal1 ? fineGridFaces"""
429 + """_FVQNew(1).data() : nullptr;
430double* realFace2 = faceIsReal2 ? fineGridFaces"""
432 + """_FVQNew(2).data() : nullptr;
433double* realFace3 = faceIsReal3 ? fineGridFaces"""
435 + """_FVQNew(3).data() : nullptr;
436double* realFace4 = faceIsReal4 ? fineGridFaces"""
438 + """_FVQNew(4).data() : nullptr;
439double* realFace5 = faceIsReal5 ? fineGridFaces"""
441 + """_FVQNew(5).data() : nullptr;
442
443double* dummyFace0 = faceIsReal0 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
444double* dummyFace1 = faceIsReal1 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
445double* dummyFace2 = faceIsReal2 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
446double* dummyFace3 = faceIsReal3 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
447double* dummyFace4 = faceIsReal4 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
448double* dummyFace5 = faceIsReal5 ? nullptr : ::tarch::allocateMemory<double>(sizeOfFace, ::tarch::MemoryLocation::Heap);
449
450::toolbox::blockstructured::interpolateCellDataAssociatedToVolumesIntoOverlappingCell_"""
452 + """(
453 repositories::instanceOf"""
455 + """_FD4.NumberOfGridCellsPerPatchPerAxis,
456 repositories::instanceOf"""
458 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch,
459 3, // halo in FD4
460 1, // halo in FV
461 repositories::instanceOf"""
463 + """_FV.NumberOfUnknowns + repositories::instanceOf"""
465 + """_FV.NumberOfAuxiliaryVariables,
466 """
467 + (
468 """InterpolationMatrixData::Data,
469 InterpolationMatrixData::Indices,
470 InterpolationMatrixData::Indptr,"""
471 if self.interpolation_method == "matrix"
472 else """"""
473 )
474 + """
475 oldQWithHalo,
476 interpolatedFVDataWithHalo,
477 """
478 + str(self._parallelisation_of_interpolation.value)
479 + """
480);
481
482::toolbox::blockstructured::projectPatchHaloOntoFaces(
483 repositories::instanceOf"""
485 + """_FV.NumberOfFiniteVolumesPerAxisPerPatch,
486 1, // int haloSize,
487 repositories::instanceOf"""
489 + """_FV.NumberOfUnknowns,
490 repositories::instanceOf"""
492 + """_FV.NumberOfAuxiliaryVariables,
493 interpolatedFVDataWithHalo,
494 faceIsReal0 ? realFace0 : dummyFace0,
495 faceIsReal1 ? realFace1 : dummyFace1,
496 faceIsReal2 ? realFace2 : dummyFace2,
497 faceIsReal3 ? realFace3 : dummyFace3,
498 faceIsReal4 ? realFace4 : dummyFace4,
499 faceIsReal5 ? realFace5 : dummyFace5
500);
501
502::tarch::freeMemory(interpolatedFVDataWithHalo, tarch::MemoryLocation::Heap );
503if (dummyFace0!=nullptr) ::tarch::freeMemory(dummyFace0, tarch::MemoryLocation::Heap );
504if (dummyFace1!=nullptr) ::tarch::freeMemory(dummyFace1, tarch::MemoryLocation::Heap );
505if (dummyFace2!=nullptr) ::tarch::freeMemory(dummyFace2, tarch::MemoryLocation::Heap );
506if (dummyFace3!=nullptr) ::tarch::freeMemory(dummyFace3, tarch::MemoryLocation::Heap );
507if (dummyFace4!=nullptr) ::tarch::freeMemory(dummyFace4, tarch::MemoryLocation::Heap );
508if (dummyFace5!=nullptr) ::tarch::freeMemory(dummyFace5, tarch::MemoryLocation::Heap );
509""",
510 )
511
513 "("
515 + """
516 and
517 repositories::instanceOf"""
519 + """_FV.isCellOverlappingWithBHImpactArea(marker)
520 and
521 not repositories::instanceOf"""
523 + """_FV.areAllFaceConnectedCellsOverlappingWithBHImpactArea(marker)
524 and
525 not marker.willBeRefined()
526 )"""
527 )
528
529 self._action_set_postprocess_solution = exahype2.solvers.rkfd.actionsets.PatchWisePostprocessSolution(
530 self,
531 """
532if (
533 repositories::instanceOf{0}_FV.isCellOverlappingWithBHImpactArea(marker)
534 and
535 not marker.willBeRefined()
536) {{
537 logTraceIn( "touchCellFirstTime(...)-inject" );
538
539 repositories::instanceOf{0}_FV.incNumberOfPatches();
540
541 //if ( repositories::instanceOf{0}_FV.areAllFaceConnectedCellsOverlappingWithBHImpactArea(marker) ) {{
542 ::toolbox::blockstructured::restrictCellIntoOverlappingCell_inject(
543 repositories::instanceOf{0}_FV.NumberOfFiniteVolumesPerAxisPerPatch,
544 repositories::instanceOf{0}_FD4.NumberOfGridCellsPerPatchPerAxis,
545 repositories::instanceOf{0}_FV.NumberOfUnknowns + repositories::instanceOf{0}_FV.NumberOfAuxiliaryVariables,
546 fineGridCell{0}_FVQ.data(),
547 fineGridCell{0}_FD4Q.data()
548 );
549 /*}}
550 else {{
551 ::toolbox::blockstructured::restrictCellIntoOverlappingCell_inject_and_average(
552 repositories::instanceOf{0}_FV.NumberOfFiniteVolumesPerAxisPerPatch,
553 repositories::instanceOf{0}_FD4.NumberOfGridCellsPerPatchPerAxis,
554 repositories::instanceOf{0}_FV.NumberOfUnknowns + repositories::instanceOf{0}_FV.NumberOfAuxiliaryVariables,
555 fineGridCell{0}_FVQ.data(),
556 fineGridCell{0}_FD4Q.data()
557 );
558 }}*/
559
560 logTraceOut( "touchCellFirstTime(...)-inject" );
561}}
562""".format(
564 ),
565 )
566
567
569 """!
570
571 Construct 4th order Finite Differences solver without a limiter
572
573 """
574
576 self,
577 name,
578 patch_size,
579 min_cell_size,
580 max_cell_size,
581 ):
583
584 CCZ4Solver_FD4_GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
585 self,
586 name=name + "_FD4",
587 patch_size=patch_size,
588 rk_order=1,
589 min_meshcell_h=min_cell_size / patch_size,
590 max_meshcell_h=max_cell_size / patch_size,
591 pde_terms_without_state=False,
592 )
593
594 self._user_action_set_includes += """
595#include "toolbox/blockstructured/Projection.h"
596#include "toolbox/blockstructured/Restriction.h"
597#include "toolbox/blockstructured/Interpolation.h"
598#include "toolbox/blockstructured/Copy.h"
599"""
600
602 self.double_constants["BlackHoleFVRegion"] = BlackHoleRegion
603
604 self.set_implementation(
605 initial_conditions=exahype2.solvers.PDETerms.User_Defined_Implementation,
606 refinement_criterion=exahype2.solvers.PDETerms.User_Defined_Implementation,
607 boundary_conditions=exahype2.solvers.PDETerms.None_Implementation,
608 )
609
612
614 """!
615
616 Tailor action set behaviour
617
618 We first make a few additional cells skeleton cells. The rationale
619 behind additional skeletons is given in the @ref benchmarks_exahype2_ccz4_single_black_hole "generic overview".
620 Given the first remark there on FD4-FV coupling, one would be tempted
621 to use the predicate
622
623 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
624 self._action_set_update_cell.additional_skeleton_guard = " " "(
625 repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.isCellOverlappingWithBHImpactArea(marker)
626 and
627 not repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.areAllFaceConnectedCellsOverlappingWithBHImpactArea(marker)
628 )
629 " " "
630 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
631
632 Once we study the other items (notably the fourth), we see that it is
633 reasonable to make all the overlap region a skeleton within the FD4
634 solver.
635
636 """
637 super(FD4SolverWithoutLimiter, self).create_action_sets()
638
639 self._action_set_handle_boundary.TemplateHandleBoundary_KernelCalls = (
640 """
641 double Qinf[59]={1.0, 0.0, 0.0, 1.0, 0.0, 1.0, //q0-5
642 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q6-11
643 0.0, 0.0, 0.0, 0.0, //q12-15
644 1.0, 0.0, 0.0, 0.0, //q16-19
645 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q20-25
646 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q26-34
647 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
648 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, //q35-52
649 0.0, 1.0, 0.0, 0.0, 0.0, 0.0 //q53-58
650 }; //approximate background solution at infinity
651 ::exahype2::fd::applySommerfeldConditions(
652 [&](
653 const double * NOALIAS Q,
654 const tarch::la::Vector<DIMENSIONS,double>& faceCentre,
655 const tarch::la::Vector<DIMENSIONS,double>& gridCellH,
656 double t,
657 double dt,
658 int normal
659 ) -> double {
660 return repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, faceCentre, gridCellH, t, dt, normal );
661 },
662 [&](
663 double * NOALIAS Q,
664 const tarch::la::Vector<DIMENSIONS,double>& faceCentre,
665 const tarch::la::Vector<DIMENSIONS,double>& gridCellH
666 ) -> void {
667 for (int i=0; i<"""
668 + str(self._unknowns + self._auxiliary_variables)
669 + """; i++) {
670 Q[i] = 0.0;
671 }
672 Q[0] = 1.0; Q[3] = 1.0; Q[5] = 1.0;
673 Q[16] = 0.95; Q[54] = 0.95;
674 },
675 marker.getX(),
676 marker.getH(),
677 {{FACE_METADATA_ACCESSOR}}.getOldTimeStamp(marker.getSelectedFaceNumber()<DIMENSIONS ? 1 : 0),
678 repositories::{{SOLVER_INSTANCE}}.getMinTimeStepSize(),
679 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
680 {{OVERLAP}},
681 {{NUMBER_OF_UNKNOWNS}},
682 {{NUMBER_OF_AUXILIARY_VARIABLES}},
683 marker.getSelectedFaceNumber(),
684 {0.0, 0.0, 0.0},
685 fineGridFace{{UNKNOWN_IDENTIFIER}}Old.data(),
686 fineGridFace{{UNKNOWN_IDENTIFIER}}New.data()
687 );
688 """
689 )
690
691
693 """!
694
695 A finite volume solver
696
697 This solver is not appropriate to simulate black holes as a stand-alone
698 solver, as it is way too diffusive. If you use it without another scheme,
699 you typically see the black hole disappear after a brief period. So we
700 have it in here merely for performance tests.
701
702 """
703
705 self,
706 name,
707 patch_size,
708 min_cell_size,
709 max_cell_size,
710 ):
711 """!
712
713 Construct the Finite Volume solver
714
715 @param patch_size: Integer
716 Defines how big the individual patches are. If you pass in 10, each
717 Finite Volume patch will have the dimensions 10x10x10.
718 @param min_cell_size: Float
719 This parameter refers to the cell size, i.e. the size of a whole
720 patch. We use this one here, to make the signature the same as for
721 the FD and DG solver variants. The superclass constructor argues
722 over finite volume sizes, and we hence have to recalibrate this
723 parameter with patch_size.
724
725 """
726
727 super(FVSolver, self).__init__(
728 name=name + "_FV",
729 patch_size=patch_size,
730 min_volume_h=min_cell_size / patch_size,
731 max_volume_h=max_cell_size / patch_size,
732 pde_terms_without_state=True,
733 )
734
735 self._user_action_set_includes += """
736#include "toolbox/blockstructured/Projection.h"
737#include "toolbox/blockstructured/Restriction.h"
738#include "toolbox/blockstructured/Interpolation.h"
739#include "toolbox/blockstructured/Copy.h"
740"""
741
743 self.double_constants["BlackHoleFVRegion"] = BlackHoleRegion
744
745 self.set_implementation(
746 initial_conditions=exahype2.solvers.PDETerms.User_Defined_Implementation,
747 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
748 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
749 )
750
753
755 """!
756
757 Tailor action set behaviour
758
759 We first make a few additional cells skeleton cells. The rationale
760 behind additional skeletons is given in the @ref benchmarks_exahype2_ccz4_single_black_hole "generic overview".
761 Given the first remark there on FD4-FV coupling, one would be tempted
762 to use the predicate
763
764 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
765 self._action_set_update_cell.additional_skeleton_guard = " " "(
766 repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.isCellOverlappingWithBHImpactArea(marker)
767 and
768 not repositories::instanceOf" " " + self._name_without_FD4_extension + " " "_FV.areAllFaceConnectedCellsOverlappingWithBHImpactArea(marker)
769 )
770 " " "
771 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
772
773 Once we study the other items (notably the fourth), we see that it is
774 reasonable to make all the overlap region a skeleton within the FD4
775 solver.
776
777 """
778 super(FVSolver, self).create_action_sets()
779
780
782 """!
783
784 Update preconfigured solver parameters
785
786 The default parameters of CCZ4 are tailored towards gauge waves or similar.
787 For the single black hole, two parameters have to be changed. That's bs and
788 sk which both have to be 1.0.
789
790 """
791 solver.double_constants["CCZ4bs"] = 1.0
792 solver.double_constants["CCZ4sk"] = 1.0
add_all_solver_constants(self)
Add domain-specific constants.
CCZ4 solver using fourth-order finite differences and global adaptive time stepping incl enclave task...
CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking.
4th order Finite Differences solver with a limiter
Definition SBH.py:205
__init__(self, name, patch_size, min_cell_size, max_cell_size, KernelParallelisation parallelisation_of_interpolation, KernelParallelisation parallelisation_of_kernels, interpolation_method)
Constructor.
Definition SBH.py:237
create_action_sets(self)
Tailor action set behaviour.
Definition SBH.py:291
Construct 4th order Finite Differences solver without a limiter.
Definition SBH.py:568
create_action_sets(self)
Tailor action set behaviour.
Definition SBH.py:613
__init__(self, name, patch_size, min_cell_size, max_cell_size)
Constructor.
Definition SBH.py:581
A finite volume solver.
Definition SBH.py:692
__init__(self, name, patch_size, min_cell_size, max_cell_size)
Construct the Finite Volume solver.
Definition SBH.py:710
create_action_sets(self)
Tailor action set behaviour.
Definition SBH.py:754
Construct the Finite Volume (limiter) scheme.
Definition SBH.py:45
_flux_implementation
Definition SBH.py:120
create_action_sets(self)
Not really a lot of things to do here.
Definition SBH.py:179
_source_term_implementation
Definition SBH.py:122
_fused_compute_kernel_call_cpu
Definition SBH.py:119
_provide_face_data_to_compute_kernels_default_guard(self)
Definition SBH.py:163
_store_cell_data_default_guard(self)
Mask out exterior cells.
Definition SBH.py:131
_ncp_implementation
Definition SBH.py:121
_provide_cell_data_to_compute_kernels_default_guard(self)
Definition SBH.py:154
_store_face_data_default_guard(self)
Definition SBH.py:169
_load_cell_data_default_guard(self)
Definition SBH.py:145
__init__(self, name, patch_size, bool amend_priorities, KernelParallelisation parallelisation_of_kernels)
Construct the limiter.
Definition SBH.py:68
enclave_task_priority
Definition SBH.py:96
_load_face_data_default_guard(self)
Definition SBH.py:174
update_solver_parameters_for_single_black_hole(solver)
Update preconfigured solver parameters.
Definition SBH.py:781