1""" This file is part of the ExaGRyPE project. For conditions of distribution and
2 use, please see the copyright notice at www.peano-framework.org
6from typing
import Dict, List, Union
13from .
import initialvalues
19 Solver for the Einstein equations in the first-order CCZ4 formulation
21 The solver is a plain exahype2.api.Solver with the 59 CCZ4 unknowns and
22 the PDE terms of CCZ4 pre-registered. All terms delegate to the
23 ExaGRyPE library (configure Peano with --enable-exagrype):
25 - the non-conservative product to exagrype::ccz4::ncp(),
26 - the volumetric source to exagrype::ccz4::source(),
27 - the maximum eigenvalue to exagrype::ccz4::maxEigenvalue(),
28 - the initial condition to one of the routines from
29 exagrype::initialvalues, @see exagrype.api.initialvalues.
31 CCZ4 has no conservative flux. You still have to assign a numerical
32 scheme, a grid construction and (optionally) a plotter, exactly as for
33 any other exahype2.api.Solver, and to add the solver to an
34 exahype2.api.Project. The project has to be three-dimensional: the
35 generated solver class refuses to compile otherwise.
39 - The fourth-order Finite Differences of the production runs are
40 available through exahype2.api.rkfd4, i.e. pass a
41 CentralDifferencesWithRungeKutta as numerical scheme. They have no
42 artificial dissipation. exagrype.api.FD4WithKODissipation is the same
43 scheme with a Kreiss-Oliger dissipation on top. Unlike the legacy
44 ExaGRyPE, neither supports adaptive mesh refinement yet.
45 - The solution is pushed back onto the CCZ4 constraints
46 (exagrype::ccz4::enforceCCZ4constraints()) only if you switch it on
47 via enforce_ccz4_constraint(). Without it, long runs drift away from
48 the constraint surface.
49 - exagrype::ccz4::ncp() omits the advection terms
50 @f$ \\beta^k \\partial _k Q @f$ of all unknowns besides the metric,
51 the lapse, the shift and phi (whose advection is part of the
52 algebraic source) and K0. It expects the numerical scheme to add them
53 with lopsided stencils. The fourth-order Finite Differences do so if
54 you select the kernel CentralDifferencesWithLopsidedAdvection with
55 ADVECTION_VELOCITY and lopsided_advection_quantities(). The Finite
56 Volumes of exahype2.api.fv do not add them, i.e. they evolve CCZ4
57 without these advection terms.
58 - The second-order formulation, black holes (TwoPunctures), tracers and
59 the ADM/Psi4 postprocessing are not available yet.
66 When to push the solution back onto the algebraic CCZ4 constraints
68 - No: never. This is the default.
69 - OnlyFinalSolution: after each task which writes a new solution
70 (exahype2.api.Solver.SolutionUpdateTaskTag), i.e. once per time
72 - IntermediateSteps: in addition after each task which writes an
73 intermediate solution (exahype2.api.Solver.IntermediateSolutionUpdateTag),
74 i.e. after each Runge-Kutta stage. For single-step schemes such as
75 the Finite Volumes, this is the same as OnlyFinalSolution.
77 @ref exagrype.api.CCZ4Solver.CCZ4Solver.enforce_ccz4_constraint()
107 The unknowns of the first-order CCZ4 formulation in the order the
108 kernels in exagrype::ccz4 expect them. The names match the legacy
113 DefaultParameters = {
134 Default values of the CCZ4 parameters, taken from the legacy ExaGRyPE
135 solvers. Integer values become int constants of the generated solver
136 class, all others double constants.
140 ADVECTION_VELOCITY =
"shift"
143 The variable which advects the unknowns, i.e. the velocity to pass to
144 lopsided advection kernels (@see lopsided_advection_quantities()).
151 parameters: Dict[str, Union[int, float]] =
None,
159 Name of the solver, @see exahype2.api.Solver.
161 @param parameters: Dict[str, Union[int, float]]
162 CCZ4 parameters that differ from DefaultParameters, e.g.
163 {"CCZ4k1": 0.0}. Keys which are not in DefaultParameters are
164 rejected, as they most likely are typos.
166 @param initial_condition: exahype2.api.InitPointWisely
167 Initial condition. Defaults to exagrype.api.initialvalues.gauge_wave().
168 Pass any other routine from exagrype.api.initialvalues, or your
169 own exahype2.api.InitPointWisely.
177 for key, value
in (parameters
or {}).items():
180 f
"Solver {name}: unknown CCZ4 parameter {key!r}. "
181 f
"Available parameters are {list(self.DefaultParameters)}."
186 'static_assert(Dimensions == 3, "CCZ4 (ExaGRyPE) is three-dimensional only");'
193 f
"static constexpr {cpp_type} {key} = {value};"
198#include "exagrype/ccz4/Kernels.h"
199#include "exagrype/initialvalues/InitialValues.h"
200#include "exagrype/initialvalues/ApplyTwoPunctures.h"
219 if initial_condition
is not None
220 else initialvalues.gauge_wave()
226 The unknowns whose advection terms exagrype::ccz4::ncp() omits
228 exagrype::ccz4::ncp() is invoked with its advection switched off.
229 The unknowns returned are those whose advection terms
230 @f$ \\beta^k \\partial _k Q @f$ hence have to be added by the
231 numerical scheme, e.g. via
233 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234 exahype2.api.rkfd4.CentralDifferencesWithRungeKutta(
235 solver, patch_size, rk_order=4,
236 right_hand_side_kernel = exahype2.api.rkfd4.CentralDifferencesWithRungeKutta.RightHandSideKernel.CentralDifferencesWithLopsidedAdvection,
237 advection_velocity = exagrype.api.CCZ4Solver.ADVECTION_VELOCITY,
238 advected_quantities = solver.lopsided_advection_quantities(),
240 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242 These are all unknowns besides the conformal metric G, the lapse,
243 the shift, phi and K0: The advection terms of the metric, the lapse,
244 the shift and phi are part of the algebraic source
245 (exagrype::ccz4::source()), which expresses them through the
246 auxiliary unknowns, i.e. the first derivatives. K0 does not evolve.
248 The advection of b and of the derivatives of the shift (dxShift,
249 dyShift, dzShift) is scaled with CCZ4bs and CCZ4sk. If either of
250 them is zero, the routine leaves these unknowns out.
252 The equation of b couples the advection of b and of Ghat (the
254 advection terms are CCZ4sk * (CCZ4xi * beta^k d_k Ghat + CCZ4bs *
255 (beta^k d_k b - beta^k d_k Ghat)). A kernel which advects each
256 quantity on its own, i.e. adds beta^k d_k b to b, reproduces this
257 only for CCZ4xi=1, CCZ4bs=1 and CCZ4sk=1. This is the case for the
258 default CCZ4xi and the moving puncture setups with CCZ4bs=CCZ4sk=1.
261 Names of unknowns, @see Unknowns.
264 excluded = {
"G",
"lapse",
"shift",
"phi",
"K0"}
266 excluded |= {
"b",
"dxShift",
"dyShift",
"dzShift"}
267 return [name
for name
in self.
Unknowns if name
not in excluded]
272 Set when the solver pushes the solution back onto the CCZ4 constraints
274 By default, the solver does not enforce the constraints. If you
275 switch the enforcement on, generate_solver_realisation() inserts a
276 task which applies exagrype::ccz4::enforceCCZ4constraints() to each
277 volume or grid point after each tagged solution update of the
280 @param value: CCZ4Solver.EnforceCCZ4Constraint
281 No, OnlyFinalSolution or IntermediateSteps.
286 f
"Solver {self.name}: enforce_ccz4_constraint() expects a "
287 f
"CCZ4Solver.EnforceCCZ4Constraint, but got {value!r}"
302 Create the solver's task graphs and insert the constraint enforcement
304 The routine first calls the superclass, which lets the grid
305 construction, the numerical scheme and the plotter add their tasks.
306 If the constraint enforcement is switched on
307 (enforce_ccz4_constraint()), it afterwards inserts the enforcement
308 after each tagged solution update of the numerical scheme. Which
309 patch a tagged task writes and which guard it uses depends on the
310 scheme, so the routine distinguishes the schemes explicitly
311 (@ref page_exahype2_solver_manipulate_solver_steps). It raises an
312 exception for any other scheme.
314 All insertions work on the patch which the tagged tasks write and
317 - exahype2.api.fv.RusanovWithExplicitEuler: one task after Update
319 - exahype2.api.fv.RusanovWithOptimisticExplicitEuler: one task after
320 both Update cell and Insert patch interior. Each cell runs exactly
321 one of the two, so the task constrains every cell once, after its
323 - exahype2.api.rkfd4.CentralDifferencesWithRungeKutta and its
324 subclass exagrype.api.FD4WithKODissipation: one task after
325 Complete time step and, for IntermediateSteps, one task after each
326 Prepare stage k on the stage input.
328 The scheme's log of the time stepping graph does not show the
329 enforcement. With TEXT or VISUALISATION logging, the routine hence
330 logs the graph once more.
355 stage_input = self._stage_input
358 f
"Solver {self.name}: cannot enforce the CCZ4 constraints for "
359 f
"the numerical scheme {type(scheme).__name__}. Supported are "
360 "exahype2.api.fv.RusanovWithExplicitEuler, "
361 "exahype2.api.fv.RusanovWithOptimisticExplicitEuler and "
362 "exahype2.api.rkfd4.CentralDifferencesWithRungeKutta."
370 time_step, exahype2.api.Solver.SolutionUpdateTaskTag
377 and stage_input
is not None
380 time_step, exahype2.api.Solver.IntermediateSolutionUpdateTag
385 f
"Time stepping task graph for {self.name} with CCZ4 constraint enforcement"
388 time_step.visualise(title=title)
390 time_step.log_as_text(title=title)
394 Tasks of time_step which carry tag and belong to this solver, as the
395 graph holds the tasks of all solvers
399 for task
in time_step.find_tasks(tag)
400 if task.name.startswith(self.
namename +
"_")
406 Insert the enforcement of the CCZ4 constraints after anchors
408 The routine creates a task which applies
409 exagrype::ccz4::enforceCCZ4constraints() to each volume or grid point
410 of patch, and inserts it directly after all anchors via
411 peano4.api.taskgraph.Graph.insert_after(). The anchors' successors,
412 e.g. the projection onto the faces, hence see the constrained data
413 only. The task uses the solver's cell guard: If several anchors
414 write patch, each cell is updated by one of them, and the task runs
415 once per cell after all of them.
417 @param time_step: peano4.api.taskgraph.Graph
418 The time stepping task graph which holds the anchors.
420 @param anchors: List[peano4.api.taskgraph.Task]
421 The tasks which write patch. If the list is empty, the routine
424 @param patch: peano4.api.datamodel.Patch
425 The cell data which the anchors write, i.e. the solution or a
431 anchor_names =
" and ".join(
432 anchor.name[len(self.
namename) + 1 :]
for anchor
in anchors
435 name=f
"{self.name}_Enforce CCZ4 constraints after {anchor_names}",
436 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
439 task.use_cell(patch, peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE)
441 toolbox.blockstructured.api.ApplyPointWiselyToPatch(
443 implementation=
"::exagrype::ccz4::enforceCCZ4constraints(Q);",
444 guard=self.grid_selector.createCellGuard(),
449 time_step.insert_after(anchors, task)
454 The CCZ4 parameters the solver is generated with (read-only copy).
462 The Finite Volume kernels hand over the jump deltaQ along one normal,
463 the fourth-order Finite Differences of exahype2.api.rkfd4 the
464 derivative along one normal times the mesh width,
465 whereas exagrype::ccz4::ncp() expects the gradient along all three
466 directions. We hence embed the jump into an otherwise empty gradient.
470 double deltaQSerialised[NumberOfUnknowns * 3];
471 for (int i = 0; i < NumberOfUnknowns; i++) {
472 deltaQSerialised[i + 0 * NumberOfUnknowns] = 0.0;
473 deltaQSerialised[i + 1 * NumberOfUnknowns] = 0.0;
474 deltaQSerialised[i + 2 * NumberOfUnknowns] = 0.0;
476 deltaQSerialised[i + normal * NumberOfUnknowns] = deltaQ[i];
478 ::exagrype::ccz4::ncp(BTimesDeltaQ, Q, deltaQSerialised, normal, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4mu, CCZ4SO);
484 tarch::memset(S, 0, NumberOfUnknowns * sizeof(double));
485 ::exagrype::ccz4::source(S, Q, CCZ4LapseType, CCZ4ds, CCZ4c, CCZ4e, CCZ4f, CCZ4bs, CCZ4sk, CCZ4xi, CCZ4itau, CCZ4eta, CCZ4k1, CCZ4k2, CCZ4k3, CCZ4SO);
491 ::exagrype::ccz4::maxEigenvalue(Q, normal, CCZ4e, CCZ4ds, CCZ4GLMc, CCZ4GLMd, lambdaMax);
When to push the solution back onto the algebraic CCZ4 constraints.
Solver for the Einstein equations in the first-order CCZ4 formulation.
Dict[str, Union[int, float]] parameters(self)
The CCZ4 parameters the solver is generated with (read-only copy).
generate_solver_realisation(self, exahype2_project, peano_project, setup_simulation, time_step, plot, mesh_adaptation)
Create the solver's task graphs and insert the constraint enforcement.
enforce_ccz4_constraint(self, "CCZ4Solver.EnforceCCZ4Constraint" value)
Set when the solver pushes the solution back onto the CCZ4 constraints.
_enforce_ccz4_constraint
One task after all writers of the new solution: The optimistic Finite Volumes write it in one of two ...
str _ncp_implementation()
The Finite Volume kernels hand over the jump deltaQ along one normal, the fourth-order Finite Differe...
List[str] lopsided_advection_quantities(self)
The unknowns whose advection terms exagrype::ccz4::ncp() omits.
_patch
One task after all writers of the new solution: The optimistic Finite Volumes write it in one of two ...
_tasks_of_this_solver(self, time_step, tag)
Tasks of time_step which carry tag and belong to this solver, as the graph holds the tasks of all sol...
_insert_constraint_enforcement(self, time_step, anchors, patch)
Insert the enforcement of the CCZ4 constraints after anchors.
__init__(self, str name, Dict[str, Union[int, float]] parameters=None, exahype2.api.InitPointWisely initial_condition=None)
Create a CCZ4 solver.
str _source_implementation()
str _max_eigenvalue_implementation()
Point-wise initial condition: given the physical position of a single degree of freedom,...
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
The non-conservative product B(Q) applied to a jump deltaQ in a given direction, i....
Abstract base class for all ExaHyPE 2 solvers.
"Solver.NumericalScheme" numerical_scheme(self)
add_abstract_solver_attribute(self, str declaration)
Add a raw C++ member attribute declaration to the generated Abstract<SolverName> class (.
str _get_default_includes(self)
Includes every generated action set can rely on being available, regardless of which action sets a co...
add_pde_term(self, PDETerm term)
Register a PDE term with this solver, or replace the one already registered under the same name and s...
add_user_solver_includes(self, str value)
Add further includes to this property, if your solver requires some additional routines from other he...
str user_solver_includes(self)
Add further includes to this property, if your solver requires some additional routines from other he...
numerical_scheme(self, "Solver.NumericalScheme" value)
str name(self)
Unique solver name.
The algebraic, volume-distributed source term S(Q) of a hyperbolic PDE - as opposed to PointSource,...
Finite Volumes with a Rusanov Riemann solver and explicit Euler time stepping, realised over a block-...
Finite Volumes with a Rusanov Riemann solver and optimistic explicit Euler time stepping,...
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
Singleton logger for the Peano 4 Python API.
One task within a peano4.api.taskgraph.Graph.
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...