Peano
Loading...
Searching...
No Matches
CCZ4Solver.py
Go to the documentation of this file.
2import exahype2
3import dastgen2
4
5from abc import abstractmethod
6
7
8class AbstractCCZ4Solver(object):
9 """!
10
11 Abstract base class for any CCZ4 solver
12
13 Each CCZ4 solver inherits from this abstract base class which really only
14 defines some generic stuff such as the unknowns and includes that every
15 single solver will use.
16
17 The solver should, more or less, work out of the box, but you have to do
18 three things if you use a subclass:
19
20 1. If you use a CCZ4 solver, you will still have to add all the libraries to
21 your Peano project such that the Makefile picks them up. For this, the
22 solver offers an add_makefile_parameters().
23
24 2. You have to set the initial conditions via
25
26 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 my_solver.set_implementation(initial_conditions = " " "
28 for (int i=0; i<NumberOfUnknowns+NumberOfAuxiliaryVariables; i++) Q[i] = 0.0;
29 ::exagrype::initialvalues::gaugeWave(Q, volumeCentre, 0);
30 " " ")
31 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32
33 At this point, different CCZ4 solver variants might require different
34 syntax. The term volumeCentre for example above is only defined in a
35 finite volume ontext.
36
37 3. Finally, you have to add domain-specific constants to the project.
38 For this, call add_all_solver_constants(). See the comment below.
39
40 Further to that, you might want to have to set boundary conditions. By
41 default, we do not set any boundary conditions. This works fine if
42 periodic boundary conditions are used. But once you switch off periodic
43 boundary conditions, you have to tell the solver how to treat the boundary.
44 This is typically done via set_implementation(), too.
45
46 ## More complex scenarios
47
48 Setting particular implementations via set_implementation() is not always
49 convenient or possible. You might want to add new functions to your classes,
50 do something in the solver constructor, and so forth. If so, feel free to
51 modify the file MySolverName.cpp which the tool generates. In this context,
52 you might want to pass in
53
54 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
55 my_solver.set_implementation(initial_conditions = exahype2.solvers.PDETerms.User_Defined_Implementation,
56 refinement_criterion = exahype2.solvers.PDETerms.User_Defined_Implementation,
57 boundary_conditions=exahype2.solvers.PDETerms.User_Defined_Implementation
58 )
59
60 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61
62 which ensures that you get the right hook-in methods generated when you
63 invoke the Python script for the first time. These methods will contain
64 todo comments for you. Subsequent runs of the Python API should not
65 overwrite the solver implementation.
66
67 ## Constants
68
69 Each CCZ4 solver requires a minimal set of constants. These are represented
70 by integer_constants and double_constants. Please augment these dictionaries.
71 Eventually, you have to submit all the constants via add_all_solver_constants().
72
73 """
74
75 """!
76
77 Dictionary which specifies the unknown names plus their cardinality
78
79 Has to be class attribute, as we need it in the constructor, i.e. before the
80 abstract object is created.
81
82 """
83 _FO_formulation_unknowns = {
84 "G": 6,
85 "K": 6,
86 "theta": 1,
87 "Z": 3,
88 "lapse": 1,
89 "shift": 3,
90 "b": 3,
91 "dLapse": 3,
92 "dxShift": 3,
93 "dyShift": 3,
94 "dzShift": 3,
95 "dxG": 6,
96 "dyG": 6,
97 "dzG": 6,
98 "traceK": 1,
99 "phi": 1,
100 "P": 3,
101 "K0": 1,
102 }
103
104 """!
105
106 Primary unknowns of the CCZ4 formulation which are there in the initial
107 formulation. All the other variables are auxiliary variables, i.e. ones
108 introduced to return to a first-order formulation. Unfortunately, the
109 ordering in _FO_formulation_unknows is motivated by the original papers
110 and not by the fact which quantities are original ones and which one are
111 helper or auxiliary variables.
112
113 """
114 _SO_formulation_unknowns = {
115 "G",
116 "K",
117 "theta",
118 "Z",
119 "lapse",
120 "shift",
121 "b",
122 "traceK",
123 "phi",
124 }
125
126 Default_Time_Step_Size_Relaxation = 0.1
127
128 def __init__(self):
129 """!
130
131 Constructor
132
133 Initialise the two dictionaries with default values (which work).
134
135 """
137 "CCZ4LapseType": 0,
138 "CCZ4SO": 0,
139 "ProductionRun":0
140 }
142 "CCZ4ds": 1.0,
143 "CCZ4c": 1.0,
144 "CCZ4e": 1.0,
145 "CCZ4f": 0.75,
146 "CCZ4bs": 0.0,
147 "CCZ4sk": 0.0,
148 "CCZ4xi": 1.0,
149 "CCZ4itau": 1.0,
150 "CCZ4eta": 1.0,
151 "CCZ4k1": 0.1,
152 "CCZ4k2": 0.0,
153 "CCZ4k3": 0.5,
154 "CCZ4GLMc": 1.2,
155 "CCZ4GLMd": 2.0,
156 "CCZ4mu": 0.2,
157 }
158
166 """!
167
168 Add the headers for the compute kernels and initial condition implementations
169
170 Usually called by the subclass constructor.
171
172 """
173 self.add_user_action_set_includes(
174 """
175#include "exagrype/ccz4/Kernels.h"
176#include "exagrype/ccz4/SecondOrderAuxiliaryVariablesReconstruction.h"
177"""
178 )
179 self.add_user_solver_includes(
180 """
181#include "exagrype/ccz4/Kernels.h"
182#include "exagrype/initialvalues/InitialValues.h"
183#include "exagrype/initialvalues/ApplyTwoPunctures.h"
184#include "exagrype/ccz4/SecondOrderAuxiliaryVariablesReconstruction.h"
185#include <cstring>
186"""
187 )
188
190 """!
191
192 Add domain-specific constants
193
194 I need a couple of constants. I could either replace them directly
195 within the Python snippets below, but I prefer here to go a different
196 way and to export them as proper C++ constants.
197
198 There are two ways to inject solver constants into Peano: We can either
199 add them to the Makefile as global const expressions, or we can add
200 them to the ExaHyPE2 solver. The latter is the route we go down here,
201 as these constants logically belong to the solver and not to the project.
202
203 This operation uses the parent class' add_solver_constants(). You still
204 can use this operation to add further parameters. Or you can, as a user,
205 always add new entries to integer_constants or double_constants and then
206 call this routine rather than adding individual constants one by one.
207
208 """
209 for key, value in self.integer_constants.items():
210 self.add_solver_constants(
211 "static constexpr int {} = {};".format(key, value)
212 )
213 for key, value in self.double_constants.items():
214 self.add_solver_constants(
215 "static constexpr double {} = {};".format(key, value)
216 )
217
218 def add_makefile_parameters(self, peano4_project, path_of_ccz4_application):
219 """!
220
221 Add include path and minimal required cpp files to makefile
222
223 If you have multiple CCZ4 solvers, i.e. different solvers of CCZ4 or multiple
224 instances of the CCZ4 type, please call this operation only once on one of
225 your solvers.
226
227 The CCZ4 kernels, the analytical initial values and the reconstruction
228 of the auxiliary variables are part of the ExaGRyPE library. Peano
229 therefore has to be configured with --enable-exagrype (or
230 -DENABLE_EXAGRYPE=ON), and the generated Makefile links against that
231 library. TwoPunctures (black hole initial data) is part of the library
232 if Peano is configured with --with-gsl. Therefore, I only add the
233 application's directory to the header search path.
234
235 You can always add further files via
236 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 peano4_project.output.makefile.add_cpp_file( "mypath/myfile.cpp" )
238 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239
240 """
241 if path_of_ccz4_application[-1] != "/":
242 path_of_ccz4_application += "/"
243
244 peano4_project.output.makefile.add_header_search_path(path_of_ccz4_application)
245
246 @abstractmethod
248 self,
249 name,
250 coordinates,
251 project,
252 number_of_entries_between_two_db_flushes,
253 data_delta_between_two_snapsots,
254 time_delta_between_two_snapsots,
255 clear_database_after_flush,
256 tracer_unknowns=None,
257 ):
258 """!
259
260 Add tracer to project
261
262 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
263 some of the arguments. Most of them are simply piped through to this
264 class.
265
266 The tracer is given a name and initial coordinates (list of three-tuples).
267 We need to know the underlying project as well, as we have to add the
268 tracing to the time stepping and the database update to the plotting.
269 ~~~~~~~~~~~~~~~~~~~~~~~
270 project.add_action_set_to_timestepping(my_interpolation)
271 project.add_action_set_to_timestepping(exahype2.tracer.DumpTracerIntoDatabase(
272 particle_set=tracer_particles,
273 solver=self,
274 filename=name + "-" + self._name,
275 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
276 output_precision=10,
277 data_delta_between_two_snapsots = data_delta_between_two_snapsots,
278 time_delta_between_two_snapsots = time_delta_between_two_snapsots,
279 clear_database_after_flush = True,
280 ))
281 ~~~~~~~~~~~~~~~~~~~~~~~
282
283 """
284 assert "should not be called"
285 pass
286
287
289 AbstractCCZ4Solver, exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStep
290):
291 """!
292
293 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
294
295 Please consult CCZ4Solver_FV_GlobalAdaptiveTimeStepWithEnclaveTasking.
296
297 """
298
300 self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state
301 ):
302 AbstractCCZ4Solver.__init__(self)
303 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStep.__init__(
304 self,
305 name=name,
306 patch_size=patch_size,
307 unknowns=sum(self._FO_formulation_unknowns.values()),
308 auxiliary_variables=0,
309 min_volume_h=min_volume_h,
310 max_volume_h=max_volume_h,
311 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
312 )
314
315 self.set_implementation(
316 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
317 ncp=construct_FV_ncp(),
318 flux=exahype2.solvers.PDETerms.None_Implementation,
319 source_term=construct_FV_source_term(),
320 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
321 eigenvalues=construct_FV_eigenvalues(),
322 )
323
324 self.postprocess_updated_patch += construct_FV_postprocessing_kernel()
325
327 self,
328 name,
329 coordinates,
330 project,
331 number_of_entries_between_two_db_flushes,
332 data_delta_between_two_snapsots,
333 time_delta_between_two_snapsots,
334 clear_database_after_flush,
335 tracer_unknowns,
336 ):
337 """!
338
339 Add tracer to project
340
341 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
342 some of the arguments. Most of them are simply piped through to this
343 class.
344
345 project: exahype2.Project
346
347 """
349 name,
350 coordinates,
351 project,
352 self,
353 number_of_entries_between_two_db_flushes,
354 data_delta_between_two_snapsots,
355 time_delta_between_two_snapsots,
356 clear_database_after_flush,
357 tracer_unknowns,
358 )
359
360
362 AbstractCCZ4Solver, exahype2.solvers.fv.musclhancock.GlobalAdaptiveTimeStep
363):
364 """!
365
366 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
367
368 Please consult CCZ4Solver_FV_GlobalAdaptiveTimeStepWithEnclaveTasking.
369
370 """
371
373 self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state
374 ):
375 AbstractCCZ4Solver.__init__(self)
376 exahype2.solvers.fv.musclhancock.GlobalAdaptiveTimeStep.__init__(
377 self,
378 name=name,
379 patch_size=patch_size,
380 unknowns=sum(self._FO_formulation_unknowns.values()),
381 auxiliary_variables=0,
382 min_volume_h=min_volume_h,
383 max_volume_h=max_volume_h,
384 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
385 )
387
388 self.set_implementation(
389 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
390 ncp=construct_FV_ncp(),
391 flux=exahype2.solvers.PDETerms.None_Implementation,
392 source_term=construct_FV_source_term(),
393 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
394 eigenvalues=construct_FV_eigenvalues(),
395 )
396
397 self.postprocess_updated_patch += construct_FV_postprocessing_kernel()
398
400 self,
401 name,
402 coordinates,
403 project,
404 number_of_entries_between_two_db_flushes,
405 data_delta_between_two_snapsots,
406 time_delta_between_two_snapsots,
407 clear_database_after_flush,
408 tracer_unknowns,
409 ):
410 """!
411
412 Add tracer to project
413
414 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
415 some of the arguments. Most of them are simply piped through to this
416 class.
417
418 project: exahype2.Project
419
420 """
422 name,
423 coordinates,
424 project,
425 self,
426 number_of_entries_between_two_db_flushes,
427 data_delta_between_two_snapsots,
428 time_delta_between_two_snapsots,
429 clear_database_after_flush,
430 tracer_unknowns,
431 )
432
433
435 AbstractCCZ4Solver,
436 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking,
437):
438 """!
439
440 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
441
442 The constructor of this classs is straightforward and realises the standard
443 steps of any numerical implementation of the CCZ4 scheme:
444
445 1. Init the actual numerical scheme. This happens through the constructor
446 of the base class.
447
448 2. Add the header files that we need, i.e. those files which contain the
449 actual CCZ4 implementation.
450
451 3. Add some constants that any CCZ4 C++ code requires.
452
453 4. Set the actual implementation, i.e. link the generic PDE terms to the
454 CCZ4-specific function calls.
455
456 5. Add the CCZ4-specific postprocessing.
457
458 """
459
461 self,
462 name,
463 patch_size,
464 min_volume_h,
465 max_volume_h,
466 pde_terms_without_state
467 ):
468 """!
469
470 Construct solver with enclave tasking and adaptive time stepping
471
472 """
473 AbstractCCZ4Solver.__init__(self)
474 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
475 self,
476 name=name,
477 patch_size=patch_size,
478 unknowns=sum(self._FO_formulation_unknowns.values()),
479 auxiliary_variables=0,
480 min_volume_h=min_volume_h,
481 max_volume_h=max_volume_h,
482 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
483 pde_terms_without_state=pde_terms_without_state
484 )
486
487 self.set_implementation(
488 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
489 ncp=construct_FV_ncp(),
490 flux=exahype2.solvers.PDETerms.None_Implementation,
491 source_term=construct_FV_source_term(),
492 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
493 eigenvalues=construct_FV_eigenvalues()
494 )
495
496 self.postprocess_updated_patch += construct_FV_postprocessing_kernel()
497
499 self,
500 name,
501 coordinates,
502 project,
503 number_of_entries_between_two_db_flushes,
504 data_delta_between_two_snapsots,
505 time_delta_between_two_snapsots,
506 clear_database_after_flush,
507 tracer_unknowns,
508 ):
509 """!
510
511 Add tracer to project
512
513 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
514 some of the arguments. Most of them are simply piped through to this
515 class.
516
517
518 project: exahype2.Project
519
520 """
522 name,
523 coordinates,
524 project,
525 self,
526 number_of_entries_between_two_db_flushes,
527 data_delta_between_two_snapsots,
528 time_delta_between_two_snapsots,
529 clear_database_after_flush,
530 tracer_unknowns,
531 )
532
533
535 AbstractCCZ4Solver, exahype2.solvers.fv.musclhancock.GlobalAdaptiveTimeStep
536):
537 """!
538
539 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
540
541 Please consult CCZ4Solver_FV_GlobalAdaptiveTimeStepWithEnclaveTasking.
542
543 """
544
546 self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state
547 ):
548 AbstractCCZ4Solver.__init__(self)
549 exahype2.solvers.fv.musclhancock.GlobalAdaptiveTimeStep.__init__(
550 self,
551 name=name,
552 patch_size=patch_size,
553 unknowns=sum(self._FO_formulation_unknowns.values()),
554 auxiliary_variables=0,
555 min_volume_h=min_volume_h,
556 max_volume_h=max_volume_h,
557 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
558 pde_terms_without_state=pde_terms_without_state,
559 )
561
562 self.set_implementation(
563 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
564 ncp=construct_FV_ncp(),
565 flux=exahype2.solvers.PDETerms.None_Implementation,
566 source_term=construct_FV_source_term(),
567 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
568 eigenvalues=construct_FV_eigenvalues(),
569 )
570
571 self.postprocess_updated_patch += construct_FV_postprocessing_kernel()
572
574 self,
575 name,
576 coordinates,
577 project,
578 number_of_entries_between_two_db_flushes,
579 data_delta_between_two_snapsots,
580 time_delta_between_two_snapsots,
581 clear_database_after_flush,
582 tracer_unknowns,
583 ):
584 """!
585
586 Add tracer to project
587
588 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
589 some of the arguments. Most of them are simply piped through to this
590 class.
591
592 project: exahype2.Project
593
594 """
596 name,
597 coordinates,
598 project,
599 self,
600 number_of_entries_between_two_db_flushes,
601 data_delta_between_two_snapsots,
602 time_delta_between_two_snapsots,
603 clear_database_after_flush,
604 tracer_unknowns,
605 )
606
607
609 return """
610#if defined(GPUOffloadingOMP)
611 double* deltaQSerialised = new double[NumberOfUnknowns*3];
612#else
613 double deltaQSerialised[NumberOfUnknowns*3];
614#endif
615 for (int i=0; i<NumberOfUnknowns; i++) {
616 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
617 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
618 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
619
620 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
621 }
622 ::exagrype::ccz4::ncp(BTimesDeltaQ, Q, deltaQSerialised, normal%Dimensions, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
623#if defined(GPUOffloadingOMP)
624 delete[] deltaQSerialised;
625#endif
626"""
627
628
630 return """
631#if defined(GPUOffloadingOMP)
632 double* deltaQSerialised = new double[NumberOfUnknowns*3];
633#else
634 double deltaQSerialised[NumberOfUnknowns*3];
635#endif
636 for (int i=0; i<NumberOfUnknowns; i++) {
637 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
638 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
639 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
640
641 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
642 }
643 ::exagrype::ccz4::ncp(BTimesDeltaQ, Q, deltaQSerialised, normal%Dimensions, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
644#if defined(GPUOffloadingOMP)
645 delete[] deltaQSerialised;
646#endif
647"""
648
649
651 return """
652 ::exagrype::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
653"""
654
655
657 return """
658 ::exagrype::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
659"""
660
661
663 return """
664 ::exagrype::ccz4::maxEigenvalue(Q, normal%Dimensions, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd, maxEigenvalue );
665"""
666
667
669 return """
670 ::exagrype::ccz4::maxEigenvalue(Q, normal%Dimensions, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd, maxEigenvalue );
671"""
672
673
675 return """
676{
677 constexpr int itmax = {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}};
678 int index = 0;
679 for (int i=0;i<itmax;i++)
680 {
681 exagrype::ccz4::enforceCCZ4constraints( newQ+index );
682 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
683 }
684 }
685"""
686
687
689 return """
690{
691 constexpr int itmax = {{NUMBER_OF_VOLUMES_PER_AXIS}} * {{NUMBER_OF_VOLUMES_PER_AXIS}} * {{NUMBER_OF_VOLUMES_PER_AXIS}};
692 int index = 0;
693 for (int i=0;i<itmax;i++)
694 {
695 exagrype::ccz4::enforceCCZ4constraints( newQ+index );
696 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
697 }
698 }
699"""
700
701
703 name,
704 coordinates,
705 project,
706 solver,
707 number_of_entries_between_two_db_flushes,
708 data_delta_between_two_snapsots,
709 time_delta_between_two_snapsots,
710 clear_database_after_flush,
711 tracer_unknowns,
712):
713 """!
714
715 Add tracer to project
716
717 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
718 some of the arguments. Most of them are simply piped through to this
719 class.
720
721 I realise this as a separate routine, as we need it for all FV flavours
722
723 """
724 number_of_attributes = (
725 (solver.unknowns + solver.auxiliary_variables)
726 if tracer_unknowns == None
727 else len(tracer_unknowns)
728 )
729 tracer_particles = project.add_tracer(
730 name=name, attribute_count=number_of_attributes
731 )
732 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
733 particle_set=tracer_particles, coordinates=coordinates
734 )
735 init_action_set.descend_invocation_order = 0
736 project.add_action_set_to_initialisation(init_action_set)
737
738 project_on_tracer_properties_kernel = ""
739 if tracer_unknowns == None:
740 project_on_tracer_properties_kernel = (
741 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
742 )
743 # project_on_tracer_properties_kernel = "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear_explicit_Euler"
744 elif len(tracer_unknowns) == 1:
745 project_on_tracer_properties_kernel = (
746 "::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
747 i, tracer_unknowns.index(i)
748 )
749 )
750 else:
751 project_on_tracer_properties_kernel = (
752 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
753 tracer_unknowns
754 )
755 .replace("[", "")
756 .replace("]", "")
757 )
758
759 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
760 tracer_particles,
761 solver,
762 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
763 )
764 tracing_action_set.descend_invocation_order = (
765 solver._action_set_update_cell.descend_invocation_order + 1
766 )
767 project.add_action_set_to_timestepping(tracing_action_set)
768 project.add_action_set_to_initialisation(tracing_action_set)
769
770 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
771 particle_set=tracer_particles,
772 solver=solver,
773 filename=name + "-" + solver._name,
774 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
775 output_precision=10,
776 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
777 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
778 clear_database_after_flush=clear_database_after_flush,
779 )
780 dump_into_database_action_set.descend_invocation_order = (
781 solver._action_set_update_cell.descend_invocation_order + 2
782 )
783 project.add_action_set_to_timestepping(dump_into_database_action_set)
784
785
787 name,
788 coordinates,
789 project,
790 solver,
791 number_of_entries_between_two_db_flushes,
792 data_delta_between_two_snapsots,
793 time_delta_between_two_snapsots,
794 clear_database_after_flush,
795 tracer_unknowns,
796):
797 """!
798
799 I realise this as a separate routine, as we need it for all FD4 flavours
800
801 This is a wrapper around all the tracer handling. It adds the tracer to the
802 exahype2.Project, but it also instantiates the solution to tracer mapping
803 as well as the database bookkeeping.
804
805 @param tracer_unknowns: Integer
806 You can set this variable to None. In this case, all variables are
807 dumped.
808
809 """
810 number_of_attributes = (
811 (solver.unknowns + solver.auxiliary_variables)
812 if tracer_unknowns == None
813 else len(tracer_unknowns)
814 )
815 tracer_particles = project.add_tracer(
816 name=name, attribute_count=number_of_attributes
817 )
818 project.add_action_set_to_initialisation(
819 exahype2.tracer.InsertParticlesByCoordinates(
820 particle_set=tracer_particles, coordinates=coordinates
821 )
822 )
823 project_on_tracer_properties_kernel = ""
824 if tracer_unknowns == None:
825 project_on_tracer_properties_kernel = (
826 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
827 )
828 elif len(tracer_unknowns) == 1:
829 project_on_tracer_properties_kernel = (
830 "::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
831 i, tracer_unknowns.index(i)
832 )
833 )
834 else:
835 project_on_tracer_properties_kernel = (
836 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
837 tracer_unknowns
838 )
839 .replace("[", "")
840 .replace("]", "")
841 )
842
843 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
844 tracer_particles,
845 solver,
846 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
847 )
848 tracing_action_set.descend_invocation_order = (
849 solver._action_set_compute_final_linear_combination.descend_invocation_order + 1
850 )
851 project.add_action_set_to_timestepping(tracing_action_set)
852 project.add_action_set_to_initialisation(tracing_action_set)
853
854 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
855 particle_set=tracer_particles,
856 solver=solver,
857 filename=name + "-" + solver._name,
858 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
859 output_precision=10,
860 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
861 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
862 clear_database_after_flush=clear_database_after_flush,
863 )
864 dump_into_database_action_set.descend_invocation_order = (
865 solver._action_set_compute_final_linear_combination.descend_invocation_order + 2
866 )
867 project.add_action_set_to_timestepping(dump_into_database_action_set)
868
869
871 AbstractCCZ4Solver,
872 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking,
873):
874 """!
875
876 CCZ4 solver using fourth-order finite differences and global adaptive time stepping incl enclave tasking
877
878 The constructor of this classs is straightforward and realises the standard
879 steps of any numerical implementation of the CCZ4 scheme:
880
881 1. Init the actual numerical scheme. This happens through the constructor
882 of the base class.
883
884 2. Add the header files that we need, i.e. those files which contain the
885 actual CCZ4 implementation.
886
887 3. Add some constants that any CCZ4 C++ code requires.
888
889 4. Set the actual implementation, i.e. link the generic PDE terms to the
890 CCZ4-specific function calls.
891
892 5. Add the CCZ4-specific postprocessing.
893
894 6. Switch to higher-order interpolation and restriction.
895
896 """
897
899 self,
900 name,
901 patch_size,
902 rk_order,
903 min_meshcell_h,
904 max_meshcell_h,
905 pde_terms_without_state,
906 second_order=False,
907 device_resident_rk=False,
908 ):
909 """!
910
911 Constructor
912
913 Calibrate the default time step size calibration with 1/16 to take into
914 account that we have a higher-order numerical scheme.
915
916 """
917 AbstractCCZ4Solver.__init__(self)
918 if second_order:
919 AbstractCCZ4Solver.enable_second_order(self)
920 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
921 self,
922 name=name,
923 patch_size=patch_size,
924 rk_order=rk_order,
925 unknowns=sum(self._FO_formulation_unknowns.values()),
926 auxiliary_variables=0,
927 min_meshcell_h=min_meshcell_h,
928 max_meshcell_h=max_meshcell_h,
930 pde_terms_without_state=pde_terms_without_state,
931 device_resident_rk=device_resident_rk,
932 plot_grid_properties=True
933 )
934
936
937 self.set_implementation(
938 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
939 ncp=construct_FD4_ncp(),
940 flux=exahype2.solvers.PDETerms.None_Implementation,
941 source_term=construct_FD4_source_term(),
942 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
943 eigenvalues=construct_FD4_eigenvalues(),
944 )
945
946 self.postprocess_updated_patch += construct_FD4_postprocessing_kernel()
947
948 """
949 # Use second order interpolation and restriction
950 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
951 self
952 )
953 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
954 self
955 )
956 """
957
958 # Use third order interpolation and restriction
959 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
960 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
961
962 """
963 # Use matrix interpolation and restriction
964 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
965 self
966 )
967 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
968 self
969 )
970 """
971
972 """
973 # Use tensor product interpolation and restriction
974 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
975 self,
976 "TP_linear_with_linear_extrap_normal_interp"
977 )
978 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
979 self,
980 "TP_average_normal_extrap"
981 )
982 """
983
985 self,
986 name,
987 coordinates,
988 project,
989 number_of_entries_between_two_db_flushes,
990 data_delta_between_two_snapsots,
991 time_delta_between_two_snapsots,
992 clear_database_after_flush,
993 tracer_unknowns,
994 ):
995 """!
996
997 Add tracer to project
998
999 This is a delegate to add_tracer_to_FD4_solver() which passes the
1000 object in as first argument.
1001
1002 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1003 some of the arguments. Most of them are simply piped through to this
1004 class.
1005
1006 @param project: exahype2.Project
1007
1008 @param tracer_unknowns: Integer
1009 You can set this variable to None. In this case, all variables are
1010 dumped.
1011
1012 """
1014 name,
1015 coordinates,
1016 project,
1017 self,
1018 number_of_entries_between_two_db_flushes,
1019 data_delta_between_two_snapsots,
1020 time_delta_between_two_snapsots,
1021 clear_database_after_flush,
1022 tracer_unknowns,
1023 )
1024
1025
1027 AbstractCCZ4Solver, exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStep
1028):
1029 """!
1030
1031 CCZ4 solver using fourth-order finite differences and global adaptive time stepping without enclave tasking
1032
1033 Consult CCZ4Solver_FD4_GlobalAdaptiveTimeStepWithEnclaveTasking please.
1034
1035 """
1036
1038 self,
1039 name,
1040 patch_size,
1041 rk_order,
1042 min_meshcell_h,
1043 max_meshcell_h,
1044 second_order=False,
1045 ):
1046 """!
1047
1048 Constructor
1049
1050 Calibrate the default time step size calibration with 1/16 to take into
1051 account that we have a higher-order numerical scheme.
1052
1053 """
1054 AbstractCCZ4Solver.__init__(self)
1055 if second_order:
1056 AbstractCCZ4Solver.enable_second_order(self)
1057 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStep.__init__(
1058 self,
1059 name=name,
1060 patch_size=patch_size,
1061 rk_order=rk_order,
1062 unknowns=sum(self._FO_formulation_unknowns.values()),
1063 auxiliary_variables=0,
1064 min_meshcell_h=min_meshcell_h,
1065 max_meshcell_h=max_meshcell_h,
1067 )
1068
1070
1071 self.set_implementation(
1072 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1073 ncp=construct_FD4_ncp(),
1074 flux=exahype2.solvers.PDETerms.None_Implementation,
1075 source_term=construct_FD4_source_term(),
1076 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1077 eigenvalues=construct_FD4_eigenvalues(),
1078 )
1079
1080 self.postprocess_updated_patch += construct_FD4_postprocessing_kernel()
1081
1082 """
1083 # Use second order interpolation and restriction
1084 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
1085 self
1086 )
1087 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
1088 self
1089 )
1090 """
1091
1092 # Use third order interpolation and restriction
1093 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
1094 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
1095
1096 """
1097 # Use matrix interpolation and restriction
1098 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
1099 self
1100 )
1101 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
1102 self
1103 )
1104 """
1105
1106 """
1107 # Use tensor product interpolation and restriction
1108 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
1109 self,
1110 "TP_linear_with_linear_extrap_normal_interp"
1111 )
1112 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
1113 self,
1114 "TP_average_normal_extrap"
1115 )
1116 """
1117
1119 self,
1120 name,
1121 coordinates,
1122 project,
1123 number_of_entries_between_two_db_flushes,
1124 data_delta_between_two_snapsots,
1125 time_delta_between_two_snapsots,
1126 clear_database_after_flush,
1127 tracer_unknowns,
1128 ):
1129 """!
1130
1131 Add tracer to project
1132
1133 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1134 some of the arguments. Most of them are simply piped through to this
1135 class.
1136
1137 project: exahype2.Project
1138
1139 """
1141 name,
1142 coordinates,
1143 project,
1144 self,
1145 number_of_entries_between_two_db_flushes,
1146 data_delta_between_two_snapsots,
1147 time_delta_between_two_snapsots,
1148 clear_database_after_flush=clear_database_after_flush,
1149 tracer_unknowns=tracer_unknowns,
1150 )
1151
1152
1154 AbstractCCZ4Solver,
1155 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking,
1156):
1157 """!
1158
1159 Variation of classic FD4 which relies on second order PDE formulation
1160
1161 The traditional ExaHyPE CCZ4 formulation is the first order formulation
1162 introduced by Dumbser et al. In this formulation, the second order terms
1163 in CCZ4 are substituted with helper variables which represent first order
1164 derivatives. While formally straightforward, keeping the whole system
1165 consistent and stricly hyperbolic is a different challenge.
1166
1167 In this revised version, we have to evolve the primary quantities of CCZ4
1168 and also the helper variables, which blows the overall system up to 59
1169 equations in its simplest form. The work by Dumbser and others suggest that
1170 this is a consistent and stable approach, but limited work is actually
1171 published on proper physical simulations. We therefore also implemented a
1172 second order PDE version within ExaHyPE.
1173
1174 This second order variant is not really second order from the start.
1175 Instead, we use the first order formulation, and we reconstruct the helper
1176 term via finite differences prior to the compute kernel application. That is,
1177 the compute kernels see variables representing first order derivatives, and
1178 they also evolve these guys. Afterwards, we throw away the evolved quantities
1179 and reconstruct them from the primary unknowns prior to the next time step.
1180
1181 This might not be super efficient (it would be faster to stick to the
1182 second order formulation right from the start), but it allows us to reuse
1183 the compute kernels written for the first order PDE formulation.
1184
1185 ## Data layout
1186
1187 We have now a smaller number of real unknowns, i.e. only those guys who
1188 belong to the "original" second-order formulation. The remaining quantities
1189 compared to a first-order formulation are technically material or auxiliary
1190 quantities. We model them as such, which allows ExaHyPE's data management
1191 to deal more efficiently with them.
1192
1193
1194 reconstruction_type: "4thOrder", "centralDifferences", "leftDifference", "rightDifference"
1195
1196 """
1197
1199 self,
1200 name,
1201 patch_size,
1202 rk_order,
1203 min_meshcell_h,
1204 max_meshcell_h,
1205 reconstruction_type,
1206 ):
1207 """!
1208
1209 Constructor
1210
1211 Calibrate the default time step size calibration with 1/16 to take into
1212 account that we have a higher-order numerical scheme.
1213
1214 """
1215 AbstractCCZ4Solver.__init__(self)
1216 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
1217 self,
1218 name=name,
1219 patch_size=patch_size,
1220 rk_order=rk_order,
1222 auxiliary_variables=sum(self._FO_formulation_unknowns.values())
1224 min_meshcell_h=min_meshcell_h,
1225 max_meshcell_h=max_meshcell_h,
1226 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation
1227 / 16.0,
1228 )
1229
1231
1232 self.set_implementation(
1233 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1234 ncp="""
1235 double deltaQSerialised[NumberOfUnknowns*3];
1236 for (int i=0; i<NumberOfUnknowns; i++) {
1237 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
1238 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
1239 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
1240
1241 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
1242 }
1243 ::exagrype::ccz4::ncpSecondOrderFormulation(BTimesDeltaQ, Q, deltaQSerialised, normal%Dimensions, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
1244""",
1245 flux=exahype2.solvers.PDETerms.None_Implementation,
1246 source_term="""
1247 tarch::memset(S, 0.0, NumberOfUnknowns*sizeof(double));
1248 ::exagrype::ccz4::sourceSecondOrderFormulation(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3);
1249""",
1250 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1251 eigenvalues="""
1252 // do we only set Q
1253 return ::exagrype::ccz4::maxEigenvalueSecondOrderFormulation(Q, normal%Dimensions, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd );
1254""",
1255 )
1256
1257 self.postprocess_updated_patch += """
1258{
1259 constexpr int itmax = {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}} * {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}};
1260 int index = 0;
1261 for (int i=0;i<itmax;i++)
1262 {
1263 exagrype::ccz4::enforceCCZ4constraintsSecondOrderFormulation( newQ+index );
1264 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
1265 }
1266 }
1267"""
1268
1269 """
1270 # Use second order interpolation and restriction
1271 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
1272 self
1273 )
1274 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
1275 self
1276 )
1277 """
1278
1279 # Use third order interpolation and restriction
1280 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
1281 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
1282
1283 """
1284 # Use matrix interpolation and restriction
1285 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
1286 self
1287 )
1288 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
1289 self
1290 )
1291 """
1292
1293 """
1294 # Use tensor product interpolation and restriction
1295 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
1296 self,
1297 "TP_linear_with_linear_extrap_normal_interp"
1298 )
1299 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
1300 self,
1301 "TP_average_normal_extrap"
1302 )
1303 """
1304
1305 self.preprocess_reconstructed_patch += (
1306 """
1307::exahype2::CellData reconstructedPatchData(
1308 oldQWithHalo,
1309 marker.x(),
1310 marker.h(),
1311 timeStamp,
1312 timeStepSize,
1313 nullptr // targetPatch
1314);
1315::exagrype::ccz4::recomputeAuxiliaryVariablesFD4_"""
1316 + reconstruction_type
1317 + """(
1318 reconstructedPatchData,
1319 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
1320 3, // haloSize,
1321 {{NUMBER_OF_UNKNOWNS}},
1322 {{NUMBER_OF_AUXILIARY_VARIABLES}}
1323);
1324"""
1325 )
1326
1328 self,
1329 name,
1330 coordinates,
1331 project,
1332 number_of_entries_between_two_db_flushes,
1333 data_delta_between_two_snapsots,
1334 time_delta_between_two_snapsots,
1335 clear_database_after_flush,
1336 tracer_unknowns,
1337 ):
1338 """!
1339
1340 Add tracer to project
1341
1342 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1343 some of the arguments. Most of them are simply piped through to this
1344 class.
1345
1346 project: exahype2.Project
1347
1348 """
1349 number_of_attributes = (
1350 (self.unknowns + self.auxiliary_variables)
1351 if tracer_unknowns == None
1352 else len(tracer_unknowns)
1353 )
1354 tracer_particles = project.add_tracer(
1355 name=name, attribute_count=number_of_attributes
1356 )
1357 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
1358 particle_set=tracer_particles, coordinates=coordinates
1359 )
1360 init_action_set.descend_invocation_order = 0
1361 project.add_action_set_to_initialisation(init_action_set)
1362
1363 project_on_tracer_properties_kernel = ""
1364 if tracer_unknowns == None:
1365 project_on_tracer_properties_kernel = (
1366 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
1367 )
1368 elif len(tracer_unknowns) == 1:
1369 project_on_tracer_properties_kernel = "::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
1370 i, tracer_unknowns.index(i)
1371 )
1372 else:
1373 project_on_tracer_properties_kernel = (
1374 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
1375 tracer_unknowns
1376 )
1377 .replace("[", "")
1378 .replace("]", "")
1379 )
1380
1381 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
1382 tracer_particles,
1383 self,
1384 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
1385 )
1386 tracing_action_set.descend_invocation_order = (
1387 self._action_set_compute_final_linear_combination.descend_invocation_order
1388 + 1
1389 )
1390 project.add_action_set_to_timestepping(tracing_action_set)
1391 project.add_action_set_to_initialisation(tracing_action_set)
1392
1393 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
1394 particle_set=tracer_particles,
1395 solver=self,
1396 filename=name + "-" + self._name,
1397 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
1398 output_precision=10,
1399 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
1400 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
1401 clear_database_after_flush=True,
1402 )
1403 dump_into_database_action_set.descend_invocation_order = (
1404 self._action_set_compute_final_linear_combination.descend_invocation_order
1405 + 2
1406 )
1407 project.add_action_set_to_timestepping(dump_into_database_action_set)
1408
1409
1411 return """
1412#if defined(GPUOffloadingOMP)
1413 double* dQdxSerialised = new double[NumberOfUnknowns*3];
1414#else
1415 double dQdxSerialised[NumberOfUnknowns*3];
1416#endif
1417 for (int i=0; i<NumberOfUnknowns; i++) {
1418 dQdxSerialised[i+0*NumberOfUnknowns] = 0.0;
1419 dQdxSerialised[i+1*NumberOfUnknowns] = 0.0;
1420 dQdxSerialised[i+2*NumberOfUnknowns] = 0.0;
1421
1422 dQdxSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
1423 }
1424 ::exagrype::ccz4::ncp(BTimesDeltaQ, Q, dQdxSerialised, normal%Dimensions, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
1425#if defined(GPUOffloadingOMP)
1426 delete[] dQdxSerialised;
1427#endif
1428"""
1429
1430
1432 return """
1433 tarch::memset(S, 0.0, NumberOfUnknowns*sizeof(double));
1434 ::exagrype::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
1435"""
1436
1437
1439 return """
1440 ::exagrype::ccz4::maxEigenvalue(Q, normal%Dimensions, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd, maxEigenvalue );
1441"""
1442
1443
1445 return """
1446{
1447 constexpr int itmax = ({{DG_ORDER}}+1) * ({{DG_ORDER}}+1) * ({{DG_ORDER}}+1);
1448 int index = 0;
1449 for (int i=0;i<itmax;i++)
1450 {
1451 exagrype::ccz4::enforceCCZ4constraints( newQ+index );
1452 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
1453 }
1454 }
1455"""
1456
1457
1459 name,
1460 coordinates,
1461 project,
1462 self,
1463 number_of_entries_between_two_db_flushes,
1464 data_delta_between_two_snapsots,
1465 time_delta_between_two_snapsots,
1466 clear_database_after_flush,
1467 tracer_unknowns,
1468):
1469 number_of_attributes = (
1470 (self.unknowns + self.auxiliary_variables)
1471 if tracer_unknowns == None
1472 else len(tracer_unknowns)
1473 )
1474 tracer_particles = project.add_tracer(
1475 name=name, attribute_count=number_of_attributes
1476 )
1477 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
1478 particle_set=tracer_particles, coordinates=coordinates
1479 )
1480 init_action_set.descend_invocation_order = 0
1481 project.add_action_set_to_initialisation(init_action_set)
1482
1483 assert tracer_unknowns == None
1484
1485 tracing_action_set = exahype2.tracer.DiscontinuousGalerkinTracing(
1486 tracer_particles,
1487 solver=self,
1488 project_on_tracer_properties_kernel="::exahype2::dg::projectAllValuesOntoParticle",
1489 )
1490 tracing_action_set.descend_invocation_order = (
1491 self._action_set_compute_final_linear_combination_and_project_solution_onto_faces.descend_invocation_order
1492 + 1
1493 )
1494 project.add_action_set_to_timestepping(tracing_action_set)
1495 project.add_action_set_to_initialisation(tracing_action_set)
1496
1497 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
1498 particle_set=tracer_particles,
1499 solver=self,
1500 filename=name + "-" + self._name,
1501 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
1502 output_precision=10,
1503 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
1504 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
1505 clear_database_after_flush=clear_database_after_flush,
1506 )
1507 dump_into_database_action_set.descend_invocation_order = (
1508 self._action_set_compute_final_linear_combination_and_project_solution_onto_faces.descend_invocation_order
1509 + 1
1510 )
1511 project.add_action_set_to_timestepping(dump_into_database_action_set)
1512
1513
1515 AbstractCCZ4Solver,
1516 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking,
1517):
1518 """!
1519
1520 CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave tasking
1521
1522 The constructor of this classs is straightforward and realises the standard
1523 steps of any numerical implementation of the CCZ4 scheme:
1524
1525 1. Init the actual numerical scheme. This happens through the constructor
1526 of the base class.
1527
1528 2. Add the header files that we need, i.e. those files which contain the
1529 actual CCZ4 implementation.
1530
1531 3. Add some constants that any CCZ4 C++ code requires.
1532
1533 4. Set the actual implementation, i.e. link the generic PDE terms to the
1534 CCZ4-specific function calls.
1535
1536 5. Add the CCZ4-specific postprocessing.
1537
1538 6. Switch to higher-order interpolation and restriction.
1539
1540 """
1541
1543 self,
1544 name,
1545 rk_order,
1546 polynomials,
1547 min_cell_h,
1548 max_cell_h,
1549 pde_terms_without_state,
1550 ):
1551 """!
1552
1553 Construct solver with enclave tasking
1554
1555 """
1556 AbstractCCZ4Solver.__init__(self)
1557 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
1558 self,
1559 name=name,
1560 rk_order=rk_order,
1561 polynomials=polynomials,
1562 unknowns=sum(self._FO_formulation_unknowns.values()),
1563 auxiliary_variables=0,
1564 min_cell_h=min_cell_h,
1565 max_cell_h=max_cell_h,
1566 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
1567 pde_terms_without_state=pde_terms_without_state,
1568 )
1569
1571
1572 self.set_implementation(
1573 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1574 ncp=construct_DG_ncp(),
1575 flux=exahype2.solvers.PDETerms.None_Implementation,
1576 source_term=construct_DG_source_term(),
1577 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1578 eigenvalues=construct_DG_eigenvalues(),
1579 point_source=exahype2.solvers.PDETerms.None_Implementation
1580 )
1581
1582 self.postprocess_updated_cell_after_final_linear_combination += (
1584 )
1585
1587 self,
1588 name,
1589 coordinates,
1590 project,
1591 number_of_entries_between_two_db_flushes,
1592 data_delta_between_two_snapsots,
1593 time_delta_between_two_snapsots,
1594 clear_database_after_flush,
1595 tracer_unknowns,
1596 ):
1597 """!
1598
1599 Add tracer to project
1600
1601 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1602 some of the arguments. Most of them are simply piped through to this
1603 class.
1604
1605 At this point, we have not yet created the Peano 4 project. Therefore, we
1606 have not yet befilled the time stepping action set.
1607
1608 project: exahype2.Project
1609
1610 """
1612 name,
1613 coordinates,
1614 project,
1615 self,
1616 number_of_entries_between_two_db_flushes,
1617 data_delta_between_two_snapsots,
1618 time_delta_between_two_snapsots,
1619 clear_database_after_flush,
1620 tracer_unknowns,
1621 )
1622
1623
1625 AbstractCCZ4Solver,
1626 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStep,
1627):
1628 """!
1629
1630 CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave tasking
1631
1632 The constructor of this classs is straightforward and realises the standard
1633 steps of any numerical implementation of the CCZ4 scheme:
1634
1635 1. Init the actual numerical scheme. This happens through the constructor
1636 of the base class.
1637
1638 2. Add the header files that we need, i.e. those files which contain the
1639 actual CCZ4 implementation.
1640
1641 3. Add some constants that any CCZ4 C++ code requires.
1642
1643 4. Set the actual implementation, i.e. link the generic PDE terms to the
1644 CCZ4-specific function calls.
1645
1646 5. Add the CCZ4-specific postprocessing.
1647
1648 6. Switch to higher-order interpolation and restriction.
1649
1650 """
1651
1653 self,
1654 name,
1655 rk_order,
1656 polynomials,
1657 min_cell_h,
1658 max_cell_h,
1659 pde_terms_without_state,
1660 ):
1661 """!
1662
1663 Construct solver with enclave tasking
1664
1665 """
1666 AbstractCCZ4Solver.__init__(self)
1667 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStep.__init__(
1668 self,
1669 name=name,
1670 rk_order=rk_order,
1671 polynomials=polynomials,
1672 unknowns=sum(self._FO_formulation_unknowns.values()),
1673 auxiliary_variables=0,
1674 min_cell_h=min_cell_h,
1675 max_cell_h=max_cell_h,
1676 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
1677 pde_terms_without_state=pde_terms_without_state,
1678 )
1679
1681
1682 self.set_implementation(
1683 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1684 ncp=construct_DG_ncp(),
1685 flux=exahype2.solvers.PDETerms.None_Implementation,
1686 source_term=construct_DG_source_term(),
1687 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1688 eigenvalues=construct_DG_eigenvalues(),
1689 )
1690
1691 self.postprocess_updated_cell_after_final_linear_combination += (
1693 )
1694
1696 self,
1697 name,
1698 coordinates,
1699 project,
1700 number_of_entries_between_two_db_flushes,
1701 data_delta_between_two_snapsots,
1702 time_delta_between_two_snapsots,
1703 clear_database_after_flush,
1704 tracer_unknowns,
1705 ):
1706 """!
1707
1708 Add tracer to project
1709
1710 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1711 some of the arguments. Most of them are simply piped through to this
1712 class.
1713
1714 At this point, we have not yet created the Peano 4 project. Therefore, we
1715 have not yet befilled the time stepping action set.
1716
1717 project: exahype2.Project
1718
1719 """
1721 name,
1722 coordinates,
1723 project,
1724 self,
1725 number_of_entries_between_two_db_flushes,
1726 data_delta_between_two_snapsots,
1727 time_delta_between_two_snapsots,
1728 clear_database_after_flush,
1729 tracer_unknowns,
1730 )
Abstract base class for any CCZ4 solver.
Definition CCZ4Solver.py:8
__init__(self)
Constructor.
_add_standard_includes(self)
Add the headers for the compute kernels and initial condition implementations.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns=None)
Add tracer to project.
add_all_solver_constants(self)
Add domain-specific constants.
add_makefile_parameters(self, peano4_project, path_of_ccz4_application)
Add include path and minimal required cpp files to makefile.
CCZ4 solver using fourth-order finite differences and global adaptive time stepping incl enclave task...
__init__(self, name, patch_size, rk_order, min_meshcell_h, max_meshcell_h, pde_terms_without_state, second_order=False, device_resident_rk=False)
Constructor.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
CCZ4 solver using fourth-order finite differences and global adaptive time stepping without enclave t...
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
__init__(self, name, patch_size, rk_order, min_meshcell_h, max_meshcell_h, second_order=False)
Constructor.
Variation of classic FD4 which relies on second order PDE formulation.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
__init__(self, name, patch_size, rk_order, min_meshcell_h, max_meshcell_h, reconstruction_type)
Constructor.
CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
__init__(self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state)
Construct solver with enclave tasking and adaptive time stepping.
CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
__init__(self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state)
Constructor.
CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking.
__init__(self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state)
Constructor.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
__init__(self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state)
Constructor.
CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave t...
__init__(self, name, rk_order, polynomials, min_cell_h, max_cell_h, pde_terms_without_state)
Construct solver with enclave tasking.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave t...
__init__(self, name, rk_order, polynomials, min_cell_h, max_cell_h, pde_terms_without_state)
Construct solver with enclave tasking.
add_tracer(self, name, coordinates, project, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
construct_FD4_ncp()
add_tracer_to_FV_solver(name, coordinates, project, solver, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
Add tracer to project.
construct_FV_source_term()
add_tracer_to_DG_solver(name, coordinates, project, self, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
construct_FV_eigenvalues()
add_tracer_to_FD4_solver(name, coordinates, project, solver, number_of_entries_between_two_db_flushes, data_delta_between_two_snapsots, time_delta_between_two_snapsots, clear_database_after_flush, tracer_unknowns)
I realise this as a separate routine, as we need it for all FD4 flavours.
construct_FD4_postprocessing_kernel()
construct_FD4_source_term()
construct_DG_eigenvalues()
construct_FV_postprocessing_kernel()
construct_FD4_eigenvalues()
construct_DG_postprocessing_kernel()
construct_DG_source_term()