... | ... | @@ -186,13 +186,121 @@ The Toolit will end with `setup build environment ... ok` if it terminated succe |
|
|
Go back to ApplicationExamples/Acoustic/ you should see several automatically generated files:
|
|
|
|
|
|
```sh
|
|
|
ls Acoustic
|
|
|
>
|
|
|
|
|
|
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.
|
|
|
|
|
|
```c++
|
|
|
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.
|
|
|
```math
|
|
|
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 ##.
|
|
|
|
|
|
```c++
|
|
|
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).
|
|
|
|
|
|
```c++
|
|
|
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
|
|
|
|
|
|
```++c
|
|
|
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:
|
|
|
|
|
|
```c++
|
|
|
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
|
|
|
|
|
|
```bash
|
|
|
make -j8
|
|
|
```
|
|
|
|
|
|
After compilation is finished run
|
|
|
|
|
|
```bash
|
|
|
./ExaHyPE_Acoustic acoustic.exahype
|
|
|
```
|
|
|
|
|
|
|
|
|
# Optional: Material Parameters
|
... | ... | |