Skip to content

Commit 6b0f725

Browse files
R-RK: Newton and sub-diagonal schemes only (#2480)
* start working on relaxation RK * start doc * docstrings + clean up * spell out * docstrings, remove secant * examples * tests * typo * increase allowed allocs * typo * test printing/show routines * rename to `u_tmp` * comment * reduce elixirs and tests * rename more explicitly * fmt * document * add sciml base * comments and format * more tests * docs * fix docs * refactor simple ssp * fix * test resize * remove unused resize! * Apply suggestions from code review * Apply suggestions from code review * Update src/time_integration/relaxation_methods/entropy_relaxation.jl * Apply suggestions from code review * Apply suggestions from code review * shorten * test * test vals * fix tet * R-RK: Newton and Sub-Diagonal * fmt * docs * fix * abstract type * remove * restore * fix options * 3d example * fd * take errors into account * fix test * fmt * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/time_integration.md * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * remove sciml * rename to ralston * rename * remove 2d --------- Co-authored-by: Hendrik Ranocha <[email protected]>
1 parent cba534b commit 6b0f725

File tree

12 files changed

+789
-2
lines changed

12 files changed

+789
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ installation and postprocessing procedures. Its features include:
4848
* CFL-based and error-based time step control
4949
* Custom explicit time integration schemes
5050
* Maximized linear stability via paired explicit Runge-Kutta methods
51+
* Relaxation Runge-Kutta methods for entropy-conservative time integration
5152
* Native support for differentiable programming
5253
* Forward mode automatic differentiation via [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl)
5354
* Periodic and weakly-enforced boundary conditions

docs/src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ installation and postprocessing procedures. Its features include:
4444
* CFL-based and error-based time step control
4545
* Custom explicit time integration schemes
4646
* Maximized linear stability via paired explicit Runge-Kutta methods
47+
* Relaxation Runge-Kutta methods for entropy-conservative time integration
4748
* Native support for differentiable programming
4849
* Forward mode automatic differentiation via [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl)
4950
* Periodic and weakly-enforced boundary conditions

docs/src/time_integration.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,91 @@ Then, the stable CFL number can be computed as described above.
215215

216216
- [`Trixi.PairedExplicitRK2`](@ref): Second-order PERK method with at least two stages.
217217
- [`Trixi.PairedExplicitRK3`](@ref): Third-order PERK method with at least three stages.
218-
- [`Trixi.PairedExplicitRK4`](@ref): Fourth-order PERK method with at least five stages.
218+
- [`Trixi.PairedExplicitRK4`](@ref): Fourth-order PERK method with at least five stages.
219+
220+
## Relaxation Runge-Kutta Methods for Entropy-Conservative Time Integration
221+
222+
While standard Runge-Kutta methods (or in fact the whole broad class of general linear methods such as multistep, additive, and partitioned Runge-Kutta methods) preserve linear solution invariants such as mass, momentum and energy, (assuming evolution in conserved variables $\boldsymbol u = (\rho, \rho v_i, \rho e)$) they do in general not preserve nonlinear solution invariants such as entropy.
223+
224+
### The Notion of Entropy
225+
226+
For an ideal gas with isentropic exponent $\gamma$, the thermodynamic entropy is given by
227+
```math
228+
s_\text{therm}(\boldsymbol u) = \ln \left( \frac{p}{\rho^\gamma} \right)
229+
```
230+
where $p$ is the pressure, $\rho$ the density, and $\gamma$ the ratio of specific heats.
231+
The mathematical entropy is then given by
232+
```math
233+
s(\boldsymbol u) \coloneqq - \underbrace{\rho}_{\equiv u_1} \cdot s_\text{therm}(\boldsymbol u) = - \rho \cdot \log \left( \frac{p(\boldsymbol u)}{\rho^\gamma} \right) \: .
234+
```
235+
The total entropy $\eta$ is then obtained by integrating the mathematical entropy $s$ over the domain $\Omega$:
236+
```math
237+
\eta(t) \coloneqq \eta \big(\boldsymbol u(t, \boldsymbol x) \big) = \int_{\Omega} s \big (\boldsymbol u(t, \boldsymbol x) \big ) \, \text{d} \boldsymbol x \tag{1}
238+
```
239+
240+
For a semidiscretized partial differential equation (PDE) of the form
241+
```math
242+
\begin{align*}
243+
\boldsymbol U(t_0) &= \boldsymbol U_0, \\
244+
\boldsymbol U'(t) &= \boldsymbol F\big(t, \boldsymbol U(t) \big) \tag{2}
245+
\end{align*}
246+
```
247+
one can construct a discrete equivalent $H$ to (1) which is obtained by computing the mathematical entropy $s$ at every node of the mesh and then integrating it over the domain $\Omega$ by applying a quadrature rule:
248+
```math
249+
H(t) \coloneqq H\big(\boldsymbol U(t)\big) = \int_{\Omega} s \big(\boldsymbol U(t) \big) \, \text{d} \Omega
250+
```
251+
252+
For a suitable spatial discretization (2) entropy-conservative systems such as the Euler equations preserve the total entropy $H(t)$ over time, i.e.,
253+
```math
254+
\frac{\text{d}}{\text{d} t} H \big(\boldsymbol U(t) \big )
255+
=
256+
\left \langle \frac{\partial H(\boldsymbol U)}{\partial \boldsymbol U}, \frac{\text{d}}{\text{d} t} \boldsymbol U(t) \right \rangle
257+
\overset{(2)}{=}
258+
\left \langle \frac{\partial H(\boldsymbol U)}{\partial \boldsymbol U}, \boldsymbol F\big(t, \boldsymbol U(t) \big) \right \rangle = 0 \tag{3}
259+
```
260+
while entropy-stable discretiations of entropy-diffusive systems such as the Navier-Stokes equations ensure that the total entropy decays over time, i.e.,
261+
```math
262+
\left \langle \frac{\partial H(\boldsymbol U)}{\partial \boldsymbol U}, \boldsymbol F(t, \boldsymbol U) \right \rangle \leq 0 \tag{4}
263+
```
264+
265+
### Ensuring Entropy-Conservation/Stability with Relaxation Runge-Kutta Methods
266+
267+
Evolving the ordinary differential equation (ODE) for the entropy (2) with a Runge-Kutta scheme gives
268+
```math
269+
H_{n+1} = H_n + \Delta t \sum_{i=1}^S b_i \, \left\langle \frac{\partial
270+
H(\boldsymbol U_{n, i})
271+
}{\partial \boldsymbol U}, \boldsymbol F(\boldsymbol U_{n, i}) \right\rangle \tag{5}
272+
```
273+
which preserves (3) and (4).
274+
In practice, however, we evolve the conserved variables $\boldsymbol U$ which results in
275+
```math
276+
\boldsymbol U_{n+1} = \boldsymbol U_n + \Delta t \sum_{i=1}^S b_i \boldsymbol F(\boldsymbol U_{n, i})
277+
```
278+
and in particular for the entropy $H$
279+
```math
280+
H(\boldsymbol U_{n+1}) = H\left( \boldsymbol U_n + \Delta t \sum_{i=1}^S b_i \boldsymbol F(\boldsymbol U_{n, i}) \right) \neq H_{n+1} \text{ computed from (5)}
281+
```
282+
283+
To resolve the difference $H(\boldsymbol U_{n+1}) - H_{n+1}$ Ketcheson, Ranocha and collaborators have introduced *relaxation* Runge-Kutta methods in a series of publications, see for instance
284+
- [Ketcheson (2019)](https://doi.org/10.1137/19M1263662): Relaxation Runge-Kutta Methods: Conservation and Stability for Inner-Product Norms
285+
- [Ranocha et al. (2020)](https://doi.org/10.1137/19M1263480): Relaxation Runge-Kutta methods: Fully discrete explicit entropy-stable schemes for the compressible Euler and Navier-Stokes equations
286+
- [Ranocha, Lóczi, and Ketcheson (2020)](https://doi.org/10.1007/s00211-020-01158-4): General relaxation methods for initial-value problems with application to multistep schemes
287+
288+
Almost miraculously, it suffices to introduce a single parameter $\gamma$ in the final update step of the Runge-Kutta method to ensure that the properties of the spatial discretization are preserved, i.e.,
289+
```math
290+
H \big(\boldsymbol U_{n+1}( \gamma ) \big)
291+
\overset{!}{=}
292+
H(\boldsymbol U_n) +
293+
\gamma \Delta t \sum_{i=1}^S b_i
294+
\left \langle
295+
\frac{\partial H(\boldsymbol U_{n, i})}{\partial \boldsymbol U_{n, i}}, \boldsymbol F(\boldsymbol U_{n, i})
296+
\right \rangle
297+
\tag{6}
298+
```
299+
This comes only at the price that one needs to solve the scalar nonlinear equation (6) for $\gamma$ at every time step.
300+
To do so, [`Trixi.RelaxationSolverNewton`](@ref) is implemented in Trixi.jl.
301+
These can then be supplied to the relaxation time algorithms such as [`Trixi.RelaxationRalston3`](@ref) and [`Trixi.RelaxationRK44`](@ref) via specifying the `relaxation_solver` keyword argument:
302+
```julia
303+
ode_algorithm = Trixi.RelaxationRK44(solver = Trixi.RelaxationSolverNewton())
304+
ode_algorithm = Trixi.RelaxationRalston3(solver = Trixi.RelaxationSolverNewton())
305+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Trixi
2+
3+
###############################################################################
4+
# semidiscretization of the compressible Euler equations
5+
6+
equations = CompressibleEulerEquations1D(1.4)
7+
8+
# Volume flux stabilizes the simulation - in contrast to standard DGSEM with
9+
# `surface_flux = flux_ranocha` only which crashes.
10+
solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha,
11+
volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha))
12+
13+
coordinates_min = -2.0
14+
coordinates_max = 2.0
15+
cells_per_dimension = 32
16+
mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max)
17+
18+
initial_condition = initial_condition_weak_blast_wave
19+
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)
20+
21+
###############################################################################
22+
# ODE solvers, callbacks etc.
23+
24+
tspan = (0.0, 1.0)
25+
ode = semidiscretize(semi, tspan)
26+
27+
summary_callback = SummaryCallback()
28+
29+
analysis_interval = 1
30+
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
31+
analysis_errors = Symbol[], # Switch off error computation
32+
# Note: `entropy` defaults to mathematical entropy
33+
analysis_integrals = (entropy,),
34+
analysis_filename = "entropy_ER.dat",
35+
save_analysis = true)
36+
37+
stepsize_callback = StepsizeCallback(cfl = 0.25)
38+
39+
callbacks = CallbackSet(summary_callback,
40+
analysis_callback,
41+
stepsize_callback)
42+
43+
###############################################################################
44+
# run the simulation
45+
46+
# Ensure exact entropy conservation by employing a relaxation Runge-Kutta method
47+
relaxation_solver = Trixi.RelaxationSolverNewton(max_iterations = 5,
48+
root_tol = eps(Float64),
49+
gamma_tol = eps(Float64))
50+
ode_alg = Trixi.RelaxationRK44(relaxation_solver = relaxation_solver)
51+
52+
sol = Trixi.solve(ode, ode_alg,
53+
dt = 42.0, save_everystep = false, callback = callbacks);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Trixi
2+
3+
###############################################################################
4+
# semidiscretization of the linear advection equation
5+
6+
advection_velocity = (1.0, 1.0, 1.0)
7+
equations = LinearScalarAdvectionEquation3D(advection_velocity)
8+
9+
solver = DGSEM(polydeg = 2, surface_flux = flux_central,
10+
volume_integral = VolumeIntegralFluxDifferencing(flux_central)) # Entropy-conservative setup
11+
12+
coordinates_min = (-1.0, -1.0, -1.0)
13+
coordinates_max = (1.0, 1.0, 1.0)
14+
# Create a uniformly refined mesh with periodic boundaries
15+
mesh = TreeMesh(coordinates_min, coordinates_max,
16+
initial_refinement_level = 3,
17+
n_cells_max = 30_000)
18+
19+
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test,
20+
solver)
21+
22+
###############################################################################
23+
# ODE solvers, callbacks etc.
24+
25+
ode = semidiscretize(semi, (0.0, 1.0))
26+
27+
summary_callback = SummaryCallback()
28+
29+
analysis_interval = 1
30+
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
31+
analysis_errors = Symbol[], # Switch off error computation
32+
# Note: `entropy` defaults to mathematical entropy
33+
analysis_integrals = (entropy,),
34+
analysis_filename = "entropy_ER.dat",
35+
save_analysis = true)
36+
37+
stepsize_callback = StepsizeCallback(cfl = 1.0)
38+
39+
callbacks = CallbackSet(summary_callback, analysis_callback,
40+
stepsize_callback)
41+
42+
###############################################################################
43+
# run the simulation
44+
45+
relaxation_solver = Trixi.RelaxationSolverNewton(max_iterations = 3,
46+
root_tol = eps(Float64),
47+
gamma_tol = eps(Float64))
48+
ode_alg = Trixi.RelaxationRalston3(relaxation_solver = relaxation_solver)
49+
50+
sol = Trixi.solve(ode, ode_alg,
51+
dt = 42.0, save_everystep = false, callback = callbacks);

0 commit comments

Comments
 (0)