Before starting with this guide please make sure that ExaHyPE has been installed correctly by following the installation guide.
The acoustic wave equation
The acoustic wave equation describes the propagation of an wave through a material. This
equation assumes that all movements are only small perturbations over the background flow
field. They can be obtained by linearizing the more general Euler equations over this back
ground field. This clearly cannot work for complex flows, e.g. for supersonic “booms”.
We describe our material by the parameters K_0
, which is the socalled bulkmodulus and by
the density \rho_0
. We solve here for velocity v
and pressure p
in one dimension
\partial_t \begin{pmatrix}
v_x\\v_y\\p
\end{pmatrix}
+ \nabla F
\begin{pmatrix}
v_x\\v_y\\p
\end{pmatrix} = 0,
where v_x, v_y
denote the velocity in $x$ and $y$direction respectively.
Further, the flux is given by:
F = \left[
\begin{pmatrix}
0 & 0 & \frac{1}{\rho_0}\\
0 & 0 & 0 \\
K_0 & 0 & 0
\end{pmatrix} ,
\begin{pmatrix}
0 & 0 & 0\\
0 & 0 & \frac{1}{\rho_0}\\
0 & K_0 & 0
\end{pmatrix} \right],
These equations are telling us that the change in time of the velocity is proportional to the gradient of pressure.
Step 1: Setting up a specification file
The first step to writing an ExaHyPE application users is a specification file. The specification file is passed to the ExaHyPE toolkit, which creates glue code, empty applicationspecific classes and optionally application and architecture tailored core routines. In the next step these application specific classes will be filled with the PDE terms.
Let's start from a template for an ADERDG specification file:
exahypeproject ##Name
/*Set paths*/
peanokernelpath const = ./Peano
exahypepath const = ./ExaHyPE
outputdirectory const = ./ApplicationExamples/Acoustic
architecture const = noarch
logfile = mylogfile.log
plottersubdirectory const = Writers
/*Configure the domain*/
computationaldomain
dimension const = ##dimensions
width = ##domain width
offset = ##offset
endtime = ##final time
end computationaldomain
/*Configure shared memory settings*/
/*sharedmemory
identifier = dummy
configure = {backgroundtasks:8}
cores = 8
propertiesfile = sharedmemory.properties
end sharedmemory*/
/*Optimiziation: DO N0T TOUCH*/
globaloptimisation
fusealgorithmicsteps = all
fusealgorithmicstepsrerunfactor = 0.99
fusealgorithmicstepsdiffusionfactor = 0.99
spawnpredictorasbackgroundthread = off
spawnamrbackgroundthreads = off
/* 0.0 und 0.8 sind schon mal zwei Faktoren */
disablevertexexchangeintimesteps = on
timestepbatchfactor = 0.0
disablemetadataexchangeinbatchedtimesteps = off
doublecompression = 0.0
spawndoublecompressionasbackgroundthread = off
end globaloptimisation
/*Defines the hyperbolic PDE*/
solver ADERDG ADERSolver
variables const = ##variables
order const = ##polynomial order of the simulation
maximummeshsize = ##mesh size
timestepping = globalfixed
type const = nonlinear
terms const = ##PDE terms, ie fluxes, sources etc
optimisation const = generic
language const = C
/*##Add plotters here if needed */
/*plot vtk::Cartesian::vertices::ascii VtkWriter
variables const = ##Number of variables to be plotted
time = ##Start time of the plotter
repeat = ##Plotting interval
output = ##File suffix
end plot */
end solver
end exahypeproject
Set up a new directory Acoustic in ApplicationExamples to hold the new acoustic application. Copy the template above there and name it acoustic.exahype.
In this file all place holders are marked by ## and need to be filled to get a working application. All other options are only used for optimizations and don't need to be touched or understood for now. When you want to begin optimizing your application the Guidebook gives a detailed overview of the options.
For now let's go through the place holders one by one and fill them in:
exahypeproject ##Name
 The name of the project. Choose something short to name your project, e.g. Acoustic.
exahypeproject Acoustic
outputdirectory const
 Defines where the the code body will be generated relative to the root directory
 In our case we use ./ApplicationExamples/Acoustic
outputdirectory const = ./ApplicationExamples/Acoustic
computationaldomain
 Here we define the number of dimensions, the simulated domain and the physical end time of the application
 The acoustic equations can be defined in two or three dimensions. We want to work in 2 dimensions to start with. Let's define our simulation on the cube
[0.5,0.5]^2
and for one second. Thus, our domain is of size 1.0 and needs to be offset by 0.5 in each direction.
computationaldomain
dimension const = 2
width = 1.0, 1.0
offset = 0.5, 0.5
endtime = 1.0
end computationaldomain
solver ADERDG
...
 This region defines the characteristics both of the simulated PDE and of the used solver.

variables const
By looking at the equation we are solving you see that the acoustic wave equation consists of 2 quantities the vectorvalued velocityv
and pressurep
. 
order const
The polynomial degree of the high order representation. We'll use order 3 for now. 
maximummeshsize
The maximum size of a single cell. ExaHyPE always has to hold a power of 3 cells in one dimension^{1}. By setting this value you define an lower limit for the number of cells which is the rounded up to the next power of 3. For our example settingmaximummeshsize
to 0.05 gives us a theoretical number of 20 cells in one dimension. The next power of three is 27, so our mesh will end up with 27 cells in each dimension and a mesh size of\frac{1}{27}
. 
type const
Here you can choose between a linear or nonlinear PDE. The acoustic wave equation is a linear PDE so we set linear here. 
terms const
The type of terms that occur in the PDE system. For the acoustic wave equation will only require a flux. We could also add source terms, nonconservative products or material matrices to the application.
solver ADERDG SWE_ADERDG
variables const = v:2,p:1
order const = 3
/* 27 points: 0.05, 9 points: 0.15 */
maximummeshsize = 0.05
timestepping = globalfixed
type const = linear
terms const = flux
optimisation const = generic
language const = C
end solver
^{1} The ExaHyPE core relies on the Peano framework for its dynamically adaptive Cartesian meshes. This framework creates treestructured cartesian meshes by subdividing the element into threes.
Adding a plotter
 In this example we add a simple vtk output plotter which is sufficient for our needs.
 Uncomment the plotter lines after
language const
and beforeend solver
and fill in the missing information:
plot vtk::Cartesian::vertices::ascii VtkWriter
variables const = 2
time = 0.0
repeat = 1e2
output = ./acoustic
end plot
 This results in a writer plotting both variables every 0.02 seconds starting at time 0. The files will have a prefix acoustic and be placed in the project directory. If you add a path it will place them into a directory instead. In this case make sure the directory exists before running the code.
Step 2: Run the Toolkit
To generate the code body apply the toolkit to the specification file we just created. Go back to the ExaHyPE root directory and hit :
./Toolkit/toolkit.sh ApplicationExamples/Acoustic/acoustic.exahype
The Toolit will end with setup build environment ... ok
if it terminated successful, else you'll receive a detailed error message.
Go back to ApplicationExamples/Acoustic/ you should see several automatically generated files:
ls
> AbstractADERSolver.cpp ADERSolver.cpp KernelCalls.cpp Writers
AbstractADERSolver.h ADERSolver.h Makefile
acoustic.exahype ADERSolver_Variables.h README_generated.md
Step 3: Write the PDE terms to complete the user solver
The PDE system is implemented in ADERSolver.cpp. If you take look at the corresponding header (ADERSolver.h) you see the functions you'll need to specify the PDE.
void adjustPointSolution(const double* const x,const double t,const double dt,double* const Q) final override;
void eigenvalues(const double* const Q,const int direction,double* const lambda) final override;
void boundaryValues(const double* const x,const double t,const double dt,const int faceIndex,const int direction,const double * const fluxIn,const double* const stateIn, const double* const gradStateIn,double *fluxOut,double* stateOut) final override;
void flux(const double* const Q,double** const F) final override;
Flux implementation and Variables class
We'll start with the implementation of the flux. To make things easier ExaHyPE comes with a nice way to directly work with symbolic variables. You can access all arrays that hold state or flux variables with the mathematical notation you defined in the specification.
We evolve the last two terms of the flux to matrix vector products as it simplifies the implementation.
F = \left[
\begin{pmatrix}
0 & 0 & \frac{1}{\rho_0}\\
0 & 0 & 0 \\
K_0 & 0 & 0
\end{pmatrix} ,
\begin{pmatrix}
0 & 0 & 0\\
0 & 0 & \frac{1}{\rho_0}\\
0 & K_0 & 0
\end{pmatrix} \right],
By using symbolic variables and upper definition of the flux we can implement the method. Here the actual implementation is left to you and marked with ##.
void Acoustic::ADERSolver::flux(const double* const Q,double** F) {
ReadOnlyVariables vars(Q);
Fluxes f(F);
f.v(##Flux for velocities);
f.p(##Flux for pressure);
}
Eigenvalues
The eigenvalues can directly be taken from upper mathematical formulation. They need to passed with respect to the dimension defined by the argument const int d
. For d=0
in x and d=1
in y (in 3D we additionally get d=2
in z).
void Acoustic::ADERSolver::eigenvalues(const double* const Q,const int d,double* lambda) {
ReadOnlyVariables vars(Q);
Variables eigs(lambda);
double u = vars.p(direction)/vars.h();
double c = std::sqrt(vars.h());
eigs.v(0) = ##eigenvalue;
eigs.v(1) = ##eigenvalue;
eigs.p() = ##eigenvalue;
}
By default only the largest eigenvalue is needed. This is due to the very basic Riemann solver used by default. If using a custom Riemann solver you may need more than just the largest eigenvalue.
Initial Values
void Acoustic::ADERSolver::adjustPointSolution(const double* const x,const double t,const double dt,double* Q) {
Variables vars(Q) ;
if (tarch::la::equals(t,0.0)) {
vars.v(0) = 0.0;
vars.v(1) = 0.0;
vars.p() = exp( 100 * (x[0]  0.5)^2  100 *(x[1]  0.5)^2);
}
}
Boundary Conditions
This method implements conditions that are applied along the boundary of the domain.
The engine passes the fields stateIn
and fluxIn
which hold the respective state and flux of the simulated domain.
In this short example we implement reflecting boundary conditions. For SWE this means we have to invert the velocity vector along the normal of the interface. As our mesh is Cartesian, the normal can be defined by the single index where it is one const int normalNonZero
.
The state can then be inverted by:
void Acoustic::ADERSolver::boundaryValues(const double* const x,const double t,const double dt,const int faceIndex,const int direction,
const double * const fluxIn,const double* const stateIn, double *fluxOut,double* stateOut) {
// Dimensions = 2
// Number of variables + parameters = 3 + 0
ReadOnlyVariables in(stateIn) ;
Variables out(stateOut);
out.v(0) = in.v(0);
out.v(1) = in.v(1);
out.p() = in.p();
out.v(direction)= in.v(direction);
\\....
Step 4: Compile & Run the program
After all methods are filled you can compile the program by running
make j8
After compilation is finished run
./ExaHyPE_Acoustic acoustic.exahype
Optional: Material Parameters
This equation becomes much more interesting, if we add material parameters that can vary in space.
 That means, that we need to use
\rho_0(x,y,z)
instead of just one constant\rho_0
.  They are not allowed to vary in time. Once we have chosen a material, the material stays the same.
 In ExaHyPE there is the possibility to add parameters directly in the specification file.