5from abc
import abstractmethod
11 Abstract base class for any CCZ4 solver
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.
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:
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().
24 2. You have to set the initial conditions via
26 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 my_solver.set_implementation(initial_conditions = " " "
28 for (int i=0; i<NumberOfUnknowns+NumberOfAuxiliaryVariables; i++) Q[i] = 0.0;
29 ::applications::exahype2::ccz4::gaugeWave(Q, volumeCentre, 0);
31 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 At this point, different CCZ4 solver variants might require different
34 syntax. The term volumeCentre for example above is only defined in a
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.
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.
46 ## More complex scenarios
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
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
60 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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().
77 Dictionary which specifies the unknown names plus their cardinality
79 Has to be class attribute, as we need it in the constructor, i.e. before the
80 abstract object is created.
83 _FO_formulation_unknowns = {
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.
114 _SO_formulation_unknowns = {
126 Default_Time_Step_Size_Relaxation = 0.1
133 Initialise the two dictionaries with default values (which work).
167 Add the headers for the compute kernels and initial condition implementations
169 Usually called by the subclass constructor.
172 self.add_user_action_set_includes(
174#include "CCZ4Kernels.h"
175#include "SecondOrderAuxiliaryVariablesReconstruction.h"
178 self.add_user_solver_includes(
180#include "CCZ4Kernels.h"
181#include "InitialValues.h"
182#include "SecondOrderAuxiliaryVariablesReconstruction.h"
190 Add domain-specific constants
192 I need a couple of constants. I could either replace them directly
193 within the Python snippets below, but I prefer here to go a different
194 way and to export them as proper C++ constants.
196 There are two ways to inject solver constants into Peano: We can either
197 add them to the Makefile as global const expressions, or we can add
198 them to the ExaHyPE2 solver. The latter is the route we go down here,
199 as these constants logically belong to the solver and not to the project.
201 This operation uses the parent class' add_solver_constants(). You still
202 can use this operation to add further parameters. Or you can, as a user,
203 always add new entries to integer_constants or double_constants and then
204 call this routine rather than adding individual constants one by one.
208 self.add_solver_constants(
209 "static constexpr int {} = {};".format(key, value)
212 self.add_solver_constants(
213 "static constexpr double {} = {};".format(key, value)
219 Add include path and minimal required cpp files to makefile
221 If you have multiple CCZ4 solvers, i.e. different solvers of CCZ4 or multiple
222 instances of the CCZ4 type, please call this operation only once on one of
223 your solvers. At the moment, I add hte following cpp files to the setup:
227 - SecondOrderAuxiliaryVariablesReconstruction.cpp
229 You can always add further files via
230 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
231 peano4_project.output.makefile.add_cpp_file( "mypath/myfile.cpp" )
232 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235 if path_of_ccz4_application[-1] !=
"/":
236 path_of_ccz4_application +=
"/"
238 peano4_project.output.makefile.add_cpp_file(
239 path_of_ccz4_application +
"InitialValues.cpp"
241 peano4_project.output.makefile.add_cpp_file(
242 path_of_ccz4_application +
"CCZ4Kernels.cpp"
244 peano4_project.output.makefile.add_cpp_file(
245 path_of_ccz4_application +
"SecondOrderAuxiliaryVariablesReconstruction.cpp"
247 peano4_project.output.makefile.add_header_search_path(path_of_ccz4_application)
255 number_of_entries_between_two_db_flushes,
256 data_delta_between_two_snapsots,
257 time_delta_between_two_snapsots,
258 clear_database_after_flush,
259 tracer_unknowns=None,
263 Add tracer to project
265 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
266 some of the arguments. Most of them are simply piped through to this
269 The tracer is given a name and initial coordinates (list of three-tuples).
270 We need to know the underlying project as well, as we have to add the
271 tracing to the time stepping and the database update to the plotting.
272 ~~~~~~~~~~~~~~~~~~~~~~~
273 project.add_action_set_to_timestepping(my_interpolation)
274 project.add_action_set_to_timestepping(exahype2.tracer.DumpTracerIntoDatabase(
275 particle_set=tracer_particles,
277 filename=name + "-" + self._name,
278 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
280 data_delta_between_two_snapsots = data_delta_between_two_snapsots,
281 time_delta_between_two_snapsots = time_delta_between_two_snapsots,
282 clear_database_after_flush = True,
284 ~~~~~~~~~~~~~~~~~~~~~~~
287 assert "should not be called"
292 AbstractCCZ4Solver, exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStep
296 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
298 Please consult CCZ4Solver_FV_GlobalAdaptiveTimeStepWithEnclaveTasking.
303 self, name, patch_size, min_volume_h, max_volume_h, pde_terms_without_state
305 AbstractCCZ4Solver.__init__(self)
306 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStep.__init__(
309 patch_size=patch_size,
311 auxiliary_variables=0,
312 min_volume_h=min_volume_h,
313 max_volume_h=max_volume_h,
314 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
318 self.set_implementation(
319 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
321 flux=exahype2.solvers.PDETerms.None_Implementation,
323 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
334 number_of_entries_between_two_db_flushes,
335 data_delta_between_two_snapsots,
336 time_delta_between_two_snapsots,
337 clear_database_after_flush,
342 Add tracer to project
344 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
345 some of the arguments. Most of them are simply piped through to this
348 project: exahype2.Project
356 number_of_entries_between_two_db_flushes,
357 data_delta_between_two_snapsots,
358 time_delta_between_two_snapsots,
359 clear_database_after_flush,
366 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking,
370 CCZ4 solver using finite volumes and global adaptive time stepping incl enclave tasking
372 The constructor of this classs is straightforward and realises the standard
373 steps of any numerical implementation of the CCZ4 scheme:
375 1. Init the actual numerical scheme. This happens through the constructor
378 2. Add the header files that we need, i.e. those files which contain the
379 actual CCZ4 implementation.
381 3. Add some constants that any CCZ4 C++ code requires.
383 4. Set the actual implementation, i.e. link the generic PDE terms to the
384 CCZ4-specific function calls.
386 5. Add the CCZ4-specific postprocessing.
396 pde_terms_without_state,
400 Construct solver with enclave tasking and adaptive time stepping
403 AbstractCCZ4Solver.__init__(self)
404 exahype2.solvers.fv.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
407 patch_size=patch_size,
409 auxiliary_variables=0,
410 min_volume_h=min_volume_h,
411 max_volume_h=max_volume_h,
412 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
413 pde_terms_without_state=pde_terms_without_state,
417 self.set_implementation(
418 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
420 flux=exahype2.solvers.PDETerms.None_Implementation,
422 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
433 number_of_entries_between_two_db_flushes,
434 data_delta_between_two_snapsots,
435 time_delta_between_two_snapsots,
436 clear_database_after_flush,
441 Add tracer to project
443 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
444 some of the arguments. Most of them are simply piped through to this
448 project: exahype2.Project
456 number_of_entries_between_two_db_flushes,
457 data_delta_between_two_snapsots,
458 time_delta_between_two_snapsots,
459 clear_database_after_flush,
466 double deltaQSerialised[NumberOfUnknowns*3];
467 for (int i=0; i<NumberOfUnknowns; i++) {
468 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
469 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
470 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
472 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
474 ::applications::exahype2::ccz4::ncp(BTimesDeltaQ, Q, deltaQSerialised, normal%DIMENSIONS, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
480 double deltaQSerialised[NumberOfUnknowns*3];
481 for (int i=0; i<NumberOfUnknowns; i++) {
482 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
483 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
484 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
486 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
488 ::applications::exahype2::ccz4::ncp(BTimesDeltaQ, Q, deltaQSerialised, normal%DIMENSIONS, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
494 ::applications::exahype2::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
500 ::applications::exahype2::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
506 return ::applications::exahype2::ccz4::maxEigenvalue(Q, normal%DIMENSIONS, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd );
512 return ::applications::exahype2::ccz4::maxEigenvalue(Q, normal%DIMENSIONS, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd );
519 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}};
521 for (int i=0;i<itmax;i++)
523 applications::exahype2::ccz4::enforceCCZ4constraints( newQ+index );
524 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
533 constexpr int itmax = {{NUMBER_OF_VOLUMES_PER_AXIS}} * {{NUMBER_OF_VOLUMES_PER_AXIS}} * {{NUMBER_OF_VOLUMES_PER_AXIS}};
535 for (int i=0;i<itmax;i++)
537 applications::exahype2::ccz4::enforceCCZ4constraints( newQ+index );
538 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
549 number_of_entries_between_two_db_flushes,
550 data_delta_between_two_snapsots,
551 time_delta_between_two_snapsots,
552 clear_database_after_flush,
557 Add tracer to project
559 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
560 some of the arguments. Most of them are simply piped through to this
563 I realise this as a separate routine, as we need it for all FV flavours
566 number_of_attributes = (
567 (solver.unknowns + solver.auxiliary_variables)
568 if tracer_unknowns ==
None
569 else len(tracer_unknowns)
571 tracer_particles = project.add_tracer(
572 name=name, attribute_count=number_of_attributes
574 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
575 particle_set=tracer_particles, coordinates=coordinates
577 init_action_set.descend_invocation_order = 0
578 project.add_action_set_to_initialisation(init_action_set)
580 project_on_tracer_properties_kernel =
""
581 if tracer_unknowns ==
None:
582 project_on_tracer_properties_kernel = (
583 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
586 elif len(tracer_unknowns) == 1:
587 project_on_tracer_properties_kernel = (
588 "::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
589 i, tracer_unknowns.index(i)
593 project_on_tracer_properties_kernel = (
594 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
601 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
604 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
606 tracing_action_set.descend_invocation_order = (
607 solver._action_set_update_cell.descend_invocation_order + 1
609 project.add_action_set_to_timestepping(tracing_action_set)
610 project.add_action_set_to_initialisation(tracing_action_set)
612 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
613 particle_set=tracer_particles,
615 filename=name +
"-" + solver._name,
616 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
618 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
619 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
620 clear_database_after_flush=clear_database_after_flush,
622 dump_into_database_action_set.descend_invocation_order = (
623 solver._action_set_update_cell.descend_invocation_order + 2
625 project.add_action_set_to_timestepping(dump_into_database_action_set)
633 number_of_entries_between_two_db_flushes,
634 data_delta_between_two_snapsots,
635 time_delta_between_two_snapsots,
636 clear_database_after_flush,
641 I realise this as a separate routine, as we need it for all FD4 flavours
643 This is a wrapper around all the tracer handling. It adds the tracer to the
644 exahype2.Project, but it also instantiates the solution to tracer mapping
645 as well as the database bookkeeping.
647 @param tracer_unknowns: Integer
648 You can set this variable to None. In this case, all variables are
652 number_of_attributes = (
653 (solver.unknowns + solver.auxiliary_variables)
654 if tracer_unknowns ==
None
655 else len(tracer_unknowns)
657 tracer_particles = project.add_tracer(
658 name=name, attribute_count=number_of_attributes
660 project.add_action_set_to_initialisation(
661 exahype2.tracer.InsertParticlesByCoordinates(
662 particle_set=tracer_particles, coordinates=coordinates
665 project_on_tracer_properties_kernel =
""
666 if tracer_unknowns ==
None:
667 project_on_tracer_properties_kernel = (
668 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
670 elif len(tracer_unknowns) == 1:
671 project_on_tracer_properties_kernel = (
672 "::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
673 i, tracer_unknowns.index(i)
677 project_on_tracer_properties_kernel = (
678 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
685 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
688 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
690 tracing_action_set.descend_invocation_order = (
691 solver._action_set_compute_final_linear_combination.descend_invocation_order + 1
693 project.add_action_set_to_timestepping(tracing_action_set)
694 project.add_action_set_to_initialisation(tracing_action_set)
696 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
697 particle_set=tracer_particles,
699 filename=name +
"-" + solver._name,
700 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
702 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
703 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
704 clear_database_after_flush=clear_database_after_flush,
706 dump_into_database_action_set.descend_invocation_order = (
707 solver._action_set_compute_final_linear_combination.descend_invocation_order + 2
709 project.add_action_set_to_timestepping(dump_into_database_action_set)
714 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking,
718 CCZ4 solver using fourth-order finite differences and global adaptive time stepping incl enclave tasking
720 The constructor of this classs is straightforward and realises the standard
721 steps of any numerical implementation of the CCZ4 scheme:
723 1. Init the actual numerical scheme. This happens through the constructor
726 2. Add the header files that we need, i.e. those files which contain the
727 actual CCZ4 implementation.
729 3. Add some constants that any CCZ4 C++ code requires.
731 4. Set the actual implementation, i.e. link the generic PDE terms to the
732 CCZ4-specific function calls.
734 5. Add the CCZ4-specific postprocessing.
736 6. Switch to higher-order interpolation and restriction.
747 pde_terms_without_state,
754 Calibrate the default time step size calibration with 1/16 to take into
755 account that we have a higher-order numerical scheme.
758 AbstractCCZ4Solver.__init__(self)
760 AbstractCCZ4Solver.enable_second_order(self)
761 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
764 patch_size=patch_size,
767 auxiliary_variables=0,
768 min_meshcell_h=min_meshcell_h,
769 max_meshcell_h=max_meshcell_h,
771 pde_terms_without_state=pde_terms_without_state,
776 self.set_implementation(
777 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
779 flux=exahype2.solvers.PDETerms.None_Implementation,
781 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
788 # Use second order interpolation and restriction
789 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
792 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
798 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
799 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
802 # Use matrix interpolation and restriction
803 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
806 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
812 # Use tensor product interpolation and restriction
813 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
815 "TP_linear_with_linear_extrap_normal_interp"
817 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
819 "TP_average_normal_extrap"
828 number_of_entries_between_two_db_flushes,
829 data_delta_between_two_snapsots,
830 time_delta_between_two_snapsots,
831 clear_database_after_flush,
836 Add tracer to project
838 This is a delegate to add_tracer_to_FD4_solver() which passes the
839 object in as first argument.
841 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
842 some of the arguments. Most of them are simply piped through to this
845 @param project: exahype2.Project
847 @param tracer_unknowns: Integer
848 You can set this variable to None. In this case, all variables are
857 number_of_entries_between_two_db_flushes,
858 data_delta_between_two_snapsots,
859 time_delta_between_two_snapsots,
860 clear_database_after_flush,
866 AbstractCCZ4Solver, exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStep
870 CCZ4 solver using fourth-order finite differences and global adaptive time stepping without enclave tasking
872 Consult CCZ4Solver_FD4_GlobalAdaptiveTimeStepWithEnclaveTasking please.
889 Calibrate the default time step size calibration with 1/16 to take into
890 account that we have a higher-order numerical scheme.
893 AbstractCCZ4Solver.__init__(self)
895 AbstractCCZ4Solver.enable_second_order(self)
896 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStep.__init__(
899 patch_size=patch_size,
902 auxiliary_variables=0,
903 min_meshcell_h=min_meshcell_h,
904 max_meshcell_h=max_meshcell_h,
910 self.set_implementation(
911 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
913 flux=exahype2.solvers.PDETerms.None_Implementation,
915 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
922 # Use second order interpolation and restriction
923 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
926 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
932 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
933 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
936 # Use matrix interpolation and restriction
937 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
940 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
946 # Use tensor product interpolation and restriction
947 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
949 "TP_linear_with_linear_extrap_normal_interp"
951 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
953 "TP_average_normal_extrap"
962 number_of_entries_between_two_db_flushes,
963 data_delta_between_two_snapsots,
964 time_delta_between_two_snapsots,
965 clear_database_after_flush,
970 Add tracer to project
972 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
973 some of the arguments. Most of them are simply piped through to this
976 project: exahype2.Project
984 number_of_entries_between_two_db_flushes,
985 data_delta_between_two_snapsots,
986 time_delta_between_two_snapsots,
987 clear_database_after_flush=clear_database_after_flush,
988 tracer_unknowns=tracer_unknowns,
994 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking,
998 Variation of classic FD4 which relies on second order PDE formulation
1000 The traditional ExaHyPE CCZ4 formulation is the first order formulation
1001 introduced by Dumbser et al. In this formulation, the second order terms
1002 in CCZ4 are substituted with helper variables which represent first order
1003 derivatives. While formally straightforward, keeping the whole system
1004 consistent and stricly hyperbolic is a different challenge.
1006 In this revised version, we have to evolve the primary quantities of CCZ4
1007 and also the helper variables, which blows the overall system up to 59
1008 equations in its simplest form. The work by Dumbser and others suggest that
1009 this is a consistent and stable approach, but limited work is actually
1010 published on proper physical simulations. We therefore also implemented a
1011 second order PDE version within ExaHyPE.
1013 This second order variant is not really second order from the start.
1014 Instead, we use the first order formulation, and we reconstruct the helper
1015 term via finite differences prior to the compute kernel application. That is,
1016 the compute kernels see variables representing first order derivatives, and
1017 they also evolve these guys. Afterwards, we throw away the evolved quantities
1018 and reconstruct them from the primary unknowns prior to the next time step.
1020 This might not be super efficient (it would be faster to stick to the
1021 second order formulation right from the start), but it allows us to reuse
1022 the compute kernels written for the first order PDE formulation.
1026 We have now a smaller number of real unknowns, i.e. only those guys who
1027 belong to the "original" second-order formulation. The remaining quantities
1028 compared to a first-order formulation are technically material or auxiliary
1029 quantities. We model them as such, which allows ExaHyPE`s data management
1030 to deal more efficiently with them.
1033 reconstruction_type: "4thOrder", "centralDifferences", "leftDifference", "rightDifference"
1044 reconstruction_type,
1050 Calibrate the default time step size calibration with 1/16 to take into
1051 account that we have a higher-order numerical scheme.
1054 AbstractCCZ4Solver.__init__(self)
1055 exahype2.solvers.rkfd.fd4.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
1058 patch_size=patch_size,
1063 min_meshcell_h=min_meshcell_h,
1064 max_meshcell_h=max_meshcell_h,
1065 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation
1071 self.set_implementation(
1072 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1074 double deltaQSerialised[NumberOfUnknowns*3];
1075 for (int i=0; i<NumberOfUnknowns; i++) {
1076 deltaQSerialised[i+0*NumberOfUnknowns] = 0.0;
1077 deltaQSerialised[i+1*NumberOfUnknowns] = 0.0;
1078 deltaQSerialised[i+2*NumberOfUnknowns] = 0.0;
1080 deltaQSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
1082 ::applications::exahype2::ccz4::ncpSecondOrderFormulation(BTimesDeltaQ, Q, deltaQSerialised, normal%DIMENSIONS, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
1084 flux=exahype2.solvers.PDETerms.None_Implementation,
1086 std::memset(S, 0.0, NumberOfUnknowns*sizeof(double));
1087 ::applications::exahype2::ccz4::sourceSecondOrderFormulation(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3);
1089 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1092 return ::applications::exahype2::ccz4::maxEigenvalueSecondOrderFormulation(Q, normal%DIMENSIONS, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd );
1096 self.postprocess_updated_patch +=
"""
1098 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}};
1100 for (int i=0;i<itmax;i++)
1102 applications::exahype2::ccz4::enforceCCZ4constraintsSecondOrderFormulation( newQ+index );
1103 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
1109 # Use second order interpolation and restriction
1110 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_interpolation(
1113 exahype2.solvers.rkfd.fd4.switch_to_FD4_second_order_restriction(
1119 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_interpolation(self)
1120 exahype2.solvers.rkfd.fd4.switch_to_FD4_third_order_restriction(self)
1123 # Use matrix interpolation and restriction
1124 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_interpolation(
1127 exahype2.solvers.rkfd.fd4.switch_to_FD4_matrix_restriction(
1133 # Use tensor product interpolation and restriction
1134 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_interpolation(
1136 "TP_linear_with_linear_extrap_normal_interp"
1138 exahype2.solvers.rkfd.fd4.switch_to_FD4_tensor_product_restriction(
1140 "TP_average_normal_extrap"
1144 self.preprocess_reconstructed_patch += (
1146::exahype2::CellData reconstructedPatchData(
1152 nullptr // targetPatch
1154::applications::exahype2::ccz4::recomputeAuxiliaryVariablesFD4_"""
1155 + reconstruction_type
1157 reconstructedPatchData,
1158 {{NUMBER_OF_GRID_CELLS_PER_PATCH_PER_AXIS}},
1160 {{NUMBER_OF_UNKNOWNS}},
1161 {{NUMBER_OF_AUXILIARY_VARIABLES}}
1171 number_of_entries_between_two_db_flushes,
1172 data_delta_between_two_snapsots,
1173 time_delta_between_two_snapsots,
1174 clear_database_after_flush,
1179 Add tracer to project
1181 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1182 some of the arguments. Most of them are simply piped through to this
1185 project: exahype2.Project
1188 number_of_attributes = (
1190 if tracer_unknowns ==
None
1191 else len(tracer_unknowns)
1193 tracer_particles = project.add_tracer(
1194 name=name, attribute_count=number_of_attributes
1196 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
1197 particle_set=tracer_particles, coordinates=coordinates
1199 init_action_set.descend_invocation_order = 0
1200 project.add_action_set_to_initialisation(init_action_set)
1202 project_on_tracer_properties_kernel =
""
1203 if tracer_unknowns ==
None:
1204 project_on_tracer_properties_kernel = (
1205 "::exahype2::fv::projectAllValuesOntoParticle_piecewiseLinear"
1207 elif len(tracer_unknowns) == 1:
1208 project_on_tracer_properties_kernel =
"::exahype2::fv::projectValueOntoParticle_piecewiseLinear<{},{}>".format(
1209 i, tracer_unknowns.index(i)
1212 project_on_tracer_properties_kernel = (
1213 "::exahype2::fv::projectValuesOntoParticle_piecewiseLinear<{}>".format(
1220 tracing_action_set = exahype2.tracer.FiniteVolumesTracing(
1223 project_on_tracer_properties_kernel=project_on_tracer_properties_kernel,
1225 tracing_action_set.descend_invocation_order = (
1226 self._action_set_compute_final_linear_combination.descend_invocation_order
1229 project.add_action_set_to_timestepping(tracing_action_set)
1230 project.add_action_set_to_initialisation(tracing_action_set)
1232 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
1233 particle_set=tracer_particles,
1235 filename=name +
"-" + self._name,
1236 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
1237 output_precision=10,
1238 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
1239 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
1240 clear_database_after_flush=
True,
1242 dump_into_database_action_set.descend_invocation_order = (
1243 self._action_set_compute_final_linear_combination.descend_invocation_order
1246 project.add_action_set_to_timestepping(dump_into_database_action_set)
1251 double dQdxSerialised[NumberOfUnknowns*3];
1252 for (int i=0; i<NumberOfUnknowns; i++) {
1253 dQdxSerialised[i+0*NumberOfUnknowns] = 0.0;
1254 dQdxSerialised[i+1*NumberOfUnknowns] = 0.0;
1255 dQdxSerialised[i+2*NumberOfUnknowns] = 0.0;
1257 dQdxSerialised[i+normal*NumberOfUnknowns] = deltaQ[i];
1259 ::applications::exahype2::ccz4::ncp(BTimesDeltaQ, Q, dQdxSerialised, normal%DIMENSIONS, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
1265 std::memset(S, 0.0, NumberOfUnknowns*sizeof(double));
1266 ::applications::exahype2::ccz4::source(S,Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
1272 return ::applications::exahype2::ccz4::maxEigenvalue(Q, normal%DIMENSIONS, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd );
1279 constexpr int itmax = ({{DG_ORDER}}+1) * ({{DG_ORDER}}+1) * ({{DG_ORDER}}+1);
1281 for (int i=0;i<itmax;i++)
1283 applications::exahype2::ccz4::enforceCCZ4constraints( newQ+index );
1284 index += {{NUMBER_OF_UNKNOWNS}} + {{NUMBER_OF_AUXILIARY_VARIABLES}};
1295 number_of_entries_between_two_db_flushes,
1296 data_delta_between_two_snapsots,
1297 time_delta_between_two_snapsots,
1298 clear_database_after_flush,
1301 number_of_attributes = (
1302 (self.unknowns + self.auxiliary_variables)
1303 if tracer_unknowns ==
None
1304 else len(tracer_unknowns)
1306 tracer_particles = project.add_tracer(
1307 name=name, attribute_count=number_of_attributes
1309 init_action_set = exahype2.tracer.InsertParticlesByCoordinates(
1310 particle_set=tracer_particles, coordinates=coordinates
1312 init_action_set.descend_invocation_order = 0
1313 project.add_action_set_to_initialisation(init_action_set)
1315 assert tracer_unknowns ==
None
1317 tracing_action_set = exahype2.tracer.DiscontinuousGalerkinTracing(
1320 project_on_tracer_properties_kernel=
"::exahype2::dg::projectAllValuesOntoParticle",
1322 tracing_action_set.descend_invocation_order = (
1323 self._action_set_compute_final_linear_combination_and_project_solution_onto_faces.descend_invocation_order
1326 project.add_action_set_to_timestepping(tracing_action_set)
1327 project.add_action_set_to_initialisation(tracing_action_set)
1329 dump_into_database_action_set = exahype2.tracer.DumpTracerIntoDatabase(
1330 particle_set=tracer_particles,
1332 filename=name +
"-" + self._name,
1333 number_of_entries_between_two_db_flushes=number_of_entries_between_two_db_flushes,
1334 output_precision=10,
1335 data_delta_between_two_snapsots=data_delta_between_two_snapsots,
1336 time_delta_between_two_snapsots=time_delta_between_two_snapsots,
1337 clear_database_after_flush=clear_database_after_flush,
1339 dump_into_database_action_set.descend_invocation_order = (
1340 self._action_set_compute_final_linear_combination_and_project_solution_onto_faces.descend_invocation_order
1343 project.add_action_set_to_timestepping(dump_into_database_action_set)
1348 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking,
1352 CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave tasking
1354 The constructor of this classs is straightforward and realises the standard
1355 steps of any numerical implementation of the CCZ4 scheme:
1357 1. Init the actual numerical scheme. This happens through the constructor
1360 2. Add the header files that we need, i.e. those files which contain the
1361 actual CCZ4 implementation.
1363 3. Add some constants that any CCZ4 C++ code requires.
1365 4. Set the actual implementation, i.e. link the generic PDE terms to the
1366 CCZ4-specific function calls.
1368 5. Add the CCZ4-specific postprocessing.
1370 6. Switch to higher-order interpolation and restriction.
1381 pde_terms_without_state,
1385 Construct solver with enclave tasking
1388 AbstractCCZ4Solver.__init__(self)
1389 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStepWithEnclaveTasking.__init__(
1393 polynomials=polynomials,
1395 auxiliary_variables=0,
1396 min_cell_h=min_cell_h,
1397 max_cell_h=max_cell_h,
1398 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
1399 pde_terms_without_state=pde_terms_without_state,
1404 self.set_implementation(
1405 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1407 flux=exahype2.solvers.PDETerms.None_Implementation,
1409 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1413 self.postprocess_updated_cell_after_final_linear_combination += (
1422 number_of_entries_between_two_db_flushes,
1423 data_delta_between_two_snapsots,
1424 time_delta_between_two_snapsots,
1425 clear_database_after_flush,
1430 Add tracer to project
1432 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1433 some of the arguments. Most of them are simply piped through to this
1436 At this point, we have not yet created the Peano 4 project. Therefore, we
1437 have not yet befilled the time stepping action set.
1439 project: exahype2.Project
1447 number_of_entries_between_two_db_flushes,
1448 data_delta_between_two_snapsots,
1449 time_delta_between_two_snapsots,
1450 clear_database_after_flush,
1457 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStep,
1461 CCZ4 solver using Runge-Kutta Discontinuous Galerkin and global adaptive time stepping incl enclave tasking
1463 The constructor of this classs is straightforward and realises the standard
1464 steps of any numerical implementation of the CCZ4 scheme:
1466 1. Init the actual numerical scheme. This happens through the constructor
1469 2. Add the header files that we need, i.e. those files which contain the
1470 actual CCZ4 implementation.
1472 3. Add some constants that any CCZ4 C++ code requires.
1474 4. Set the actual implementation, i.e. link the generic PDE terms to the
1475 CCZ4-specific function calls.
1477 5. Add the CCZ4-specific postprocessing.
1479 6. Switch to higher-order interpolation and restriction.
1490 pde_terms_without_state,
1494 Construct solver with enclave tasking
1497 AbstractCCZ4Solver.__init__(self)
1498 exahype2.solvers.rkdg.rusanov.GlobalAdaptiveTimeStep.__init__(
1502 polynomials=polynomials,
1504 auxiliary_variables=0,
1505 min_cell_h=min_cell_h,
1506 max_cell_h=max_cell_h,
1507 time_step_relaxation=AbstractCCZ4Solver.Default_Time_Step_Size_Relaxation,
1508 pde_terms_without_state=pde_terms_without_state,
1513 self.set_implementation(
1514 boundary_conditions=exahype2.solvers.PDETerms.Empty_Implementation,
1516 flux=exahype2.solvers.PDETerms.None_Implementation,
1518 refinement_criterion=exahype2.solvers.PDETerms.Empty_Implementation,
1522 self.postprocess_updated_cell_after_final_linear_combination += (
1531 number_of_entries_between_two_db_flushes,
1532 data_delta_between_two_snapsots,
1533 time_delta_between_two_snapsots,
1534 clear_database_after_flush,
1539 Add tracer to project
1541 Consult exahype2.tracer.DumpTracerIntoDatabase for an explanation of
1542 some of the arguments. Most of them are simply piped through to this
1545 At this point, we have not yet created the Peano 4 project. Therefore, we
1546 have not yet befilled the time stepping action set.
1548 project: exahype2.Project
1556 number_of_entries_between_two_db_flushes,
1557 data_delta_between_two_snapsots,
1558 time_delta_between_two_snapsots,
1559 clear_database_after_flush,
Abstract base class for any CCZ4 solver.
dict _SO_formulation_unknowns
__init__(self)
Constructor.
float Default_Time_Step_Size_Relaxation
_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.
enable_second_order(self)
Default_Time_Step_Size_Relaxation
dict _FO_formulation_unknowns
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...
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, pde_terms_without_state, second_order=False)
Constructor.
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.
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 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.
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()