From 14151e636ef654cb5421b3a7e498a9d76ed46a64 Mon Sep 17 00:00:00 2001 From: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:49:51 +0100 Subject: [PATCH 01/27] Add entry for gmsh tutorial in introduction (#1829) * add entry for gmsh tutorial in introduction * Update docs/literate/src/files/index.jl --------- Co-authored-by: Daniel Doehring Co-authored-by: Daniel Doehring --- docs/literate/src/files/index.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/literate/src/files/index.jl b/docs/literate/src/files/index.jl index e259d25fb2f..26637e5b24b 100644 --- a/docs/literate/src/files/index.jl +++ b/docs/literate/src/files/index.jl @@ -108,20 +108,26 @@ # software in the Trixi.jl ecosystem, and then run a simulation using Trixi.jl on said mesh. # In the end, the tutorial briefly explains how to simulate an example using AMR via `P4estMesh`. -# ### [15 Explicit time stepping](@ref time_stepping) +# ### [15 P4est mesh from gmsh](@ref p4est_from_gmsh) +#- +# This tutorial describes how to obtain a [`P4estMesh`](@ref) from an existing mesh generated +# by [`gmsh`](https://gmsh.info/) or any other meshing software that can export to the Abaqus +# input `.inp` format. The tutorial demonstrates how edges/faces can be associated with boundary conditions based on the physical nodesets. + +# ### [16 Explicit time stepping](@ref time_stepping) #- # This tutorial is about time integration using [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl). # It explains how to use their algorithms and presents two types of time step choices - with error-based # and CFL-based adaptive step size control. -# ### [16 Differentiable programming](@ref differentiable_programming) +# ### [17 Differentiable programming](@ref differentiable_programming) #- # This part deals with some basic differentiable programming topics. For example, a Jacobian, its # eigenvalues and a curve of total energy (through the simulation) are calculated and plotted for # a few semidiscretizations. Moreover, we calculate an example for propagating errors with Measurement.jl # at the end. -# ### [17 Custom semidiscretization](@ref custom_semidiscretization) +# ### [18 Custom semidiscretization](@ref custom_semidiscretization) #- # This tutorial describes the [semidiscretiations](@ref overview-semidiscretizations) of Trixi.jl # and explains how to extend them for custom tasks. From 5fec7f42121be7d01d8645fc91fe0da8567f3946 Mon Sep 17 00:00:00 2001 From: ArseniyKholod <119304909+ArseniyKholod@users.noreply.github.com> Date: Tue, 6 Feb 2024 20:52:50 +0100 Subject: [PATCH 02/27] Getting started with trixi (#1343) * 0th tutorial v1 * 0th tutorial v2 * 0th tutorial v3 (topic for developers) * 0th tutorial v4 * 0th tutorial v5 * 0th tutorial v6 * 0th tutorial v6.1 * 0th tutorial v6.2 * 0th tutorial v7 (new example) * 0th tutorial v8 * 0th tutorial v8.1 * 0th tutorial v9 New structure + new usage example * 0th tutorial v9.1 * 0th tutorial v9.2 * Revert "0th tutorial v9.2" This reverts commit e2da5c24c71ec5ebb86ead4da9e6dc33f8b2cf7f. * 0th tutorial v9.3 (test) * Revert "0th tutorial v9.3 (test)" This reverts commit 05d3d1c22729fc65f6a85bc224e0376bf7cc79ac. * 0th tutorial v9.3 (test) * 0th tutorial v9.3 (test checks without diff. prog.) * 0th tutorial v9.3 (test new diff. prog.) * 0th tutorial v9.3 (test new diff. prog. v2) * 0th tutorial v9.3 (test update of packages) * 0th tutorial v9.3 (test update of packages v2) * 0th tutorial v9.3 (downgrade Measurements.jl) * 0th tutorial v9.4 * 0th tutorial v9.5 * 0th tutorial review * 0th tutorial review 2 * 0th tutorial v9.6 * delete test files * Revert "rename into getting_started.jl" This reverts commit 6605ece69240d8bc850c6ef0b14b94beaac5eee6. * Update docs/make.jl Co-authored-by: Michael Schlottke-Lakemper * Update Project.toml Co-authored-by: Michael Schlottke-Lakemper * Update Project.toml Co-authored-by: Michael Schlottke-Lakemper * Update docs/make.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * rename into getting_started.jl * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started_with_Trixi.jl Co-authored-by: Michael Schlottke-Lakemper * correction of spelling errors * cleaning out directory * Correction according to the comments above * Trixi installation for Linux * Update getting_started.jl * cross-referencing correction * spelling * Update .gitignore Co-authored-by: Michael Schlottke-Lakemper * Update docs/make.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update .gitignore * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * new plot in Modifying an existing setup * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * julia/shell-formatting * Update getting_started.jl * Update getting_started.jl * Correction of Modifying part * Usage update * Update getting_started.jl * add Visualize the solution * spell check * correction * correction * add picture paraview * divide in two parts & correction * divide in 3 parts * Update docs/literate/src/files/getting_started.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update create_first_setup.jl * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update getting_started.jl * Update getting_started.jl * Update create_first_setup.jl * Update changing_trixi.jl * Update changing_trixi.jl * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/getting_started.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * move files to subfolder * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update create_first_setup.jl * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/create_first_setup.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/changing_trixi.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/changing_trixi.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/changing_trixi.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/changing_trixi.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * Update docs/literate/src/files/changing_trixi.jl Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> * add transition between 2nd and 3rd parts * Update docs/make.jl Co-authored-by: Michael Schlottke-Lakemper * clear out folder * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update getting_started.jl * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/getting_started.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update getting_started.jl * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update create_first_setup.jl * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update create_first_setup.jl * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * spelling * delete julia, tabs * add juliaup * add intro * rm * Apply suggestions from code review Co-authored-by: Daniel Doehring * Apply suggestions from code review Co-authored-by: Daniel Doehring * Update docs/literate/src/files/first_steps/getting_started.jl * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/first_steps/changing_trixi.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/first_steps/create_first_setup.jl Co-authored-by: Andrew Winters * add save solution dt --------- Co-authored-by: Michael Schlottke-Lakemper Co-authored-by: Simon Candelaresi <10759273+SimonCan@users.noreply.github.com> Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com> Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Co-authored-by: Daniel Doehring Co-authored-by: Andrew Winters --- .../src/files/first_steps/changing_trixi.jl | 77 +++++ .../files/first_steps/create_first_setup.jl | 268 ++++++++++++++++++ .../src/files/first_steps/getting_started.jl | 242 ++++++++++++++++ docs/literate/src/files/index.jl | 43 +-- docs/make.jl | 6 + 5 files changed, 618 insertions(+), 18 deletions(-) create mode 100644 docs/literate/src/files/first_steps/changing_trixi.jl create mode 100644 docs/literate/src/files/first_steps/create_first_setup.jl create mode 100644 docs/literate/src/files/first_steps/getting_started.jl diff --git a/docs/literate/src/files/first_steps/changing_trixi.jl b/docs/literate/src/files/first_steps/changing_trixi.jl new file mode 100644 index 00000000000..551377a6a71 --- /dev/null +++ b/docs/literate/src/files/first_steps/changing_trixi.jl @@ -0,0 +1,77 @@ +#src # Changing Trixi.jl itself + +# If you plan on editing Trixi.jl itself, you can download Trixi.jl locally and run it from +# the cloned directory. + + +# ## Cloning Trixi.jl + + +# ### Windows + +# If you are using Windows, you can clone Trixi.jl by using the GitHub Desktop tool: +# - If you do not have a GitHub account yet, create it on +# the [GitHub website](https://github.com/join). +# - Download and install [GitHub Desktop](https://desktop.github.com/) and then log in to +# your account. +# - Open GitHub Desktop, press `Ctrl+Shift+O`. +# - In the opened window, paste `trixi-framework/Trixi.jl` and choose the path to the folder where +# you want to save Trixi.jl. Then click `Clone` and Trixi.jl will be cloned to your computer. + +# Now you cloned Trixi.jl and only need to tell Julia to use the local clone as the package sources: +# - Open a terminal using `Win+r` and `cmd`. Navigate to the folder with the cloned Trixi.jl using `cd`. +# - Create a new directory `run`, enter it, and start Julia with the `--project=.` flag: +# ```shell +# mkdir run +# cd run +# julia --project=. +# ``` +# - Now run the following commands to install all relevant packages: +# ```julia +# using Pkg; Pkg.develop(PackageSpec(path="..")) # Tell Julia to use the local Trixi.jl clone +# Pkg.add(["OrdinaryDiffEq", "Plots"]) # Install additional packages +# ``` + +# Now you already installed Trixi.jl from your local clone. Note that if you installed Trixi.jl +# this way, you always have to start Julia with the `--project` flag set to your `run` directory, +# e.g., +# ```shell +# julia --project=. +# ``` +# if already inside the `run` directory. + + +# ### Linux + +# You can clone Trixi.jl to your computer by executing the following commands: +# ```shell +# git clone git@github.com:trixi-framework/Trixi.jl.git +# # If an error occurs, try the following: +# # git clone https://github.com/trixi-framework/Trixi.jl +# cd Trixi.jl +# mkdir run +# cd run +# julia --project=. -e 'using Pkg; Pkg.develop(PackageSpec(path=".."))' # Tell Julia to use the local Trixi.jl clone +# julia --project=. -e 'using Pkg; Pkg.add(["OrdinaryDiffEq", "Plots"])' # Install additional packages +# ``` +# Note that if you installed Trixi.jl this way, +# you always have to start Julia with the `--project` flag set to your `run` directory, e.g., +# ```shell +# julia --project=. +# ``` +# if already inside the `run` directory. + + +# ## Additional reading + +# To further delve into Trixi.jl, you may have a look at the following introductory tutorials. +# - [Introduction to DG methods](@ref scalar_linear_advection_1d) will teach you how to set up a +# simple way to approximate the solution of a hyperbolic partial differential equation. It will +# be especially useful to learn about the +# [Discontinuous Galerkin method](https://en.wikipedia.org/wiki/Discontinuous_Galerkin_method) +# and the way it is implemented in Trixi.jl. +# - [Adding a new scalar conservation law](@ref adding_new_scalar_equations) and +# [Adding a non-conservative equation](@ref adding_nonconservative_equation) +# describe how to add new physics models that are not yet included in Trixi.jl. +# - [Callbacks](@ref callbacks-id) gives an overview of how to regularly execute specific actions +# during a simulation, e.g., to store the solution or adapt the mesh. diff --git a/docs/literate/src/files/first_steps/create_first_setup.jl b/docs/literate/src/files/first_steps/create_first_setup.jl new file mode 100644 index 00000000000..906a6f93461 --- /dev/null +++ b/docs/literate/src/files/first_steps/create_first_setup.jl @@ -0,0 +1,268 @@ +#src # Create first setup + +# In this part of the introductory guide, we will create a first Trixi.jl setup as an extension of +# [`elixir_advection_basic.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_advection_basic.jl). +# Since Trixi.jl has a common basic structure for the setups, you can create your own by extending +# and modifying the following example. + +# Let's consider the linear advection equation for a state ``u = u(x, y, t)`` on the two-dimensional spatial domain +# ``[-1, 1] \times [-1, 1]`` with a source term +# ```math +# \frac{\partial}{\partial t}u + \frac{\partial}{\partial x} (0.2 u) - \frac{\partial}{\partial y} (0.7 u) = - 2 e^{-t} +# \sin\bigl(2 \pi (x - t) \bigr) \sin\bigl(2 \pi (y - t) \bigr), +# ``` +# with the initial condition +# ```math +# u(x, y, 0) = \sin\bigl(\pi x \bigr) \sin\bigl(\pi y \bigr), +# ``` +# and periodic boundary conditions. + +# The first step is to create and open a file with the .jl extension. You can do this with your +# favorite text editor (if you do not have one, we recommend [VS Code](https://code.visualstudio.com/)). +# In this file you will create your setup. + +# To be able to use functionalities of Trixi.jl, you always need to load Trixi.jl itself +# and the [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) package. + +using Trixi +using OrdinaryDiffEq + +# The next thing to do is to choose an equation that is suitable for your problem. To see all the +# currently implemented equations, take a look at +# [`src/equations`](https://github.com/trixi-framework/Trixi.jl/tree/main/src/equations). +# If you are interested in adding a new physics model that has not yet been implemented in +# Trixi.jl, take a look at the tutorials +# [Adding a new scalar conservation law](@ref adding_new_scalar_equations) or +# [Adding a non-conservative equation](@ref adding_nonconservative_equation). + +# The linear scalar advection equation in two spatial dimensions +# ```math +# \frac{\partial}{\partial t}u + \frac{\partial}{\partial x} (a_1 u) + \frac{\partial}{\partial y} (a_2 u) = 0 +# ``` +# is already implemented in Trixi.jl as +# [`LinearScalarAdvectionEquation2D`](@ref), for which we need to define a two-dimensional parameter +# `advection_velocity` describing the parameters ``a_1`` and ``a_2``. Appropriate for our problem is `(0.2, -0.7)`. + +advection_velocity = (0.2, -0.7) +equations = LinearScalarAdvectionEquation2D(advection_velocity) + +# To solve our problem numerically using Trixi.jl, we have to discretize the spatial +# domain, for which we set up a mesh. One of the most used meshes in Trixi.jl is the +# [`TreeMesh`](@ref). The spatial domain used is ``[-1, 1] \times [-1, 1]``. We set an initial number +# of elements in the mesh using `initial_refinement_level`, which describes the initial number of +# hierarchical refinements. In this simple case, the total number of elements is `2^initial_refinement_level` +# throughout the simulation. The variable `n_cells_max` is used to limit the number of elements in the mesh, +# which cannot be exceeded when using [adaptive mesh refinement](@ref Adaptive-mesh-refinement). + +# All minimum and all maximum coordinates must be combined into `Tuples`. + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 30_000) + +# To approximate the solution of the defined model, we create a [`DGSEM`](@ref) solver. +# The solution in each of the recently defined mesh elements will be approximated by a polynomial +# of degree `polydeg`. For more information about discontinuous Galerkin methods, +# check out the [Introduction to DG methods](@ref scalar_linear_advection_1d) tutorial. + +solver = DGSEM(polydeg=3) + +# Now we need to define an initial condition for our problem. All the already implemented +# initial conditions for [`LinearScalarAdvectionEquation2D`](@ref) can be found in +# [`src/equations/linear_scalar_advection_2d.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/src/equations/linear_scalar_advection_2d.jl). +# If you want to use, for example, a Gaussian pulse, it can be used as follows: +# ```julia +# initial_conditions = initial_condition_gauss +# ``` +# But to show you how an arbitrary initial condition can be implemented in a way suitable for +# Trixi.jl, we define our own initial conditions. +# ```math +# u(x, y, 0) = \sin\bigl(\pi x \bigr) \sin\bigl(\pi y \bigr). +# ``` +# The initial conditions function must take spatial coordinates, time and equation as arguments +# and returns an initial condition as a statically sized vector `SVector`. Following the same structure, you +# can define your own initial conditions. The time variable `t` can be unused in the initial +# condition, but might also be used to describe an analytical solution if known. If you use the +# initial condition as analytical solution, you can analyze your numerical solution by computing +# the error, see also the +# [section about analyzing the solution](https://trixi-framework.github.io/Trixi.jl/stable/callbacks/#Analyzing-the-numerical-solution). + +function initial_condition_sinpi(x, t, equations::LinearScalarAdvectionEquation2D) + scalar = sinpi(x[1]) * sinpi(x[2]) + return SVector(scalar) +end +initial_condition = initial_condition_sinpi + +# The next step is to define a function of the source term corresponding to our problem. +# ```math +# f(u, x, y, t) = - 2 e^{-t} \sin\bigl(2 \pi (x - t) \bigr) \sin\bigl(2 \pi (y - t) \bigr) +# ``` +# This function must take the state variable, the spatial coordinates, the time and the +# equation itself as arguments and returns the source term as a static vector `SVector`. + +function source_term_exp_sinpi(u, x, t, equations::LinearScalarAdvectionEquation2D) + scalar = - 2 * exp(-t) * sinpi(2*(x[1] - t)) * sinpi(2*(x[2] - t)) + return SVector(scalar) +end + +# Now we collect all the information that is necessary to define a spatial discretization, +# which leaves us with an ODE problem in time with a span from 0.0 to 1.0. +# This approach is commonly referred to as the method of lines. + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; + source_terms = source_term_exp_sinpi) +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan); + +# At this point, our problem is defined. We will use the `solve` function defined in +# [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) to get the solution. +# OrdinaryDiffEq.jl gives us the ability to customize the solver +# using callbacks without actually modifying it. Trixi.jl already has some implemented +# [Callbacks](@ref callbacks-id). The most widely used callbacks in Trixi.jl are +# [step control callbacks](https://docs.sciml.ai/DiffEqCallbacks/stable/step_control/) that are +# activated at the end of each time step to perform some actions, e.g. to print statistics. +# We will show you how to use some of the common callbacks. + +# To print a summary of the simulation setup at the beginning +# and to reset timers we use the [`SummaryCallback`](@ref). +# When the returned callback is executed directly, the current timer values are shown. + +summary_callback = SummaryCallback() + +# We also want to analyze the current state of the solution in regular intervals. +# The [`AnalysisCallback`](@ref) outputs some useful statistical information during the solving process +# every `interval` time steps. + +analysis_callback = AnalysisCallback(semi, interval = 5) + +# It is also possible to control the time step size using the [`StepsizeCallback`](@ref) if the time +# integration method isn't adaptive itself. To get more details, look at +# [CFL based step size control](@ref CFL-based-step-size-control). + +stepsize_callback = StepsizeCallback(cfl = 1.6) + +# To save the current solution in regular intervals we use the [`SaveSolutionCallback`](@ref). +# We would like to save the initial and final solutions as well. The data +# will be saved as HDF5 files located in the `out` folder. Afterwards it is possible to visualize +# a solution from saved files using Trixi2Vtk.jl and ParaView, which is described below in the +# section [Visualize the solution](@ref Visualize-the-solution). + +save_solution = SaveSolutionCallback(interval = 5, + save_initial_solution = true, + save_final_solution = true) + +# Alternatively, we have the option to print solution files at fixed time intervals. +# ```julua +# save_solution = SaveSolutionCallback(dt = 0.1, +# save_initial_solution = true, +# save_final_solution = true) +# ``` + +# Another useful callback is the [`SaveRestartCallback`](@ref). It saves information for restarting +# in regular intervals. We are interested in saving a restart file for the final solution as +# well. To perform a restart, you need to configure the restart setup in a special way, which is +# described in the section [Restart simulation](@ref restart). + +save_restart = SaveRestartCallback(interval = 100, save_final_restart = true) + +# Create a `CallbackSet` to collect all callbacks so that they can be passed to the `solve` +# function. + +callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback, save_solution, + save_restart) + +# The last step is to choose the time integration method. OrdinaryDiffEq.jl defines a wide range of +# [ODE solvers](https://docs.sciml.ai/DiffEqDocs/latest/solvers/ode_solve/), e.g. +# `CarpenterKennedy2N54(williamson_condition = false)`. We will pass the ODE +# problem, the ODE solver and the callbacks to the `solve` function. Also, to use +# `StepsizeCallback`, we must explicitly specify the initial trial time step `dt`, the selected +# value is not important, because it will be overwritten by the `StepsizeCallback`. And there is no +# need to save every step of the solution, we are only interested in the final result. + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), dt = 1.0, + save_everystep = false, callback = callbacks); + +# Finally, we print the timer summary. + +summary_callback() + +# Now you can plot the solution as shown below, analyze it and improve the stability, accuracy or +# efficiency of your setup. + + +# ## Visualize the solution + +# In the previous part of the tutorial, we calculated the final solution of the given problem, now we want +# to visualize it. A more detailed explanation of visualization methods can be found in the section +# [Visualization](@ref visualization). + + +# ### Using Plots.jl + +# The first option is to use the [Plots.jl](https://github.com/JuliaPlots/Plots.jl) package +# directly after calculations, when the solution is saved in the `sol` variable. We load the +# package and use the `plot` function. + +using Plots +plot(sol) + +# To show the mesh on the plot, we need to extract the visualization data from the solution as +# a [`PlotData2D`](@ref) object. Mesh extraction is possible using the [`getmesh`](@ref) function. +# Plots.jl has the `plot!` function that allows you to modify an already built graph. + +pd = PlotData2D(sol) +plot!(getmesh(pd)) + + +# ### Using Trixi2Vtk.jl + +# Another way to visualize a solution is to extract it from a saved HDF5 file. After we used the +# `solve` function with [`SaveSolutionCallback`](@ref) there is a file with the final solution. +# It is located in the `out` folder and is named as follows: `solution_index.h5`. The `index` +# is the final time step of the solution that is padded to 6 digits with zeros from the beginning. +# With [Trixi2Vtk](@ref) you can convert the HDF5 output file generated by Trixi.jl into a VTK file. +# This can be used in visualization tools such as [ParaView](https://www.paraview.org) or +# [VisIt](https://visit.llnl.gov) to plot the solution. The important thing is that currently +# Trixi2Vtk.jl supports conversion only for solutions in 2D and 3D spatial domains. + +# If you haven't added Trixi2Vtk.jl to your project yet, you can add it as follows. +# ```julia +# import Pkg +# Pkg.add(["Trixi2Vtk"]) +# ``` +# Now we load the Trixi2Vtk.jl package and convert the file `out/solution_000018.h5` with +# the final solution using the [`trixi2vtk`](@ref) function saving the resulting file in the +# `out` folder. + +using Trixi2Vtk +trixi2vtk(joinpath("out", "solution_000018.h5"), output_directory="out") + +# Now two files `solution_000018.vtu` and `solution_000018_celldata.vtu` have been generated in the +# `out` folder. The first one contains all the information for visualizing the solution, the +# second one contains all the cell-based or discretization-based information. + +# Now let's visualize the solution from the generated files in ParaView. Follow this short +# instruction to get the visualization. +# - Download, install and open [ParaView](https://www.paraview.org/download/). +# - Press `Ctrl+O` and select the generated files `solution_000018.vtu` and +# `solution_000018_celldata.vtu` from the `out` folder. +# - In the upper-left corner in the Pipeline Browser window, left-click on the eye-icon near +# `solution_000018.vtu`. +# - In the lower-left corner in the Properties window, change the Coloring from Solid Color to +# scalar. This already generates the visualization of the final solution. +# - Now let's add the mesh to the visualization. In the upper-left corner in the +# Pipeline Browser window, left-click on the eye-icon near `solution_000018_celldata.vtu`. +# - In the lower-left corner in the Properties window, change the Representation from Surface +# to Wireframe. Then a white grid should appear on the visualization. +# Now, if you followed the instructions exactly, you should get a similar image as shown in the +# section [Using Plots.jl](@ref Using-Plots.jl): + +# ![paraview_trixi2vtk_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/0c29139b-6c5d-4d5c-86e1-f4ebc95aca7e) + +# After completing this tutorial you are able to set up your own simulations with +# Trixi.jl. If you have an interest in contributing to Trixi.jl as a developer, refer to the third +# part of the introduction titled [Changing Trixi.jl itself](@ref changing_trixi). + +Sys.rm("out"; recursive=true, force=true) #hide #md \ No newline at end of file diff --git a/docs/literate/src/files/first_steps/getting_started.jl b/docs/literate/src/files/first_steps/getting_started.jl new file mode 100644 index 00000000000..2bfaf33b5fc --- /dev/null +++ b/docs/literate/src/files/first_steps/getting_started.jl @@ -0,0 +1,242 @@ +#src # Getting started + +# Trixi.jl is a numerical simulation framework for conservation laws and +# is written in the [Julia programming language](https://julialang.org/). +# This tutorial is intended for beginners in Julia and Trixi.jl. +# After reading it, you will know how to install Julia and Trixi.jl on your computer, +# and you will be able to download setup files from our GitHub repository, modify them, +# and run simulations. + +# The contents of this tutorial: +# - [Julia installation](@ref Julia-installation) +# - [Trixi.jl installation](@ref Trixi.jl-installation) +# - [Running a simulation](@ref Running-a-simulation) +# - [Getting an existing setup file](@ref Getting-an-existing-setup-file) +# - [Modifying an existing setup](@ref Modifying-an-existing-setup) + + +# ## Julia installation + +# Trixi.jl is compatible with the latest stable release of Julia. Additional details regarding Julia +# support can be found in the [`README.md`](https://github.com/trixi-framework/Trixi.jl#installation) +# file. The current default Julia installation is managed through `juliaup`. You may follow our +# concise installation guidelines for Windows, Linux, and MacOS provided below. In the event of any +# issues during the installation process, please consult the official +# [Julia installation instruction](https://julialang.org/downloads/). + + +# ### Windows + +# - Open a terminal by pressing `Win+r` and entering `cmd` in the opened window. +# - To install Julia, execute the following command in the terminal: +# ```shell +# winget install julia -s msstore +# ``` +# - Verify the successful installation of Julia by executing the following command in the terminal: +# ```shell +# julia +# ``` +# To exit Julia, execute `exit()` or press `Ctrl+d`. + + +# ### Linux and MacOS + +# - To install Julia, run the following command in a terminal: +# ```shell +# curl -fsSL https://install.julialang.org | sh +# ``` +# Follow the instructions displayed in the terminal during the installation process. +# - If an error occurs during the execution of the previous command, you may need to install +# `curl`. On Ubuntu-type systems, you can use the following command: +# ```shell +# sudo apt install curl +# ``` +# After installing `curl`, repeat the first step once more to proceed with Julia installation. +# - Verify the successful installation of Julia by executing the following command in the terminal: +# ```shell +# julia +# ``` +# To exit Julia, execute `exit()` or press `Ctrl+d`. + + +# ## Trixi.jl installation + +# Trixi.jl and its related tools are registered Julia packages, thus their installation +# happens inside Julia. +# For a smooth workflow experience with Trixi.jl, you need to install +# [Trixi.jl](https://github.com/trixi-framework/Trixi.jl), +# [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl), and +# [Plots.jl](https://github.com/JuliaPlots/Plots.jl). + +# - Open a terminal and start Julia. +# - Execute following commands: +# ```julia +# import Pkg +# Pkg.add(["OrdinaryDiffEq", "Plots", "Trixi"]) +# ``` + +# Now you have installed all these +# packages. [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) provides time +# integration schemes used by Trixi.jl and [Plots.jl](https://github.com/JuliaPlots/Plots.jl) +# can be used to directly visualize Trixi.jl results from the Julia REPL. + + +# ## Usage + + +# ### Running a simulation + +# To get you started, Trixi.jl has a large set +# of [example setups](https://github.com/trixi-framework/Trixi.jl/tree/main/examples), that can be +# taken as a basis for your future investigations. In Trixi.jl, we call these setup files +# "elixirs", since they contain Julia code that takes parts of Trixi.jl and combines them into +# something new. + +# Any of the examples can be executed using the [`trixi_include`](@ref) +# function. `trixi_include(...)` expects +# a single string argument with a path to a file containing Julia code. +# For convenience, the [`examples_dir`](@ref) function returns a path to the +# [`examples`](https://github.com/trixi-framework/Trixi.jl/tree/main/examples) +# folder, which has been locally downloaded while installing Trixi.jl. +# `joinpath(...)` can be used to join path components into a full path. + +# Let's execute a short two-dimensional problem setup. It approximates the solution of +# the compressible Euler equations in 2D for an ideal gas ([`CompressibleEulerEquations2D`](@ref)) +# with a weak blast wave as the initial condition. + +# Start Julia in a terminal and execute the following code: + +# ```julia +# using Trixi, OrdinaryDiffEq +# trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl")) +# ``` +using Trixi, OrdinaryDiffEq #hide #md +trixi_include(@__MODULE__,joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl")) #hide #md + +# To analyze the result of the computation, we can use the Plots.jl package and the function +# `plot(...)`, which creates a graphical representation of the solution. `sol` is a variable +# defined in the executed example and it contains the solution at the final moment of the simulation. + +using Plots +plot(sol) + +# To obtain a list of all Trixi.jl elixirs execute +# [`get_examples`](@ref). It returns the paths to all example setups. + +get_examples() + +# Editing an existing elixir is the best way to start your first own investigation using Trixi.jl. + + +# ### Getting an existing setup file + +# To edit an existing elixir, you first have to find a suitable one and then copy it to a local +# folder. Let's have a look at how to download the `elixir_euler_ec.jl` elixir used in the previous +# section from the [Trixi.jl GitHub repository](https://github.com/trixi-framework/Trixi.jl). + +# - All examples are located inside +# the [`examples`](https://github.com/trixi-framework/Trixi.jl/tree/main/examples) folder. +# - Navigate to the +# file [`elixir_euler_ec.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_ec.jl). +# - Right-click the `Raw` button on the right side of the webpage and choose `Save as...` +# (or `Save Link As...`). +# - Choose a folder and save the file. + + +# ### Modifying an existing setup + +# As an example, we will change the initial condition for calculations that occur in +# `elixir_euler_ec.jl`. In this example we consider the compressible Euler equations in two spatial +# dimensions, +# ```math +# \frac{\partial}{\partial t} +# \begin{pmatrix} +# \rho \\ \rho v_1 \\ \rho v_2 \\ \rho e +# \end{pmatrix} +# + +# \frac{\partial}{\partial x} +# \begin{pmatrix} +# \rho v_1 \\ \rho v_1^2 + p \\ \rho v_1 v_2 \\ (\rho e + p) v_1 +# \end{pmatrix} +# + +# \frac{\partial}{\partial y} +# \begin{pmatrix} +# \rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + p \\ (\rho e + p) v_2 +# \end{pmatrix} +# = +# \begin{pmatrix} +# 0 \\ 0 \\ 0 \\ 0 +# \end{pmatrix}, +# ``` +# for an ideal gas with the specific heat ratio ``\gamma``. +# Here, ``\rho`` is the density, ``v_1`` and ``v_2`` are the velocities, ``e`` is the specific +# total energy, and +# ```math +# p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right) +# ``` +# is the pressure. +# Initial conditions consist of initial values for ``\rho``, ``\rho v_1``, +# ``\rho v_2`` and ``\rho e``. +# One of the common initial conditions for the compressible Euler equations is a simple density +# wave. Let's implement it. + +# - Open the downloaded file `elixir_euler_ec.jl` with a text editor. +# - Go to the line with the following code: +# ```julia +# initial_condition = initial_condition_weak_blast_wave +# ``` +# Here, [`initial_condition_weak_blast_wave`](@ref) is used as the initial condition. +# - Comment out the line using the `#` symbol: +# ```julia +# # initial_condition = initial_condition_weak_blast_wave +# ``` +# - Now you can create your own initial conditions. Add the following code after the +# commented line: + +function initial_condition_density_waves(x, t, equations::CompressibleEulerEquations2D) + v1 = 0.1 # velocity along x-axis + v2 = 0.2 # velocity along y-axis + rho = 1.0 + 0.98 * sinpi(sum(x) - t * (v1 + v2)) # density wave profile + p = 20 # pressure + rho_e = p / (equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2) + return SVector(rho, rho*v1, rho*v2, rho_e) +end +initial_condition = initial_condition_density_waves + +# - Execute the following code one more time, but instead of `path/to/file` paste the path to the +# `elixir_euler_ec.jl` file that you just edited. +# ```julia +# using Trixi +# trixi_include(path/to/file) +# using Plots +# plot(sol) +# ``` +# Then you will obtain a new solution from running the simulation with a different initial +# condition. + +trixi_include(@__MODULE__,joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), #hide #md + initial_condition=initial_condition) #hide #md +pd = PlotData2D(sol) #hide #md +p1 = plot(pd["rho"]) #hide #md +p2 = plot(pd["v1"], clim=(0.05, 0.15)) #hide #md +p3 = plot(pd["v2"], clim=(0.15, 0.25)) #hide #md +p4 = plot(pd["p"], clim=(10, 30)) #hide #md +plot(p1, p2, p3, p4) #hide #md + +# To get exactly the same picture execute the following. +# ```julia +# pd = PlotData2D(sol) +# p1 = plot(pd["rho"]) +# p2 = plot(pd["v1"], clim=(0.05, 0.15)) +# p3 = plot(pd["v2"], clim=(0.15, 0.25)) +# p4 = plot(pd["p"], clim=(10, 30)) +# plot(p1, p2, p3, p4) +# ``` + +# Feel free to make further changes to the initial condition to observe different solutions. + +# Now you are able to download, modify and execute simulation setups for Trixi.jl. To explore +# further details on setting up a new simulation with Trixi.jl, refer to the second part of +# the introduction titled [Create first setup](@ref create_first_setup). + +Sys.rm("out"; recursive=true, force=true) #hide #md \ No newline at end of file diff --git a/docs/literate/src/files/index.jl b/docs/literate/src/files/index.jl index 26637e5b24b..1fc025d84da 100644 --- a/docs/literate/src/files/index.jl +++ b/docs/literate/src/files/index.jl @@ -14,20 +14,27 @@ # There are tutorials for the following topics: -# ### [1 Introduction to DG methods](@ref scalar_linear_advection_1d) +# ### [1 First steps in Trixi.jl](@ref getting_started) +#- +# This tutorial provides guidance for getting started with Trixi.jl, and Julia as well. It outlines +# the installation procedures for both Julia and Trixi.jl, the execution of Trixi.jl elixirs, the +# fundamental structure of a Trixi.jl setup, the visualization of results, and the development +# process for Trixi.jl. + +# ### [2 Introduction to DG methods](@ref scalar_linear_advection_1d) #- # This tutorial gives an introduction to discontinuous Galerkin (DG) methods with the example of the # scalar linear advection equation in 1D. Starting with some theoretical explanations, we first implement # a raw version of a discontinuous Galerkin spectral element method (DGSEM). Then, we will show how # to use features of Trixi.jl to achieve the same result. -# ### [2 DGSEM with flux differencing](@ref DGSEM_FluxDiff) +# ### [3 DGSEM with flux differencing](@ref DGSEM_FluxDiff) #- # To improve stability often the flux differencing formulation of the DGSEM (split form) is used. # We want to present the idea and formulation on a basic 1D level. Then, we show how this formulation # can be implemented in Trixi.jl and analyse entropy conservation for two different flux combinations. -# ### [3 Shock capturing with flux differencing and stage limiter](@ref shock_capturing) +# ### [4 Shock capturing with flux differencing and stage limiter](@ref shock_capturing) #- # Using the flux differencing formulation, a simple procedure to capture shocks is a hybrid blending # of a high-order DG method and a low-order subcell finite volume (FV) method. We present the idea on a @@ -35,20 +42,20 @@ # explained and added to an exemplary simulation of the Sedov blast wave with the 2D compressible Euler # equations. -# ### [4 Non-periodic boundary conditions](@ref non_periodic_boundaries) +# ### [5 Non-periodic boundary conditions](@ref non_periodic_boundaries) #- # Thus far, all examples used periodic boundaries. In Trixi.jl, you can also set up a simulation with # non-periodic boundaries. This tutorial presents the implementation of the classical Dirichlet # boundary condition with a following example. Then, other non-periodic boundaries are mentioned. -# ### [5 DG schemes via `DGMulti` solver](@ref DGMulti_1) +# ### [6 DG schemes via `DGMulti` solver](@ref DGMulti_1) #- # This tutorial is about the more general DG solver [`DGMulti`](@ref), introduced [here](@ref DGMulti). # We are showing some examples for this solver, for instance with discretization nodes by Gauss or # triangular elements. Moreover, we present a simple way to include pre-defined triangulate meshes for # non-Cartesian domains using the package [StartUpDG.jl](https://github.com/jlchan/StartUpDG.jl). -# ### [6 Other SBP schemes (FD, CGSEM) via `DGMulti` solver](@ref DGMulti_2) +# ### [7 Other SBP schemes (FD, CGSEM) via `DGMulti` solver](@ref DGMulti_2) #- # Supplementary to the previous tutorial about DG schemes via the `DGMulti` solver we now present # the possibility for `DGMulti` to use other SBP schemes via the package @@ -56,7 +63,7 @@ # For instance, we show how to set up a finite differences (FD) scheme and a continuous Galerkin # (CGSEM) method. -# ### [7 Upwind FD SBP schemes](@ref upwind_fdsbp) +# ### [8 Upwind FD SBP schemes](@ref upwind_fdsbp) #- # General SBP schemes can not only be used via the [`DGMulti`](@ref) solver but # also with a general `DG` solver. In particular, upwind finite difference SBP @@ -64,42 +71,42 @@ # schemes in the `DGMulti` framework, the interface is based on the package # [SummationByPartsOperators.jl](https://github.com/ranocha/SummationByPartsOperators.jl). -# ### [8 Adding a new scalar conservation law](@ref adding_new_scalar_equations) +# ### [9 Adding a new scalar conservation law](@ref adding_new_scalar_equations) #- # This tutorial explains how to add a new physics model using the example of the cubic conservation # law. First, we define the equation using a `struct` `CubicEquation` and the physical flux. Then, # the corresponding standard setup in Trixi.jl (`mesh`, `solver`, `semi` and `ode`) is implemented # and the ODE problem is solved by OrdinaryDiffEq's `solve` method. -# ### [9 Adding a non-conservative equation](@ref adding_nonconservative_equation) +# ### [10 Adding a non-conservative equation](@ref adding_nonconservative_equation) #- # In this part, another physics model is implemented, the nonconservative linear advection equation. # We run two different simulations with different levels of refinement and compare the resulting errors. -# ### [10 Parabolic terms](@ref parabolic_terms) +# ### [11 Parabolic terms](@ref parabolic_terms) #- # This tutorial describes how parabolic terms are implemented in Trixi.jl, e.g., # to solve the advection-diffusion equation. -# ### [11 Adding new parabolic terms](@ref adding_new_parabolic_terms) +# ### [12 Adding new parabolic terms](@ref adding_new_parabolic_terms) #- # This tutorial describes how new parabolic terms can be implemented using Trixi.jl. -# ### [12 Adaptive mesh refinement](@ref adaptive_mesh_refinement) +# ### [13 Adaptive mesh refinement](@ref adaptive_mesh_refinement) #- # Adaptive mesh refinement (AMR) helps to increase the accuracy in sensitive or turbolent regions while # not wasting resources for less interesting parts of the domain. This leads to much more efficient # simulations. This tutorial presents the implementation strategy of AMR in Trixi.jl, including the use of # different indicators and controllers. -# ### [13 Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) +# ### [14 Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) #- # In this tutorial, the use of Trixi.jl's structured curved mesh type [`StructuredMesh`](@ref) is explained. # We present the two basic option to initialize such a mesh. First, the curved domain boundaries # of a circular cylinder are set by explicit boundary functions. Then, a fully curved mesh is # defined by passing the transformation mapping. -# ### [14 Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) +# ### [15 Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) #- # The purpose of this tutorial is to demonstrate how to use the [`UnstructuredMesh2D`](@ref) # functionality of Trixi.jl. This begins by running and visualizing an available unstructured @@ -108,26 +115,26 @@ # software in the Trixi.jl ecosystem, and then run a simulation using Trixi.jl on said mesh. # In the end, the tutorial briefly explains how to simulate an example using AMR via `P4estMesh`. -# ### [15 P4est mesh from gmsh](@ref p4est_from_gmsh) +# ### [16 P4est mesh from gmsh](@ref p4est_from_gmsh) #- # This tutorial describes how to obtain a [`P4estMesh`](@ref) from an existing mesh generated # by [`gmsh`](https://gmsh.info/) or any other meshing software that can export to the Abaqus # input `.inp` format. The tutorial demonstrates how edges/faces can be associated with boundary conditions based on the physical nodesets. -# ### [16 Explicit time stepping](@ref time_stepping) +# ### [17 Explicit time stepping](@ref time_stepping) #- # This tutorial is about time integration using [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl). # It explains how to use their algorithms and presents two types of time step choices - with error-based # and CFL-based adaptive step size control. -# ### [17 Differentiable programming](@ref differentiable_programming) +# ### [18 Differentiable programming](@ref differentiable_programming) #- # This part deals with some basic differentiable programming topics. For example, a Jacobian, its # eigenvalues and a curve of total energy (through the simulation) are calculated and plotted for # a few semidiscretizations. Moreover, we calculate an example for propagating errors with Measurement.jl # at the end. -# ### [18 Custom semidiscretization](@ref custom_semidiscretization) +# ### [19 Custom semidiscretization](@ref custom_semidiscretization) #- # This tutorial describes the [semidiscretiations](@ref overview-semidiscretizations) of Trixi.jl # and explains how to extend them for custom tasks. diff --git a/docs/make.jl b/docs/make.jl index 7fce3b31e24..584f151b5f3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -48,6 +48,12 @@ end # "title" => ["subtitle 1" => ("folder 1", "filename 1.jl"), # "subtitle 2" => ("folder 2", "filename 2.jl")] files = [ + # Topic: introduction + "First steps in Trixi.jl" => [ + "Getting started" => ("first_steps", "getting_started.jl"), + "Create first setup" => ("first_steps", "create_first_setup.jl"), + "Changing Trixi.jl itself" => ("first_steps", "changing_trixi.jl"), + ], # Topic: DG semidiscretizations "Introduction to DG methods" => "scalar_linear_advection_1d.jl", "DGSEM with flux differencing" => "DGSEM_FluxDiff.jl", From fa18c8bab4c6855a989691ede7f8947c5e3ea945 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 7 Feb 2024 07:19:49 +0100 Subject: [PATCH 03/27] fix benchmarks configuration (#1837) --- benchmark/benchmarks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index a3f7d1d2569..15d1d96c05f 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -55,5 +55,5 @@ let SUITE["latency"]["euler_2d"] = @benchmarkable run( `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_kelvin_helmholtz_instability.jl"), tspan=(0.0, 1.0e-10), save_restart=TrivialCallback(), save_solution=TrivialCallback())'`) seconds=60 SUITE["latency"]["mhd_2d"] = @benchmarkable run( - `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_mhd_blast_wave.jl"), tspan=(0.0, 1.0e-10), save_restart=TrivialCallback(), save_solution=TrivialCallback())'`) seconds=60 + `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_mhd_blast_wave.jl"), tspan=(0.0, 1.0e-10), save_solution=TrivialCallback())'`) seconds=60 end From 8c6d9bc727219e470f56f3317997f17eb5615842 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 7 Feb 2024 07:27:40 +0100 Subject: [PATCH 04/27] Make CI fail if Codecov fails (#1834) --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e388366fc8..86bd3f836e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,7 +134,8 @@ jobs: file: ./lcov.info flags: unittests name: codecov-umbrella - fail_ci_if_error: false + fail_ci_if_error: true + verbose: true token: ${{ secrets.CODECOV_TOKEN }} # The standard setup of Coveralls is just annoying for parallel builds, see, e.g., # https://github.com/trixi-framework/Trixi.jl/issues/691 From 4fb8160c397df922e8fc4906a5c8f92225c21ecd Mon Sep 17 00:00:00 2001 From: Michael Schlottke-Lakemper Date: Wed, 7 Feb 2024 08:43:50 +0100 Subject: [PATCH 05/27] Update compat bounds for Makie, CairoMakie (#1836) --- Project.toml | 2 +- docs/Project.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index e99b08e0e81..9b624c7733c 100644 --- a/Project.toml +++ b/Project.toml @@ -68,7 +68,7 @@ LinearAlgebra = "1" LinearMaps = "2.7, 3.0" LoopVectorization = "0.12.118" MPI = "0.20" -Makie = "0.19" +Makie = "0.19, 0.20" MuladdMacro = "0.2.2" Octavian = "0.3.5" OffsetArrays = "1.3" diff --git a/docs/Project.toml b/docs/Project.toml index 3a091f5b4f1..cc48aeb8ed9 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -12,7 +12,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi2Vtk = "bc1476a1-1ca6-4cc3-950b-c312b255ff95" [compat] -CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" +CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10, 0.11" Documenter = "1" ForwardDiff = "0.10" HOHQMesh = "0.1, 0.2" From 3e6872bd486a4cfcc94bd2c31b2fe8510670a7a2 Mon Sep 17 00:00:00 2001 From: Michael Schlottke-Lakemper Date: Wed, 7 Feb 2024 09:06:07 +0100 Subject: [PATCH 06/27] Enable CI testing on Apple Silicon (#1830) * Enable CI testing on Apple Silicon * Use `threaded` instead of `threaded_legacy` --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86bd3f836e5..9d398f187b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,6 +101,10 @@ jobs: os: windows-latest arch: x64 trixi_test: threaded + - version: '1.9' + os: macos-14 + arch: arm64 + trixi_test: threaded steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 From fe6a5276e1ea92a23d4897ca33a057288f277e8f Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 7 Feb 2024 10:37:22 +0100 Subject: [PATCH 07/27] coverallsapp at v2 (#1777) Co-authored-by: Michael Schlottke-Lakemper --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d398f187b3..a7dfe033a90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -200,7 +200,7 @@ jobs: coverage = merge_coverage_counts(coverage) @show covered_lines, total_lines = get_summary(coverage) LCOV.writefile("./lcov.info", coverage) - - uses: coverallsapp/github-action@master + - uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: ./lcov.info From 4369c1c00b3e44de43bba95adeedfb37fd09551c Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 14 Feb 2024 07:56:08 +0100 Subject: [PATCH 08/27] Fix formatter to older version (#1843) * Fix formatter to older version * fix JuliaFormatter version also in utils folder * Update utils/trixi-format-file.jl Co-authored-by: Arpit Babbar * Update utils/trixi-format.jl Co-authored-by: Arpit Babbar * Apply suggestions from code review Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * format --------- Co-authored-by: Arpit Babbar Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .github/workflows/FormatCheck.yml | 2 +- utils/trixi-format-file.jl | 3 ++- utils/trixi-format.jl | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index a733cb7cc21..7297f1c3ff5 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -29,7 +29,7 @@ jobs: # TODO: Change the call below to # format(".") run: | - julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter"))' + julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.45"))' julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])' - name: Format check run: | diff --git a/utils/trixi-format-file.jl b/utils/trixi-format-file.jl index c4d8e7c9032..9b9a0e4949c 100755 --- a/utils/trixi-format-file.jl +++ b/utils/trixi-format-file.jl @@ -2,7 +2,8 @@ using Pkg Pkg.activate(; temp = true, io = devnull) -Pkg.add("JuliaFormatter"; preserve = PRESERVE_ALL, io = devnull) +Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.45"); preserve = PRESERVE_ALL, + io = devnull) using JuliaFormatter: format_file diff --git a/utils/trixi-format.jl b/utils/trixi-format.jl index d1e7efa656a..63f14078807 100755 --- a/utils/trixi-format.jl +++ b/utils/trixi-format.jl @@ -2,7 +2,8 @@ using Pkg Pkg.activate(; temp = true, io = devnull) -Pkg.add("JuliaFormatter"; preserve = PRESERVE_ALL, io = devnull) +Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.45"); preserve = PRESERVE_ALL, + io = devnull) using JuliaFormatter: format From 4f33837e3c95b5af21057850c30ef603a9191d86 Mon Sep 17 00:00:00 2001 From: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> Date: Thu, 15 Feb 2024 08:50:30 +0100 Subject: [PATCH 09/27] Use `trixi_include` from TrixiBase.jl (#1832) * Use `trixi_include` from TrixiBase.jl * Add compat entry for TrixiBase.jl * Remove unused functions * Use `TrixiBase.walkexpr` * Fix docs * Add TrixiBase.jl API reference * Add TrixiBase to docs dependencies * Import `TrixiBase` * Remove `find_assignment` * Add TrixiBase to makedocs modules * Apply suggestions from code review Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --------- Co-authored-by: Hendrik Ranocha Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- Project.toml | 2 + docs/Project.toml | 2 + docs/make.jl | 4 +- docs/src/conventions.md | 10 +- docs/src/reference-trixibase.md | 9 ++ src/Trixi.jl | 3 +- src/auxiliary/precompile.jl | 3 - src/auxiliary/special_elixirs.jl | 158 +------------------------------ src/callbacks_step/trivial.jl | 4 +- test/test_unit.jl | 97 ------------------- 10 files changed, 31 insertions(+), 261 deletions(-) create mode 100644 docs/src/reference-trixibase.md diff --git a/Project.toml b/Project.toml index 9b624c7733c..b4a06a70688 100644 --- a/Project.toml +++ b/Project.toml @@ -45,6 +45,7 @@ TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" Triangulate = "f7e6ffb2-c36d-4f8f-a77e-16e897189344" TriplotBase = "981d1d27-644d-49a2-9326-4793e63143c3" TriplotRecipes = "808ab39a-a642-4abf-81ff-4cb34ebbffa3" +TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" [weakdeps] Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" @@ -95,6 +96,7 @@ TimerOutputs = "0.5.7" Triangulate = "2.0" TriplotBase = "0.1" TriplotRecipes = "0.1" +TrixiBase = "0.1.1" julia = "1.8" [extras] diff --git a/docs/Project.toml b/docs/Project.toml index cc48aeb8ed9..3b8d169fdb8 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -10,6 +10,7 @@ OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi2Vtk = "bc1476a1-1ca6-4cc3-950b-c312b255ff95" +TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" [compat] CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10, 0.11" @@ -23,3 +24,4 @@ OrdinaryDiffEq = "6.49.1" Plots = "1.9" Test = "1" Trixi2Vtk = "0.3" +TrixiBase = "0.1.1" diff --git a/docs/make.jl b/docs/make.jl index 584f151b5f3..946b803b71e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -8,6 +8,7 @@ end using Trixi using Trixi2Vtk +using TrixiBase # Get Trixi.jl root directory trixi_root_dir = dirname(@__DIR__) @@ -82,7 +83,7 @@ tutorials = create_tutorials(files) # Make documentation makedocs( # Specify modules for which docstrings should be shown - modules = [Trixi, Trixi2Vtk], + modules = [Trixi, TrixiBase, Trixi2Vtk], # Set sitename to Trixi.jl sitename = "Trixi.jl", # Provide additional formatting options @@ -128,6 +129,7 @@ makedocs( "Troubleshooting and FAQ" => "troubleshooting.md", "Reference" => [ "Trixi.jl" => "reference-trixi.md", + "TrixiBase.jl" => "reference-trixibase.md", "Trixi2Vtk.jl" => "reference-trixi2vtk.md" ], "Authors" => "authors.md", diff --git a/docs/src/conventions.md b/docs/src/conventions.md index dab1b8533a5..4f9e0ec4e67 100644 --- a/docs/src/conventions.md +++ b/docs/src/conventions.md @@ -47,10 +47,12 @@ Trixi.jl is distributed with several examples in the form of elixirs, small Julia scripts containing everything to set up and run a simulation. Working interactively from the Julia REPL with these scripts can be quite convenient while for exploratory research and development of Trixi.jl. For example, you -can use the convenience function [`trixi_include`](@ref) to `include` an elixir -with some modified arguments. To enable this, it is helpful to use a consistent -naming scheme in elixirs, since [`trixi_include`](@ref) can only perform simple -replacements. Some standard variables names are +can use the convenience function +[`trixi_include`](@ref) +to `include` an elixir with some modified arguments. To enable this, it is +helpful to use a consistent naming scheme in elixirs, since +[`trixi_include`](@ref) +can only perform simple replacements. Some standard variables names are - `polydeg` for the polynomial degree of a solver - `surface_flux` for the numerical flux at surfaces diff --git a/docs/src/reference-trixibase.md b/docs/src/reference-trixibase.md new file mode 100644 index 00000000000..c7a970f88ec --- /dev/null +++ b/docs/src/reference-trixibase.md @@ -0,0 +1,9 @@ +# TrixiBase.jl API + +```@meta +CurrentModule = TrixiBase +``` + +```@autodocs +Modules = [TrixiBase] +``` diff --git a/src/Trixi.jl b/src/Trixi.jl index 8d74fbc9736..ea72fbc915f 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -70,6 +70,7 @@ using Triangulate: Triangulate, TriangulateIO, triangulate export TriangulateIO # for type parameter in DGMultiMesh using TriplotBase: TriplotBase using TriplotRecipes: DGTriPseudocolor +@reexport using TrixiBase: TrixiBase, trixi_include @reexport using SimpleUnPack: @unpack using SimpleUnPack: @pack! using DataStructures: BinaryHeap, FasterForward, extract_all! @@ -129,7 +130,7 @@ include("callbacks_step/callbacks_step.jl") include("callbacks_stage/callbacks_stage.jl") include("semidiscretization/semidiscretization_euler_gravity.jl") -# `trixi_include` and special elixirs such as `convergence_test` +# Special elixirs such as `convergence_test` include("auxiliary/special_elixirs.jl") # Plot recipes and conversion functions to visualize results with Plots.jl diff --git a/src/auxiliary/precompile.jl b/src/auxiliary/precompile.jl index 9cec502f6cb..4d5399b5ba3 100644 --- a/src/auxiliary/precompile.jl +++ b/src/auxiliary/precompile.jl @@ -577,9 +577,6 @@ function _precompile_manual_() @assert Base.precompile(Tuple{typeof(show), Base.TTY, lbm_collision_callback_type}) @assert Base.precompile(Tuple{typeof(show), IOContext{Base.TTY}, MIME"text/plain", lbm_collision_callback_type}) - - # infrastructure, special elixirs - @assert Base.precompile(Tuple{typeof(trixi_include), String}) end @assert Base.precompile(Tuple{typeof(init_mpi)}) diff --git a/src/auxiliary/special_elixirs.jl b/src/auxiliary/special_elixirs.jl index 5fdd9aea0c5..d71a27aa96a 100644 --- a/src/auxiliary/special_elixirs.jl +++ b/src/auxiliary/special_elixirs.jl @@ -5,58 +5,6 @@ @muladd begin #! format: noindent -# Note: We can't call the method below `Trixi.include` since that is created automatically -# inside `module Trixi` to `include` source files and evaluate them within the global scope -# of `Trixi`. However, users will want to evaluate in the global scope of `Main` or something -# similar to manage dependencies on their own. -""" - trixi_include([mod::Module=Main,] elixir::AbstractString; kwargs...) - -`include` the file `elixir` and evaluate its content in the global scope of module `mod`. -You can override specific assignments in `elixir` by supplying keyword arguments. -It's basic purpose is to make it easier to modify some parameters while running Trixi.jl from the -REPL. Additionally, this is used in tests to reduce the computational burden for CI while still -providing examples with sensible default values for users. - -Before replacing assignments in `elixir`, the keyword argument `maxiters` is inserted -into calls to `solve` and `Trixi.solve` with it's default value used in the SciML ecosystem -for ODEs, see the "Miscellaneous" section of the -[documentation](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/). - -# Examples - -```jldoctest -julia> redirect_stdout(devnull) do - trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_extended.jl"), - tspan=(0.0, 0.1)) - sol.t[end] - end -[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient. -0.1 -``` -""" -function trixi_include(mod::Module, elixir::AbstractString; kwargs...) - # Check that all kwargs exist as assignments - code = read(elixir, String) - expr = Meta.parse("begin \n$code \nend") - expr = insert_maxiters(expr) - - for (key, val) in kwargs - # This will throw an error when `key` is not found - find_assignment(expr, key) - end - - # Print information on potential wait time only in non-parallel case - if !mpi_isparallel() - @info "You just called `trixi_include`. Julia may now compile the code, please be patient." - end - Base.include(ex -> replace_assignments(insert_maxiters(ex); kwargs...), mod, elixir) -end - -function trixi_include(elixir::AbstractString; kwargs...) - trixi_include(Main, elixir; kwargs...) -end - """ convergence_test([mod::Module=Main,] elixir::AbstractString, iterations; kwargs...) @@ -177,112 +125,15 @@ end # Helper methods used in the functions defined above -# Apply the function `f` to `expr` and all sub-expressions recursively. -walkexpr(f, expr::Expr) = f(Expr(expr.head, (walkexpr(f, arg) for arg in expr.args)...)) -walkexpr(f, x) = f(x) - -# Insert the keyword argument `maxiters` into calls to `solve` and `Trixi.solve` -# with default value `10^5` if it is not already present. -function insert_maxiters(expr) - maxiters_default = 10^5 - - expr = walkexpr(expr) do x - if x isa Expr - is_plain_solve = x.head === Symbol("call") && x.args[1] === Symbol("solve") - is_trixi_solve = (x.head === Symbol("call") && x.args[1] isa Expr && - x.args[1].head === Symbol(".") && - x.args[1].args[1] === Symbol("Trixi") && - x.args[1].args[2] isa QuoteNode && - x.args[1].args[2].value === Symbol("solve")) - - if is_plain_solve || is_trixi_solve - # Do nothing if `maxiters` is already set as keyword argument... - for arg in x.args - # This detects the case where `maxiters` is set as keyword argument - # without or before a semicolon - if (arg isa Expr && arg.head === Symbol("kw") && - arg.args[1] === Symbol("maxiters")) - return x - end - - # This detects the case where maxiters is set as keyword argument - # after a semicolon - if (arg isa Expr && arg.head === Symbol("parameters")) - # We need to check each keyword argument listed here - for nested_arg in arg.args - if (nested_arg isa Expr && - nested_arg.head === Symbol("kw") && - nested_arg.args[1] === Symbol("maxiters")) - return x - end - end - end - end - - # ...and insert it otherwise. - push!(x.args, Expr(Symbol("kw"), Symbol("maxiters"), maxiters_default)) - end - end - return x - end - - return expr -end - -# Replace assignments to `key` in `expr` by `key = val` for all `(key,val)` in `kwargs`. -function replace_assignments(expr; kwargs...) - # replace explicit and keyword assignments - expr = walkexpr(expr) do x - if x isa Expr - for (key, val) in kwargs - if (x.head === Symbol("=") || x.head === :kw) && - x.args[1] === Symbol(key) - x.args[2] = :($val) - # dump(x) - end - end - end - return x - end - - return expr -end - -# find a (keyword or common) assignment to `destination` in `expr` -# and return the assigned value -function find_assignment(expr, destination) - # declare result to be able to assign to it in the closure - local result - found = false - - # find explicit and keyword assignments - walkexpr(expr) do x - if x isa Expr - if (x.head === Symbol("=") || x.head === :kw) && - x.args[1] === Symbol(destination) - result = x.args[2] - found = true - # dump(x) - end - end - return x - end - - if !found - throw(ArgumentError("assignment `$destination` not found in expression")) - end - - result -end - -# searches the parameter that specifies the mesh reslution in the elixir +# Searches for the assignment that specifies the mesh resolution in the elixir function extract_initial_resolution(elixir, kwargs) code = read(elixir, String) expr = Meta.parse("begin \n$code \nend") try # get the initial_refinement_level from the elixir - initial_refinement_level = find_assignment(expr, :initial_refinement_level) + initial_refinement_level = TrixiBase.find_assignment(expr, + :initial_refinement_level) if haskey(kwargs, :initial_refinement_level) return kwargs[:initial_refinement_level] @@ -294,7 +145,8 @@ function extract_initial_resolution(elixir, kwargs) if isa(e, ArgumentError) try # get cells_per_dimension from the elixir - cells_per_dimension = eval(find_assignment(expr, :cells_per_dimension)) + cells_per_dimension = eval(TrixiBase.find_assignment(expr, + :cells_per_dimension)) if haskey(kwargs, :cells_per_dimension) return kwargs[:cells_per_dimension] diff --git a/src/callbacks_step/trivial.jl b/src/callbacks_step/trivial.jl index a55b7d85b13..fb93cf96c0c 100644 --- a/src/callbacks_step/trivial.jl +++ b/src/callbacks_step/trivial.jl @@ -8,8 +8,8 @@ """ TrivialCallback() -A callback that does nothing. This can be useful to disable some callbacks -easily via [`trixi_include`](@ref). +A callback that does nothing. This can be useful to disable some callbacks easily via +[`trixi_include`](@ref). """ function TrivialCallback() DiscreteCallback(trivial_callback, trivial_callback, diff --git a/test/test_unit.jl b/test/test_unit.jl index 7943d952f71..3b8dc3c4331 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1529,103 +1529,6 @@ end @test mesh.boundary_faces[:entire_boundary] == [1, 2] end - -@testset "trixi_include" begin - @trixi_testset "Basic" begin - example = """ - x = 4 - """ - - filename = tempname() - try - open(filename, "w") do file - write(file, example) - end - - # Use `@trixi_testset`, which wraps code in a temporary module, and call - # `trixi_include` with `@__MODULE__` in order to isolate this test. - @test_warn "You just called" trixi_include(@__MODULE__, filename) - @test @isdefined x - @test x == 4 - - @test_warn "You just called" trixi_include(@__MODULE__, filename, x = 7) - @test x == 7 - - @test_throws "assignment `y` not found in expression" trixi_include(@__MODULE__, - filename, - y = 3) - finally - rm(filename, force = true) - end - end - - @trixi_testset "With `solve` Without `maxiters`" begin - # `trixi_include` assumes this to be the `solve` function of OrdinaryDiffEq, - # and therefore tries to insert the kwarg `maxiters`, which will fail here. - example = """ - solve() = 0 - x = solve() - """ - - filename = tempname() - try - open(filename, "w") do file - write(file, example) - end - - # Use `@trixi_testset`, which wraps code in a temporary module, and call - # `trixi_include` with `@__MODULE__` in order to isolate this test. - @test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__, - filename) - - @test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__, - filename, - maxiters = 3) - finally - rm(filename, force = true) - end - end - - @trixi_testset "With `solve` with `maxiters`" begin - # We need another example file that we include with `Base.include` first, in order to - # define the `solve` method without `trixi_include` trying to insert `maxiters` kwargs. - # Then, we can test that `trixi_include` inserts the kwarg in the `solve()` call. - example1 = """ - solve(; maxiters=0) = maxiters - """ - - example2 = """ - x = solve() - """ - - filename1 = tempname() - filename2 = tempname() - try - open(filename1, "w") do file - write(file, example1) - end - open(filename2, "w") do file - write(file, example2) - end - - # Use `@trixi_testset`, which wraps code in a temporary module, and call - # `Base.include` and `trixi_include` with `@__MODULE__` in order to isolate this test. - Base.include(@__MODULE__, filename1) - @test_warn "You just called" trixi_include(@__MODULE__, filename2) - @test @isdefined x - # This is the default `maxiters` inserted by `trixi_include` - @test x == 10^5 - - @test_warn "You just called" trixi_include(@__MODULE__, filename2, - maxiters = 7) - # Test that `maxiters` got overwritten - @test x == 7 - finally - rm(filename1, force = true) - rm(filename2, force = true) - end - end -end end end #module From 08c6034139451ba03be2abb6748bcd402f151b5d Mon Sep 17 00:00:00 2001 From: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:37:50 +0100 Subject: [PATCH 10/27] Don't export `TrixiBase` (#1846) --- src/Trixi.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index ea72fbc915f..8ab8085d4e8 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -70,7 +70,8 @@ using Triangulate: Triangulate, TriangulateIO, triangulate export TriangulateIO # for type parameter in DGMultiMesh using TriplotBase: TriplotBase using TriplotRecipes: DGTriPseudocolor -@reexport using TrixiBase: TrixiBase, trixi_include +@reexport using TrixiBase: trixi_include +using TrixiBase: TrixiBase @reexport using SimpleUnPack: @unpack using SimpleUnPack: @pack! using DataStructures: BinaryHeap, FasterForward, extract_all! From a872bc55e545baf36be91a949940434ae89f3426 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 16 Feb 2024 06:24:33 +0100 Subject: [PATCH 11/27] set version to v0.6.9 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b4a06a70688..10bf79cf9a5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.6.9-pre" +version = "0.6.9" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 29e173eb5f955771755cc28342e07c9903204327 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 16 Feb 2024 06:24:52 +0100 Subject: [PATCH 12/27] set development version to v0.6.10-pre --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 10bf79cf9a5..af3e6b4d078 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.6.9" +version = "0.6.10-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 3c9374bb6c336be32c56d5c13b213ae3900269a3 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 20 Feb 2024 16:15:48 +0100 Subject: [PATCH 13/27] Classic LWR traffic flow (#1840) * Add classic LWR traffic flow model to Trixi * fmt * shorten * Update examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl * Update examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl * rm IC const, fmt * add davis wave speed estimate for upcoming change * news and md * Use euler * fmt * Update examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl * Update examples/tree_1d_dgsem/elixir_traffic_flow_lwr_trafficjam.jl * Update NEWS.md Co-authored-by: Andrew Winters * Andrew's suggestions * Apply suggestions from code review Co-authored-by: Hendrik Ranocha * add domain of u * back to carpenter kennedy * Update NEWS.md Co-authored-by: Andrew Winters --------- Co-authored-by: Andrew Winters Co-authored-by: Hendrik Ranocha --- NEWS.md | 1 + README.md | 2 +- .../elixir_traffic_flow_lwr_greenlight.jl | 80 ++++++++++++ .../elixir_traffic_flow_lwr_convergence.jl | 54 ++++++++ .../elixir_traffic_flow_lwr_trafficjam.jl | 82 +++++++++++++ src/Trixi.jl | 3 +- src/equations/equations.jl | 5 + src/equations/traffic_flow_lwr_1d.jl | 116 ++++++++++++++++++ test/test_structured_1d.jl | 15 +++ test/test_tree_1d.jl | 3 + test/test_tree_1d_traffic_flow_lwr.jl | 42 +++++++ 11 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl create mode 100644 examples/tree_1d_dgsem/elixir_traffic_flow_lwr_convergence.jl create mode 100644 examples/tree_1d_dgsem/elixir_traffic_flow_lwr_trafficjam.jl create mode 100644 src/equations/traffic_flow_lwr_1d.jl create mode 100644 test/test_tree_1d_traffic_flow_lwr.jl diff --git a/NEWS.md b/NEWS.md index 02a723fca45..feccd1f9852 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,7 @@ for human readability. - Different boundary conditions for quad/hex meshes in Abaqus format, even if not generated by HOHQMesh, can now be digested by Trixi in 2D and 3D. - Subcell (positivity) limiting support for nonlinear variables in 2D for `TreeMesh` +- Added Lighthill-Whitham-Richards (LWR) traffic model ## Changes when updating to v0.6 from v0.5.x diff --git a/README.md b/README.md index c531ab4d1a4..71370d3478e 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ installation and postprocessing procedures. Its features include: * Hyperbolic diffusion equations for elliptic problems * Lattice-Boltzmann equations (D2Q9 and D3Q27 schemes) * Shallow water equations - * Several scalar conservation laws (e.g., linear advection, Burgers' equation) + * Several scalar conservation laws (e.g., linear advection, Burgers' equation, LWR traffic flow) * Multi-physics simulations * [Self-gravitating gas dynamics](https://github.com/trixi-framework/paper-self-gravitating-gas-dynamics) * Shared-memory parallelization via multithreading diff --git a/examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl b/examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl new file mode 100644 index 00000000000..e5badf14451 --- /dev/null +++ b/examples/structured_1d_dgsem/elixir_traffic_flow_lwr_greenlight.jl @@ -0,0 +1,80 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### + +equations = TrafficFlowLWREquations1D() + +solver = DGSEM(polydeg = 3, surface_flux = FluxHLL(min_max_speed_davis)) + +coordinates_min = (-1.0,) # minimum coordinate +coordinates_max = (1.0,) # maximum coordinate +cells_per_dimension = (64,) + +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, + periodicity = false) + +# Example inspired from http://www.clawpack.org/riemann_book/html/Traffic_flow.html#Example:-green-light +# Green light that at x = 0 which switches at t = 0 from red to green. +# To the left there are cars bumper to bumper, to the right there are no cars. +function initial_condition_greenlight(x, t, equation::TrafficFlowLWREquations1D) + scalar = x[1] < 0.0 ? 1.0 : 0.0 + + return SVector(scalar) +end + +############################################################################### +# Specify non-periodic boundary conditions + +# Assume that there are always cars waiting at the left +function inflow(x, t, equations::TrafficFlowLWREquations1D) + return initial_condition_greenlight(coordinates_min, t, equations) +end +boundary_condition_inflow = BoundaryConditionDirichlet(inflow) + +# Cars may leave the modeled domain +function boundary_condition_outflow(u_inner, orientation, normal_direction, x, t, + surface_flux_function, + equations::TrafficFlowLWREquations1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, orientation, equations) + + return flux +end + +boundary_conditions = (x_neg = boundary_condition_inflow, + x_pos = boundary_condition_outflow) + +initial_condition = initial_condition_greenlight + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +stepsize_callback = StepsizeCallback(cfl = 1.2) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_convergence.jl b/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_convergence.jl new file mode 100644 index 00000000000..59258018f8c --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_convergence.jl @@ -0,0 +1,54 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### + +equations = TrafficFlowLWREquations1D() + +# Use first order finite volume to prevent oscillations at the shock +solver = DGSEM(polydeg = 3, surface_flux = flux_hll) + +coordinates_min = 0.0 # minimum coordinate +coordinates_max = 2.0 # maximum coordinate + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 30_000) + +############################################################################### +# Specify non-periodic boundary conditions + +initial_condition = initial_condition_convergence_test +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +stepsize_callback = StepsizeCallback(cfl = 1.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_trafficjam.jl b/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_trafficjam.jl new file mode 100644 index 00000000000..d3a17b513fc --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_traffic_flow_lwr_trafficjam.jl @@ -0,0 +1,82 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### + +equations = TrafficFlowLWREquations1D() + +# Use first order finite volume to prevent oscillations at the shock +solver = DGSEM(polydeg = 0, surface_flux = flux_lax_friedrichs) + +coordinates_min = -1.0 # minimum coordinate +coordinates_max = 1.0 # maximum coordinate + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 9, + n_cells_max = 30_000, + periodicity = false) + +# Example taken from http://www.clawpack.org/riemann_book/html/Traffic_flow.html#Example:-Traffic-jam +# Discontinuous initial condition (Riemann Problem) leading to a shock that moves to the left. +# The shock corresponds to the traffic congestion. +function initial_condition_traffic_jam(x, t, equation::TrafficFlowLWREquations1D) + scalar = x[1] < 0.0 ? 0.5 : 1.0 + + return SVector(scalar) +end + +############################################################################### +# Specify non-periodic boundary conditions + +function outflow(x, t, equations::TrafficFlowLWREquations1D) + return initial_condition_traffic_jam(coordinates_min, t, equations) +end +boundary_condition_outflow = BoundaryConditionDirichlet(outflow) + +function boundary_condition_inflow(u_inner, orientation, normal_direction, x, t, + surface_flux_function, + equations::TrafficFlowLWREquations1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, orientation, equations) + + return flux +end + +boundary_conditions = (x_neg = boundary_condition_outflow, + x_pos = boundary_condition_inflow) + +initial_condition = initial_condition_traffic_jam + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +stepsize_callback = StepsizeCallback(cfl = 1.0) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +# Note: Be careful when increasing the polynomial degree and switching from first order finite volume +# to some actual DG method - in that case, you should also exchange the ODE solver. +sol = solve(ode, Euler(), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index 8ab8085d4e8..bf0986084af 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -157,7 +157,8 @@ export AcousticPerturbationEquations2D, ShallowWaterTwoLayerEquations1D, ShallowWaterTwoLayerEquations2D, ShallowWaterEquationsQuasi1D, LinearizedEulerEquations2D, - PolytropicEulerEquations2D + PolytropicEulerEquations2D, + TrafficFlowLWREquations1D export LaplaceDiffusion1D, LaplaceDiffusion2D, LaplaceDiffusion3D, CompressibleNavierStokesDiffusion1D, CompressibleNavierStokesDiffusion2D, diff --git a/src/equations/equations.jl b/src/equations/equations.jl index c041bf117ba..65875a2a7e5 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -507,4 +507,9 @@ include("linearized_euler_2d.jl") abstract type AbstractEquationsParabolic{NDIMS, NVARS, GradientVariables} <: AbstractEquations{NDIMS, NVARS} end + +# Lighthill-Witham-Richards (LWR) traffic flow model +abstract type AbstractTrafficFlowLWREquations{NDIMS, NVARS} <: + AbstractEquations{NDIMS, NVARS} end +include("traffic_flow_lwr_1d.jl") end # @muladd diff --git a/src/equations/traffic_flow_lwr_1d.jl b/src/equations/traffic_flow_lwr_1d.jl new file mode 100644 index 00000000000..a4d2613a5c8 --- /dev/null +++ b/src/equations/traffic_flow_lwr_1d.jl @@ -0,0 +1,116 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +@doc raw""" + TrafficFlowLWREquations1D + +The classic Lighthill-Witham Richards (LWR) model for 1D traffic flow. +The car density is denoted by $u \in [0, 1]$ and +the maximum possible speed (e.g. due to speed limits) is $v_{\text{max}}$. +```math +\partial_t u + v_{\text{max}} \partial_1 [u (1 - u)] = 0 +``` +For more details see e.g. Section 11.1 of +- Randall LeVeque (2002) +Finite Volume Methods for Hyperbolic Problems +[DOI: 10.1017/CBO9780511791253]https://doi.org/10.1017/CBO9780511791253 +""" +struct TrafficFlowLWREquations1D{RealT <: Real} <: AbstractTrafficFlowLWREquations{1, 1} + v_max::RealT + + function TrafficFlowLWREquations1D(v_max = 1.0) + new{typeof(v_max)}(v_max) + end +end + +varnames(::typeof(cons2cons), ::TrafficFlowLWREquations1D) = ("car-density",) +varnames(::typeof(cons2prim), ::TrafficFlowLWREquations1D) = ("car-density",) + +""" + initial_condition_convergence_test(x, t, equations::TrafficFlowLWREquations1D) + +A smooth initial condition used for convergence tests. +""" +function initial_condition_convergence_test(x, t, equations::TrafficFlowLWREquations1D) + c = 2.0 + A = 1.0 + L = 1 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * (x[1] - t)) + + return SVector(scalar) +end + +""" + source_terms_convergence_test(u, x, t, equations::TrafficFlowLWREquations1D) + +Source terms used for convergence tests in combination with +[`initial_condition_convergence_test`](@ref). +""" +@inline function source_terms_convergence_test(u, x, t, + equations::TrafficFlowLWREquations1D) + # Same settings as in `initial_condition` + c = 2.0 + A = 1.0 + L = 1 + f = 1 / L + omega = 2 * pi * f + du = omega * cos(omega * (x[1] - t)) * + (-1 - equations.v_max * (2 * sin(omega * (x[1] - t)) + 3)) + + return SVector(du) +end + +# Calculate 1D flux in for a single point +@inline function flux(u, orientation::Integer, equations::TrafficFlowLWREquations1D) + return SVector(equations.v_max * u[1] * (1.0 - u[1])) +end + +# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::TrafficFlowLWREquations1D) + λ_max = max(abs(equations.v_max * (1.0 - 2 * u_ll[1])), + abs(equations.v_max * (1.0 - 2 * u_rr[1]))) +end + +# Calculate minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::TrafficFlowLWREquations1D) + jac_L = equations.v_max * (1.0 - 2 * u_ll[1]) + jac_R = equations.v_max * (1.0 - 2 * u_rr[1]) + + λ_min = min(jac_L, jac_R) + λ_max = max(jac_L, jac_R) + + return λ_min, λ_max +end + +@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::TrafficFlowLWREquations1D) + min_max_speed_naive(u_ll, u_rr, orientation, equations) +end + +@inline function max_abs_speeds(u, equations::TrafficFlowLWREquations1D) + return (abs(equations.v_max * (1.0 - 2 * u[1])),) +end + +# Convert conservative variables to primitive +@inline cons2prim(u, equations::TrafficFlowLWREquations1D) = u + +# Convert conservative variables to entropy variables +@inline cons2entropy(u, equations::TrafficFlowLWREquations1D) = u + +# Calculate entropy for a conservative state `cons` +@inline entropy(u::Real, ::TrafficFlowLWREquations1D) = 0.5 * u^2 +@inline entropy(u, equations::TrafficFlowLWREquations1D) = entropy(u[1], equations) + +# Calculate total energy for a conservative state `cons` +@inline energy_total(u::Real, ::TrafficFlowLWREquations1D) = 0.5 * u^2 +@inline energy_total(u, equations::TrafficFlowLWREquations1D) = energy_total(u[1], + equations) +end # @muladd diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index f0eecfa9acd..fea06554c57 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -138,6 +138,21 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + +@trixi_testset "elixir_traffic_flow_lwr_greenlight.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_traffic_flow_lwr_greenlight.jl"), + l2=[0.2005523261652845], + linf=[0.5052827913468407]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index 4654f6313f7..8b470278ffd 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -47,6 +47,9 @@ isdir(outdir) && rm(outdir, recursive = true) # FDSBP methods on the TreeMesh include("test_tree_1d_fdsbp.jl") + + # Traffic flow LWR + include("test_tree_1d_traffic_flow_lwr.jl") end # Coverage test for all initial conditions diff --git a/test/test_tree_1d_traffic_flow_lwr.jl b/test/test_tree_1d_traffic_flow_lwr.jl new file mode 100644 index 00000000000..54412e314b3 --- /dev/null +++ b/test/test_tree_1d_traffic_flow_lwr.jl @@ -0,0 +1,42 @@ +module TestExamples1DTrafficFlowLWR + +using Test +using Trixi + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") + +@testset "Traffic-flow LWR" begin +#! format: noindent + +@trixi_testset "elixir_traffic_flow_lwr_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_traffic_flow_lwr_convergence.jl"), + l2=[0.0008455067389588569], + linf=[0.004591951086623913]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_traffic_flow_lwr_trafficjam.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_traffic_flow_lwr_trafficjam.jl"), + l2=[0.1761758135539748], linf=[0.5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end +end + +end # module From c5e743aa1b229562132e3bbfbd936e995404739f Mon Sep 17 00:00:00 2001 From: Simon Candelaresi <10759273+SimonCan@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:38:26 +0000 Subject: [PATCH 14/27] WIP: Sc/polytropic 2d wave speed (#1816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added coupling converters. * Added generic converter_function for structured 2d meshes. * Added example elixir for coupling converters. * Cleaned up converter coupling elixir. * Added equations in coupling converters. * Added converter functions. * Added identity converter function. * Autoformat for converter coupling implementation. * Added coupled converter elixir. * Corrected file name of coupled converters test. * Removed redundant doc string. * Added function signature in doc string. * Removed coverage_override in coupled tests. * Removed old commented code. * Update make.jl Added interface coupling docs to the main menu. * Update make.jl Moved converter coupling section. * Create coupling.md * Update coupling.md Added some documentation on coupling converters. * Removed troublesome AnalysisCallbackCoupled from test. * Chenged coupling converter function. * Changed coupling converter function and updated tests. * Sepcialized coupling function call. * Removed volume coupling from documentation to avoit confusion. * Update src/coupling_converters/coupling_converters.jl Co-authored-by: Hendrik Ranocha * Removed redundant converter function for coupling. * Removed redundant coupling converter file mentioned in some files. * Autoreformatted. * Removed old coupled elixir and replaced it with one using converter functions. * Updated errors for coupled tests. * Corrected test results for coupled equations. * Corrected comment. * Removed coupled test from special tests. * Removed coupled test from specials. * Chaned the coupling function to the identity. * Updated coupling tests. * Updated errors for coupled test. * Added advice about binary compatability for coupled equations in the documentation. * Typo. * Added numerical fluxes. * Corrected rs copy routine. Now loop over this semi's components. * Reformatted equations source file. * Removed problemating include of time_integration.jl. * Removed export of deleted methods. * Reverted to old version of compressible Euler multicomponent with no support for structured grid. * Renamed documentation file for multi-physics coupling. * Renamed doc reference. * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/src/multi-physics_coupling.md Co-authored-by: Michael Schlottke-Lakemper * Update docs/src/multi-physics_coupling.md Co-authored-by: Michael Schlottke-Lakemper * Update docs/src/multi-physics_coupling.md Co-authored-by: Michael Schlottke-Lakemper * Reinstated structured_2d_dgsem coupled in special tests. * Update examples/structured_2d_dgsem/elixir_advection_coupled.jl Co-authored-by: Michael Schlottke-Lakemper * Renamed CouplingFunction to CouplingConverter. * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Michael Schlottke-Lakemper * Cleaned the copy of coupled boundary values. * Reduced time span for example coupling elixir. * Removed redundant loop. * Applied formatter. * Removed default coupling covnerter function. * Moved coupling converter function into elixir. * Apply suggestions from code review Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/make.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Removed coupling_converters.jl from the include. * Corrected introduced issue with coupling boundary copy. The latest change to clean up the boundary copying introduced a bug related to the determination of the wrong node indices. This is now corrected. * Corrected comment on final simulation time. * Updated errors for coupled test to reflect changed final simulation time. * Added miladd. * Corrected coordinate finding in semidiscretization_coupled. * Fixed issued related to memory allocation. * Corrected loop over semidiscretization. * Removed commented out code. * Fixed type instability with loops over semidiscretizations using lispy tuple programming. * Removed obsolete code. * Fixed another typa instability in coupled semidiscretization. * Cleaning up of the coupled semidiscretization. * Autoformatted coupled semidiscretization. * Fixed last type instability in coupling. * Autoformatter on semidiscretization. * Fixed bug in boundary values copy that arose when coupling multiple systems. * aplpied autoformatter on coupled semidiscretization. * Extended the structured 2d example elixir for the coupled advection to 4 semidiscretizations. This hase two purpuses: 1. Users are given an example fro 2d coupling avoiding common pitfalls. 2. This increases the code coverege for the test. * Updated test results for coupled advection in 2d to reflect the 4 semidiscretizations that are now used. * Added correct errors for tests for the coupled adveciton equations in structured 2d. * Update examples/structured_2d_dgsem/elixir_advection_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update examples/structured_2d_dgsem/elixir_advection_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Update src/semidiscretization/semidiscretization_coupled.jl Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> * Corrected foreach_enumerate implementation. * Fix closing parens * Remove unused recursive rhs! * Pass equations to converter function * Apply formatting * Reverted copy_to_coupled_boundary to previou version to avoid type instability. * Corrected computation of coupled semidiscretizations and fixed memory issue. * Removed redundant nelements function, as it is no longer used. * Applied autoformatter. * Added max_abs_speed_naive( and max_abs_speed_naive for PolytropicEulerEquations2D. * Reverted coupling elixir to main branch version. The modified version should be part of a different PR. * Removed some modified coupling code as this should be part of a different PR. * Reverted changes on ooupling semidiscretization as this should be part of a different PR. * Reverted changes partaining the coupling PR. * Removed changes partaining coupling PR. * REverted to version including elixir_euler_warm_bubble.jl tests. * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrew Winters * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrew Winters * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrew Winters * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrés Rueda-Ramírez * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrés Rueda-Ramírez * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Daniel Doehring * Added consistency and rotation test for LAx-friedrich fluxes for polytropic equations in 2d. * Applied auto-formatter on polytropic 2d equation. * Update src/equations/polytropic_euler_2d.jl Co-authored-by: Andrew Winters --------- Co-authored-by: Michael Schlottke-Lakemper Co-authored-by: Hendrik Ranocha Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com> Co-authored-by: Andrew Winters Co-authored-by: Andrés Rueda-Ramírez Co-authored-by: Daniel Doehring Co-authored-by: iomsn --- src/equations/polytropic_euler_2d.jl | 40 ++++++++++++++++++++++++++++ test/test_unit.jl | 24 +++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/equations/polytropic_euler_2d.jl b/src/equations/polytropic_euler_2d.jl index f5d2f7b0bad..e900fd64073 100644 --- a/src/equations/polytropic_euler_2d.jl +++ b/src/equations/polytropic_euler_2d.jl @@ -301,6 +301,46 @@ end return abs(v1) + c, abs(v2) + c end +# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation as the +# maximum velocity magnitude plus the maximum speed of sound +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::PolytropicEulerEquations2D) + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + + # Get the velocity value in the appropriate direction + if orientation == 1 + v_ll = v1_ll + v_rr = v1_rr + else # orientation == 2 + v_ll = v2_ll + v_rr = v2_rr + end + # Calculate sound speeds (we have p = kappa * rho^gamma) + c_ll = sqrt(equations.gamma * equations.kappa * rho_ll^(equations.gamma - 1)) + c_rr = sqrt(equations.gamma * equations.kappa * rho_rr^(equations.gamma - 1)) + + λ_max = max(abs(v_ll), abs(v_rr)) + max(c_ll, c_rr) +end + +@inline function max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::PolytropicEulerEquations2D) + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + + # Calculate normal velocities and sound speed (we have p = kappa * rho^gamma) + # left + v_ll = (v1_ll * normal_direction[1] + + v2_ll * normal_direction[2]) + c_ll = sqrt(equations.gamma * equations.kappa * rho_ll^(equations.gamma - 1)) + # right + v_rr = (v1_rr * normal_direction[1] + + v2_rr * normal_direction[2]) + c_rr = sqrt(equations.gamma * equations.kappa * rho_rr^(equations.gamma - 1)) + + return max(abs(v_ll), abs(v_rr)) + max(c_ll, c_rr) * norm(normal_direction) +end + # Convert conservative variables to primitive @inline function cons2prim(u, equations::PolytropicEulerEquations2D) rho, rho_v1, rho_v2 = u diff --git a/test/test_unit.jl b/test/test_unit.jl index 3b8dc3c4331..c1379587cc8 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -858,6 +858,30 @@ end end end +@timed_testset "Consistency check for Lax-Friedrich flux: Polytropic CEE" begin + for gamma in [1.4, 1.0, 5 / 3] + kappa = 0.5 # Scaling factor for the pressure. + equations = PolytropicEulerEquations2D(gamma, kappa) + u = SVector(1.1, -0.5, 2.34) + + orientations = [1, 2] + for orientation in orientations + @test flux_lax_friedrichs(u, u, orientation, equations) ≈ + flux(u, orientation, equations) + end + + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + + for normal_direction in normal_directions + @test flux_lax_friedrichs(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) + end + end +end + @timed_testset "Consistency check for HLL flux with Davis wave speed estimates: LEE" begin flux_hll = FluxHLL(min_max_speed_davis) From e98a76b92fa1272b547b2abc997cfb1d885012f4 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 21 Feb 2024 11:02:15 +0100 Subject: [PATCH 15/27] improve benchmarks --- benchmark/benchmarks.jl | 12 ++++++++---- benchmark/run_benchmarks.jl | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index 15d1d96c05f..0d6fabcd4a9 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -2,6 +2,9 @@ # readability #! format: off +using Pkg +Pkg.activate(@__DIR__) + using BenchmarkTools using Trixi @@ -47,13 +50,14 @@ end let SUITE["latency"] = BenchmarkGroup() SUITE["latency"]["default_example"] = @benchmarkable run( - `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(default_example())'`) seconds=60 + `$(Base.julia_cmd()) --project=$(@__DIR__) -e 'using Trixi; trixi_include(default_example())'`) seconds=60 for polydeg in [3, 7] command = "using Trixi; trixi_include(joinpath(examples_dir(), \"tree_2d_dgsem\", \"elixir_advection_extended.jl\"), tspan=(0.0, 1.0e-10), polydeg=$(polydeg), save_restart=TrivialCallback(), save_solution=TrivialCallback())" - SUITE["latency"]["polydeg_$polydeg"] = @benchmarkable run($`$(Base.julia_cmd()) -e $command`) seconds=60 + SUITE["latency"]["polydeg_$polydeg"] = @benchmarkable run( + $`$(Base.julia_cmd()) --project=$(@__DIR__) -e $command`) seconds=60 end SUITE["latency"]["euler_2d"] = @benchmarkable run( - `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_kelvin_helmholtz_instability.jl"), tspan=(0.0, 1.0e-10), save_restart=TrivialCallback(), save_solution=TrivialCallback())'`) seconds=60 + `$(Base.julia_cmd()) --project=$(@__DIR__) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_kelvin_helmholtz_instability.jl"), tspan=(0.0, 1.0e-10), save_solution=TrivialCallback())'`) seconds=60 SUITE["latency"]["mhd_2d"] = @benchmarkable run( - `$(Base.julia_cmd()) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_mhd_blast_wave.jl"), tspan=(0.0, 1.0e-10), save_solution=TrivialCallback())'`) seconds=60 + `$(Base.julia_cmd()) --project=$(@__DIR__) -e 'using Trixi; trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_mhd_blast_wave.jl"), tspan=(0.0, 1.0e-10), save_solution=TrivialCallback())'`) seconds=60 end diff --git a/benchmark/run_benchmarks.jl b/benchmark/run_benchmarks.jl index 3a92a9ba700..e4e15223ea7 100644 --- a/benchmark/run_benchmarks.jl +++ b/benchmark/run_benchmarks.jl @@ -1,3 +1,7 @@ +using Pkg +Pkg.activate(@__DIR__) +Pkg.develop(PackageSpec(path=dirname(@__DIR__))) +Pkg.instantiate() using PkgBenchmark using Trixi From 40b73cfde2a707dfc8d76ea92712a2287fd2e9e2 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 21 Feb 2024 11:12:54 +0100 Subject: [PATCH 16/27] format benchmarks --- benchmark/run_benchmarks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/run_benchmarks.jl b/benchmark/run_benchmarks.jl index e4e15223ea7..7b8c25752f8 100644 --- a/benchmark/run_benchmarks.jl +++ b/benchmark/run_benchmarks.jl @@ -1,6 +1,6 @@ using Pkg Pkg.activate(@__DIR__) -Pkg.develop(PackageSpec(path=dirname(@__DIR__))) +Pkg.develop(PackageSpec(path = dirname(@__DIR__))) Pkg.instantiate() using PkgBenchmark From c3c0986a2eaf52a145cd59ab591ea3af75b40571 Mon Sep 17 00:00:00 2001 From: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:39:41 +0100 Subject: [PATCH 17/27] Create Downgrade.yml (second try) (#1848) * add downgrade.yml and bump compats * also downgrade test/Project.toml * bump lower compat for ForwardDiff in tests * allow older version of HDF5 * allow newest versions of Makie and CairoMakie * allow newest version of T8code * remove compat 0.11 from CairoMakie --- .github/workflows/Downgrade.yml | 86 +++++++++++++++++++++++++++++++++ Project.toml | 24 ++++----- test/Project.toml | 6 +-- 3 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/Downgrade.yml diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml new file mode 100644 index 00000000000..c84b1026d1b --- /dev/null +++ b/.github/workflows/Downgrade.yml @@ -0,0 +1,86 @@ +name: Downgrade + +on: + pull_request: + paths-ignore: + - 'AUTHORS.md' + - 'CITATION.bib' + - 'CONTRIBUTING.md' + - 'LICENSE.md' + - 'NEWS.md' + - 'README.md' + - '.zenodo.json' + - '.github/workflows/benchmark.yml' + - '.github/workflows/CompatHelper.yml' + - '.github/workflows/TagBot.yml' + - 'benchmark/**' + - 'docs/**' + - 'utils/**' + workflow_dispatch: + +# Cancel redundant CI tests automatically +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + downgrade_test: + if: "!contains(github.event.head_commit.message, 'skip ci')" + # We could also include the Julia version as in + # name: ${{ matrix.trixi_test }} - ${{ matrix.os }} - Julia ${{ matrix.version }} - ${{ matrix.arch }} - ${{ github.event_name }} + # to be more specific. However, that requires us updating the required CI tests whenever we update Julia. + name: Downgrade ${{ matrix.trixi_test }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - '1.9' + # - '~1.9.0-0' # including development versions + # - 'nightly' + os: + - ubuntu-latest + arch: + - x64 + trixi_test: + # - tree_part1 + # - tree_part2 + # - tree_part3 + # - tree_part4 + # - tree_part5 + # - tree_part6 + # - structured + # - p4est_part1 + # - p4est_part2 + # - t8code_part1 + # - unstructured_dgmulti + # - parabolic + # - paper_self_gravitating_gas_dynamics + # - misc_part1 + # - misc_part2 + # - performance_specializations_part1 + # - performance_specializations_part2 + # - mpi + - threaded + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - run: julia -e 'using InteractiveUtils; versioninfo(verbose=true)' + - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-downgrade-compat@v1 + with: + skip: LinearAlgebra,Printf,SparseArrays,DiffEqBase + projects: ., test + - uses: julia-actions/julia-buildpkg@v1 + env: + PYTHON: "" + - name: Run tests without coverage + uses: julia-actions/julia-runtest@v1 + with: + coverage: false + env: + PYTHON: "" + TRIXI_TEST: ${{ matrix.trixi_test }} diff --git a/Project.toml b/Project.toml index af3e6b4d078..9bed045637a 100644 --- a/Project.toml +++ b/Project.toml @@ -62,17 +62,17 @@ DiffEqCallbacks = "2.25" Downloads = "1.6" EllipsisNotation = "1.0" FillArrays = "0.13.2, 1" -ForwardDiff = "0.10.18" -HDF5 = "0.14, 0.15, 0.16, 0.17" +ForwardDiff = "0.10.24" +HDF5 = "0.16.10, 0.17" IfElse = "0.1" LinearAlgebra = "1" LinearMaps = "2.7, 3.0" -LoopVectorization = "0.12.118" +LoopVectorization = "0.12.151" MPI = "0.20" Makie = "0.19, 0.20" MuladdMacro = "0.2.2" -Octavian = "0.3.5" -OffsetArrays = "1.3" +Octavian = "0.3.21" +OffsetArrays = "1.12" P4est = "0.4.9" Polyester = "0.7.5" PrecompileTools = "1.1" @@ -81,19 +81,19 @@ RecipesBase = "1.1" Reexport = "1.0" Requires = "1.1" SciMLBase = "1.90, 2" -Setfield = "0.8, 1" +Setfield = "1" SimpleUnPack = "1.1" SparseArrays = "1" -StartUpDG = "0.17" -Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" +StartUpDG = "0.17.7" +Static = "0.8.7" StaticArrayInterface = "1.4" -StaticArrays = "1" -StrideArrays = "0.1.18" -StructArrays = "0.6" +StaticArrays = "1.5" +StrideArrays = "0.1.26" +StructArrays = "0.6.11" SummationByPartsOperators = "0.5.41" T8code = "0.4.3, 0.5" TimerOutputs = "0.5.7" -Triangulate = "2.0" +Triangulate = "2.2" TriplotBase = "0.1" TriplotRecipes = "0.1" TrixiBase = "0.1.1" diff --git a/test/Project.toml b/test/Project.toml index ecae0ac0900..a376c2805ea 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -13,13 +13,13 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] Aqua = "0.8" -CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" +CairoMakie = "0.10" Downloads = "1" -ForwardDiff = "0.10" +ForwardDiff = "0.10.24" LinearAlgebra = "1" MPI = "0.20" OrdinaryDiffEq = "6.49.1" -Plots = "1.16" +Plots = "1.19" Printf = "1" Random = "1" Test = "1" From 1b2abd00e9b74d2cd185b0d06c5cf3182011e6c4 Mon Sep 17 00:00:00 2001 From: ArseniyKholod <119304909+ArseniyKholod@users.noreply.github.com> Date: Wed, 21 Feb 2024 12:48:03 +0200 Subject: [PATCH 18/27] Doc: Core aspects of the basic setup (#1699) * Doc: Core aspects of the basic setup * update pictures * Update innards_of_the_basic_setup.jl * mention ODE-Solvers * Revert "Revert "Merge branch 'main' into semidiscretization-doc"" This reverts commit 85d6e8b50261885ad198ae4036e8599189912e56. * Revert "Merge branch 'main' into semidiscretization-doc" This reverts commit b8f8b0bc167a476b3dead39f6aadf4fe43601e7d, reversing changes made to bb518f50053cef054220fd35542f52a47214a997. * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/literate/src/files/innards_of_the_basic_setup.jl Co-authored-by: Michael Schlottke-Lakemper * Update docs/make.jl Co-authored-by: Michael Schlottke-Lakemper * Rename innards_of_the_basic_setup.jl to behind_the_scenes_simulation_setup.jl * add plot scripts * Format_and_last_review_changes * spell+output_directory_figures * spell * N->polydeg * add README for plots * line length <=100 * Update docs/literate/src/files/behind_the_scenes_simulation_setup_plots/README.md * add empty lines * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Andrew Winters * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * mention method of lines * Update behind_the_scenes_simulation_setup.jl * Update behind_the_scenes_simulation_setup.jl * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * simplify rhs description * format * add interpolation to mortars * Update behind_the_scenes_simulation_setup.jl * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * add resizability explanation * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Daniel Doehring * format * add introduction as 2nd tutorial * fix * Update docs/literate/src/files/behind_the_scenes_simulation_setup.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> * add unsafe_wrap explanation --------- Co-authored-by: Michael Schlottke-Lakemper Co-authored-by: Andrew Winters Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> Co-authored-by: Daniel Doehring --- .../behind_the_scenes_simulation_setup.jl | 253 ++++++++++++++++++ .../Project.toml | 2 + .../README.md | 15 ++ ...scretizationHyperbolic_structure_figure.jl | 64 +++++ .../src/generate_boundary_figure.jl | 190 +++++++++++++ .../src/generate_elements_figure.jl | 117 ++++++++ .../src/generate_interfaces_figure.jl | 157 +++++++++++ .../src/generate_mortars_figure.jl | 166 ++++++++++++ .../src/generate_nodes_figure.jl | 6 + .../src/generate_treemesh_figure.jl | 26 ++ .../src/rhs_structure_figure.jl | 43 +++ .../src/semidiscretize_structure_figure.jl | 51 ++++ docs/literate/src/files/index.jl | 45 ++-- docs/make.jl | 3 +- 14 files changed, 1119 insertions(+), 19 deletions(-) create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/Project.toml create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/README.md create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/SemidiscretizationHyperbolic_structure_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_boundary_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_elements_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_interfaces_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_mortars_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_nodes_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_treemesh_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/rhs_structure_figure.jl create mode 100644 docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/semidiscretize_structure_figure.jl diff --git a/docs/literate/src/files/behind_the_scenes_simulation_setup.jl b/docs/literate/src/files/behind_the_scenes_simulation_setup.jl new file mode 100644 index 00000000000..c93660e9bc1 --- /dev/null +++ b/docs/literate/src/files/behind_the_scenes_simulation_setup.jl @@ -0,0 +1,253 @@ +#src # Behind the scenes of a simulation setup + +# This tutorial will guide you through a simple Trixi.jl setup ("elixir"), giving an overview of +# what happens in the background during the initialization of a simulation. While the setup +# described herein does not cover all details, it involves relatively stable parts of Trixi.jl that +# are unlikely to undergo significant changes in the near future. The goal is to clarify some of +# the more fundamental, *technical* concepts that are applicable to a variety of +# (also more complex) configurations. + +# Trixi.jl follows the [method of lines](http://www.scholarpedia.org/article/Method_of_lines) concept for solving partial differential equations (PDEs). +# Firstly, the PDEs are reduced to a (potentially huge) system of +# ordinary differential equations (ODEs) by discretizing the spatial derivatives. Subsequently, +# these generated ODEs may be solved with methods available in OrdinaryDiffEq.jl or those specifically +# implemented in Trixi.jl. The following steps elucidate the process of transitioning from PDEs to +# ODEs within the framework of Trixi.jl. + +# ## Basic setup + +# Import essential libraries and specify an equation. + +using Trixi, OrdinaryDiffEq +equations = LinearScalarAdvectionEquation2D((-0.2, 0.7)) + +# Generate a spatial discretization using a [`TreeMesh`](@ref) with a pre-coarsened set of cells. + +coordinates_min = (-2.0, -2.0) +coordinates_max = (2.0, 2.0) + +coarsening_patches = ((type = "box", coordinates_min = [0.0, -2.0], + coordinates_max = [2.0, 0.0]),) + +mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level = 2, + n_cells_max = 30_000, + coarsening_patches = coarsening_patches) + +# The created `TreeMesh` looks like the following: + +# ![TreeMesh_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/d5ef76ee-8246-4730-a692-b472c06063a3) + +# Instantiate a [`DGSEM`](@ref) solver with a user-specified polynomial degree. The solver +# will define `polydeg + 1` [Gauss-Lobatto nodes](https://en.wikipedia.org/wiki/Gaussian_quadrature#Gauss%E2%80%93Lobatto_rules) and their associated weights within +# the reference interval ``[-1, 1]`` in each spatial direction. These nodes will be subsequently +# used to approximate solutions on each leaf cell of the `TreeMesh`. + +solver = DGSEM(polydeg = 3) + +# Gauss-Lobatto nodes with `polydeg = 3`: + +# ![Gauss-Lobatto_nodes_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/1d894611-801e-4f75-bff0-d77ca1c672e5) + +# ## Overview of the [`SemidiscretizationHyperbolic`](@ref) type + +# At this stage, all necessary components for configuring the spatial discretization are in place. +# The remaining task is to combine these components into a single structure that will be used +# throughout the entire simulation process. This is where [`SemidiscretizationHyperbolic`](@ref) +# comes into play. + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) + +# The constructor for the `SemidiscretizationHyperbolic` object calls numerous sub-functions to +# perform the necessary initialization steps. A brief description of the key sub-functions is +# provided below. + + +# - `init_elements(leaf_cell_ids, mesh, equations, dg.basis, RealT, uEltype)` + +# The fundamental elements for approximating the solution are the leaf +# cells. The solution is constructed as a polynomial of the degree specified in the `DGSEM` +# solver in each spatial direction on each leaf cell. This polynomial approximation is evaluated +# at the Gauss-Lobatto nodes mentioned earlier. The `init_elements` function extracts +# these leaf cells from the `TreeMesh`, assigns them the label "elements", records their +# coordinates, and maps the Gauss-Lobatto nodes from the 1D interval ``[-1, 1]`` onto each coordinate axis +# of every element. + + +# ![elements_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/9f486670-b579-4e42-8697-439540c8bbb4) + +# The visualization of elements with nodes shown here includes spaces between elements, which do +# not exist in reality. This spacing is included only for illustrative purposes to underscore the +# separation of elements and the independent projection of nodes onto each element. + + +# - `init_interfaces(leaf_cell_ids, mesh, elements)` + +# At this point, the elements with nodes have been defined; however, they lack the necessary +# communication functionality. This is crucial because the local solution polynomials on the +# elements are not independent of each other. Furthermore, nodes on the boundary of adjacent +# elements share the same spatial location, which requires a method to combine this into a +# meaningful solution. +# Here [Riemann solvers](https://en.wikipedia.org/wiki/Riemann_solver#Approximate_solvers) +# come into play which can handle the principal ambiguity of a multi-valued solution at the +# same spatial location. + +# As demonstrated earlier, the elements can have varying sizes. Let us initially consider +# neighbors with equal size. For these elements, the `init_interfaces` function generates +# interfaces that store information about adjacent elements, their relative positions, and +# allocate containers for sharing solution data between neighbors during the solution process. + +# In our visualization, these interfaces would conceptually resemble tubes connecting the +# corresponding elements. + +# ![interfaces_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/bc3b6b02-afbc-4371-aaf7-c7bdc5a6c540) + + +# - `init_mortars(leaf_cell_ids, mesh, elements, dg.mortar)` + +# Returning to the consideration of different sizes among adjacent elements, within the +# `TreeMesh`, adjacent leaf cells can vary in side length by a maximum factor of two. This +# implies that a large element has one neighbor of +# equal size with a connection through an interface, or two neighbors at half the size, +# requiring a connection through so called "mortars". In 3D, a large element would have +# four small neighbor elements. + +# Mortars store information about the connected elements, their relative positions, and allocate +# containers for storing the solutions along the boundaries between these elements. + +# Due to the differing sizes of adjacent elements, it is not feasible to directly map boundary +# nodes of adjacent elements. Therefore, the concept of mortars employs a mass-conserving +# interpolation function to map boundary nodes from a larger element to a smaller one. + +# In our visualization, mortars are represented as branched tubes. + +# ![mortars_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/43a95a60-3a31-4b1f-8724-14049e7a0481) + + +# - `init_boundaries(leaf_cell_ids, mesh, elements)` + +# In order to apply boundary conditions, it is necessary to identify the locations of the +# boundaries. Therefore, we initialize a "boundaries" object, which records the elements that +# contain boundaries, specifies which side of an element is a boundary, stores the coordinates +# of boundary nodes, and allocates containers for managing solutions at these boundaries. + +# In our visualization, boundaries and their corresponding nodes are highlighted with green, +# semi-transparent lines. + +# ![boundaries_example](https://github.com/trixi-framework/Trixi.jl/assets/119304909/21996b20-4a22-4dfb-b16a-e2c22c2f29fe) + +# All the structures mentioned earlier are collected as a cache of type `NamedTuple`. Subsequently, +# an object of type `SemidiscretizationHyperbolic` is initialized using this cache, initial and +# boundary conditions, equations, mesh and solver. + +# In conclusion, the primary purpose of a `SemidiscretizationHyperbolic` is to collect equations, +# the geometric representation of the domain, and approximation instructions, creating specialized +# structures to interconnect these components in a manner that enables their utilization for +# the numerical solution of partial differential equations (PDEs). + +# As evident from the earlier description of `SemidiscretizationHyperbolic`, it comprises numerous +# functions called subsequently. Without delving into details, the structure of the primary calls +# are illustrated as follows: + +# ![SemidiscretizationHyperbolic_structure](https://github.com/trixi-framework/Trixi.jl/assets/119304909/8bf59422-0537-4d7a-9f13-d9b2253c19d7) + +# ## Overview of the [`semidiscretize`](@ref) function + +# At this stage, we have defined the equations and configured the domain's discretization. The +# final step before solving is to select a suitable time span and apply the corresponding initial +# conditions, which are already stored in the initialized `SemidiscretizationHyperbolic` object. + +# The purpose of the [`semidiscretize`](@ref) function is to wrap the semidiscretization as an +# `ODEProblem` within the specified time interval. During this procedure the approximate solution +# is created at the given initial time via the specified `initial_condition` function from the +# `SemidiscretizationHyperbolic` object. This `ODEProblem` can be subsequently passed to the +# `solve` function from the [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) package +# or to [`Trixi.solve`](@ref). + +ode = semidiscretize(semi, (0.0, 1.0)); + +# The `semidiscretize` function involves a deep tree of subsequent calls, with the primary ones +# explained below. + + +# - `allocate_coefficients(mesh, equations, solver, cache)` + +# To apply initial conditions, a data structure ("container") needs to be generated to store the +# initial values of the target variables for each node within each element. + +# Since only one-dimensional `Array`s are `resize!`able in Julia, we use `Vector`s as an internal +# storage for the target variables and `resize!` them whenever needed, e.g. to change the number +# of elements. Then, during the solving process the same memory is reused by `unsafe_wrap`ping +# multi-dimensional `Array`s around the internal storage. + +# - `wrap_array(u_ode, semi)` + +# As previously noted, `u_ode` is constructed as a 1D vector to ensure compatibility with +# OrdinaryDiffEq.jl. However, for internal use within Trixi.jl, identifying which part of the +# vector relates to specific variables, elements, or nodes can be challenging. + +# This is why the `u_ode` vector is wrapped by the `wrap_array` function using `unsafe_wrap` +# to form a multidimensional array `u`. In this array, the first dimension corresponds to +# variables, followed by N dimensions corresponding to nodes for each of N space dimensions. +# The last dimension corresponds to the elements. +# Consequently, navigation within this multidimensional array becomes noticeably easier. + +# "Wrapping" in this context involves the creation of a reference to the same storage location +# but with an alternative structural representation. This approach enables the use of both +# instances `u` and `u_ode` as needed, so that changes are simultaneously reflected in both. +# This is possible because, from a storage perspective, they share the same stored data, while +# access to this data is provided in different ways. + + +# - `compute_coefficients!(u, initial_conditions, t, mesh::DG, equations, solver, cache)` + +# Now the variable `u`, intended to store solutions, has been allocated and wrapped, it is time +# to apply the initial conditions. The `compute_coefficients!` function calculates the initial +# conditions for each variable at every node within each element and properly stores them in the +# `u` array. + +# At this stage, the `semidiscretize` function has all the necessary components to initialize and +# return an `ODEProblem` object, which will be used by the `solve` function to compute the +# solution. + +# In summary, the internal workings of `semidiscretize` with brief descriptions can be presented +# as follows. + +# ![semidiscretize_structure](https://github.com/trixi-framework/Trixi.jl/assets/119304909/491eddc4-aadb-4e29-8c76-a7c821d0674e) + +# ## Functions `solve` and `rhs!` + +# Once the `ODEProblem` object is initialized, the `solve` function and one of the ODE solvers from +# the OrdinaryDiffEq.jl package can be utilized to compute an approximated solution using the +# instructions contained in the `ODEProblem` object. + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), dt = 0.01, + save_everystep = false); + +# Since the `solve` function and the ODE solver have no knowledge +# of a particular spatial discretization, it is necessary to define a +# "right-hand-side function", `rhs!`, within Trixi.jl. + +# Trixi.jl includes a set of `rhs!` functions designed to compute `du`, i.e., +# ``\frac{\partial u}{\partial t}`` according to the structure +# of the setup. These `rhs!` functions calculate interface, mortars, and boundary fluxes, in +# addition to surface and volume integrals, in order to construct the `du` vector. This `du` vector +# is then used by the time integration method to obtain the solution at the subsequent time step. +# The `rhs!` function is called by time integration methods in each iteration of the solve loop +# within OrdinaryDiffEq.jl, with arguments `du`, `u`, `semidiscretization`, and the current time. + +# Trixi.jl uses a two-levels approach for `rhs!` functions. The first level is limited to a +# single function for each `semidiscretization` type, and its role is to redirect data to the +# target `rhs!` for specific solver and mesh types. This target `rhs!` function is responsible +# for calculating `du`. + +# Path from the `solve` function call to the appropriate `rhs!` function call: + +# ![rhs_structure](https://github.com/trixi-framework/Trixi.jl/assets/119304909/dbea9a0e-25a4-4afa-855e-01f1ad619982) + +# Computed solution: + +using Plots +plot(sol) +pd = PlotData2D(sol) +plot!(getmesh(pd)) diff --git a/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/Project.toml b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/Project.toml new file mode 100644 index 00000000000..43aec5b7f54 --- /dev/null +++ b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/Project.toml @@ -0,0 +1,2 @@ +[deps] +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" diff --git a/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/README.md b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/README.md new file mode 100644 index 00000000000..011b5c75860 --- /dev/null +++ b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/README.md @@ -0,0 +1,15 @@ +# Plots for the tutorial "Behind the scenes of a simulation setup" + +To create all the images for the tutorial, execute the following command from the directory of this `README.md`: +```julia +pkg> activate . +julia> include.(readdir("src"; join=true)) +``` +To create all images from a different directory, substitute `"src"` with the path to the `src` +folder. The resulting images will be generated in your current directory as PNG files. + +To generate a specific image, run the following command while replacing `"path/to/src"` and `"file_name"` with the appropriate values: +```julia +pkg> activate . +julia> include(joinpath("path/to/src", "file_name")) +``` \ No newline at end of file diff --git a/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/SemidiscretizationHyperbolic_structure_figure.jl b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/SemidiscretizationHyperbolic_structure_figure.jl new file mode 100644 index 00000000000..cae7b19d470 --- /dev/null +++ b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/SemidiscretizationHyperbolic_structure_figure.jl @@ -0,0 +1,64 @@ +using Plots +plot(Shape([(-2.3,4.5), (2.35,4.5), (2.35,2.5), (-2.3,2.5)]), linecolor="black", fillcolor="white", label=false,linewidth=2, size=(800,600), showaxis=false, grid=false, xlim=(-2.4,2.8), ylim=(-25,5.5)) +annotate!(2.3, 3.5, ("SemidiscretizationHyperbolic(mesh, equations, initial_conditions, solver; source_terms, +boundary_conditions, RealT, uEltype, initial_cache) ", 10, :black, :right)) +annotate!(-2.3, 1.5, ("creates and returns SemidiscretizationHyperbolic object, initialized using a mesh, equations, +initial_conditions, boundary_conditions, source_terms, solver and cache", 9, :black, :left)) +plot!([-1.2,-1.2],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +plot!([-1.2,-1.4],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +plot!([-1.2,-1.],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +annotate!(-1, -0.7, ("specialized for mesh +and solver types", 9, :black, :left)) +plot!([1.25,1.25],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +plot!([1.25,1.05],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +plot!([1.25,1.45],[0.6,-2],arrow=true,color=:black,linewidth=2,label="") +annotate!(1.48, -0.7, ("specialized for mesh +and boundary_conditions +types", 9, :black, :left)) + +plot!(Shape([(-2.3,-2), (-0.1,-2), (-0.1,-4), (-2.3,-4)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.2, -3, ("create_cache(mesh::TreeMesh, equations, + solver::Dg, RealT, uEltype)", 10, :black, :center)) +plot!([-2.22,-2.22],[-4,-22],arrow=false,color=:black,linewidth=2,label="") + +plot!(Shape([(-0.05,-2), (2.6,-2), (2.6,-4), (-0.05,-4)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(1.27, -3, ("digest_boundary_conditions(boundary_conditions, + mesh, solver, cache)", 10, :black, :center)) +annotate!(2.6, -5, ("if necessary, converts passed boundary_conditions + into a suitable form for processing by Trixi.jl", 9, :black, :right)) + +plot!(Shape([(-2,-6), (-0.55,-6), (-0.55,-7.1), (-2,-7.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.95, -6.5, ("local_leaf_cells(mesh.tree)", 10, :black, :left)) +annotate!(-2, -7.5, ("returns cells for which an element needs to be created (i.e. all leaf cells)", 9, :black, :left)) +plot!([-2.22,-2],[-6.5,-6.5],arrow=true,color=:black,linewidth=2,label="") + +plot!(Shape([(-2,-9), (1.73,-9), (1.73,-10.1), (-2,-10.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.95, -9.5, ("init_elements(leaf_cell_ids, mesh, equations, dg.basis, RealT, uEltype)", 10, :black, :left)) +annotate!(-2, -10.5, ("creates and initializes elements, projects Gauss-Lobatto basis onto each of them", 9, :black, :left)) +plot!([-2.22,-2],[-9.5,-9.5],arrow=true,color=:black,linewidth=2,label="") + +plot!(Shape([(-2,-12), (0.4,-12), (0.4,-13.1), (-2,-13.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.95, -12.5, ("init_interfaces(leaf_cell_ids, mesh, elements)", 10, :black, :left)) +annotate!(-2, -13.5, ("creates and initializes interfaces between each pair of adjacent elements of the same size", 9, :black, :left)) +plot!([-2.22,-2],[-12.5,-12.5],arrow=true,color=:black,linewidth=2,label="") + +plot!(Shape([(-2,-15), (0.5,-15), (0.5,-16.1), (-2,-16.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.95, -15.5, ("init_boundaries(leaf_cell_ids, mesh, elements)", 10, :black, :left)) +annotate!(-2, -17, ("creates and initializes boundaries, remembers each boundary element, as well as the coordinates of +each boundary node", 9, :black, :left)) +plot!([-2.22,-2],[-15.5,-15.5],arrow=true,color=:black,linewidth=2,label="") + +plot!(Shape([(-1.6,-18), (1.3,-18), (1.3,-19.1), (-1.6,-19.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.55, -18.5, ("init_mortars(leaf_cell_ids, mesh, elements, dg.mortar)", 10, :black, :left)) +annotate!(-1.6, -20, ("creates and initializes mortars (type of interfaces) between each triple of adjacent coarsened +and corresponding small elements", 9, :black, :left)) +plot!([-2.22,-1.6],[-18.5,-18.5],arrow=true,color=:black,linewidth=2,label="") +annotate!(-2.15, -19, ("2D and 3D", 8, :black, :left)) + +plot!(Shape([(-2,-21), (1.5,-21), (1.5,-23.1), (-2,-23.1)]), linecolor="black", fillcolor="white", label=false,linewidth=2) +annotate!(-1.95, -22, ("create_cache(mesh, equations, dg.volume_integral, dg, uEltype) +for 2D and 3D create_cache(mesh, equations, dg.mortar, uEltype)", 10, :black, :left)) +annotate!(-2, -23.5, ("add specialized parts of the cache required to compute the volume integral, etc.", 9, :black, :left)) +plot!([-2.22,-2],[-22,-22],arrow=true,color=:black,linewidth=2,label="") + +savefig("./SemidiscretizationHyperbolic") \ No newline at end of file diff --git a/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_boundary_figure.jl b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_boundary_figure.jl new file mode 100644 index 00000000000..14475d21339 --- /dev/null +++ b/docs/literate/src/files/behind_the_scenes_simulation_setup_plots/src/generate_boundary_figure.jl @@ -0,0 +1,190 @@ +using Plots + +function min(coordinates::Vector{Tuple{Float64, Float64}}, i) + min=coordinates[1][i] + for j in coordinates + if min>j[i] + min=j[i] + end + end + return min +end + +function max(coordinates::Vector{Tuple{Float64, Float64}}, i) + max=coordinates[1][i] + for j in coordinates + if maxj[i] + min=j[i] + end + end + return min +end + +function max(coordinates::Vector{Tuple{Float64, Float64}}, i) + max=coordinates[1][i] + for j in coordinates + if maxj[i] + min=j[i] + end + end + return min +end + +function max(coordinates::Vector{Tuple{Float64, Float64}}, i) + max=coordinates[1][i] + for j in coordinates + if maxj[i] + min=j[i] + end + end + return min +end + +function max(coordinates::Vector{Tuple{Float64, Float64}}, i) + max=coordinates[1][i] + for j in coordinates + if max ("first_steps", "create_first_setup.jl"), "Changing Trixi.jl itself" => ("first_steps", "changing_trixi.jl"), ], + "Behind the scenes of a simulation setup" => "behind_the_scenes_simulation_setup.jl", # Topic: DG semidiscretizations "Introduction to DG methods" => "scalar_linear_advection_1d.jl", "DGSEM with flux differencing" => "DGSEM_FluxDiff.jl", @@ -76,7 +77,7 @@ files = [ # Topic: other stuff "Explicit time stepping" => "time_stepping.jl", "Differentiable programming" => "differentiable_programming.jl", - "Custom semidiscretizations" => "custom_semidiscretization.jl" + "Custom semidiscretizations" => "custom_semidiscretization.jl", ] tutorials = create_tutorials(files) From 88e4a09b919548ad308e94dfe1b515947b581558 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Thu, 22 Feb 2024 13:49:15 +0100 Subject: [PATCH 19/27] Update benchmarking docs (#1849) * Update benchmarking docs * Update performance.md * Update docs/src/performance.md Co-authored-by: Daniel Doehring --------- Co-authored-by: Daniel Doehring --- docs/src/performance.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/src/performance.md b/docs/src/performance.md index 82d7f501f63..40970e58c5c 100644 --- a/docs/src/performance.md +++ b/docs/src/performance.md @@ -106,7 +106,22 @@ resulting performance improvements of Trixi.jl are given in the following blog p We use [PkgBenchmark.jl](https://github.com/JuliaCI/PkgBenchmark.jl) to provide a standard set of benchmarks for Trixi.jl. The relevant benchmark script is [benchmark/benchmarks.jl](https://github.com/trixi-framework/Trixi.jl/blob/main/benchmark/benchmarks.jl). -You can run a standard set of benchmarks via +To benchmark the changes made in a PR, please proceed as follows: + +1. Check out the latest `main` branch of your Trixi.jl development repository. +2. Check out the latest development branch of your PR. +3. Change your working directory to the `benchmark` directory of Trixi.jl. +4. Execute `julia run_benchmarks.jl`. + +This will take some hours to complete and requires at least 8 GiB of RAM. When everything is finished, some +output files will be created in the `benchmark` directory of Trixi.jl. + +!!! warning + Please note that the benchmark scripts use `--check-bounds=no` at the moment. + Thus, they will not work in any useful way for Julia v1.10 (and newer?), see + [Julia issue #50985](https://github.com/JuliaLang/julia/issues/50985). + +You can also run a standard set of benchmarks manually via ```julia julia> using PkgBenchmark, Trixi From 9f7eadb3c056ee63af051c1397bfe50fa9ba9a47 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Thu, 22 Feb 2024 14:13:39 +0100 Subject: [PATCH 20/27] set version to v0.6.10 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9bed045637a..221e96643ae 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.6.10-pre" +version = "0.6.10" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 5185abd96a0319599d01d57d196ecabdaa083477 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Thu, 22 Feb 2024 14:13:52 +0100 Subject: [PATCH 21/27] set development version to v0.6.11-pre --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 221e96643ae..551e069b934 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.6.10" +version = "0.6.11-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 029ddea44cedc076251a5e6c832af7f0bec4ed90 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Fri, 23 Feb 2024 05:25:00 +0100 Subject: [PATCH 22/27] Own `sqrt` and `log` returning `NaN` for "correct" multi-thread behaviour (#1781) * Introduce NaNMath for unsafe sqrt and log * performance measurements * implement log myself * Try out different log implementation * remove NaNMath, own implementation * remove unrelated * Update src/equations/compressible_euler_2d.jl * NaNSqrt for quasi 1d CEE * fmt * Update src/auxiliary/math.jl * Update src/auxiliary/math.jl * Update src/auxiliary/math.jl * for comparison * Update src/auxiliary/math.jl Co-authored-by: Hendrik Ranocha * Update src/auxiliary/math.jl Co-authored-by: Hendrik Ranocha * llvm version log * Catch ints in sqrt_ * Use sqrt_ log_ everywhere * docu * fmt * replace in comment * try exporting nan funcs * enable SIMD again * Bring back SIMD * doc * Update src/auxiliary/math.jl Co-authored-by: Hendrik Ranocha * Update src/auxiliary/math.jl Co-authored-by: Hendrik Ranocha * docstring fmt * remove redundant docstrings * no own names * fmt * revert unintended * revert * remove unintended * revert * fmt * comments * update test vals * test vals * test vals * Preferences * Update Project.toml * Update src/Trixi.jl * fmt * docstrings * docstrings * docstrings * compat info * Apply suggestions from code review Co-authored-by: Hendrik Ranocha * escape " * fmt * fix benchmarks configuration * skip UUIDs in downgrade CI job * Update src/auxiliary/math.jl Co-authored-by: Hendrik Ranocha * Update Project.toml Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --------- Co-authored-by: Hendrik Ranocha Co-authored-by: Hendrik Ranocha Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .github/workflows/Downgrade.yml | 2 +- Project.toml | 4 ++ src/Trixi.jl | 6 ++ src/auxiliary/math.jl | 97 +++++++++++++++++++++++++++++++++ test/test_parabolic_1d.jl | 12 ++-- test/test_unstructured_2d.jl | 6 +- 6 files changed, 117 insertions(+), 10 deletions(-) diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml index c84b1026d1b..dd5d8ee7e32 100644 --- a/.github/workflows/Downgrade.yml +++ b/.github/workflows/Downgrade.yml @@ -72,7 +72,7 @@ jobs: - uses: julia-actions/cache@v1 - uses: julia-actions/julia-downgrade-compat@v1 with: - skip: LinearAlgebra,Printf,SparseArrays,DiffEqBase + skip: LinearAlgebra,Printf,SparseArrays,UUIDs,DiffEqBase projects: ., test - uses: julia-actions/julia-buildpkg@v1 env: diff --git a/Project.toml b/Project.toml index 551e069b934..6b27e6e9999 100644 --- a/Project.toml +++ b/Project.toml @@ -25,6 +25,7 @@ OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" P4est = "7d669430-f675-4ae7-b43e-fab78ec5a902" Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" @@ -46,6 +47,7 @@ Triangulate = "f7e6ffb2-c36d-4f8f-a77e-16e897189344" TriplotBase = "981d1d27-644d-49a2-9326-4793e63143c3" TriplotRecipes = "808ab39a-a642-4abf-81ff-4cb34ebbffa3" TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [weakdeps] Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" @@ -76,6 +78,7 @@ OffsetArrays = "1.12" P4est = "0.4.9" Polyester = "0.7.5" PrecompileTools = "1.1" +Preferences = "1.3" Printf = "1" RecipesBase = "1.1" Reexport = "1.0" @@ -97,6 +100,7 @@ Triangulate = "2.2" TriplotBase = "0.1" TriplotRecipes = "0.1" TrixiBase = "0.1.1" +UUIDs = "1.6" julia = "1.8" [extras] diff --git a/src/Trixi.jl b/src/Trixi.jl index bf0986084af..b7f7767a9d8 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -76,6 +76,12 @@ using TrixiBase: TrixiBase using SimpleUnPack: @pack! using DataStructures: BinaryHeap, FasterForward, extract_all! +using UUIDs: UUID +using Preferences: @load_preference, set_preferences! + +const _PREFERENCE_SQRT = @load_preference("sqrt", "sqrt_Trixi_NaN") +const _PREFERENCE_LOG = @load_preference("log", "log_Trixi_NaN") + # finite difference SBP operators using SummationByPartsOperators: AbstractDerivativeOperator, AbstractNonperiodicDerivativeOperator, DerivativeOperator, diff --git a/src/auxiliary/math.jl b/src/auxiliary/math.jl index 38ea0bda8c8..9e3aaa181bf 100644 --- a/src/auxiliary/math.jl +++ b/src/auxiliary/math.jl @@ -5,6 +5,103 @@ @muladd begin #! format: noindent +const TRIXI_UUID = UUID("a7f1ee26-1774-49b1-8366-f1abc58fbfcb") + +""" + Trixi.set_sqrt_type(type; force = true) + +Set the `type` of the square root function to be used in Trixi.jl. +The default is `"sqrt_Trixi_NaN"` which returns `NaN` for negative arguments +instead of throwing an error. +Alternatively, you can set `type` to `"sqrt_Base"` to use the Julia built-in `sqrt` function +which provides a stack-trace of the error which might come in handy when debugging code. +""" +function set_sqrt_type(type; force = true) + @assert type == "sqrt_Trixi_NaN"||type == "sqrt_Base" "Only allowed `sqrt` function types are `\"sqrt_Trixi_NaN\"` and `\"sqrt_Base\"`" + set_preferences!(TRIXI_UUID, "sqrt" => type, force = force) + @info "Please restart Julia and reload Trixi.jl for the `sqrt` computation change to take effect" +end + +@static if _PREFERENCE_SQRT == "sqrt_Trixi_NaN" + """ + Trixi.sqrt(x::Real) + + Custom square root function which returns `NaN` for negative arguments instead of throwing an error. + This is required to ensure [correct results for multithreaded computations](https://github.com/trixi-framework/Trixi.jl/issues/1766) + when using the [`Polyester` package](https://github.com/JuliaSIMD/Polyester.jl), + i.e., using the `@batch` macro instead of the Julia built-in `@threads` macro, see [`@threaded`](@ref). + + We dispatch this function for `Float64, Float32, Float16` to the LLVM intrinsics + `llvm.sqrt.f64`, `llvm.sqrt.f32`, `llvm.sqrt.f16` as for these the LLVM functions can be used out-of the box, + i.e., they return `NaN` for negative arguments. + In principle, one could also use the `sqrt_llvm` call, but for transparency and consistency with [`log`](@ref) we + spell out the datatype-dependent functions here. + For other types, such as integers or dual numbers required for algorithmic differentiation, we + fall back to the Julia built-in `sqrt` function after a check for negative arguments. + Since these cases are not performance critical, the check for negativity does not hurt here + and can (as of now) even be optimized away by the compiler due to the implementation of `sqrt` in Julia. + + When debugging code, it might be useful to change the implementation of this function to redirect to + the Julia built-in `sqrt` function, as this reports the exact place in code where the domain is violated + in the stacktrace. + + See also [`Trixi.set_sqrt_type`](@ref). + """ + @inline sqrt(x::Real) = x < zero(x) ? oftype(x, NaN) : Base.sqrt(x) + + # For `sqrt` we could use the `sqrt_llvm` call, ... + #@inline sqrt(x::Union{Float64, Float32, Float16}) = Base.sqrt_llvm(x) + + # ... but for transparency and consistency we use the direct LLVM calls here. + @inline sqrt(x::Float64) = ccall("llvm.sqrt.f64", llvmcall, Float64, (Float64,), x) + @inline sqrt(x::Float32) = ccall("llvm.sqrt.f32", llvmcall, Float32, (Float32,), x) + @inline sqrt(x::Float16) = ccall("llvm.sqrt.f16", llvmcall, Float16, (Float16,), x) +end + +""" + Trixi.set_log_type(type; force = true) + +Set the `type` of the (natural) `log` function to be used in Trixi.jl. +The default is `"sqrt_Trixi_NaN"` which returns `NaN` for negative arguments +instead of throwing an error. +Alternatively, you can set `type` to `"sqrt_Base"` to use the Julia built-in `sqrt` function +which provides a stack-trace of the error which might come in handy when debugging code. +""" +function set_log_type(type; force = true) + @assert type == "log_Trixi_NaN"||type == "log_Base" "Only allowed log function types are `\"log_Trixi_NaN\"` and `\"log_Base\"`." + set_preferences!(TRIXI_UUID, "log" => type, force = force) + @info "Please restart Julia and reload Trixi.jl for the `log` computation change to take effect" +end + +@static if _PREFERENCE_LOG == "log_Trixi_NaN" + """ + Trixi.log(x::Real) + + Custom natural logarithm function which returns `NaN` for negative arguments instead of throwing an error. + This is required to ensure [correct results for multithreaded computations](https://github.com/trixi-framework/Trixi.jl/issues/1766) + when using the [`Polyester` package](https://github.com/JuliaSIMD/Polyester.jl), + i.e., using the `@batch` macro instead of the Julia built-in `@threads` macro, see [`@threaded`](@ref). + + We dispatch this function for `Float64, Float32, Float16` to the respective LLVM intrinsics + `llvm.log.f64`, `llvm.log.f32`, `llvm.log.f16` as for this the LLVM functions can be used out-of the box, i.e., + they return `NaN` for negative arguments. + For other types, such as integers or dual numbers required for algorithmic differentiation, we + fall back to the Julia built-in `log` function after a check for negative arguments. + Since these cases are not performance critical, the check for negativity does not hurt here. + + When debugging code, it might be useful to change the implementation of this function to redirect to + the Julia built-in `log` function, as this reports the exact place in code where the domain is violated + in the stacktrace. + + See also [`Trixi.set_log_type`](@ref). + """ + @inline log(x::Real) = x < zero(x) ? oftype(x, NaN) : Base.log(x) + + @inline log(x::Float64) = ccall("llvm.log.f64", llvmcall, Float64, (Float64,), x) + @inline log(x::Float32) = ccall("llvm.log.f32", llvmcall, Float32, (Float32,), x) + @inline log(x::Float16) = ccall("llvm.log.f16", llvmcall, Float16, (Float16,), x) +end + """ ln_mean(x, y) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index c1cfec052fe..41d375e2e31 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -195,14 +195,14 @@ end Prandtl = prandtl_number(), gradient_variables = GradientVariablesEntropy()), l2=[ - 2.459359632523962e-5, - 2.3928390718460263e-5, - 0.00011252414117082376, + 2.4593501090944024e-5, + 2.3928163240907908e-5, + 0.00011252309905552921, ], linf=[ - 0.0001185052018830568, - 0.00018987717854305393, - 0.0009597503607920999, + 0.0001185048754512863, + 0.0001898766501935486, + 0.0009597450028770993, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 139b423ead1..83b8318c926 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -710,9 +710,9 @@ end 1.0066867437607972e-13, 6.889210012578449e-14, 1.568290814572709e-13], - linf=[5.963762816918461e-10, - 5.08869890669672e-11, - 1.1581377523661729e-10, + linf=[2.353373051988683e-10, + 2.801543719233024e-11, + 3.930469838486772e-11, 4.61017890529547e-11], tspan=(0.0, 0.1), atol=1.0e-11) From 62610bb6a858eedfaf8fe61f074aa757441a08d1 Mon Sep 17 00:00:00 2001 From: Patrick Ersing <114223904+patrickersing@users.noreply.github.com> Date: Fri, 23 Feb 2024 05:30:08 +0100 Subject: [PATCH 23/27] Separation of TrixiShallowWater.jl (#1809) * remove wet_dry functionality for SWE-1D * remove wet_dry functionality for SWE-2D * remove twolayer equations * remove limiters from swe_quasi_1d * remove export of min_max_speed_chen_noelle * remove elixirs * update news.md * add unit tests to increase coverage * Change news.md according to code review Co-authored-by: Hendrik Ranocha --------- Co-authored-by: Andrew Winters Co-authored-by: Hendrik Ranocha --- NEWS.md | 13 + .../elixir_shallowwater_conical_island.jl | 114 --- .../elixir_shallowwater_parabolic_bowl.jl | 119 --- ...ixir_shallowwater_well_balanced_wet_dry.jl | 207 ----- .../elixir_shallowwater_beach.jl | 123 --- .../elixir_shallowwater_parabolic_bowl.jl | 119 --- ...lixir_shallowwater_twolayer_convergence.jl | 60 -- .../elixir_shallowwater_twolayer_dam_break.jl | 94 -- ...xir_shallowwater_twolayer_well_balanced.jl | 86 -- ...ixir_shallowwater_well_balanced_wet_dry.jl | 172 ---- .../elixir_shallowwater_conical_island.jl | 117 --- .../elixir_shallowwater_parabolic_bowl.jl | 121 --- ...lixir_shallowwater_twolayer_convergence.jl | 60 -- ...xir_shallowwater_twolayer_well_balanced.jl | 81 -- ...ixir_shallowwater_well_balanced_wet_dry.jl | 206 ----- ...ixir_shallowwater_three_mound_dam_break.jl | 133 --- ...lixir_shallowwater_twolayer_convergence.jl | 63 -- .../elixir_shallowwater_twolayer_dam_break.jl | 147 ---- ...xir_shallowwater_twolayer_well_balanced.jl | 81 -- src/Trixi.jl | 12 +- src/callbacks_stage/callbacks_stage.jl | 2 - .../positivity_shallow_water.jl | 89 -- .../positivity_shallow_water_dg1d.jl | 89 -- .../positivity_shallow_water_dg2d.jl | 90 -- src/equations/equations.jl | 2 - src/equations/numerical_fluxes.jl | 23 - src/equations/shallow_water_1d.jl | 187 +--- src/equations/shallow_water_2d.jl | 266 +----- src/equations/shallow_water_quasi_1d.jl | 37 +- src/equations/shallow_water_two_layer_1d.jl | 511 ----------- src/equations/shallow_water_two_layer_2d.jl | 805 ------------------ src/solvers/dgsem_tree/indicators.jl | 76 -- src/solvers/dgsem_tree/indicators_1d.jl | 109 --- src/solvers/dgsem_tree/indicators_2d.jl | 110 --- test/test_structured_2d.jl | 78 -- test/test_tree_1d.jl | 2 - test/test_tree_1d_shallowwater.jl | 75 -- test/test_tree_1d_shallowwater_twolayer.jl | 74 -- test/test_tree_2d_part3.jl | 3 - test/test_tree_2d_shallowwater.jl | 79 -- test/test_tree_2d_shallowwater_twolayer.jl | 88 -- test/test_unit.jl | 34 +- test/test_unstructured_2d.jl | 101 --- 43 files changed, 56 insertions(+), 5002 deletions(-) delete mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl delete mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl delete mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_beach.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl delete mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl delete mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl delete mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl delete mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl delete mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl delete mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl delete mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl delete mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl delete mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl delete mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl delete mode 100644 src/callbacks_stage/positivity_shallow_water.jl delete mode 100644 src/callbacks_stage/positivity_shallow_water_dg1d.jl delete mode 100644 src/callbacks_stage/positivity_shallow_water_dg2d.jl delete mode 100644 src/equations/shallow_water_two_layer_1d.jl delete mode 100644 src/equations/shallow_water_two_layer_2d.jl delete mode 100644 test/test_tree_1d_shallowwater_twolayer.jl delete mode 100644 test/test_tree_2d_shallowwater_twolayer.jl diff --git a/NEWS.md b/NEWS.md index feccd1f9852..ecc91581e9a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,19 @@ Trixi.jl follows the interpretation of [semantic versioning (semver)](https://ju used in the Julia ecosystem. Notable changes will be documented in this file for human readability. +## Changes when updating to v0.7 from v0.6.x + +#### Added + +#### Changed + +#### Deprecated + +#### Removed +- Some specialized shallow water specific features are no longer available directly in + Trixi.jl, but are moved to a dedicated repository: [TrixiShallowWater.jl](https://github.com/trixi-framework/TrixiShallowWater.jl). This includes all features related to wetting and drying, as well as the `ShallowWaterTwoLayerEquations1D` and `ShallowWaterTwoLayerEquations2D`. + However, the basic shallow water equations are still part of Trixi.jl. We'll also be updating the TrixiShallowWater.jl documentation with instructions on how to use these relocated features in the future. + ## Changes in the v0.6 lifecycle #### Added diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl deleted file mode 100644 index e65ed19221e..00000000000 --- a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl +++ /dev/null @@ -1,114 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) - -""" - initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - -Initial condition for the [`ShallowWaterEquations2D`](@ref) to test the [`hydrostatic_reconstruction_chen_noelle`](@ref) -and its handling of discontinuous water heights at the start in combination with wetting and -drying. The bottom topography is given by a conical island in the middle of the domain. Around that -island, there is a cylindrical water column at t=0 and the rest of the domain is dry. This -discontinuous water height is smoothed by a logistic function. This simulation uses periodic -boundary conditions. -""" -function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values - - v1 = 0.0 - v2 = 0.0 - - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) - - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 0.3 # center point of function - k = -25.0 # sharpness of transfer - - H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_conical_island - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(4) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Get the StructuredMesh and setup a periodic mesh - -coordinates_min = (-1.0, -1.0) -coordinates_max = (1.0, 1.0) - -cells_per_dimension = (16, 16) - -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solver - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl deleted file mode 100644 index bc198f18835..00000000000 --- a/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ /dev/null @@ -1,119 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.81) - -""" - initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - -Well-known initial condition to test the [`hydrostatic_reconstruction_chen_noelle`](@ref) and its -wet-dry mechanics. This test has an analytical solution. The initial condition is defined by the -analytical solution at time t=0. The bottom topography defines a bowl and the water level is given -by an oscillating lake. - -The original test and its analytical solution were first presented in -- William C. Thacker (1981) - Some exact solutions to the nonlinear shallow-water wave equations - [DOI: 10.1017/S0022112081001882](https://doi.org/10.1017/S0022112081001882). - -The particular setup below is taken from Section 6.2 of -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and Timothy Warburton (2018) - An entropy stable discontinuous Galerkin method for the shallow water equations on - curvilinear meshes with wet/dry fronts accelerated by GPUs - [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). -""" -function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_parabolic_bowl - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(4) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.6, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### - -coordinates_min = (-2.0, -2.0) -coordinates_max = (2.0, 2.0) - -cells_per_dimension = (150, 150) - -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_kinetic, - energy_internal)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl deleted file mode 100644 index 8e492b1ba05..00000000000 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ /dev/null @@ -1,207 +0,0 @@ - -using OrdinaryDiffEq -using Trixi -using Printf: @printf, @sprintf - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.812) - -""" - initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) - -Initial condition with a complex (discontinuous) bottom topography to test the well-balanced -property for the [`hydrostatic_reconstruction_chen_noelle`](@ref) including dry areas within the -domain. The errors from the analysis callback are not important but the error for this -lake-at-rest test case `∑|H0-(h+b)|` should be around machine roundoff. - -The initial condition is taken from Section 5.2 of the paper: -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -function initial_condition_complex_bottom_well_balanced(x, t, - equations::ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_complex_bottom_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) - -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(3) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the StructuredMesh for the domain [0, 1]^2 - -coordinates_min = (0.0, 0.0) -coordinates_max = (1.0, 1.0) - -cells_per_dimension = (16, 16) - -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Workaround to set a discontinuous water and bottom topography for -# debugging and testing. Essentially, this is a slight augmentation of the -# `compute_coefficients` where the `x` node value passed here is slightly -# perturbed to the left / right in order to set a true discontinuity that avoids -# the doubled value of the LGL nodes at a particular element interface. -# -# Note! The errors from the analysis callback are not important but the error -# for this lake at rest test case `∑|H0-(h+b)|` should be near machine roundoff. - -# point to the data we want to augment -u = Trixi.wrap_array(ode.u0, semi) -# reset the initial condition -for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, - semi.solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]), x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]), x_node[2]) - end - u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), - equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end -end - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, - ode_default_options()..., callback = callbacks, adaptive = false); - -summary_callback() # print the timer summary - -############################################################################### -# Workaround to compute the well-balancedness error for this particular problem -# that has two reference water heights. One for a lake to the left of the -# discontinuous bottom topography `H0_upper = 2.5` and another for a lake to the -# right of the discontinuous bottom topography `H0_lower = 1.5`. - -# Declare a special version of the function to compute the lake-at-rest error -# OBS! The reference water height values are hardcoded for convenience. -function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) - h, _, _, b = u - - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max(2.5, b + equations.threshold_limiter) - else - H0_wet_dry = max(1.5, b + equations.threshold_limiter) - end - - return abs(H0_wet_dry - (h + b)) -end - -# point to the data we want to analyze -u = Trixi.wrap_array(sol[end], semi) -# Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, - semi.cache; - normalize = true) do u, i, j, element, - equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, - i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]), x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]), x_node[2]) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) -end - -# report the well-balancedness lake-at-rest error to the screen -println("─"^100) -println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summary(solver), - " at final time " * @sprintf("%10.8e", tspan[end])) - -@printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) -@printf(" % 10.8e", l1_well_balance_error) -println() -println("─"^100) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl deleted file mode 100644 index 378079ca334..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl +++ /dev/null @@ -1,123 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations1D(gravity_constant = 9.812) - -""" - initial_condition_beach(x, t, equations:: ShallowWaterEquations1D) -Initial condition to simulate a wave running towards a beach and crashing. Difficult test -including both wetting and drying in the domain using slip wall boundary conditions. -The bottom topography is altered to be differentiable on the domain [0,8] and -differs from the reference below. - -The water height and speed functions used here, are adapted from the initial condition -found in section 5.2 of the paper: - - Andreas Bollermann, Sebastian Noelle, Maria Lukáčová-Medvid’ová (2011) - Finite volume evolution Galerkin methods for the shallow water equations with dry beds\n - [DOI: 10.4208/cicp.220210.020710a](https://dx.doi.org/10.4208/cicp.220210.020710a) -""" -function initial_condition_beach(x, t, equations::ShallowWaterEquations1D) - D = 1 - delta = 0.02 - gamma = sqrt((3 * delta) / (4 * D)) - x_a = sqrt((4 * D) / (3 * delta)) * acosh(sqrt(20)) - - f = D + 40 * delta * sech(gamma * (8 * x[1] - x_a))^2 - - # steep curved beach - b = 0.01 + 99 / 409600 * 4^x[1] - - if x[1] >= 6 - H = b - v = 0.0 - else - H = f - v = sqrt(equations.gravity / D) * H - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) -end - -initial_condition = initial_condition_beach -boundary_condition = boundary_condition_slip_wall - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(3) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the TreeMesh for the domain [0, 8] - -coordinates_min = 0.0 -coordinates_max = 8.0 - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 7, - n_cells_max = 10_000, - periodicity = false) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions = boundary_condition) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_kinetic, - energy_internal)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(dt = 0.5, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl deleted file mode 100644 index a586562af7e..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ /dev/null @@ -1,119 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations1D(gravity_constant = 9.81) - -""" - initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations1D) - -Well-known initial condition to test the [`hydrostatic_reconstruction_chen_noelle`](@ref) and its -wet-dry mechanics. This test has analytical solutions. The initial condition is defined by the -analytical solution at time t=0. The bottom topography defines a bowl and the water level is given -by an oscillating lake. - -The original test and its analytical solution in two dimensions were first presented in -- William C. Thacker (1981) - Some exact solutions to the nonlinear shallow-water wave equations - [DOI: 10.1017/S0022112081001882](https://doi.org/10.1017/S0022112081001882). - -The particular setup below is taken from Section 6.2 of -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and Timothy Warburton (2018) - An entropy stable discontinuous Galerkin method for the shallow water equations on - curvilinear meshes with wet/dry fronts accelerated by GPUs - [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). -""" -function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations1D) - a = 1 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v = -sigma * ω * sin(ω * t) - - b = h_0 * x[1]^2 / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) -end - -initial_condition = initial_condition_parabolic_bowl - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(5) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the TreeMesh for the domain [-2, 2] - -coordinates_min = -2.0 -coordinates_max = 2.0 - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 6, - n_cells_max = 10_000) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_kinetic, - energy_internal)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl deleted file mode 100644 index e6a01849852..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ /dev/null @@ -1,60 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations - -equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 10.0, rho_upper = 0.9, - rho_lower = 1.0) - -initial_condition = initial_condition_convergence_test - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 3, - surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the TreeMesh and setup a periodic mesh - -coordinates_min = 0.0 -coordinates_max = sqrt(2.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 3, - n_cells_max = 10_000, - periodicity = true) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_terms_convergence_test) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 500, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -# use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl deleted file mode 100644 index 03b93754d0f..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ /dev/null @@ -1,94 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations for a dam break -# test with a discontinuous bottom topography function to test entropy conservation - -equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 9.81, H0 = 2.0, - rho_upper = 0.9, rho_lower = 1.0) - -# Initial condition of a dam break with a discontinuous water heights and bottom topography. -# Works as intended for TreeMesh1D with `initial_refinement_level=5`. If the mesh -# refinement level is changed the initial condition below may need changed as well to -# ensure that the discontinuities lie on an element interface. -function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations1D) - v1_upper = 0.0 - v1_lower = 0.0 - - # Set the discontinuity - if x[1] <= 10.0 - H_lower = 2.0 - H_upper = 4.0 - b = 0.0 - else - H_lower = 1.5 - H_upper = 3.0 - b = 0.5 - end - - return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) -end - -initial_condition = initial_condition_dam_break - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 3, - surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the TreeMesh and setup a non-periodic mesh - -coordinates_min = 0.0 -coordinates_max = 20.0 -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 5, - n_cells_max = 10000, - periodicity = false) - -boundary_condition = boundary_condition_slip_wall - -# create the semidiscretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions = boundary_condition) - -############################################################################### -# ODE solvers - -tspan = (0.0, 0.4) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_total, - energy_kinetic, - energy_internal)) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 500, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -# use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl deleted file mode 100644 index 098e3aaf601..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ /dev/null @@ -1,86 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations to test well-balancedness - -equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 1.0, H0 = 0.6, - rho_upper = 0.9, rho_lower = 1.0) - -""" - initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations1D) - -Initial condition to test well balanced with a bottom topography from Fjordholm -- Ulrik Skre Fjordholm (2012) - Energy conservative and stable schemes for the two-layer shallow water equations. - [DOI: 10.1142/9789814417099_0039](https://doi.org/10.1142/9789814417099_0039) -""" -function initial_condition_fjordholm_well_balanced(x, t, - equations::ShallowWaterTwoLayerEquations1D) - inicenter = 0.5 - x_norm = x[1] - inicenter - r = abs(x_norm) - - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v1_lower = 0.0 - b = r <= 0.1 ? 0.2 * (cos(10 * pi * (x[1] - 0.5)) + 1) : 0.0 - return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) -end - -initial_condition = initial_condition_fjordholm_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 3, - surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the TreeMesh and setup a periodic mesh - -coordinates_min = 0.0 -coordinates_max = 1.0 -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 4, - n_cells_max = 10_000, - periodicity = true) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (lake_at_rest_error,)) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl deleted file mode 100644 index 26a8960ab46..00000000000 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ /dev/null @@ -1,172 +0,0 @@ - -using OrdinaryDiffEq -using Trixi -using Printf: @printf, @sprintf - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations1D(gravity_constant = 9.812) - -""" - initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations1D) - -Initial condition with a complex (discontinuous) bottom topography to test the well-balanced -property for the [`hydrostatic_reconstruction_chen_noelle`](@ref) including dry areas within the -domain. The errors from the analysis callback are not important but the error for this -lake-at-rest test case `∑|H0-(h+b)|` should be around machine roundoff. - -The initial condition is taken from Section 5.2 of the paper: -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -function initial_condition_complex_bottom_well_balanced(x, t, - equations::ShallowWaterEquations1D) - v = 0.0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) -end - -initial_condition = initial_condition_complex_bottom_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(3) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the TreeMesh for the domain [0, 1] - -coordinates_min = 0.0 -coordinates_max = 1.0 - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 6, - n_cells_max = 10_000) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 25.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 5000, - save_initial_solution = true, - save_final_solution = true) - -stepsize_callback = StepsizeCallback(cfl = 1.5) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, - ode_default_options()..., callback = callbacks, adaptive = false); - -summary_callback() # print the timer summary - -############################################################################### -# Workaround to compute the well-balancedness error for this particular problem -# that has two reference water heights. One for a lake to the left of the -# discontinuous bottom topography `H0_upper = 2.5` and another for a lake to the -# right of the discontinuous bottom topography `H0_lower = 1.5`. - -# Declare a special version of the function to compute the lake-at-rest error -# OBS! The reference water height values are hardcoded for convenience. -function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations1D) - h, _, b = u - - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max(2.5, b + equations.threshold_limiter) - else - H0_wet_dry = max(1.5, b + equations.threshold_limiter) - end - - return abs(H0_wet_dry - (h + b)) -end - -# point to the data we want to analyze -u = Trixi.wrap_array(sol[end], semi) -# Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, - semi.cache; - normalize = true) do u, i, element, - equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, - i, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1])) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1])) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) -end - -# report the well-balancedness lake-at-rest error to the screen -println("─"^100) -println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summary(solver), - " at final time " * @sprintf("%10.8e", tspan[end])) - -@printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) -@printf(" % 10.8e", l1_well_balance_error) -println() -println("─"^100) diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl deleted file mode 100644 index 349b3741869..00000000000 --- a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl +++ /dev/null @@ -1,117 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) - -""" - initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - -Initial condition for the [`ShallowWaterEquations2D`](@ref) to test the [`hydrostatic_reconstruction_chen_noelle`](@ref) -and its handling of discontinuous water heights at the start in combination with wetting and -drying. The bottom topography is given by a conical island in the middle of the domain. Around that -island, there is a cylindrical water column at t=0 and the rest of the domain is dry. This -discontinuous water height is smoothed by a logistic function. This simulation uses a Dirichlet -boundary condition with the initial values. Due to the dry cells at the boundary, this has the -effect of an outflow which can be seen in the simulation. -""" -function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values - - v1 = 0.0 - v2 = 0.0 - - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) - - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 0.3 # center point of function - k = -25.0 # sharpness of transfer - - H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_conical_island -boundary_conditions = BoundaryConditionDirichlet(initial_condition) - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(4) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Get the TreeMesh and setup a mesh - -coordinates_min = (-1.0, -1.0) -coordinates_max = (1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 4, - n_cells_max = 10_000, - periodicity = false) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions = boundary_conditions) - -############################################################################### -# ODE solver - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl deleted file mode 100644 index 2008019cc31..00000000000 --- a/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ /dev/null @@ -1,121 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.81) - -""" - initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - -Well-known initial condition to test the [`hydrostatic_reconstruction_chen_noelle`](@ref) and its -wet-dry mechanics. This test has an analytical solution. The initial condition is defined by the -analytical solution at time t=0. The bottom topography defines a bowl and the water level is given -by an oscillating lake. - -The original test and its analytical solution were first presented in -- William C. Thacker (1981) - Some exact solutions to the nonlinear shallow-water wave equations - [DOI: 10.1017/S0022112081001882](https://doi.org/10.1017/S0022112081001882). - -The particular setup below is taken from Section 6.2 of -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and Timothy Warburton (2018) - An entropy stable discontinuous Galerkin method for the shallow water equations on - curvilinear meshes with wet/dry fronts accelerated by GPUs - [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). -""" -function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_parabolic_bowl -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(7) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.6, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the TreeMesh for the domain [-2, 2]^2 - -coordinates_min = (-2.0, -2.0) -coordinates_max = (2.0, 2.0) - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 5, - n_cells_max = 10_000) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_kinetic, - energy_internal)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); - -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl deleted file mode 100644 index 790916e4467..00000000000 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ /dev/null @@ -1,60 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations - -equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, - rho_lower = 1.0) - -initial_condition = initial_condition_convergence_test - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 3, - surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the TreeMesh and setup a periodic mesh - -coordinates_min = (0.0, 0.0) -coordinates_max = (sqrt(2.0), sqrt(2.0)) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 3, - n_cells_max = 20_000, - periodicity = true) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_terms_convergence_test) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 500, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -# use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl deleted file mode 100644 index 264c26390fe..00000000000 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ /dev/null @@ -1,81 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations with a bottom topography function -# to test well-balancedness - -equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 9.81, H0 = 0.6, - rho_upper = 0.9, rho_lower = 1.0) - -# An initial condition with constant total water height, zero velocities and a bottom topography to -# test well-balancedness -function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? - 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), - equations) -end - -initial_condition = initial_condition_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 3, surface_flux = surface_flux, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the TreeMesh and setup a periodic mesh - -coordinates_min = (0.0, 0.0) -coordinates_max = (1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 3, - n_cells_max = 10_000, - periodicity = true) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solver - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - extra_analysis_integrals = (lake_at_rest_error,)) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl deleted file mode 100644 index 034411c2b54..00000000000 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ /dev/null @@ -1,206 +0,0 @@ - -using OrdinaryDiffEq -using Trixi -using Printf: @printf, @sprintf - -############################################################################### -# Semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.812) - -""" - initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) - -Initial condition with a complex (discontinuous) bottom topography to test the well-balanced -property for the [`hydrostatic_reconstruction_chen_noelle`](@ref) including dry areas within the -domain. The errors from the analysis callback are not important but the error for this -lake-at-rest test case `∑|H0-(h+b)|` should be around machine roundoff. - -The initial condition is taken from Section 5.2 of the paper: -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -function initial_condition_complex_bottom_well_balanced(x, t, - equations::ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_complex_bottom_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(3) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Create the TreeMesh for the domain [0, 1]^2 - -coordinates_min = (0.0, 0.0) -coordinates_max = (1.0, 1.0) - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 3, - n_cells_max = 10_000) - -# create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 50.0) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Workaround to set a discontinuous water and bottom topography for -# debugging and testing. Essentially, this is a slight augmentation of the -# `compute_coefficients` where the `x` node value passed here is slightly -# perturbed to the left / right in order to set a true discontinuity that avoids -# the doubled value of the LGL nodes at a particular element interface. -# -# Note! The errors from the analysis callback are not important but the error -# for this lake at rest test case `∑|H0-(h+b)|` should be near machine roundoff. - -# point to the data we want to augment -u = Trixi.wrap_array(ode.u0, semi) -# reset the initial condition -for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, - semi.solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]), x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]), x_node[2]) - end - u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), - equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end -end - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -stepsize_callback = StepsizeCallback(cfl = 2.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -############################################################################### -# run the simulation - -sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, - ode_default_options()..., callback = callbacks, adaptive = false); - -summary_callback() # print the timer summary - -############################################################################### -# Workaround to compute the well-balancedness error for this particular problem -# that has two reference water heights. One for a lake to the left of the -# discontinuous bottom topography `H0_upper = 2.5` and another for a lake to the -# right of the discontinuous bottom topography `H0_lower = 1.5`. - -# Declare a special version of the function to compute the lake-at-rest error -# OBS! The reference water height values are hardcoded for convenience. -function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) - h, _, _, b = u - - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - - if x[1] < 0.5 - H0_wet_dry = max(2.5, b + equations.threshold_limiter) - else - H0_wet_dry = max(1.5, b + equations.threshold_limiter) - end - - return abs(H0_wet_dry - (h + b)) -end - -# point to the data we want to analyze -u = Trixi.wrap_array(sol[end], semi) -# Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, - semi.cache; - normalize = true) do u, i, j, element, - equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, - i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]), x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]), x_node[2]) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) -end - -# report the well-balancedness lake-at-rest error to the screen -println("─"^100) -println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summary(solver), - " at final time " * @sprintf("%10.8e", tspan[end])) - -@printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) -@printf(" % 10.8e", l1_well_balance_error) -println() -println("─"^100) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl deleted file mode 100644 index df321aad267..00000000000 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl +++ /dev/null @@ -1,133 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the shallow water equations -# -# TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.875, - threshold_limiter = 1e-12, threshold_wet = 1e-14) - -""" - initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) - -Initial condition simulating a dam break. The bottom topography is given by one large and two smaller -mounds. The mounds are flooded by the water for t > 0. To smooth the discontinuity, a logistic function -is applied. - -The initial conditions is taken from Section 6.3 of the paper: -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and Timothy Warburton (2018) - An entropy stable discontinuous Galerkin method for the shallow water equations on - curvilinear meshes with wet/dry fronts accelerated by GPUs\n - [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038) -""" -function initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) - - # Set the background values - v1 = 0.0 - v2 = 0.0 - - x1, x2 = x - M_1 = 1 - 0.1 * sqrt((x1 - 30.0)^2 + (x2 - 22.5)^2) - M_2 = 1 - 0.1 * sqrt((x1 - 30.0)^2 + (x2 - 7.5)^2) - M_3 = 2.8 - 0.28 * sqrt((x1 - 47.5)^2 + (x2 - 15.0)^2) - - b = max(0.0, M_1, M_2, M_3) - - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 8 # center point of function - k = -75.0 # sharpness of transfer - - H = max(b, L / (1.0 + exp(-k * (x1 - x0)))) - - # Avoid division by zero by adjusting the initial condition with a small dry state threshold - # that defaults to 500*eps() ≈ 1e-13 in double precision and is set in the constructor above - # for the ShallowWaterEquations struct. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) -end - -initial_condition = initial_condition_three_mounds - -function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, - equations::ShallowWaterEquations2D) - # Impulse and bottom from inside, height from external state - u_outer = SVector(equations.threshold_wet, u_inner[2], u_inner[3], u_inner[4]) - - # calculate the boundary flux - flux = surface_flux_function(u_inner, u_outer, normal_direction, equations) - - return flux -end - -boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_slip_wall) - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, - hydrostatic_reconstruction_chen_noelle), - flux_nonconservative_chen_noelle) - -basis = LobattoLegendreBasis(4) - -indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable = waterheight_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(basis, surface_flux, volume_integral) - -############################################################################### -# Get the unstructured quad mesh from a file (downloads the file if not available locally) -mesh_file = Trixi.download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", - joinpath(@__DIR__, "mesh_three_mound.mesh")) - -mesh = UnstructuredMesh2D(mesh_file) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - boundary_conditions = boundary_conditions) - -############################################################################### -# ODE solver - -tspan = (0.0, 20.0) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - -############################################################################### -# run the simulation - -stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) - -sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl deleted file mode 100644 index fcc08b6f991..00000000000 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ /dev/null @@ -1,63 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations with a periodic -# bottom topography function (set in the initial conditions) - -equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, - rho_lower = 1.0) - -initial_condition = initial_condition_convergence_test - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 6, surface_flux = surface_flux, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# This setup is for the curved, split form convergence test on a periodic domain - -# Get the unstructured quad mesh from a file (downloads the file if not available locally) -mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) - -mesh = UnstructuredMesh2D(mesh_file, periodicity = true) - -# Create the semidiscretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_terms_convergence_test) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 500, - save_initial_solution = true, - save_final_solution = true) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl deleted file mode 100644 index 821f31c52ac..00000000000 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ /dev/null @@ -1,147 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations for a dam break test with a -# discontinuous bottom topography function to test energy conservation - -equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, rho_upper = 0.9, - rho_lower = 1.0) - -# This test case uses a special work around to setup a truly discontinuous bottom topography -# function and initial condition for this academic testcase of entropy conservation. First, a -# dummy initial_condition_dam_break is introduced to create the semidiscretization. Then the initial -# condition is reset with the true discontinuous values from initial_condition_discontinuous_dam_break. - -function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations2D) - if x[1] < sqrt(2) / 2 - H_upper = 1.0 - H_lower = 0.6 - b = 0.1 - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.0 - end - - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), - equations) -end - -initial_condition = initial_condition_dam_break - -boundary_condition_constant = BoundaryConditionDirichlet(initial_condition_dam_break) - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 6, surface_flux = surface_flux, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# Get the unstructured quad mesh from a file (downloads the file if not available locally) -mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) - -mesh = UnstructuredMesh2D(mesh_file, periodicity = false) - -# Boundary conditions -boundary_condition = Dict(:Top => boundary_condition_slip_wall, - :Left => boundary_condition_slip_wall, - :Right => boundary_condition_slip_wall, - :Bottom => boundary_condition_slip_wall) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, - solver, boundary_conditions = boundary_condition) - -############################################################################### -# ODE solver - -tspan = (0.0, 0.5) -ode = semidiscretize(semi, tspan) - -############################################################################### -# Workaround to set a discontinuous bottom topography and initial condition for debugging and testing. - -# alternative version of the initial conditinon used to setup a truly discontinuous -# test case and initial condition. -# In contrast to the usual signature of initial conditions, this one get passed the -# `element_id` explicitly. In particular, this initial conditions works as intended -# only for the specific mesh loaded above! - -function initial_condition_discontinuous_dam_break(x, t, element_id, - equations::ShallowWaterTwoLayerEquations2D) - # Constant values - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Left side of discontinuity - IDs = [1, 2, 5, 6, 9, 10, 13, 14] - if element_id in IDs - H_upper = 1.0 - H_lower = 0.6 - b = 0.0 - # Right side of discontinuity - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.1 - end - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), - equations) -end - -# point to the data we want to augment -u = Trixi.wrap_array(ode.u0, semi) -# reset the initial condition -for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, - semi.solver, i, j, element) - u_node = initial_condition_discontinuous_dam_break(x_node, first(tspan), element, - equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end -end - -############################################################################### -# Callbacks - -summary_callback = SummaryCallback() - -analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = false, - extra_analysis_integrals = (energy_total, - energy_kinetic, - energy_internal)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 500, - save_initial_solution = true, - save_final_solution = true) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl deleted file mode 100644 index ca1f54595bb..00000000000 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ /dev/null @@ -1,81 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# Semidiscretization of the two-layer shallow water equations with a discontinuous bottom -# topography to test well-balancedness - -equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, H0 = 0.6, - rho_upper = 0.9, rho_lower = 1.0) - -# An initial condition with constant total water height, zero velocities and a bottom topography to -# test well-balancedness -function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Bottom Topography - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? - 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), - equations) -end - -initial_condition = initial_condition_well_balanced - -############################################################################### -# Get the DG approximation space - -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) -surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal) -solver = DGSEM(polydeg = 6, surface_flux = surface_flux, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - -############################################################################### -# This setup is for the curved, split form well-balancedness testing - -# Get the unstructured quad mesh from a file (downloads the file if not available locally) -mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) - -mesh = UnstructuredMesh2D(mesh_file, periodicity = true) - -# Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solver - -tspan = (0.0, 10.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - extra_analysis_integrals = (lake_at_rest_error,)) - -stepsize_callback = StepsizeCallback(cfl = 1.0) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 1000, - save_initial_solution = true, - save_final_solution = true) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index b7f7767a9d8..5f8cd9cae8e 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -160,7 +160,6 @@ export AcousticPerturbationEquations2D, InviscidBurgersEquation1D, LatticeBoltzmannEquations2D, LatticeBoltzmannEquations3D, ShallowWaterEquations1D, ShallowWaterEquations2D, - ShallowWaterTwoLayerEquations1D, ShallowWaterTwoLayerEquations2D, ShallowWaterEquationsQuasi1D, LinearizedEulerEquations2D, PolytropicEulerEquations2D, @@ -179,16 +178,12 @@ export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_kennedy_gruber, flux_shima_etal, flux_ec, flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal, - flux_es_ersing_etal, flux_nonconservative_ersing_etal, + flux_nonconservative_ersing_etal, flux_chan_etal, flux_nonconservative_chan_etal, flux_winters_etal, hydrostatic_reconstruction_audusse_etal, flux_nonconservative_audusse_etal, -# TODO: TrixiShallowWater: move anything with "chen_noelle" to new file - hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, - flux_hll_chen_noelle, FluxPlusDissipation, DissipationGlobalLaxFriedrichs, DissipationLocalLaxFriedrichs, FluxLaxFriedrichs, max_abs_speed_naive, FluxHLL, min_max_speed_naive, min_max_speed_davis, min_max_speed_einfeldt, - min_max_speed_chen_noelle, FluxLMARS, FluxRotated, flux_shima_etal_turbo, flux_ranocha_turbo, @@ -239,8 +234,6 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, -# TODO: TrixiShallowWater: move new indicator - IndicatorHennemannGassnerShallowWater, VolumeIntegralUpwind, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, SurfaceIntegralUpwind, @@ -276,8 +269,7 @@ export load_mesh, load_time, load_timestep, load_timestep!, load_dt, export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorLöhner, IndicatorLoehner, IndicatorMax -# TODO: TrixiShallowWater: move new limiter -export PositivityPreservingLimiterZhangShu, PositivityPreservingLimiterShallowWater +export PositivityPreservingLimiterZhangShu export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 70d60de7914..d5abc1d227d 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -8,6 +8,4 @@ include("positivity_zhang_shu.jl") include("subcell_limiter_idp_correction.jl") include("subcell_bounds_check.jl") -# TODO: TrixiShallowWater: move specific limiter file -include("positivity_shallow_water.jl") end # @muladd diff --git a/src/callbacks_stage/positivity_shallow_water.jl b/src/callbacks_stage/positivity_shallow_water.jl deleted file mode 100644 index 36276026fe9..00000000000 --- a/src/callbacks_stage/positivity_shallow_water.jl +++ /dev/null @@ -1,89 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin -#! format: noindent - -# TODO: TrixiShallowWater: generic wet/dry limiter - -""" - PositivityPreservingLimiterShallowWater(; variables) - -The limiter is specifically designed for the shallow water equations. -It is applied to all scalar `variables` in their given order -using the defined `threshold_limiter` from the [`ShallowWaterEquations1D`](@ref) struct -or the [`ShallowWaterEquations2D`](@ref) struct to determine the minimal acceptable values. -The order of the `variables` is important and might have a strong influence -on the robustness. - -As opposed to the standard version of the [`PositivityPreservingLimiterZhangShu`](@ref), -nodes with a water height below the `threshold_limiter` are treated in a special way. -To avoid numerical problems caused by velocities close to zero, -the velocity is cut off, such that the node can be identified as "dry". The special feature of the -`ShallowWaterEquations` used here is that the bottom topography is stored as an additional -quantity in the solution vector `u`. However, the value of the bottom topography -should not be changed. That is why, it is not limited. - -After the limiting process is applied to all degrees of freedom, for safety reasons, -the `threshold_limiter` is applied again on all the DG nodes in order to avoid water height below. -In the case where the cell mean value is below the threshold before applying the limiter, -there could still be dry nodes afterwards due to the logic of the limiter. - -This fully-discrete positivity-preserving limiter is based on the work of -- Zhang, Shu (2011) - Maximum-principle-satisfying and positivity-preserving high-order schemes - for conservation laws: survey and new developments - [doi: 10.1098/rspa.2011.0153](https://doi.org/10.1098/rspa.2011.0153) -""" -struct PositivityPreservingLimiterShallowWater{N, Variables <: NTuple{N, Any}} - variables::Variables -end - -function PositivityPreservingLimiterShallowWater(; variables) - PositivityPreservingLimiterShallowWater(variables) -end - -function (limiter!::PositivityPreservingLimiterShallowWater)(u_ode, integrator, - semi::AbstractSemidiscretization, - t) - u = wrap_array(u_ode, semi) - @trixi_timeit timer() "positivity-preserving limiter" limiter_shallow_water!(u, - limiter!.variables, - mesh_equations_solver_cache(semi)...) -end - -# Iterate over tuples in a type-stable way using "lispy tuple programming", -# similar to https://stackoverflow.com/a/55849398: -# Iterating over tuples of different functions isn't type-stable in general -# but accessing the first element of a tuple is type-stable. Hence, it's good -# to process one element at a time and replace iteration by recursion here. -# Note that you shouldn't use this with too many elements per tuple since the -# compile times can increase otherwise - but a handful of elements per tuple -# is definitely fine. -function limiter_shallow_water!(u, variables::NTuple{N, Any}, - mesh, - equations::Union{ShallowWaterEquations1D, - ShallowWaterEquations2D}, - solver, cache) where {N} - variable = first(variables) - remaining_variables = Base.tail(variables) - - limiter_shallow_water!(u, equations.threshold_limiter, variable, mesh, equations, - solver, cache) - limiter_shallow_water!(u, remaining_variables, mesh, equations, solver, cache) - return nothing -end - -# terminate the type-stable iteration over tuples -function limiter_shallow_water!(u, variables::Tuple{}, - mesh, - equations::Union{ShallowWaterEquations1D, - ShallowWaterEquations2D}, - solver, cache) - nothing -end - -include("positivity_shallow_water_dg1d.jl") -include("positivity_shallow_water_dg2d.jl") -end # @muladd diff --git a/src/callbacks_stage/positivity_shallow_water_dg1d.jl b/src/callbacks_stage/positivity_shallow_water_dg1d.jl deleted file mode 100644 index 13c6866e895..00000000000 --- a/src/callbacks_stage/positivity_shallow_water_dg1d.jl +++ /dev/null @@ -1,89 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin -#! format: noindent - -# TODO: TrixiShallowWater: 1D wet/dry limiter should move - -function limiter_shallow_water!(u, threshold::Real, variable, - mesh::AbstractMesh{1}, - equations::ShallowWaterEquations1D, - dg::DGSEM, cache) - @unpack weights = dg.basis - - @threaded for element in eachelement(dg, cache) - # determine minimum value - value_min = typemax(eltype(u)) - for i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, element) - value_min = min(value_min, variable(u_node, equations)) - end - - # detect if limiting is necessary - value_min < threshold || continue - - # compute mean value - u_mean = zero(get_node_vars(u, equations, dg, 1, element)) - for i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, element) - u_mean += u_node * weights[i] - end - # note that the reference element is [-1,1]^ndims(dg), thus the weights sum to 2 - u_mean = u_mean / 2^ndims(mesh) - - # We compute the value directly with the mean values, as we assume that - # Jensen's inequality holds (e.g. pressure for compressible Euler equations). - value_mean = variable(u_mean, equations) - theta = (value_mean - threshold) / (value_mean - value_min) - for i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, element) - - # Cut off velocity in case that the waterheight is smaller than the threshold - - h_node, h_v_node, b_node = u_node - h_mean, h_v_mean, _ = u_mean # b_mean is not used as b_node must not be overwritten - - # Set them both to zero to apply linear combination correctly - if h_node <= threshold - h_v_node = zero(eltype(u)) - h_v_mean = zero(eltype(u)) - end - - u_node = SVector(h_node, h_v_node, b_node) - u_mean = SVector(h_mean, h_v_mean, b_node) - - # When velocity is cut off, the only averaged value is the waterheight, - # because the velocity is set to zero and this value is passed. - # Otherwise, the velocity is averaged, as well. - # Note that the auxiliary bottom topography variable `b` is never limited. - set_node_vars!(u, theta * u_node + (1 - theta) * u_mean, - equations, dg, i, element) - end - end - - # "Safety" application of the wet/dry thresholds over all the DG nodes - # on the current `element` after the limiting above in order to avoid dry nodes. - # If the value_mean < threshold before applying limiter, there - # could still be dry nodes afterwards due to logic of the limiting - @threaded for element in eachelement(dg, cache) - for i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, element) - - h, hv, b = u_node - - if h <= threshold - h = threshold - hv = zero(eltype(u)) - end - - u_node = SVector(h, hv, b) - - set_node_vars!(u, u_node, equations, dg, i, element) - end - end - - return nothing -end -end # @muladd diff --git a/src/callbacks_stage/positivity_shallow_water_dg2d.jl b/src/callbacks_stage/positivity_shallow_water_dg2d.jl deleted file mode 100644 index da3a25fdcf4..00000000000 --- a/src/callbacks_stage/positivity_shallow_water_dg2d.jl +++ /dev/null @@ -1,90 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin -#! format: noindent - -# TODO: TrixiShallowWater: 2D wet/dry limiter should move - -function limiter_shallow_water!(u, threshold::Real, variable, - mesh::AbstractMesh{2}, - equations::ShallowWaterEquations2D, dg::DGSEM, cache) - @unpack weights = dg.basis - - @threaded for element in eachelement(dg, cache) - # determine minimum value - value_min = typemax(eltype(u)) - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - value_min = min(value_min, variable(u_node, equations)) - end - - # detect if limiting is necessary - value_min < threshold || continue - - # compute mean value - u_mean = zero(get_node_vars(u, equations, dg, 1, 1, element)) - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_mean += u_node * weights[i] * weights[j] - end - # note that the reference element is [-1,1]^ndims(dg), thus the weights sum to 2 - u_mean = u_mean / 2^ndims(mesh) - - # We compute the value directly with the mean values, as we assume that - # Jensen's inequality holds (e.g. pressure for compressible Euler equations). - value_mean = variable(u_mean, equations) - theta = (value_mean - threshold) / (value_mean - value_min) - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - - # Cut off velocity in case that the water height is smaller than the threshold - - h_node, h_v1_node, h_v2_node, b_node = u_node - h_mean, h_v1_mean, h_v2_mean, _ = u_mean # b_mean is not used as it must not be overwritten - - if h_node <= threshold - h_v1_node = zero(eltype(u)) - h_v2_node = zero(eltype(u)) - h_v1_mean = zero(eltype(u)) - h_v2_mean = zero(eltype(u)) - end - - u_node = SVector(h_node, h_v1_node, h_v2_node, b_node) - u_mean = SVector(h_mean, h_v1_mean, h_v2_mean, b_node) - - # When velocities are cut off, the only averaged value is the water height, - # because the velocities are set to zero and this value is passed. - # Otherwise, the velocities are averaged, as well. - # Note that the auxiliary bottom topography variable `b` is never limited. - set_node_vars!(u, theta * u_node + (1 - theta) * u_mean, - equations, dg, i, j, element) - end - end - - # "Safety" application of the wet/dry thresholds over all the DG nodes - # on the current `element` after the limiting above in order to avoid dry nodes. - # If the value_mean < threshold before applying limiter, there - # could still be dry nodes afterwards due to logic of the limiting - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - - h, h_v1, h_v2, b = u_node - - if h <= threshold - h = threshold - h_v1 = zero(eltype(u)) - h_v2 = zero(eltype(u)) - end - - u_node = SVector(h, h_v1, h_v2, b) - - set_node_vars!(u, u_node, equations, dg, i, j, element) - end - end - - return nothing -end -end # @muladd diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 65875a2a7e5..8f476cf6f16 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -405,8 +405,6 @@ abstract type AbstractShallowWaterEquations{NDIMS, NVARS} <: AbstractEquations{NDIMS, NVARS} end include("shallow_water_1d.jl") include("shallow_water_2d.jl") -include("shallow_water_two_layer_1d.jl") -include("shallow_water_two_layer_2d.jl") include("shallow_water_quasi_1d.jl") # CompressibleEulerEquations diff --git a/src/equations/numerical_fluxes.jl b/src/equations/numerical_fluxes.jl index 44d523b6e89..87fcb412244 100644 --- a/src/equations/numerical_fluxes.jl +++ b/src/equations/numerical_fluxes.jl @@ -326,29 +326,6 @@ This is a [`FluxHLL`](@ref)-type two-wave solver with special estimates of the w """ const flux_hlle = FluxHLL(min_max_speed_einfeldt) -# TODO: TrixiShallowWater: move the chen_noelle flux structure to the new package - -# An empty version of the `min_max_speed_chen_noelle` function is declared here -# in order to create a dimension agnostic version of `flux_hll_chen_noelle`. -# The full description of this wave speed estimate can be found in the docstrings -# for `min_max_speed_chen_noelle` in `shallow_water_1d.jl` or `shallow_water_2d.jl`. -function min_max_speed_chen_noelle end - -""" - flux_hll_chen_noelle = FluxHLL(min_max_speed_chen_noelle) - -An instance of [`FluxHLL`](@ref) specific to the shallow water equations that -uses the wave speed estimates from [`min_max_speed_chen_noelle`](@ref). -This HLL flux is guaranteed to have zero numerical mass flux out of a "dry" element, -maintain positivity of the water height, and satisfy an entropy inequality. - -For complete details see Section 2.4 of the following reference -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI: 10.1137/15M1053074](https://doi.org/10.1137/15M1053074) -""" -const flux_hll_chen_noelle = FluxHLL(min_max_speed_chen_noelle) - """ flux_shima_etal_turbo(u_ll, u_rr, orientation_or_normal_direction, equations) diff --git a/src/equations/shallow_water_1d.jl b/src/equations/shallow_water_1d.jl index 25ce0fa79fe..e348ef946b7 100644 --- a/src/equations/shallow_water_1d.jl +++ b/src/equations/shallow_water_1d.jl @@ -6,7 +6,7 @@ #! format: noindent @doc raw""" - ShallowWaterEquations1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing) + ShallowWaterEquations1D(; gravity, H0 = 0) Shallow water equations (SWE) in one space dimension. The equations are given by ```math @@ -24,12 +24,6 @@ also defines the total water height as ``H = h + b``. The additional quantity ``H_0`` is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness. -Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not -have to be passed, as default values are defined within the struct. The first one, `threshold_limiter`, is -used in [`PositivityPreservingLimiterShallowWater`](@ref) on the water height, as a (small) shift on the initial -condition and cutoff before the next time step. The second one, `threshold_wet`, is applied on the water height to -define when the flow is "wet" before calculating the numerical flux. - The bottom topography function ``b(x)`` is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable `b` to zero. @@ -51,35 +45,16 @@ References for the SWE are many but a good introduction is available in Chapter [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253) """ struct ShallowWaterEquations1D{RealT <: Real} <: AbstractShallowWaterEquations{1, 3} - # TODO: TrixiShallowWater: where should the `threshold_limiter` and `threshold_wet` live? - # how to "properly" export these constants across the two packages? gravity::RealT # gravitational constant H0::RealT # constant "lake-at-rest" total water height - # `threshold_limiter` used in `PositivityPreservingLimiterShallowWater` on water height, - # as a (small) shift on the initial condition and cutoff before the next time step. - # Default is 500*eps() which in double precision is ≈1e-13. - threshold_limiter::RealT - # `threshold_wet` applied on water height to define when the flow is "wet" - # before calculating the numerical flux. - # Default is 5*eps() which in double precision is ≈1e-15. - threshold_wet::RealT end # Allow for flexibility to set the gravitational constant within an elixir depending on the # application where `gravity_constant=1.0` or `gravity_constant=9.81` are common values. # The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" # well-balancedness test cases. -# Strict default values for thresholds that performed well in many numerical experiments -function ShallowWaterEquations1D(; gravity_constant, H0 = zero(gravity_constant), - threshold_limiter = nothing, threshold_wet = nothing) - T = promote_type(typeof(gravity_constant), typeof(H0)) - if threshold_limiter === nothing - threshold_limiter = 500 * eps(T) - end - if threshold_wet === nothing - threshold_wet = 5 * eps(T) - end - ShallowWaterEquations1D(gravity_constant, H0, threshold_limiter, threshold_wet) +function ShallowWaterEquations1D(; gravity_constant, H0 = zero(gravity_constant)) + ShallowWaterEquations1D(gravity_constant, H0) end have_nonconservative_terms(::ShallowWaterEquations1D) = True() @@ -332,54 +307,6 @@ Further details on the hydrostatic reconstruction and its motivation can be foun z) end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - flux_nonconservative_chen_noelle(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterEquations1D) - -Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. -The discretization uses the `hydrostatic_reconstruction_chen_noelle` on the conservative -variables. - -Should be used together with [`FluxHydrostaticReconstruction`](@ref) and -[`hydrostatic_reconstruction_chen_noelle`](@ref) in the surface flux to ensure consistency. - -Further details on the hydrostatic reconstruction and its motivation can be found in -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function flux_nonconservative_chen_noelle(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterEquations1D) - - # Pull the water height and bottom topography on the left - h_ll, _, b_ll = u_ll - h_rr, _, b_rr = u_rr - - H_ll = h_ll + b_ll - H_rr = h_rr + b_rr - - b_star = min(max(b_ll, b_rr), min(H_ll, H_rr)) - - # Create the hydrostatic reconstruction for the left solution state - u_ll_star, _ = hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, equations) - - # Copy the reconstructed water height for easier to read code - h_ll_star = u_ll_star[1] - - z = zero(eltype(u_ll)) - # Includes two parts: - # (i) Diagonal (consistent) term from the volume flux that uses `b_ll` to avoid - # cross-averaging across a discontinuous bottom topography - # (ii) True surface part that uses `h_ll` and `h_ll_star` to handle discontinuous bathymetry - return SVector(z, - equations.gravity * h_ll * b_ll - - equations.gravity * (h_ll_star + h_ll) * (b_ll - b_star), - z) -end - """ flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations1D) @@ -521,67 +448,6 @@ Further details on this hydrostatic reconstruction and its motivation can be fou return u_ll_star, u_rr_star end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations1D) - -A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness -for a general bottom topography of the [`ShallowWaterEquations1D`](@ref). The reconstructed solution states -`u_ll_star` and `u_rr_star` variables are used to evaluate the surface numerical flux at the interface. -The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. -Use in combination with the generic numerical flux routine [`FluxHydrostaticReconstruction`](@ref). - -Further details on this hydrostatic reconstruction and its motivation can be found in -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, - equations::ShallowWaterEquations1D) - # Unpack left and right water heights and bottom topographies - h_ll, _, b_ll = u_ll - h_rr, _, b_rr = u_rr - - # Get the velocities on either side - v_ll = velocity(u_ll, equations) - v_rr = velocity(u_rr, equations) - - H_ll = b_ll + h_ll - H_rr = b_rr + h_rr - - b_star = min(max(b_ll, b_rr), min(H_ll, H_rr)) - - # Compute the reconstructed water heights - h_ll_star = min(H_ll - b_star, h_ll) - h_rr_star = min(H_rr - b_star, h_rr) - - # Set the water height to be at least the value stored in the variable threshold after - # the hydrostatic reconstruction is applied and before the numerical flux is calculated - # to avoid numerical problem with arbitrary small values. Interfaces with a water height - # lower or equal to the threshold can be declared as dry. - # The default value for `threshold_wet` is ≈ 5*eps(), or 1e-15 in double precision, is set - # in the `ShallowWaterEquations1D` struct. This threshold value can be changed in the constructor - # call of this equation struct in an elixir. - threshold = equations.threshold_wet - - if (h_ll_star <= threshold) - h_ll_star = threshold - v_ll = zero(v_ll) - end - - if (h_rr_star <= threshold) - h_rr_star = threshold - v_rr = zero(v_rr) - end - - # Create the conservative variables using the reconstruted water heights - u_ll_star = SVector(h_ll_star, h_ll_star * v_ll, b_ll) - u_rr_star = SVector(h_rr_star, h_rr_star * v_rr, b_rr) - - return u_ll_star, u_rr_star -end - # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation as the # maximum velocity magnitude plus the maximum speed of sound @inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, @@ -646,39 +512,6 @@ end return λ_min, λ_max end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations1D) - -The approximated speeds for the HLL type numerical flux used by Chen and Noelle for their -hydrostatic reconstruction. As they state in the paper, these speeds are chosen for the numerical -flux to ensure positivity and to satisfy an entropy inequality. - -Further details on this hydrostatic reconstruction and its motivation can be found in -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations1D) - # Get the velocity quantities - v_ll = velocity(u_ll, equations) - v_rr = velocity(u_rr, equations) - - # Calculate the wave celerity on the left and right - h_ll = waterheight(u_ll, equations) - h_rr = waterheight(u_rr, equations) - - a_ll = sqrt(equations.gravity * h_ll) - a_rr = sqrt(equations.gravity * h_rr) - - λ_min = min(v_ll - a_ll, v_rr - a_rr, zero(eltype(u_ll))) - λ_max = max(v_ll + a_ll, v_rr + a_rr, zero(eltype(u_ll))) - - return λ_min, λ_max -end - # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations1D) @@ -841,20 +674,10 @@ end end # Calculate the error for the "lake-at-rest" test case where H = h+b should -# be a constant value over time. Note, assumes there is a single reference -# water height `H0` with which to compare. -# -# TODO: TrixiShallowWater: where should `threshold_limiter` live? May need -# to modify or have different versions of the `lake_at_rest_error` function +# be a constant value over time. @inline function lake_at_rest_error(u, equations::ShallowWaterEquations1D) h, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - H0_wet_dry = max(equations.H0, b + equations.threshold_limiter) - - return abs(H0_wet_dry - (h + b)) + return abs(equations.H0 - (h + b)) end end # @muladd diff --git a/src/equations/shallow_water_2d.jl b/src/equations/shallow_water_2d.jl index 6728d7d5553..74a299a51e6 100644 --- a/src/equations/shallow_water_2d.jl +++ b/src/equations/shallow_water_2d.jl @@ -6,7 +6,7 @@ #! format: noindent @doc raw""" - ShallowWaterEquations2D(; gravity, H0 = 0, threshold_limiter = nothing, threshold_wet = nothing) + ShallowWaterEquations2D(; gravity, H0 = 0) Shallow water equations (SWE) in two space dimensions. The equations are given by ```math @@ -27,12 +27,6 @@ also defines the total water height as ``H = h + b``. The additional quantity ``H_0`` is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness. -Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not -have to be passed, as default values are defined within the struct. The first one, `threshold_limiter`, is -used in [`PositivityPreservingLimiterShallowWater`](@ref) on the water height, as a (small) shift on the initial -condition and cutoff before the next time step. The second one, `threshold_wet`, is applied on the water height to -define when the flow is "wet" before calculating the numerical flux. - The bottom topography function ``b(x,y)`` is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable `b` to zero. @@ -54,18 +48,8 @@ References for the SWE are many but a good introduction is available in Chapter [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253) """ struct ShallowWaterEquations2D{RealT <: Real} <: AbstractShallowWaterEquations{2, 4} - # TODO: TrixiShallowWater: where should the `threshold_limiter` and `threshold_wet` live? - # how to "properly" export these constants across the two packages? gravity::RealT # gravitational constant H0::RealT # constant "lake-at-rest" total water height - # `threshold_limiter` used in `PositivityPreservingLimiterShallowWater` on water height, - # as a (small) shift on the initial condition and cutoff before the next time step. - # Default is 500*eps() which in double precision is ≈1e-13. - threshold_limiter::RealT - # `threshold_wet` applied on water height to define when the flow is "wet" - # before calculating the numerical flux. - # Default is 5*eps() which in double precision is ≈1e-15. - threshold_wet::RealT end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -73,16 +57,8 @@ end # The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" # well-balancedness test cases. # Strict default values for thresholds that performed well in many numerical experiments -function ShallowWaterEquations2D(; gravity_constant, H0 = zero(gravity_constant), - threshold_limiter = nothing, threshold_wet = nothing) - T = promote_type(typeof(gravity_constant), typeof(H0)) - if threshold_limiter === nothing - threshold_limiter = 500 * eps(T) - end - if threshold_wet === nothing - threshold_wet = 5 * eps(T) - end - ShallowWaterEquations2D(gravity_constant, H0, threshold_limiter, threshold_wet) +function ShallowWaterEquations2D(; gravity_constant, H0 = zero(gravity_constant)) + ShallowWaterEquations2D(gravity_constant, H0) end have_nonconservative_terms(::ShallowWaterEquations2D) = True() @@ -460,69 +436,6 @@ Further details for the hydrostatic reconstruction and its motivation can be fou return u_ll_star, u_rr_star end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations2D) - -A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness -for a general bottom topography of the [`ShallowWaterEquations2D`](@ref). The reconstructed solution states -`u_ll_star` and `u_rr_star` variables are then used to evaluate the surface numerical flux at the interface. -The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. -Use in combination with the generic numerical flux routine [`FluxHydrostaticReconstruction`](@ref). - -Further details on this hydrostatic reconstruction and its motivation can be found in -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, - equations::ShallowWaterEquations2D) - # Unpack left and right water heights and bottom topographies - h_ll, _, _, b_ll = u_ll - h_rr, _, _, b_rr = u_rr - - # Get the velocities on either side - v1_ll, v2_ll = velocity(u_ll, equations) - v1_rr, v2_rr = velocity(u_rr, equations) - - H_ll = b_ll + h_ll - H_rr = b_rr + h_rr - - b_star = min(max(b_ll, b_rr), min(H_ll, H_rr)) - - # Compute the reconstructed water heights - h_ll_star = min(H_ll - b_star, h_ll) - h_rr_star = min(H_rr - b_star, h_rr) - - # Set the water height to be at least the value stored in the variable threshold after - # the hydrostatic reconstruction is applied and before the numerical flux is calculated - # to avoid numerical problem with arbitrary small values. Interfaces with a water height - # lower or equal to the threshold can be declared as dry. - # The default value for `threshold_wet` is ≈5*eps(), or 1e-15 in double precision, is set - # in the `ShallowWaterEquations2D` struct. This threshold value can be changed in the constructor - # call of this equation struct in an elixir. - threshold = equations.threshold_wet - - if (h_ll_star <= threshold) - h_ll_star = threshold - v1_ll = zero(v1_ll) - v2_ll = zero(v2_ll) - end - - if (h_rr_star <= threshold) - h_rr_star = threshold - v1_rr = zero(v1_rr) - v2_rr = zero(v2_rr) - end - - # Create the conservative variables using the reconstruted water heights - u_ll_star = SVector(h_ll_star, h_ll_star * v1_ll, h_ll_star * v2_ll, b_ll) - u_rr_star = SVector(h_rr_star, h_rr_star * v1_rr, h_rr_star * v2_rr, b_rr) - - return u_ll_star, u_rr_star -end - """ flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations2D) @@ -608,104 +521,6 @@ end return SVector(f1, f2, f3, f4) end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - flux_nonconservative_chen_noelle(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterEquations2D) - flux_nonconservative_chen_noelle(u_ll, u_rr, - normal_direction_ll ::AbstractVector, - normal_direction_average ::AbstractVector, - equations::ShallowWaterEquations2D) - -Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. -The discretization uses the [`hydrostatic_reconstruction_chen_noelle`](@ref) on the conservative -variables. - -Should be used together with [`FluxHydrostaticReconstruction`](@ref) and -[`hydrostatic_reconstruction_chen_noelle`](@ref) in the surface flux to ensure consistency. - -Further details on the hydrostatic reconstruction and its motivation can be found in -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function flux_nonconservative_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations2D) - # Pull the water height and bottom topography on the left - h_ll, _, _, b_ll = u_ll - h_rr, _, _, b_rr = u_rr - - H_ll = h_ll + b_ll - H_rr = h_rr + b_rr - - b_star = min(max(b_ll, b_rr), min(H_ll, H_rr)) - - # Create the hydrostatic reconstruction for the left solution state - u_ll_star, _ = hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, equations) - - # Copy the reconstructed water height for easier to read code - h_ll_star = u_ll_star[1] - - z = zero(eltype(u_ll)) - # Includes two parts: - # (i) Diagonal (consistent) term from the volume flux that uses `b_ll` to avoid - # cross-averaging across a discontinuous bottom topography - # (ii) True surface part that uses `h_ll` and `h_ll_star` to handle discontinuous bathymetry - g = equations.gravity - if orientation == 1 - f = SVector(z, - g * h_ll * b_ll - g * (h_ll_star + h_ll) * (b_ll - b_star), - z, z) - else # orientation == 2 - f = SVector(z, z, - g * h_ll * b_ll - g * (h_ll_star + h_ll) * (b_ll - b_star), - z) - end - - return f -end - -@inline function flux_nonconservative_chen_noelle(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquations2D) - # Pull the water height and bottom topography on the left - h_ll, _, _, b_ll = u_ll - h_rr, _, _, b_rr = u_rr - - H_ll = h_ll + b_ll - H_rr = h_rr + b_rr - - b_star = min(max(b_ll, b_rr), min(H_ll, H_rr)) - - # Create the hydrostatic reconstruction for the left solution state - u_ll_star, _ = hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, equations) - - # Copy the reconstructed water height for easier to read code - h_ll_star = u_ll_star[1] - - # Comes in two parts: - # (i) Diagonal (consistent) term from the volume flux that uses `normal_direction_average` - # but we use `b_ll` to avoid cross-averaging across a discontinuous bottom topography - - f2 = normal_direction_average[1] * equations.gravity * h_ll * b_ll - f3 = normal_direction_average[2] * equations.gravity * h_ll * b_ll - - # (ii) True surface part that uses `normal_direction_ll`, `h_ll` and `h_ll_star` - # to handle discontinuous bathymetry - - f2 -= normal_direction_ll[1] * equations.gravity * (h_ll_star + h_ll) * - (b_ll - b_star) - f3 -= normal_direction_ll[2] * equations.gravity * (h_ll_star + h_ll) * - (b_ll - b_star) - - # First and last equations do not have a nonconservative flux - f1 = f4 = zero(eltype(u_ll)) - - return SVector(f1, f2, f3, f4) -end - """ flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations2D) @@ -1020,67 +835,6 @@ end return λ_min, λ_max end -# TODO: TrixiShallowWater: move wet/dry specific routine -""" - min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations2D) - min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquations2D) - -Special estimate of the minimal and maximal wave speed of the shallow water equations for -the left and right states `u_ll, u_rr`. These approximate speeds are used for the HLL-type -numerical flux [`flux_hll_chen_noelle`](@ref). These wave speed estimates -together with a particular hydrostatic reconstruction technique guarantee -that the numerical flux is positive and satisfies an entropy inequality. - -Further details on this hydrostatic reconstruction and its motivation can be found in -the reference below. The definition of the wave speeds are given in Equation (2.20). -- Guoxian Chen and Sebastian Noelle (2017) - A new hydrostatic reconstruction scheme based on subcell reconstructions - [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) -""" -@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations2D) - h_ll = waterheight(u_ll, equations) - v1_ll, v2_ll = velocity(u_ll, equations) - h_rr = waterheight(u_rr, equations) - v1_rr, v2_rr = velocity(u_rr, equations) - - a_ll = sqrt(equations.gravity * h_ll) - a_rr = sqrt(equations.gravity * h_rr) - - if orientation == 1 # x-direction - λ_min = min(v1_ll - a_ll, v1_rr - a_rr, zero(eltype(u_ll))) - λ_max = max(v1_ll + a_ll, v1_rr + a_rr, zero(eltype(u_ll))) - else # y-direction - λ_min = min(v2_ll - a_ll, v2_rr - a_rr, zero(eltype(u_ll))) - λ_max = max(v2_ll + a_ll, v2_rr + a_rr, zero(eltype(u_ll))) - end - - return λ_min, λ_max -end - -@inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquations2D) - h_ll = waterheight(u_ll, equations) - v1_ll, v2_ll = velocity(u_ll, equations) - h_rr = waterheight(u_rr, equations) - v1_rr, v2_rr = velocity(u_rr, equations) - - v_normal_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] - v_normal_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] - - norm_ = norm(normal_direction) - - a_ll = sqrt(equations.gravity * h_ll) * norm_ - a_rr = sqrt(equations.gravity * h_rr) * norm_ - - λ_min = min(v_normal_ll - a_ll, v_normal_rr - a_rr, zero(eltype(u_ll))) - λ_max = max(v_normal_ll + a_ll, v_normal_rr + a_rr, zero(eltype(u_ll))) - - return λ_min, λ_max -end - # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations2D) @@ -1327,20 +1081,10 @@ end end # Calculate the error for the "lake-at-rest" test case where H = h+b should -# be a constant value over time. Note, assumes there is a single reference -# water height `H0` with which to compare. -# -# TODO: TrixiShallowWater: where should `threshold_limiter` live? May need -# to modify or have different versions of the `lake_at_rest_error` function +# be a constant value over time. @inline function lake_at_rest_error(u, equations::ShallowWaterEquations2D) h, _, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - H0_wet_dry = max(equations.H0, b + equations.threshold_limiter) - - return abs(H0_wet_dry - (h + b)) + return abs(equations.H0 - (h + b)) end end # @muladd diff --git a/src/equations/shallow_water_quasi_1d.jl b/src/equations/shallow_water_quasi_1d.jl index d52fbab841d..51c360104a7 100644 --- a/src/equations/shallow_water_quasi_1d.jl +++ b/src/equations/shallow_water_quasi_1d.jl @@ -22,12 +22,6 @@ The gravitational constant is denoted by `g`, the (possibly) variable bottom top The additional quantity ``H_0`` is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness. -Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not -have to be passed, as default values are defined within the struct. The first one, `threshold_limiter`, is -used in [`PositivityPreservingLimiterShallowWater`](@ref) on the water height, as a (small) shift on the initial -condition and cutoff before the next time step. The second one, `threshold_wet`, is applied on the water height to -define when the flow is "wet" before calculating the numerical flux. - The bottom topography function ``b(x)`` and channel width ``a(x)`` are set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable `b` to zero and ``a`` to one. @@ -47,14 +41,6 @@ struct ShallowWaterEquationsQuasi1D{RealT <: Real} <: AbstractShallowWaterEquations{1, 4} gravity::RealT # gravitational constant H0::RealT # constant "lake-at-rest" total water height - # `threshold_limiter` used in `PositivityPreservingLimiterShallowWater` on water height, - # as a (small) shift on the initial condition and cutoff before the next time step. - # Default is 500*eps() which in double precision is ≈1e-13. - threshold_limiter::RealT - # `threshold_wet` applied on water height to define when the flow is "wet" - # before calculating the numerical flux. - # Default is 5*eps() which in double precision is ≈1e-15. - threshold_wet::RealT end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -62,17 +48,8 @@ end # The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" # well-balancedness test cases. # Strict default values for thresholds that performed well in many numerical experiments -function ShallowWaterEquationsQuasi1D(; gravity_constant, H0 = zero(gravity_constant), - threshold_limiter = nothing, - threshold_wet = nothing) - T = promote_type(typeof(gravity_constant), typeof(H0)) - if threshold_limiter === nothing - threshold_limiter = 500 * eps(T) - end - if threshold_wet === nothing - threshold_wet = 5 * eps(T) - end - ShallowWaterEquationsQuasi1D(gravity_constant, H0, threshold_limiter, threshold_wet) +function ShallowWaterEquationsQuasi1D(; gravity_constant, H0 = zero(gravity_constant)) + ShallowWaterEquationsQuasi1D(gravity_constant, H0) end have_nonconservative_terms(::ShallowWaterEquationsQuasi1D) = True() @@ -338,18 +315,10 @@ end # be a constant value over time. Note, assumes there is a single reference # water height `H0` with which to compare. # -# TODO: TrixiShallowWater: where should `threshold_limiter` live? May need -# to modify or have different versions of the `lake_at_rest_error` function @inline function lake_at_rest_error(u, equations::ShallowWaterEquationsQuasi1D) _, _, b, _ = u h = waterheight(u, equations) - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - H0_wet_dry = max(equations.H0, b + equations.threshold_limiter) - - return abs(H0_wet_dry - (h + b)) + return abs(equations.H0 - (h + b)) end end # @muladd diff --git a/src/equations/shallow_water_two_layer_1d.jl b/src/equations/shallow_water_two_layer_1d.jl deleted file mode 100644 index 42ff393593e..00000000000 --- a/src/equations/shallow_water_two_layer_1d.jl +++ /dev/null @@ -1,511 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin -#! format: noindent - -# TODO: TrixiShallowWater: 1D two layer equations should move to new package - -@doc raw""" - ShallowWaterTwoLayerEquations1D(gravity, H0, rho_upper, rho_lower) - -Two-Layer Shallow Water equations (2LSWE) in one space dimension. The equations are given by -```math -\begin{alignat*}{4} -&\frac{\partial}{\partial t}h_{upper} -&&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper}\right) -&&= 0 \\ -&\frac{\partial}{\partial t}\left(h_{upper}v_{1,upper}\right) -&&+ \frac{\partial}{\partial x}\left(h_{upper}v_{1,upper}^2 + \dfrac{gh_{upper}^2}{2}\right) -&&= -gh_{upper}\frac{\partial}{\partial x}\left(b+h_{lower}\right)\\ -&\frac{\partial}{\partial t}h_{lower} -&&+ \frac{\partial}{\partial x}\left(h_{lower}v_{1,lower}\right) -&&= 0 \\ -&\frac{\partial}{\partial t}\left(h_{lower}v_{1,lower}\right) -&&+ \frac{\partial}{\partial x}\left(h_{lower}v_{1,lower}^2 + \dfrac{gh_{lower}^2}{2}\right) -&&= -gh_{lower}\frac{\partial}{\partial x}\left(b+\dfrac{\rho_{upper}}{\rho_{lower}}h_{upper}\right). -\end{alignat*} -``` -The unknown quantities of the 2LSWE are the water heights of the {lower} layer ``h_{lower}`` and the -{upper} layer ``h_{upper}`` with respective velocities ``v_{1,upper}`` and ``v_{1,lower}``. The gravitational constant is -denoted by `g`, the layer densitites by ``\rho_{upper}``and ``\rho_{lower}`` and the (possibly) variable -bottom topography function ``b(x)``. The conservative variable water height ``h_{lower}`` is measured -from the bottom topography ``b`` and ``h_{upper}`` relative to ``h_{lower}``, therefore one also defines the -total water heights as ``H_{upper} = h_{upper} + h_{upper} + b`` and ``H_{lower} = h_{lower} + b``. - -The densities must be chosen such that ``\rho_{upper} < \rho_{lower}``, to make sure that the heavier fluid -``\rho_{lower}`` is in the bottom layer and the lighter fluid ``\rho_{upper}`` in the {upper} layer. - -The additional quantity ``H_0`` is also available to store a reference value for the total water -height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness. - -The bottom topography function ``b(x)`` is set inside the initial condition routine -for a particular problem setup. - -In addition to the unknowns, Trixi currently stores the bottom topography values at the -approximation points despite being fixed in time. This is done for convenience of computing the -bottom topography gradients on the fly during the approximation as well as computing auxiliary -quantities like the total water height ``H`` or the entropy variables. -This affects the implementation and use of these equations in various ways: -* The flux values corresponding to the bottom topography must be zero. -* The bottom topography values must be included when defining initial conditions, boundary - conditions or source terms. -* [`AnalysisCallback`](@ref) analyzes this variable. -* Trixi's visualization tools will visualize the bottom topography by default. - -A good introduction for the 2LSWE is available in Chapter 12 of the book: -- Benoit Cushman-Roisin (2011)\ - Introduction to geophyiscal fluid dynamics: physical and numerical aspects\ - \ - ISBN: 978-0-12-088759-0 -""" -struct ShallowWaterTwoLayerEquations1D{RealT <: Real} <: - AbstractShallowWaterEquations{1, 5} - gravity::RealT # gravitational constant - H0::RealT # constant "lake-at-rest" total water height - rho_upper::RealT # lower layer density - rho_lower::RealT # upper layer density - r::RealT # ratio of rho_upper / rho_lower -end - -# Allow for flexibility to set the gravitational constant within an elixir depending on the -# application where `gravity_constant=1.0` or `gravity_constant=9.81` are common values. -# The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" -# well-balancedness test cases. Densities must be specified such that rho_upper <= rho_lower. -function ShallowWaterTwoLayerEquations1D(; gravity_constant, - H0 = zero(gravity_constant), rho_upper, - rho_lower) - # Assign density ratio if rho_upper <= rho_lower - if rho_upper > rho_lower - error("Invalid input: Densities must be chosen such that rho_upper <= rho_lower") - else - r = rho_upper / rho_lower - end - ShallowWaterTwoLayerEquations1D(gravity_constant, H0, rho_upper, rho_lower, r) -end - -have_nonconservative_terms(::ShallowWaterTwoLayerEquations1D) = True() -function varnames(::typeof(cons2cons), ::ShallowWaterTwoLayerEquations1D) - ("h_upper", "h_v_upper", - "h_lower", "h_v_lower", "b") -end -# Note, we use the total water height, H_lower = h_upper + h_lower + b, and first layer total height -# H_upper = h_upper + b as the first primitive variable for easier visualization and setting initial -# conditions -function varnames(::typeof(cons2prim), ::ShallowWaterTwoLayerEquations1D) - ("H_upper", "v_upper", - "H_lower", "v_lower", "b") -end - -# Set initial conditions at physical location `x` for time `t` -""" - initial_condition_convergence_test(x, t, equations::ShallowWaterTwoLayerEquations1D) - -A smooth initial condition used for convergence tests in combination with -[`source_terms_convergence_test`](@ref) (and -[`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) in non-periodic domains). -""" -function initial_condition_convergence_test(x, t, - equations::ShallowWaterTwoLayerEquations1D) - # some constants are chosen such that the function is periodic on the domain [0,sqrt(2)] - ω = 2.0 * pi * sqrt(2.0) - - H_lower = 2.0 + 0.1 * sin(ω * x[1] + t) - H_upper = 4.0 + 0.1 * cos(ω * x[1] + t) - v_lower = 1.0 - v_upper = 0.9 - b = 1.0 + 0.1 * cos(2.0 * ω * x[1]) - - return prim2cons(SVector(H_upper, v_upper, H_lower, v_lower, b), equations) -end - -""" - source_terms_convergence_test(u, x, t, equations::ShallowWaterTwoLayerEquations1D) - -Source terms used for convergence tests in combination with -[`initial_condition_convergence_test`](@ref) -(and [`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) -in non-periodic domains). -""" -@inline function source_terms_convergence_test(u, x, t, - equations::ShallowWaterTwoLayerEquations1D) - # Same settings as in `initial_condition_convergence_test`. Some derivative simplify because - # this manufactured solution velocity is taken to be constant - ω = 2 * pi * sqrt(2.0) - - du1 = (-0.1 * cos(t + ω * x[1]) - 0.1 * sin(t + ω * x[1]) - - 0.09 * ω * cos(t + ω * x[1]) + - -0.09 * ω * sin(t + ω * x[1])) - du2 = (5.0 * (-0.1 * ω * cos(t + ω * x[1]) - 0.1 * ω * sin(t + ω * x[1])) * - (4.0 + 0.2 * cos(t + ω * x[1]) + - -0.2 * sin(t + ω * x[1])) + - 0.1 * ω * (20.0 + cos(t + ω * x[1]) - sin(t + ω * x[1])) * - cos(t + - ω * x[1]) - 0.09 * cos(t + ω * x[1]) - 0.09 * sin(t + ω * x[1]) - - 0.081 * ω * cos(t + ω * x[1]) + - -0.081 * ω * sin(t + ω * x[1])) - du3 = 0.1 * cos(t + ω * x[1]) + 0.1 * ω * cos(t + ω * x[1]) + - 0.2 * ω * sin(2.0 * ω * x[1]) - du4 = ((10.0 + sin(t + ω * x[1]) - cos(2ω * x[1])) * - (-0.09 * ω * cos(t + ω * x[1]) - 0.09 * ω * sin(t + - ω * x[1]) - - 0.2 * ω * sin(2 * ω * x[1])) + 0.1 * cos(t + ω * x[1]) + - 0.1 * ω * cos(t + ω * x[1]) + - 5.0 * (0.1 * ω * cos(t + ω * x[1]) + 0.2 * ω * sin(2.0 * ω * x[1])) * - (2.0 + 0.2 * sin(t + ω * x[1]) + - -0.2 * cos(2.0 * ω * x[1])) + 0.2 * ω * sin(2.0 * ω * x[1])) - - return SVector(du1, du2, du3, du4, zero(eltype(u))) -end - -""" - boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function, - equations::ShallowWaterTwoLayerEquations1D) - -Create a boundary state by reflecting the normal velocity component and keep -the tangential velocity component unchanged. The boundary water height is taken from -the internal value. - -For details see Section 9.2.5 of the book: -- Eleuterio F. Toro (2001) - Shock-Capturing Methods for Free-Surface Shallow Flows - 1st edition - ISBN 0471987662 -""" -@inline function boundary_condition_slip_wall(u_inner, orientation_or_normal, direction, - x, t, surface_flux_function, - equations::ShallowWaterTwoLayerEquations1D) - # create the "external" boundary solution state - u_boundary = SVector(u_inner[1], - -u_inner[2], - u_inner[3], - -u_inner[4], - u_inner[5]) - - # calculate the boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - f = surface_flux_function(u_inner, u_boundary, orientation_or_normal, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - f = surface_flux_function(u_boundary, u_inner, orientation_or_normal, equations) - end - return f -end - -# Calculate 1D flux for a single point -# Note, the bottom topography has no flux -@inline function flux(u, orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v_upper, h_lower, h_v_lower, _ = u - - # Calculate velocities - v_upper, v_lower = velocity(u, equations) - # Calculate pressure - p_upper = 0.5 * equations.gravity * h_upper^2 - p_lower = 0.5 * equations.gravity * h_lower^2 - - f1 = h_v_upper - f2 = h_v_upper * v_upper + p_upper - f3 = h_v_lower - f4 = h_v_lower * v_lower + p_lower - - return SVector(f1, f2, f3, f4, zero(eltype(u))) -end - -""" - flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - -!!! warning "Experimental code" - This numerical flux is experimental and may change in any future release. - -Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term -that contains the gradient of the bottom topography [`ShallowWaterTwoLayerEquations1D`](@ref) and an -additional term that couples the momentum of both layers. - -This is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy -conservation and well-balancedness in both the volume and surface when combined with -[`flux_wintermeyer_etal`](@ref). - -For further details see: -- Patrick Ersing, Andrew R. Winters (2023) - An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on - curvilinear meshes - [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) -""" -@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Pull the necessary left and right state information - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - b_rr = u_rr[5] - b_ll = u_ll[5] - - # Calculate jumps - h_upper_jump = (h_upper_rr - h_upper_ll) - h_lower_jump = (h_lower_rr - h_lower_ll) - b_jump = (b_rr - b_ll) - - z = zero(eltype(u_ll)) - - # Bottom gradient nonconservative term: (0, g*h_upper*(b+h_lower)_x, - # 0, g*h_lower*(b+r*h_upper)_x, 0) - f = SVector(z, - equations.gravity * h_upper_ll * (b_jump + h_lower_jump), - z, - equations.gravity * h_lower_ll * (b_jump + equations.r * h_upper_jump), - z) - return f -end - -""" - flux_wintermeyer_etal(u_ll, u_rr, orientation, - equations::ShallowWaterTwoLayerEquations1D) - -Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. -When the bottom topography is nonzero this scheme will be well-balanced when used with the -nonconservative [`flux_nonconservative_ersing_etal`](@ref). To obtain the flux for the -two-layer shallow water equations the flux that is described in the paper for the normal shallow -water equations is used within each layer. - -Further details are available in Theorem 1 of the paper: -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) - An entropy stable nodal discontinuous Galerkin method for the two dimensional - shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry - [DOI: 10.1016/j.jcp.2017.03.036](https://doi.org/10.1016/j.jcp.2017.03.036) -""" -@inline function flux_wintermeyer_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Unpack left and right state - h_upper_ll, h_v_upper_ll, h_lower_ll, h_v_lower_ll, _ = u_ll - h_upper_rr, h_v_upper_rr, h_lower_rr, h_v_lower_rr, _ = u_rr - - # Get the velocities on either side - v_upper_ll, v_lower_ll = velocity(u_ll, equations) - v_upper_rr, v_lower_rr = velocity(u_rr, equations) - - # Average each factor of products in flux - v_upper_avg = 0.5 * (v_upper_ll + v_upper_rr) - v_lower_avg = 0.5 * (v_lower_ll + v_lower_rr) - p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr - - # Calculate fluxes - f1 = 0.5 * (h_v_upper_ll + h_v_upper_rr) - f2 = f1 * v_upper_avg + p_upper_avg - f3 = 0.5 * (h_v_lower_ll + h_v_lower_rr) - f4 = f3 * v_lower_avg + p_lower_avg - - return SVector(f1, f2, f3, f4, zero(eltype(u_ll))) -end - -""" - flux_es_ersing_etal(u_ll, u_rr, orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations1D) -Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative -[`flux_wintermeyer_etal`](@ref) and adds a Lax-Friedrichs type dissipation dependent on the jump of -entropy variables. - -For further details see: -- Patrick Ersing, Andrew R. Winters (2023) - An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on - curvilinear meshes - [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) -""" -@inline function flux_es_ersing_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Compute entropy conservative flux but without the bottom topography - f_ec = flux_wintermeyer_etal(u_ll, u_rr, - orientation, - equations) - - # Get maximum signal velocity - λ = max_abs_speed_naive(u_ll, u_rr, orientation, equations) - # Get entropy variables but without the bottom topography - q_rr = cons2entropy(u_rr, equations) - q_ll = cons2entropy(u_ll, equations) - - # Average values from left and right - u_avg = (u_ll + u_rr) / 2 - - # Introduce variables for better readability - rho_upper = equations.rho_upper - rho_lower = equations.rho_lower - g = equations.gravity - drho = rho_upper - rho_lower - - # Compute entropy Jacobian coefficients - h11 = -rho_lower / (g * rho_upper * drho) - h12 = -rho_lower * u_avg[2] / (g * rho_upper * u_avg[1] * drho) - h13 = 1.0 / (g * drho) - h14 = u_avg[4] / (g * u_avg[3] * drho) - h21 = -rho_lower * u_avg[2] / (g * rho_upper * u_avg[1] * drho) - h22 = ((g * rho_upper * u_avg[1]^3 - g * rho_lower * u_avg[1]^3 + - -rho_lower * u_avg[2]^2) / (g * rho_upper * u_avg[1]^2 * drho)) - h23 = u_avg[2] / (g * u_avg[1] * drho) - h24 = u_avg[2] * u_avg[4] / (g * u_avg[1] * u_avg[3] * drho) - h31 = 1.0 / (g * drho) - h32 = u_avg[2] / (g * u_avg[1] * drho) - h33 = -1.0 / (g * drho) - h34 = -u_avg[4] / (g * u_avg[3] * drho) - h41 = u_avg[4] / (g * u_avg[3] * drho) - h42 = u_avg[2] * u_avg[4] / (g * u_avg[1] * u_avg[3] * drho) - h43 = -u_avg[4] / (g * u_avg[3] * drho) - h44 = ((g * rho_upper * u_avg[3]^3 - g * rho_lower * u_avg[3]^3 + - -rho_lower * u_avg[4]^2) / (g * rho_lower * u_avg[3]^2 * drho)) - - # Entropy Jacobian matrix - H = @SMatrix [[h11;; h12;; h13;; h14;; 0]; - [h21;; h22;; h23;; h24;; 0]; - [h31;; h32;; h33;; h34;; 0]; - [h41;; h42;; h43;; h44;; 0]; - [0;; 0;; 0;; 0;; 0]] - - # Add dissipation to entropy conservative flux to obtain entropy stable flux - f_es = f_ec - 0.5 * λ * H * (q_rr - q_ll) - - return SVector(f_es[1], f_es[2], f_es[3], f_es[4], zero(eltype(u_ll))) -end - -# Calculate approximation for maximum wave speed for local Lax-Friedrichs-type dissipation as the -# maximum velocity magnitude plus the maximum speed of sound. This function uses approximate -# eigenvalues using the speed of the barotropic mode as there is no simple way to calculate them -# analytically. -# -# A good overview of the derivation is given in: -# - Jonas Nycander, Andrew McC. Hogg, Leela M. Frankcombe (2008) -# Open boundary conditions for nonlinear channel Flows -# [DOI: 10.1016/j.ocemod.2008.06.003](https://doi.org/10.1016/j.ocemod.2008.06.003) -@inline function max_abs_speed_naive(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Unpack left and right state - h_upper_ll, h_v_upper_ll, h_lower_ll, h_v_lower_ll, _ = u_ll - h_upper_rr, h_v_upper_rr, h_lower_rr, h_v_lower_rr, _ = u_rr - - # Get the averaged velocity - v_m_ll = (h_v_upper_ll + h_v_lower_ll) / (h_upper_ll + h_lower_ll) - v_m_rr = (h_v_upper_rr + h_v_lower_rr) / (h_upper_rr + h_lower_rr) - - # Calculate the wave celerity on the left and right - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - c_ll = sqrt(equations.gravity * (h_upper_ll + h_lower_ll)) - c_rr = sqrt(equations.gravity * (h_upper_rr + h_lower_rr)) - - return (max(abs(v_m_ll) + c_ll, abs(v_m_rr) + c_rr)) -end - -# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom -# topography -@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations1D) - λ = dissipation.max_abs_speed(u_ll, u_rr, orientation_or_normal_direction, - equations) - diss = -0.5 * λ * (u_rr - u_ll) - return SVector(diss[1], diss[2], diss[3], diss[4], zero(eltype(u_ll))) -end - -# Absolute speed of the barotropic mode -@inline function max_abs_speeds(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v_upper, h_lower, h_v_lower, _ = u - - # Calculate averaged velocity of both layers - v_m = (h_v_upper + h_v_lower) / (h_upper + h_lower) - c = sqrt(equations.gravity * (h_upper + h_lower)) - - return (abs(v_m) + c) -end - -# Helper function to extract the velocity vector from the conservative variables -@inline function velocity(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v_upper, h_lower, h_v_lower, _ = u - - v_upper = h_v_upper / h_upper - v_lower = h_v_lower / h_lower - return SVector(v_upper, v_lower) -end - -# Convert conservative variables to primitive -@inline function cons2prim(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, _, h_lower, _, b = u - - H_lower = h_lower + b - H_upper = h_lower + h_upper + b - v_upper, v_lower = velocity(u, equations) - return SVector(H_upper, v_upper, H_lower, v_lower, b) -end - -# Convert conservative variables to entropy variables -# Note, only the first four are the entropy variables, the fifth entry still just carries the -# bottom topography values for convenience -@inline function cons2entropy(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, _, h_lower, _, b = u - v_upper, v_lower = velocity(u, equations) - - w1 = (equations.rho_upper * - (equations.gravity * (h_upper + h_lower + b) - 0.5 * v_upper^2)) - w2 = equations.rho_upper * v_upper - w3 = (equations.rho_lower * - (equations.gravity * (equations.r * h_upper + h_lower + b) - 0.5 * v_lower^2)) - w4 = equations.rho_lower * v_lower - return SVector(w1, w2, w3, w4, b) -end - -# Convert primitive to conservative variables -@inline function prim2cons(prim, equations::ShallowWaterTwoLayerEquations1D) - H_upper, v_upper, H_lower, v_lower, b = prim - - h_lower = H_lower - b - h_upper = H_upper - h_lower - b - h_v_upper = h_upper * v_upper - h_v_lower = h_lower * v_lower - return SVector(h_upper, h_v_upper, h_lower, h_v_lower, b) -end - -@inline function waterheight(u, equations::ShallowWaterTwoLayerEquations1D) - return SVector(u[1], u[3]) -end - -# Entropy function for the shallow water equations is the total energy -@inline function entropy(cons, equations::ShallowWaterTwoLayerEquations1D) - energy_total(cons, equations) -end - -# Calculate total energy for a conservative state `cons` -@inline function energy_total(cons, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v_upper, h_lower, h_v_lower, b = cons - # Set new variables for better readability - g = equations.gravity - rho_upper = equations.rho_upper - rho_lower = equations.rho_lower - - e = (0.5 * rho_upper * (h_v_upper^2 / h_upper + g * h_upper^2) + - 0.5 * rho_lower * (h_v_lower^2 / h_lower + g * h_lower^2) + - g * rho_lower * h_lower * b + g * rho_upper * h_upper * (h_lower + b)) - return e -end - -# Calculate kinetic energy for a conservative state `cons` -@inline function energy_kinetic(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v_upper, h_lower, h_v_lower, _ = u - return (0.5 * equations.rho_upper * h_v_upper^2 / h_upper + - 0.5 * equations.rho_lower * h_v_lower^2 / h_lower) -end - -# Calculate potential energy for a conservative state `cons` -@inline function energy_internal(cons, equations::ShallowWaterTwoLayerEquations1D) - return energy_total(cons, equations) - energy_kinetic(cons, equations) -end - -# Calculate the error for the "lake-at-rest" test case where H = h_upper+h_lower+b should -# be a constant value over time -@inline function lake_at_rest_error(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, _, h_lower, _, b = u - return abs(equations.H0 - (h_upper + h_lower + b)) -end -end # @muladd diff --git a/src/equations/shallow_water_two_layer_2d.jl b/src/equations/shallow_water_two_layer_2d.jl deleted file mode 100644 index a31d881f2ef..00000000000 --- a/src/equations/shallow_water_two_layer_2d.jl +++ /dev/null @@ -1,805 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin -#! format: noindent - -# TODO: TrixiShallowWater: 2D two layer equations should move to new package - -@doc raw""" - ShallowWaterTwoLayerEquations2D(gravity, H0, rho_upper, rho_lower) - -Two-Layer Shallow water equations (2LSWE) in two space dimension. The equations are given by -```math -\begin{alignat*}{8} -&\frac{\partial}{\partial t}h_{upper} -&&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper}\right) -&&+ \frac{\partial}{\partial y}\left(h_{upper} v_{2,upper}\right) \quad -&&= \quad 0 \\ -&\frac{\partial}{\partial t}\left(h_{upper} v_{1,upper}\right) -&&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper}^2 + \frac{gh_{upper}^2}{2}\right) -&&+ \frac{\partial}{\partial y}\left(h_{upper} v_{1,upper} v_{2,upper}\right) \quad -&&= -gh_{upper}\frac{\partial}{\partial x}\left(b+h_{lower}\right) \\ -&\frac{\partial}{\partial t}\left(h_{upper} v_{2,upper}\right) -&&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper} v_{2,upper}\right) -&&+ \frac{\partial}{\partial y}\left(h_{upper} v_{2,upper}^2 + \frac{gh_{upper}^2}{2}\right) -&&= -gh_{upper}\frac{\partial}{\partial y}\left(b+h_{lower}\right)\\ -&\frac{\partial}{\partial t}h_{lower} -&&+ \frac{\partial}{\partial x}\left(h_{lower} v_{1,lower}\right) -&&+ \frac{\partial}{\partial y}\left(h_{lower} v_{2,lower}\right) -&&= \quad 0 \\ -&\frac{\partial}{\partial t}\left(h_{lower} v_{1,lower}\right) -&&+ \frac{\partial}{\partial x}\left(h_{lower} v_{1,lower}^2 + \frac{gh_{lower}^2}{2}\right) -&&+ \frac{\partial}{\partial y}\left(h_{lower} v_{1,lower} v_{2,lower}\right) -&&= -gh_{lower}\frac{\partial}{\partial x}\left(b+\frac{\rho_{upper}}{\rho_{lower}} h_{upper}\right)\\ -&\frac{\partial}{\partial t}\left(h_{lower} v_{2,lower}\right) -&&+ \frac{\partial}{\partial x}\left(h_{lower} v_{1,lower} v_{2,lower}\right) -&&+ \frac{\partial}{\partial y}\left(h_{lower} v_{2,lower}^2 + \frac{gh_{lower}^2}{2}\right) -&&= -gh_{lower}\frac{\partial}{\partial y}\left(b+\frac{\rho_{upper}}{\rho_{lower}} h_{upper}\right) -\end{alignat*} -``` -The unknown quantities of the 2LSWE are the water heights of the lower layer ``h_{lower}`` and the -upper -layer ``h_{upper}`` and the respective velocities in x-direction ``v_{1,lower}`` and ``v_{1,upper}`` and in y-direction -``v_{2,lower}`` and ``v_{2,upper}``. The gravitational constant is denoted by `g`, the layer densitites by -``\rho_{upper}``and ``\rho_{lower}`` and the (possibly) variable bottom topography function by ``b(x)``. -Conservative variable water height ``h_{lower}`` is measured from the bottom topography ``b`` and ``h_{upper}`` -relative to ``h_{lower}``, therefore one also defines the total water heights as ``H_{lower} = h_{lower} + b`` and -``H_{upper} = h_{upper} + h_{lower} + b``. - -The densities must be chosen such that ``\rho_{upper} < \rho_{lower}``, to make sure that the heavier fluid -``\rho_{lower}`` is in the bottom layer and the lighter fluid ``\rho_{upper}`` in the upper layer. - -The additional quantity ``H_0`` is also available to store a reference value for the total water -height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness. - -The bottom topography function ``b(x)`` is set inside the initial condition routine -for a particular problem setup. - -In addition to the unknowns, Trixi currently stores the bottom topography values at the -approximation points despite being fixed in time. This is done for convenience of computing the -bottom topography gradients on the fly during the approximation as well as computing auxiliary -quantities like the total water height ``H`` or the entropy variables. -This affects the implementation and use of these equations in various ways: -* The flux values corresponding to the bottom topography must be zero. -* The bottom topography values must be included when defining initial conditions, boundary - conditions or source terms. -* [`AnalysisCallback`](@ref) analyzes this variable. -* Trixi's visualization tools will visualize the bottom topography by default. - -A good introduction for the 2LSWE is available in Chapter 12 of the book: - - Benoit Cushman-Roisin (2011)\ - Introduction to geophyiscal fluid dynamics: physical and numerical aspects\ - \ - ISBN: 978-0-12-088759-0 -""" -struct ShallowWaterTwoLayerEquations2D{RealT <: Real} <: - AbstractShallowWaterEquations{2, 7} - gravity::RealT # gravitational constant - H0::RealT # constant "lake-at-rest" total water height - rho_upper::RealT # lower layer density - rho_lower::RealT # upper layer density - r::RealT # ratio of rho_upper / rho_lower -end - -# Allow for flexibility to set the gravitational constant within an elixir depending on the -# application where `gravity_constant=1.0` or `gravity_constant=9.81` are common values. -# The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" -# well-balancedness test cases. Densities must be specified such that rho_upper < rho_lower. -function ShallowWaterTwoLayerEquations2D(; gravity_constant, - H0 = zero(gravity_constant), rho_upper, - rho_lower) - # Assign density ratio if rho_upper <= rho_lower - if rho_upper > rho_lower - error("Invalid input: Densities must be chosen such that rho_upper <= rho_lower") - else - r = rho_upper / rho_lower - end - ShallowWaterTwoLayerEquations2D(gravity_constant, H0, rho_upper, rho_lower, r) -end - -have_nonconservative_terms(::ShallowWaterTwoLayerEquations2D) = True() -function varnames(::typeof(cons2cons), ::ShallowWaterTwoLayerEquations2D) - ("h_upper", "h_v1_upper", "h_v2_upper", "h_lower", "h_v1_lower", "h_v2_lower", "b") -end -# Note, we use the total water height, H_upper = h_upper + h_lower + b, and first layer total height -# H_lower = h_lower + b as the first primitive variable for easier visualization and setting initial -# conditions -function varnames(::typeof(cons2prim), ::ShallowWaterTwoLayerEquations2D) - ("H_upper", "v1_upper", "v2_upper", "H_lower", "v1_lower", "v2_lower", "b") -end - -# Set initial conditions at physical location `x` for time `t` -""" - initial_condition_convergence_test(x, t, equations::ShallowWaterTwoLayerEquations2D) - -A smooth initial condition used for convergence tests in combination with -[`source_terms_convergence_test`](@ref). Constants must be set to ``rho_{upper} = 0.9``, -``rho_{lower} = 1.0``, ``g = 10.0``. -""" -function initial_condition_convergence_test(x, t, - equations::ShallowWaterTwoLayerEquations2D) - # some constants are chosen such that the function is periodic on the domain [0,sqrt(2)]^2] - ω = 2.0 * pi * sqrt(2.0) - - H_lower = 2.0 + 0.1 * sin(ω * x[1] + t) * cos(ω * x[2] + t) - H_upper = 4.0 + 0.1 * cos(ω * x[1] + t) * sin(ω * x[2] + t) - v1_lower = 1.0 - v1_upper = 0.9 - v2_lower = 0.9 - v2_upper = 1.0 - b = 1.0 + 0.1 * cos(0.5 * ω * x[1]) * sin(0.5 * ω * x[2]) - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, - b), equations) -end - -""" - source_terms_convergence_test(u, x, t, equations::ShallowWaterTwoLayerEquations2D) - -Source terms used for convergence tests in combination with -[`initial_condition_convergence_test`](@ref). -""" -@inline function source_terms_convergence_test(u, x, t, - equations::ShallowWaterTwoLayerEquations2D) - # Same settings as in `initial_condition_convergence_test`. - # some constants are chosen such that the function is periodic on the domain [0,sqrt(2)]^2] - ω = 2.0 * pi * sqrt(2.0) - - # Source terms obtained with SymPy - du1 = 0.01 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.01 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2]) - du2 = (5.0 * - (-0.1 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) - - 0.1 * ω * sin(t + ω * x[1]) * sin(t + - ω * x[2])) * - (4.0 + 0.2cos(t + ω * x[1]) * sin(t + ω * x[2]) - - 0.2 * sin(t + ω * x[1]) * cos(t + - ω * x[2])) + - 0.009 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.009 * ω * sin(t + ω * x[1]) * sin(t + - ω * x[2]) + - 0.1 * ω * - (20.0 + cos(t + ω * x[1]) * sin(t + ω * x[2]) - - sin(t + ω * x[1]) * cos(t + - ω * x[2])) * cos(t + ω * x[1]) * cos(t + ω * x[2])) - du3 = (5.0 * - (0.1 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.1 * ω * sin(t + ω * x[1]) * sin(t + - ω * x[2])) * - (4.0 + 0.2 * cos(t + ω * x[1]) * sin(t + ω * x[2]) - - 0.2 * sin(t + ω * x[1]) * cos(t + - ω * x[2])) + - 0.01ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.01 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2]) + - -0.1 * ω * - (20.0 + cos(t + ω * x[1]) * sin(t + ω * x[2]) - - sin(t + ω * x[1]) * cos(t + ω * x[2])) * sin(t + - ω * x[1]) * sin(t + ω * x[2])) - du4 = (0.1 * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.1 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.05 * ω * sin(0.5 * ω * x[1]) * sin(0.5 * ω * x[2]) - - 0.1 * sin(t + ω * x[1]) * sin(t + ω * x[2]) + - -0.045 * ω * cos(0.5 * ω * x[1]) * cos(0.5 * ω * x[2]) - - 0.09 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2])) - du5 = ((10.0 + sin(t + ω * x[1]) * cos(t + ω * x[2]) - - cos(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) * (-0.09 * ω * cos(t + - ω * x[1]) * cos(t + ω * x[2]) - - 0.09 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2]) + - -0.05 * ω * sin(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) + - 5.0 * - (0.1 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.05 * ω * sin(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) * - (2.0 + 0.2 * sin(t + ω * x[1]) * cos(t + ω * x[2]) + - -0.2 * cos(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) + - 0.1 * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.1 * ω * cos(t + - ω * x[1]) * cos(t + ω * x[2]) + - 0.05 * ω * sin(0.5 * ω * x[1]) * sin(0.5 * ω * x[2]) - - 0.1 * sin(t + - ω * x[1]) * sin(t + ω * x[2]) - - 0.045 * ω * cos(0.5 * ω * x[1]) * cos(0.5 * ω * x[2]) - - 0.09 * ω * sin(t + - ω * x[1]) * sin(t + ω * x[2])) - du6 = ((10.0 + sin(t + ω * x[1]) * cos(t + ω * x[2]) + - -cos(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) * - (0.05 * ω * cos(0.5 * ω * x[1]) * cos(0.5 * ω * x[2]) + - 0.09 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.09 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2])) + - 5.0 * - (-0.05 * ω * cos(0.5 * ω * x[1]) * cos(0.5 * ω * x[2]) - - 0.1 * ω * sin(t + ω * x[1]) * sin(t + - ω * x[2])) * - (2.0 + 0.2 * sin(t + ω * x[1]) * cos(t + ω * x[2]) + - -0.2 * cos(0.5 * ω * x[1]) * sin(0.5 * ω * x[2])) + - 0.09cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.09 * ω * cos(t + ω * x[1]) * cos(t + ω * x[2]) + - 0.045 * ω * sin(0.5 * ω * x[1]) * sin(0.5 * ω * x[2]) + - -0.09 * sin(t + ω * x[1]) * sin(t + ω * x[2]) - - 0.0405 * ω * cos(0.5 * ω * x[1]) * cos(0.5 * ω * x[2]) + - -0.081 * ω * sin(t + ω * x[1]) * sin(t + ω * x[2])) - - return SVector(du1, du2, du3, du4, du5, du6, zero(eltype(u))) -end - -""" - boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function, - equations::ShallowWaterTwoLayerEquations2D) - -Create a boundary state by reflecting the normal velocity component and keep -the tangential velocity component unchanged. The boundary water height is taken from -the internal value. - -For details see Section 9.2.5 of the book: -- Eleuterio F. Toro (2001) - Shock-Capturing Methods for Free-Surface Shallow Flows - 1st edition - ISBN 0471987662 -""" -@inline function boundary_condition_slip_wall(u_inner, normal_direction::AbstractVector, - x, t, surface_flux_function, - equations::ShallowWaterTwoLayerEquations2D) - # normalize the outward pointing direction - normal = normal_direction / norm(normal_direction) - - # compute the normal velocity - v_normal_upper = normal[1] * u_inner[2] + normal[2] * u_inner[3] - v_normal_lower = normal[1] * u_inner[5] + normal[2] * u_inner[6] - - # create the "external" boundary solution state - u_boundary = SVector(u_inner[1], - u_inner[2] - 2.0 * v_normal_upper * normal[1], - u_inner[3] - 2.0 * v_normal_upper * normal[2], - u_inner[4], - u_inner[5] - 2.0 * v_normal_lower * normal[1], - u_inner[6] - 2.0 * v_normal_lower * normal[2], - u_inner[7]) - - # calculate the boundary flux - flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) - return flux -end - -# Calculate 1D flux for a single point -# Note, the bottom topography has no flux -@inline function flux(u, orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_v1_upper, h_v2_upper, h_lower, h_v1_lower, h_v2_lower, _ = u - - # Calculate velocities - v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - - # Calculate pressure - p_upper = 0.5 * equations.gravity * h_upper^2 - p_lower = 0.5 * equations.gravity * h_lower^2 - - # Calculate fluxes depending on orientation - if orientation == 1 - f1 = h_v1_upper - f2 = h_v1_upper * v1_upper + p_upper - f3 = h_v1_upper * v2_upper - f4 = h_v1_lower - f5 = h_v1_lower * v1_lower + p_lower - f6 = h_v1_lower * v2_lower - else - f1 = h_v2_upper - f2 = h_v2_upper * v1_upper - f3 = h_v2_upper * v2_upper + p_upper - f4 = h_v2_lower - f5 = h_v2_lower * v1_lower - f6 = h_v2_lower * v2_lower + p_lower - end - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u))) -end - -# Calculate 1D flux for a single point in the normal direction -# Note, this directional vector is not normalized and the bottom topography has no flux -@inline function flux(u, normal_direction::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_lower = waterheight(u, equations) - v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - - v_normal_upper = v1_upper * normal_direction[1] + v2_upper * normal_direction[2] - v_normal_lower = v1_lower * normal_direction[1] + v2_lower * normal_direction[2] - h_v_upper_normal = h_upper * v_normal_upper - h_v_lower_normal = h_lower * v_normal_lower - - p_upper = 0.5 * equations.gravity * h_upper^2 - p_lower = 0.5 * equations.gravity * h_lower^2 - - f1 = h_v_upper_normal - f2 = h_v_upper_normal * v1_upper + p_upper * normal_direction[1] - f3 = h_v_upper_normal * v2_upper + p_upper * normal_direction[2] - f4 = h_v_lower_normal - f5 = h_v_lower_normal * v1_lower + p_lower * normal_direction[1] - f6 = h_v_lower_normal * v2_lower + p_lower * normal_direction[2] - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u))) -end - -""" - flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - flux_nonconservative_ersing_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - -!!! warning "Experimental code" - This numerical flux is experimental and may change in any future release. - -Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term -that contains the gradient of the bottom topography [`ShallowWaterTwoLayerEquations2D`](@ref) and an -additional term that couples the momentum of both layers. - -This is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy -conservation and well-balancedness in both the volume and surface when combined with -[`flux_wintermeyer_etal`](@ref). - -For further details see: -- Patrick Ersing, Andrew R. Winters (2023) - An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on - curvilinear meshes - [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) -""" -@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - # Pull the necessary left and right state information - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - b_rr = u_rr[7] - b_ll = u_ll[7] - - # Calculate jumps - h_upper_jump = (h_upper_rr - h_upper_ll) - h_lower_jump = (h_lower_rr - h_lower_ll) - b_jump = (b_rr - b_ll) - - z = zero(eltype(u_ll)) - - # Bottom gradient nonconservative term: (0, g*h_upper*(b + h_lower)_x, g*h_upper*(b + h_lower)_y , - # 0, g*h_lower*(b + r*h_upper)_x, - # g*h_lower*(b + r*h_upper)_y, 0) - if orientation == 1 - f = SVector(z, - equations.gravity * h_upper_ll * (b_jump + h_lower_jump), - z, z, - equations.gravity * h_lower_ll * - (b_jump + equations.r * h_upper_jump), - z, z) - else # orientation == 2 - f = SVector(z, z, - equations.gravity * h_upper_ll * (b_jump + h_lower_jump), - z, z, - equations.gravity * h_lower_ll * - (b_jump + equations.r * h_upper_jump), - z) - end - - return f -end - -@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - # Pull the necessary left and right state information - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - b_rr = u_rr[7] - b_ll = u_ll[7] - - # Calculate jumps - h_upper_jump = (h_upper_rr - h_upper_ll) - h_lower_jump = (h_lower_rr - h_lower_ll) - b_jump = (b_rr - b_ll) - - # Note this routine only uses the `normal_direction_average` and the average of the - # bottom topography to get a quadratic split form DG gradient on curved elements - return SVector(zero(eltype(u_ll)), - normal_direction_average[1] * equations.gravity * h_upper_ll * - (b_jump + h_lower_jump), - normal_direction_average[2] * equations.gravity * h_upper_ll * - (b_jump + h_lower_jump), - zero(eltype(u_ll)), - normal_direction_average[1] * equations.gravity * h_lower_ll * - (b_jump + equations.r * h_upper_jump), - normal_direction_average[2] * equations.gravity * h_lower_ll * - (b_jump + equations.r * h_upper_jump), - zero(eltype(u_ll))) -end - -""" - flux_wintermeyer_etal(u_ll, u_rr, orientation, - equations::ShallowWaterTwoLayerEquations2D) - flux_wintermeyer_etal(u_ll, u_rr, - normal_direction::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - -Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. -When the bottom topography is nonzero this scheme will be well-balanced when used with the -nonconservative [`flux_nonconservative_ersing_etal`](@ref). To obtain the flux for the -two-layer shallow water equations the flux that is described in the paper for the normal shallow -water equations is used within each layer. - -Further details are available in Theorem 1 of the paper: -- Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) - An entropy stable nodal discontinuous Galerkin method for the two dimensional - shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry - [DOI: 10.1016/j.jcp.2017.03.036](https://doi.org/10.1016/j.jcp.2017.03.036) -""" -@inline function flux_wintermeyer_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, h_v1_upper_ll, h_v2_upper_ll, h_lower_ll, h_v1_lower_ll, h_v2_lower_ll, _ = u_ll - h_upper_rr, h_v1_upper_rr, h_v2_upper_rr, h_lower_rr, h_v1_lower_rr, h_v2_lower_rr, _ = u_rr - - # Get the velocities on either side - v1_upper_ll, v2_upper_ll, v1_lower_ll, v2_lower_ll = velocity(u_ll, equations) - v1_upper_rr, v2_upper_rr, v1_lower_rr, v2_lower_rr = velocity(u_rr, equations) - - # Average each factor of products in flux - v1_upper_avg = 0.5 * (v1_upper_ll + v1_upper_rr) - v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) - v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) - v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr - - # Calculate fluxes depending on orientation - if orientation == 1 - f1 = 0.5 * (h_v1_upper_ll + h_v1_upper_rr) - f2 = f1 * v1_upper_avg + p_upper_avg - f3 = f1 * v2_upper_avg - f4 = 0.5 * (h_v1_lower_ll + h_v1_lower_rr) - f5 = f4 * v1_lower_avg + p_lower_avg - f6 = f4 * v2_lower_avg - else - f1 = 0.5 * (h_v2_upper_ll + h_v2_upper_rr) - f2 = f1 * v1_upper_avg - f3 = f1 * v2_upper_avg + p_upper_avg - f4 = 0.5 * (h_v2_lower_ll + h_v2_lower_rr) - f5 = f4 * v1_lower_avg - f6 = f4 * v2_lower_avg + p_lower_avg - end - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) -end - -@inline function flux_wintermeyer_etal(u_ll, u_rr, - normal_direction::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, h_v1_upper_ll, h_v2_upper_ll, h_lower_ll, h_v1_lower_ll, h_v2_lower_ll, _ = u_ll - h_upper_rr, h_v1_upper_rr, h_v2_upper_rr, h_lower_rr, h_v1_lower_rr, h_v2_lower_rr, _ = u_rr - - # Get the velocities on either side - v1_upper_ll, v2_upper_ll, v1_lower_ll, v2_lower_ll = velocity(u_ll, equations) - v1_upper_rr, v2_upper_rr, v1_lower_rr, v2_lower_rr = velocity(u_rr, equations) - - # Average each factor of products in flux - v1_upper_avg = 0.5 * (v1_upper_ll + v1_upper_rr) - v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) - v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) - v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr - h_v1_upper_avg = 0.5 * (h_v1_upper_ll + h_v1_upper_rr) - h_v2_upper_avg = 0.5 * (h_v2_upper_ll + h_v2_upper_rr) - h_v1_lower_avg = 0.5 * (h_v1_lower_ll + h_v1_lower_rr) - h_v2_lower_avg = 0.5 * (h_v2_lower_ll + h_v2_lower_rr) - - # Calculate fluxes depending on normal_direction - f1 = h_v1_upper_avg * normal_direction[1] + h_v2_upper_avg * normal_direction[2] - f2 = f1 * v1_upper_avg + p_upper_avg * normal_direction[1] - f3 = f1 * v2_upper_avg + p_upper_avg * normal_direction[2] - f4 = h_v1_lower_avg * normal_direction[1] + h_v2_lower_avg * normal_direction[2] - f5 = f4 * v1_lower_avg + p_lower_avg * normal_direction[1] - f6 = f4 * v2_lower_avg + p_lower_avg * normal_direction[2] - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) -end - -""" - flux_es_ersing_etal(u_ll, u_rr, orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations2D) - -Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative -[`flux_wintermeyer_etal`](@ref) and adds a Lax-Friedrichs type dissipation dependent on the jump of -entropy variables. - -For further details see: -- Patrick Ersing, Andrew R. Winters (2023) - An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on - curvilinear meshes - [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) -""" -@inline function flux_es_ersing_etal(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations2D) - # Compute entropy conservative flux but without the bottom topography - f_ec = flux_wintermeyer_etal(u_ll, u_rr, - orientation_or_normal_direction, - equations) - - # Get maximum signal velocity - λ = max_abs_speed_naive(u_ll, u_rr, orientation_or_normal_direction, equations) - - # Get entropy variables but without the bottom topography - q_rr = cons2entropy(u_rr, equations) - q_ll = cons2entropy(u_ll, equations) - - # Average values from left and right - u_avg = (u_ll + u_rr) / 2 - - # Introduce variables for better readability - rho_upper = equations.rho_upper - rho_lower = equations.rho_lower - g = equations.gravity - drho = rho_upper - rho_lower - - # Compute entropy Jacobian coefficients - h11 = -rho_lower / (g * rho_upper * drho) - h12 = -rho_lower * u_avg[2] / (g * rho_upper * u_avg[1] * drho) - h13 = -rho_lower * u_avg[3] / (g * rho_upper * u_avg[1] * drho) - h14 = 1.0 / (g * drho) - h15 = u_avg[5] / (g * u_avg[4] * drho) - h16 = u_avg[6] / (g * u_avg[4] * drho) - h21 = -rho_lower * u_avg[2] / (g * rho_upper * u_avg[1] * drho) - h22 = ((g * rho_upper * u_avg[1]^3 - g * rho_lower * u_avg[1]^3 + - -rho_lower * u_avg[2]^2) / (g * rho_upper * u_avg[1]^2 * drho)) - h23 = -rho_lower * u_avg[2] * u_avg[3] / (g * rho_upper * u_avg[1]^2 * drho) - h24 = u_avg[2] / (g * u_avg[1] * drho) - h25 = u_avg[2] * u_avg[5] / (g * u_avg[1] * u_avg[4] * drho) - h26 = u_avg[2] * u_avg[6] / (g * u_avg[1] * u_avg[4] * drho) - h31 = -rho_lower * u_avg[3] / (g * rho_upper * u_avg[1] * drho) - h32 = -rho_lower * u_avg[2] * u_avg[3] / (g * rho_upper * u_avg[1]^2 * drho) - h33 = ((g * rho_upper * u_avg[1]^3 - g * rho_lower * u_avg[1]^3 + - -rho_lower * u_avg[3]^2) / (g * rho_upper * u_avg[1]^2 * drho)) - h34 = u_avg[3] / (g * u_avg[1] * drho) - h35 = u_avg[3] * u_avg[5] / (g * u_avg[1] * u_avg[4] * drho) - h36 = u_avg[3] * u_avg[6] / (g * u_avg[1] * u_avg[4] * drho) - h41 = 1.0 / (g * drho) - h42 = u_avg[2] / (g * u_avg[1] * drho) - h43 = u_avg[3] / (g * u_avg[1] * drho) - h44 = -1.0 / (g * drho) - h45 = -u_avg[5] / (g * u_avg[4] * drho) - h46 = -u_avg[6] / (g * u_avg[4] * drho) - h51 = u_avg[5] / (g * u_avg[4] * drho) - h52 = u_avg[2] * u_avg[5] / (g * u_avg[1] * u_avg[4] * drho) - h53 = u_avg[3] * u_avg[5] / (g * u_avg[1] * u_avg[4] * drho) - h54 = -u_avg[5] / (g * u_avg[4] * drho) - h55 = ((g * rho_upper * u_avg[4]^3 - g * rho_lower * u_avg[4]^3 + - -rho_lower * u_avg[5]^2) / (g * rho_lower * u_avg[4]^2 * drho)) - h56 = -u_avg[5] * u_avg[6] / (g * u_avg[4]^2 * drho) - h61 = u_avg[6] / (g * u_avg[4] * drho) - h62 = u_avg[2] * u_avg[6] / (g * u_avg[1] * u_avg[4] * drho) - h63 = u_avg[3] * u_avg[6] / (g * u_avg[1] * u_avg[4] * drho) - h64 = -u_avg[6] / (g * u_avg[4] * drho) - h65 = -u_avg[5] * u_avg[6] / (g * u_avg[4]^2 * drho) - h66 = ((g * rho_upper * u_avg[4]^3 - g * rho_lower * u_avg[4]^3 + - -rho_lower * u_avg[6]^2) / (g * rho_lower * u_avg[4]^2 * drho)) - - # Entropy Jacobian matrix - H = @SMatrix [[h11;; h12;; h13;; h14;; h15;; h16;; 0]; - [h21;; h22;; h23;; h24;; h25;; h26;; 0]; - [h31;; h32;; h33;; h34;; h35;; h36;; 0]; - [h41;; h42;; h43;; h44;; h45;; h46;; 0]; - [h51;; h52;; h53;; h54;; h55;; h56;; 0]; - [h61;; h62;; h63;; h64;; h65;; h66;; 0]; - [0;; 0;; 0;; 0;; 0;; 0;; 0]] - - # Add dissipation to entropy conservative flux to obtain entropy stable flux - f_es = f_ec - 0.5 * λ * H * (q_rr - q_ll) - - return SVector(f_es[1], f_es[2], f_es[3], f_es[4], f_es[5], f_es[6], - zero(eltype(u_ll))) -end - -# Calculate approximation for maximum wave speed for local Lax-Friedrichs-type dissipation as the -# maximum velocity magnitude plus the maximum speed of sound. This function uses approximate -# eigenvalues using the speed of the barotropic mode as there is no simple way to calculate them -# analytically. -# -# A good overview of the derivation is given in: -# - Jonas Nycander, Andrew McC. Hogg, Leela M. Frankcombe (2008) -# Open boundary conditions for nonlinear channel Flows -# [DOI: 10.1016/j.ocemod.2008.06.003](https://doi.org/10.1016/j.ocemod.2008.06.003) -@inline function max_abs_speed_naive(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, h_v1_upper_ll, h_v2_upper_ll, h_lower_ll, h_v1_lower_ll, h_v2_lower_ll, _ = u_ll - h_upper_rr, h_v1_upper_rr, h_v2_upper_rr, h_lower_rr, h_v1_lower_rr, h_v2_lower_rr, _ = u_rr - - # Calculate averaged velocity of both layers - if orientation == 1 - v_m_ll = (h_v1_upper_ll + h_v1_lower_ll) / (h_upper_ll + h_lower_ll) - v_m_rr = (h_v1_upper_rr + h_v1_lower_rr) / (h_upper_rr + h_lower_rr) - else - v_m_ll = (h_v2_upper_ll + h_v2_lower_ll) / (h_upper_ll + h_lower_ll) - v_m_rr = (h_v2_upper_rr + h_v2_lower_rr) / (h_upper_rr + h_lower_rr) - end - - # Calculate the wave celerity on the left and right - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - - c_ll = sqrt(equations.gravity * (h_upper_ll + h_lower_ll)) - c_rr = sqrt(equations.gravity * (h_upper_rr + h_lower_rr)) - - return (max(abs(v_m_ll), abs(v_m_rr)) + max(c_ll, c_rr)) -end - -@inline function max_abs_speed_naive(u_ll, u_rr, - normal_direction::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, _, _, h_lower_ll, _, _, _ = u_ll - h_upper_rr, _, _, h_lower_rr, _, _, _ = u_rr - - # Extract and compute the velocities in the normal direction - v1_upper_ll, v2_upper_ll, v1_lower_ll, v2_lower_ll = velocity(u_ll, equations) - v1_upper_rr, v2_upper_rr, v1_lower_rr, v2_lower_rr = velocity(u_rr, equations) - - v_upper_dot_n_ll = v1_upper_ll * normal_direction[1] + - v2_upper_ll * normal_direction[2] - v_upper_dot_n_rr = v1_upper_rr * normal_direction[1] + - v2_upper_rr * normal_direction[2] - v_lower_dot_n_ll = v1_lower_ll * normal_direction[1] + - v2_lower_ll * normal_direction[2] - v_lower_dot_n_rr = v1_lower_rr * normal_direction[1] + - v2_lower_rr * normal_direction[2] - - # Calculate averaged velocity of both layers - v_m_ll = (v_upper_dot_n_ll * h_upper_ll + v_lower_dot_n_ll * h_lower_ll) / - (h_upper_ll + h_lower_ll) - v_m_rr = (v_upper_dot_n_rr * h_upper_rr + v_lower_dot_n_rr * h_lower_rr) / - (h_upper_rr + h_lower_rr) - - # Compute the wave celerity on the left and right - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - - c_ll = sqrt(equations.gravity * (h_upper_ll + h_lower_ll)) - c_rr = sqrt(equations.gravity * (h_upper_rr + h_lower_rr)) - - # The normal velocities are already scaled by the norm - return max(abs(v_m_ll), abs(v_m_rr)) + max(c_ll, c_rr) * norm(normal_direction) -end - -# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography -@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations2D) - λ = dissipation.max_abs_speed(u_ll, u_rr, orientation_or_normal_direction, - equations) - diss = -0.5 * λ * (u_rr - u_ll) - return SVector(diss[1], diss[2], diss[3], diss[4], diss[5], diss[6], - zero(eltype(u_ll))) -end - -# Absolute speed of the barotropic mode -@inline function max_abs_speeds(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_v1_upper, h_v2_upper, h_lower, h_v1_lower, h_v2_lower, _ = u - - # Calculate averaged velocity of both layers - v1_m = (h_v1_upper + h_v1_lower) / (h_upper + h_lower) - v2_m = (h_v2_upper + h_v2_lower) / (h_upper + h_lower) - - h_upper, h_lower = waterheight(u, equations) - v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - - c = sqrt(equations.gravity * (h_upper + h_lower)) - return (max(abs(v1_m) + c, abs(v1_upper), abs(v1_lower)), - max(abs(v2_m) + c, abs(v2_upper), abs(v2_lower))) -end - -# Helper function to extract the velocity vector from the conservative variables -@inline function velocity(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_v1_upper, h_v2_upper, h_lower, h_v1_lower, h_v2_lower, _ = u - - v1_upper = h_v1_upper / h_upper - v2_upper = h_v2_upper / h_upper - v1_lower = h_v1_lower / h_lower - v2_lower = h_v2_lower / h_lower - - return SVector(v1_upper, v2_upper, v1_lower, v2_lower) -end - -# Convert conservative variables to primitive -@inline function cons2prim(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, _, _, h_lower, _, _, b = u - - H_lower = h_lower + b - H_upper = h_lower + h_upper + b - v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - - return SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b) -end - -# Convert conservative variables to entropy variables -# Note, only the first four are the entropy variables, the fifth entry still just carries the bottom -# topography values for convenience. -# In contrast to general usage the entropy variables are denoted with q instead of w, because w is -# already used for velocity in y-Direction -@inline function cons2entropy(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, _, _, h_lower, _, _, b = u - # Assign new variables for better readability - rho_upper = equations.rho_upper - rho_lower = equations.rho_lower - v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - - w1 = (rho_upper * (equations.gravity * (h_upper + h_lower + b) + - -0.5 * (v1_upper^2 + v2_upper^2))) - w2 = rho_upper * v1_upper - w3 = rho_upper * v2_upper - w4 = (rho_lower * (equations.gravity * (equations.r * h_upper + h_lower + b) + - -0.5 * (v1_lower^2 + v2_lower^2))) - w5 = rho_lower * v1_lower - w6 = rho_lower * v2_lower - return SVector(w1, w2, w3, w4, w5, w6, b) -end - -# Convert primitive to conservative variables -@inline function prim2cons(prim, equations::ShallowWaterTwoLayerEquations2D) - H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b = prim - - h_lower = H_lower - b - h_upper = H_upper - h_lower - b - h_v1_upper = h_upper * v1_upper - h_v2_upper = h_upper * v2_upper - h_v1_lower = h_lower * v1_lower - h_v2_lower = h_lower * v2_lower - return SVector(h_upper, h_v1_upper, h_v2_upper, h_lower, h_v1_lower, h_v2_lower, b) -end - -@inline function waterheight(u, equations::ShallowWaterTwoLayerEquations2D) - return SVector(u[1], u[4]) -end - -# Entropy function for the shallow water equations is the total energy -@inline function entropy(cons, equations::ShallowWaterTwoLayerEquations2D) - energy_total(cons, equations) -end - -# Calculate total energy for a conservative state `cons` -@inline function energy_total(cons, equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_v1_upper, h_v2_upper, h_lower, h_v2_lower, h_v2_lower, b = cons - g = equations.gravity - rho_upper = equations.rho_upper - rho_lower = equations.rho_lower - - e = (0.5 * rho_upper * - (h_v1_upper^2 / h_upper + h_v2_upper^2 / h_upper + g * h_upper^2) + - 0.5 * rho_lower * - (h_v2_lower^2 / h_lower + h_v2_lower^2 / h_lower + g * h_lower^2) + - g * rho_lower * h_lower * b + g * rho_upper * h_upper * (h_lower + b)) - return e -end - -# Calculate kinetic energy for a conservative state `cons` -@inline function energy_kinetic(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, h_v1_upper, h_v2_upper, h_lower, h_v2_lower, h_v2_lower, _ = u - - return (0.5 * equations.rho_upper * h_v1_upper^2 / h_upper + - 0.5 * equations.rho_upper * h_v2_upper^2 / h_upper + - 0.5 * equations.rho_lower * h_v2_lower^2 / h_lower + - 0.5 * equations.rho_lower * h_v2_lower^2 / h_lower) -end - -# Calculate potential energy for a conservative state `cons` -@inline function energy_internal(cons, equations::ShallowWaterTwoLayerEquations2D) - return energy_total(cons, equations) - energy_kinetic(cons, equations) -end - -# Calculate the error for the "lake-at-rest" test case where H = h_upper+h_lower+b should -# be a constant value over time -@inline function lake_at_rest_error(u, equations::ShallowWaterTwoLayerEquations2D) - h_upper, _, _, h_lower, _, _, b = u - return abs(equations.H0 - (h_upper + h_lower + b)) -end -end # @muladd diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index bb9109f2762..9f25a6d2dbb 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -101,82 +101,6 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorHennemannGass summary_box(io, "IndicatorHennemannGassner", setup) end -# TODO: TrixiShallowWater: move the new indicator and all associated routines to the new package -""" - IndicatorHennemannGassnerShallowWater(equations::AbstractEquations, basis; - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable) - -Modified version of the [`IndicatorHennemannGassner`](@ref) -indicator used for shock-capturing for shallow water equations. After -the element-wise values for the blending factors are computed an additional check -is made to see if the element is partially wet. In this case, partially wet elements -are set to use the pure finite volume scheme that is guaranteed to be well-balanced -for this wet/dry transition state of the flow regime. - -See also [`VolumeIntegralShockCapturingHG`](@ref). - -## References - -- Hennemann, Gassner (2020) - "A provably entropy stable subcell shock capturing approach for high order split form DG" - [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) -""" -struct IndicatorHennemannGassnerShallowWater{RealT <: Real, Variable, Cache} <: - AbstractIndicator - alpha_max::RealT - alpha_min::RealT - alpha_smooth::Bool - variable::Variable - cache::Cache -end - -# this method is used when the indicator is constructed as for shock-capturing volume integrals -# of the shallow water equations -# It modifies the shock-capturing indicator to use full FV method in dry cells -function IndicatorHennemannGassnerShallowWater(equations::AbstractShallowWaterEquations, - basis; - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - variable) - alpha_max, alpha_min = promote(alpha_max, alpha_min) - cache = create_cache(IndicatorHennemannGassner, equations, basis) - IndicatorHennemannGassnerShallowWater{typeof(alpha_max), typeof(variable), - typeof(cache)}(alpha_max, alpha_min, - alpha_smooth, variable, cache) -end - -function Base.show(io::IO, indicator::IndicatorHennemannGassnerShallowWater) - @nospecialize indicator # reduce precompilation time - - print(io, "IndicatorHennemannGassnerShallowWater(") - print(io, indicator.variable) - print(io, ", alpha_max=", indicator.alpha_max) - print(io, ", alpha_min=", indicator.alpha_min) - print(io, ", alpha_smooth=", indicator.alpha_smooth) - print(io, ")") -end - -function Base.show(io::IO, ::MIME"text/plain", - indicator::IndicatorHennemannGassnerShallowWater) - @nospecialize indicator # reduce precompilation time - - if get(io, :compact, false) - show(io, indicator) - else - setup = [ - "indicator variable" => indicator.variable, - "max. α" => indicator.alpha_max, - "min. α" => indicator.alpha_min, - "smooth α" => (indicator.alpha_smooth ? "yes" : "no"), - ] - summary_box(io, "IndicatorHennemannGassnerShallowWater", setup) - end -end - function (indicator_hg::IndicatorHennemannGassner)(u, mesh, equations, dg::DGSEM, cache; kwargs...) @unpack alpha_smooth = indicator_hg diff --git a/src/solvers/dgsem_tree/indicators_1d.jl b/src/solvers/dgsem_tree/indicators_1d.jl index dff87bfe06c..4796ddcc602 100644 --- a/src/solvers/dgsem_tree/indicators_1d.jl +++ b/src/solvers/dgsem_tree/indicators_1d.jl @@ -24,115 +24,6 @@ function create_cache(typ::Type{IndicatorHennemannGassner}, mesh, create_cache(typ, equations, dg.basis) end -# Modified indicator for ShallowWaterEquations1D to apply full FV method on cells -# containing some "dry" LGL nodes. That is, if an element is partially "wet" then it becomes a -# full FV element. -# -# TODO: TrixiShallowWater: move new indicator type -function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, - 3}, - mesh, - equations::ShallowWaterEquations1D, - dg::DGSEM, cache; - kwargs...) - @unpack alpha_max, alpha_min, alpha_smooth, variable = indicator_hg - @unpack alpha, alpha_tmp, indicator_threaded, modal_threaded = indicator_hg.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - # magic parameters - threshold = 0.5 * 10^(-1.8 * (nnodes(dg))^0.25) - parameter_s = log((1 - 0.0001) / 0.0001) - - # If the water height `h` at one LGL node is lower than `threshold_partially_wet` - # the indicator sets the element-wise blending factor alpha[element] = 1 - # via the local variable `indicator_wet`. In turn, this ensures that a pure - # FV method is used in partially wet cells and guarantees the well-balanced property. - # - # Hard-coded cut-off value of `threshold_partially_wet = 1e-4` was determined through many numerical experiments. - # Overall idea is to increase robustness when computing the velocity on (nearly) dry cells which - # could be "dangerous" due to division of conservative variables, e.g., v = hv / h. - # Here, the impact of the threshold on the number of cells being updated with FV is not that - # significant. However, its impact on the robustness is very significant. - # The value can be seen as a trade-off between accuracy and stability. - # Well-balancedness of the scheme on partially wet cells with hydrostatic reconstruction - # can only be proven for the FV method (see Chen and Noelle). - # Therefore we set alpha to one regardless of its given maximum value. - threshold_partially_wet = 1e-4 - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - modal = modal_threaded[Threads.threadid()] - - # (Re-)set dummy variable for alpha_dry - indicator_wet = 1 - - # Calculate indicator variables at Gauss-Lobatto nodes - for i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, element) - h, _, _ = u_local - - if h <= threshold_partially_wet - indicator_wet = 0 - end - - indicator[i] = indicator_hg.variable(u_local, equations) - end - - # Convert to modal representation - multiply_scalar_dimensionwise!(modal, dg.basis.inverse_vandermonde_legendre, - indicator) - - # Calculate total energies for all modes, without highest, without two highest - total_energy = zero(eltype(modal)) - for i in 1:nnodes(dg) - total_energy += modal[i]^2 - end - total_energy_clip1 = zero(eltype(modal)) - for i in 1:(nnodes(dg) - 1) - total_energy_clip1 += modal[i]^2 - end - total_energy_clip2 = zero(eltype(modal)) - for i in 1:(nnodes(dg) - 2) - total_energy_clip2 += modal[i]^2 - end - - # Calculate energy in higher modes - energy = max((total_energy - total_energy_clip1) / total_energy, - (total_energy_clip1 - total_energy_clip2) / total_energy_clip1) - - alpha_element = 1 / (1 + exp(-parameter_s / threshold * (energy - threshold))) - - # Take care of the case close to pure DG - if alpha_element < alpha_min - alpha_element = zero(alpha_element) - end - - # Take care of the case close to pure FV - if alpha_element > 1 - alpha_min - alpha_element = one(alpha_element) - end - - # Clip the maximum amount of FV allowed or set to one depending on indicator_wet - if indicator_wet == 0 - alpha[element] = 1 - else # Element is not defined as dry but wet - alpha[element] = min(alpha_max, alpha_element) - end - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end - # Use this function barrier and unpack inside to avoid passing closures to Polyester.jl # with @batch (@threaded). # Otherwise, @threaded does not work here with Julia ARM on macOS. diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index fa8ed481eb9..665d2254e5d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -28,116 +28,6 @@ function create_cache(typ::Type{IndicatorHennemannGassner}, mesh, create_cache(typ, equations, dg.basis) end -# Modified indicator for ShallowWaterEquations2D to apply full FV method on cells -# containing some "dry" LGL nodes. That is, if an element is partially "wet" then it becomes a -# full FV element. -# -# TODO: TrixiShallowWater: move new indicator type -function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, - 4}, - mesh, - equations::ShallowWaterEquations2D, - dg::DGSEM, cache; - kwargs...) - @unpack alpha_max, alpha_min, alpha_smooth, variable = indicator_hg - @unpack alpha, alpha_tmp, indicator_threaded, modal_threaded, modal_tmp1_threaded = indicator_hg.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - # magic parameters - threshold = 0.5 * 10^(-1.8 * (nnodes(dg))^0.25) - parameter_s = log((1 - 0.0001) / 0.0001) - - # If the water height `h` at one LGL node is lower than `threshold_partially_wet` - # the indicator sets the element-wise blending factor alpha[element] = 1 - # via the local variable `indicator_wet`. In turn, this ensures that a pure - # FV method is used in partially wet cells and guarantees the well-balanced property. - # - # Hard-coded cut-off value of `threshold_partially_wet = 1e-4` was determined through many numerical experiments. - # Overall idea is to increase robustness when computing the velocity on (nearly) dry cells which - # could be "dangerous" due to division of conservative variables, e.g., v1 = hv1 / h. - # Here, the impact of the threshold on the number of cells being updated with FV is not that - # significant. However, its impact on the robustness is very significant. - # The value can be seen as a trade-off between accuracy and stability. - # Well-balancedness of the scheme on partially wet cells with hydrostatic reconstruction - # can only be proven for the FV method (see Chen and Noelle). - # Therefore we set alpha to be one regardless of its given value from the modal indicator. - threshold_partially_wet = 1e-4 - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - modal = modal_threaded[Threads.threadid()] - modal_tmp1 = modal_tmp1_threaded[Threads.threadid()] - - # (Re-)set dummy variable for alpha_dry - indicator_wet = 1 - - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - h, _, _, _ = u_local - - if h <= threshold_partially_wet - indicator_wet = 0 - end - - indicator[i, j] = indicator_hg.variable(u_local, equations) - end - - # Convert to modal representation - multiply_scalar_dimensionwise!(modal, dg.basis.inverse_vandermonde_legendre, - indicator, modal_tmp1) - - # Calculate total energies for all modes, without highest, without two highest - total_energy = zero(eltype(modal)) - for j in 1:nnodes(dg), i in 1:nnodes(dg) - total_energy += modal[i, j]^2 - end - total_energy_clip1 = zero(eltype(modal)) - for j in 1:(nnodes(dg) - 1), i in 1:(nnodes(dg) - 1) - total_energy_clip1 += modal[i, j]^2 - end - total_energy_clip2 = zero(eltype(modal)) - for j in 1:(nnodes(dg) - 2), i in 1:(nnodes(dg) - 2) - total_energy_clip2 += modal[i, j]^2 - end - - # Calculate energy in higher modes - energy = max((total_energy - total_energy_clip1) / total_energy, - (total_energy_clip1 - total_energy_clip2) / total_energy_clip1) - - alpha_element = 1 / (1 + exp(-parameter_s / threshold * (energy - threshold))) - - # Take care of the case close to pure DG - if alpha_element < alpha_min - alpha_element = zero(alpha_element) - end - - # Take care of the case close to pure FV - if alpha_element > 1 - alpha_min - alpha_element = one(alpha_element) - end - - # Clip the maximum amount of FV allowed or set to 1 depending on indicator_wet - if indicator_wet == 0 - alpha[element] = 1 - else # Element is not defined as dry but wet - alpha[element] = min(alpha_max, alpha_element) - end - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end - # Use this function barrier and unpack inside to avoid passing closures to Polyester.jl # with @batch (@threaded). # Otherwise, @threaded does not work here with Julia ARM on macOS. diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 522510a42e3..f5fb169033a 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -1,7 +1,5 @@ module TestExamplesStructuredMesh2D -# TODO: TrixiShallowWater: move any wet/dry tests to new package - using Test using Trixi @@ -907,82 +905,6 @@ end end end -@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2=[ - 0.019731646454942086, - 1.0694532773278277e-14, - 1.1969913383405568e-14, - 0.0771517260037954, - ], - linf=[ - 0.4999999999998892, - 6.067153702623552e-14, - 4.4849667259339357e-14, - 1.9999999999999993, - ], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), - l2=[ - 0.04593154164306353, - 0.1644534881916908, - 0.16445348819169076, - 0.0011537702354532122, - ], - linf=[ - 0.21100717610846442, - 0.9501592344310412, - 0.950159234431041, - 0.021790250683516296, - ], - tspan=(0.0, 0.025)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2=[ - 0.00015285369980313484, - 1.9536806395943226e-5, - 9.936906607758672e-5, - 5.0686313334616055e-15, - ], - linf=[ - 0.003316119030459211, - 0.0005075409427972817, - 0.001986721761060583, - 4.701794509287538e-14, - ], - tspan=(0.0, 0.025), cells_per_dimension=(40, 40)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - @trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec_shockcapturing.jl"), l2=[0.0364192725149364, 0.0426667193422069, 0.04261673001449095, diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index 8b470278ffd..4a25a51a45e 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -42,8 +42,6 @@ isdir(outdir) && rm(outdir, recursive = true) # Shallow water include("test_tree_1d_shallowwater.jl") - # Two-layer Shallow Water - include("test_tree_1d_shallowwater_twolayer.jl") # FDSBP methods on the TreeMesh include("test_tree_1d_fdsbp.jl") diff --git a/test/test_tree_1d_shallowwater.jl b/test/test_tree_1d_shallowwater.jl index 2269e858928..f9be63b87fd 100644 --- a/test/test_tree_1d_shallowwater.jl +++ b/test/test_tree_1d_shallowwater.jl @@ -1,7 +1,5 @@ module TestExamples1DShallowWater -# TODO: TrixiShallowWater: move any wet/dry tests to new package - using Test using Trixi @@ -119,32 +117,6 @@ end end end -@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2=[ - 0.00965787167169024, - 5.345454081916856e-14, - 0.03857583749209928, - ], - linf=[ - 0.4999999999998892, - 2.2447689894899726e-13, - 1.9999999999999714, - ], - tspan=(0.0, 0.25), - # Soften the tolerance as test results vary between different CPUs - atol=1000 * eps()) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - @trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ @@ -339,53 +311,6 @@ end end end -@trixi_testset "elixir_shallowwater_beach.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_beach.jl"), - l2=[ - 0.17979210479598923, - 1.2377495706611434, - 6.289818963361573e-8, - ], - linf=[ - 0.845938394800688, - 3.3740800777086575, - 4.4541473087633676e-7, - ], - tspan=(0.0, 0.05), - atol=3e-10) # see https://github.com/trixi-framework/Trixi.jl/issues/1617 - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2=[ - 8.965981683033589e-5, - 1.8565707397810857e-5, - 4.1043039226164336e-17, - ], - linf=[ - 0.00041080213807871235, - 0.00014823261488938177, - 2.220446049250313e-16, - ], - tspan=(0.0, 0.05)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - @trixi_testset "elixir_shallow_water_quasi_1d_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallow_water_quasi_1d_source_terms.jl"), diff --git a/test/test_tree_1d_shallowwater_twolayer.jl b/test/test_tree_1d_shallowwater_twolayer.jl deleted file mode 100644 index 180fb3ec3b3..00000000000 --- a/test/test_tree_1d_shallowwater_twolayer.jl +++ /dev/null @@ -1,74 +0,0 @@ -module TestExamples1DShallowWaterTwoLayer - -# TODO: TrixiShallowWater: move two layer tests to new package - -using Test -using Trixi - -include("test_trixi.jl") - -EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") - -@testset "Shallow Water Two layer" begin - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_convergence.jl"), - l2=[0.005012009872109003, 0.002091035326731071, - 0.005049271397924551, - 0.0024633066562966574, 0.0004744186597732739], - linf=[0.0213772149343594, 0.005385752427290447, - 0.02175023787351349, - 0.008212004668840978, 0.0008992474511784199], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_well_balanced.jl"), - l2=[8.949288784402005e-16, 4.0636427176237915e-17, - 0.001002881985401548, - 2.133351105037203e-16, 0.0010028819854016578], - linf=[2.6229018956769323e-15, 1.878451903240623e-16, - 0.005119880996670156, - 8.003199803957679e-16, 0.005119880996670666], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end - - @trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_dam_break.jl"), - l2=[0.1000774903431289, 0.5670692949571057, 0.08764242501014498, - 0.45412307886094555, 0.013638618139749523], - linf=[0.586718937495144, 2.1215606128311584, 0.5185911311186155, - 1.820382495072612, 0.5], - surface_flux=(flux_lax_friedrichs, - flux_nonconservative_ersing_etal), - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end -end - -end # module diff --git a/test/test_tree_2d_part3.jl b/test/test_tree_2d_part3.jl index ce9b3bc04f8..0eff564132c 100644 --- a/test/test_tree_2d_part3.jl +++ b/test/test_tree_2d_part3.jl @@ -26,9 +26,6 @@ isdir(outdir) && rm(outdir, recursive = true) # Shallow water include("test_tree_2d_shallowwater.jl") - # Two-Layer Shallow Water - include("test_tree_2d_shallowwater_twolayer.jl") - # FDSBP methods on the TreeMesh include("test_tree_2d_fdsbp.jl") end diff --git a/test/test_tree_2d_shallowwater.jl b/test/test_tree_2d_shallowwater.jl index 1f3dfbf5267..93a8cb63667 100644 --- a/test/test_tree_2d_shallowwater.jl +++ b/test/test_tree_2d_shallowwater.jl @@ -1,7 +1,5 @@ module TestExamples2DShallowWater -# TODO: TrixiShallowWater: move any wet/dry tests to new package - using Test using Trixi @@ -145,32 +143,6 @@ end end end -@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2=[ - 0.030186039395610056, - 2.513287752536758e-14, - 1.3631397744897607e-16, - 0.10911781485920438, - ], - linf=[ - 0.49999999999993505, - 5.5278950497971455e-14, - 7.462550826772548e-16, - 2.0, - ], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - @trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ @@ -277,57 +249,6 @@ end end end -@trixi_testset "elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), - l2=[ - 0.0459315416430658, - 0.1644534881916991, - 0.16445348819169914, - 0.0011537702354532694, - ], - linf=[ - 0.21100717610846464, - 0.9501592344310412, - 0.9501592344310417, - 0.021790250683516282, - ], - tspan=(0.0, 0.025)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2=[ - 0.00025345501281482687, - 4.4525120338817177e-5, - 0.00015991819160294247, - 7.750412064917294e-15, - ], - linf=[ - 0.004664246019836723, - 0.0004972780116736669, - 0.0028735707270457628, - 6.866729407306593e-14, - ], - tspan=(0.0, 0.025), - basis=LobattoLegendreBasis(3)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - @trixi_testset "elixir_shallowwater_wall.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_wall.jl"), l2=[ diff --git a/test/test_tree_2d_shallowwater_twolayer.jl b/test/test_tree_2d_shallowwater_twolayer.jl deleted file mode 100644 index 802bf4e021c..00000000000 --- a/test/test_tree_2d_shallowwater_twolayer.jl +++ /dev/null @@ -1,88 +0,0 @@ -module TestExamples2DShallowWaterTwoLayer - -# TODO: TrixiShallowWater: move two layer tests to new package - -using Test -using Trixi - -include("test_trixi.jl") - -EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") - -@testset "Two-Layer Shallow Water" begin - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_convergence.jl"), - l2=[0.0004016779699408397, 0.005466339651545468, - 0.006148841330156112, - 0.0002882339012602492, 0.0030120142442780313, - 0.002680752838455618, - 8.873630921431545e-6], - linf=[0.002788654460984752, 0.01484602033450666, - 0.017572229756493973, - 0.0016010835493927011, 0.009369847995372549, - 0.008407961775489636, - 3.361991620143279e-5], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_well_balanced.jl"), - l2=[3.2935164267930016e-16, 4.6800825611195103e-17, - 4.843057532147818e-17, - 0.0030769233188015013, 1.4809161150389857e-16, - 1.509071695038043e-16, - 0.0030769233188014935], - linf=[2.248201624865942e-15, 2.346382070278936e-16, - 2.208565017494899e-16, - 0.026474051138910493, 9.237568031609006e-16, - 7.520758026187046e-16, - 0.026474051138910267], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced with flux_lax_friedrichs.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_well_balanced.jl"), - l2=[2.0525741072929735e-16, 6.000589392730905e-17, - 6.102759428478984e-17, - 0.0030769233188014905, 1.8421386173122792e-16, - 1.8473184927121752e-16, - 0.0030769233188014935], - linf=[7.355227538141662e-16, 2.960836949170518e-16, - 4.2726562436938764e-16, - 0.02647405113891016, 1.038795478061861e-15, - 1.0401789378532516e-15, - 0.026474051138910267], - surface_flux=(flux_lax_friedrichs, - flux_nonconservative_ersing_etal), - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end - end -end - -end # module diff --git a/test/test_unit.jl b/test/test_unit.jl index c1379587cc8..1907a281718 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -420,11 +420,6 @@ end (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) - # TODO: TrixiShallowWater: move unit test - indicator_hg_swe = IndicatorHennemannGassnerShallowWater(1.0, 0.0, true, "variable", - "cache") - @test_nowarn show(stdout, indicator_hg_swe) - indicator_loehner = IndicatorLöhner(1.0, "variable", (; cache = nothing)) @test_nowarn show(stdout, indicator_loehner) @@ -543,7 +538,7 @@ end end @timed_testset "Shallow water conversion between conservative/entropy variables" begin - H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 + H, v1, v2, b, a = 3.5, 0.25, 0.1, 0.4, 0.3 let equations = ShallowWaterEquations1D(gravity_constant = 9.8) cons_vars = prim2cons(SVector(H, v1, b), equations) @@ -572,6 +567,14 @@ end entropy_vars = cons2entropy(cons_vars, equations) @test cons_vars ≈ entropy2cons(entropy_vars, equations) end + + let equations = ShallowWaterEquationsQuasi1D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, b, a), equations) + entropy_vars = cons2entropy(cons_vars, equations) + + total_energy = energy_total(cons_vars, equations) + @test entropy(cons_vars, equations) ≈ a * total_energy + end end @timed_testset "boundary_condition_do_nothing" begin @@ -697,6 +700,14 @@ end u = SVector(1, 0.5, 0.0) @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) + u_ll = SVector(0.1, 1.0, 0.0) + u_rr = SVector(0.1, 1.0, 0.0) + @test flux_hll(u_ll, u_rr, 1, equations) ≈ flux(u_ll, 1, equations) + + u_ll = SVector(0.1, -1.0, 0.0) + u_rr = SVector(0.1, -1.0, 0.0) + @test flux_hll(u_ll, u_rr, 1, equations) ≈ flux(u_rr, 1, equations) + equations = ShallowWaterEquations2D(gravity_constant = 9.81) normal_directions = [SVector(1.0, 0.0), SVector(0.0, 1.0), @@ -707,6 +718,17 @@ end @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) end + + normal_direction = SVector(1.0, 0.0, 0.0) + u_ll = SVector(0.1, 1.0, 1.0, 0.0) + u_rr = SVector(0.1, 1.0, 1.0, 0.0) + @test flux_hll(u_ll, u_rr, normal_direction, equations) ≈ + flux(u_ll, normal_direction, equations) + + u_ll = SVector(0.1, -1.0, -1.0, 0.0) + u_rr = SVector(0.1, -1.0, -1.0, 0.0) + @test flux_hll(u_ll, u_rr, normal_direction, equations) ≈ + flux(u_rr, normal_direction, equations) end @timed_testset "Consistency check for HLL flux (naive): MHD" begin diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 83b8318c926..04eb9f679aa 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -1,7 +1,5 @@ module TestExamplesUnstructuredMesh2D -# TODO: TrixiShallowWater: move any wet/dry and two layer tests - using Test using Trixi @@ -566,105 +564,6 @@ end end end -@trixi_testset "elixir_shallowwater_three_mound_dam_break.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_three_mound_dam_break.jl"), - l2=[ - 0.0892957892027502, - 0.30648836484407915, - 2.28712547616214e-15, - 0.0008778654298684622, - ], - linf=[ - 0.850329472915091, - 2.330631694956507, - 5.783660020252348e-14, - 0.04326237921249021, - ], - basis=LobattoLegendreBasis(3), - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_convergence.jl"), - l2=[0.0007935561625451243, 0.008825315509943844, - 0.002429969315645897, - 0.0007580145888686304, 0.004495741879625235, - 0.0015758146898767814, - 6.849532064729749e-6], - linf=[0.0059205195991136605, 0.08072126590166251, - 0.03463806075399023, - 0.005884818649227186, 0.042658506561995546, - 0.014125956138838602, 2.5829318284764646e-5], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_well_balanced.jl"), - l2=[4.706532184998499e-16, 1.1215950712872183e-15, - 6.7822712922421565e-16, - 0.002192812926266047, 5.506855295923691e-15, - 3.3105180099689275e-15, - 0.0021928129262660085], - linf=[4.468647674116255e-15, 1.3607872120431166e-14, - 9.557155049520056e-15, - 0.024280130945632084, 6.68910907640583e-14, - 4.7000983997100496e-14, - 0.024280130945632732], - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - -@trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_twolayer_dam_break.jl"), - l2=[0.012447632879122346, 0.012361250464676683, - 0.0009551519536340908, - 0.09119400061322577, 0.015276216721920347, - 0.0012126995108983853, 0.09991983966647647], - linf=[0.044305765721807444, 0.03279620980615845, - 0.010754320388190101, - 0.111309922939555, 0.03663360204931427, - 0.014332822306649284, - 0.10000000000000003], - surface_flux=(flux_lax_friedrichs, - flux_nonconservative_ersing_etal), - tspan=(0.0, 0.25)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end -end - # TODO: FD; for now put the unstructured tests for the 2D FDSBP here. @trixi_testset "FDSBP (central): elixir_advection_basic.jl" begin @test_trixi_include(joinpath(pkgdir(Trixi, "examples", "unstructured_2d_fdsbp"), From 5418274987eec6bade5432ead7c91f1d4a842610 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Fri, 23 Feb 2024 05:31:01 +0100 Subject: [PATCH 24/27] Make `min_max_speed_davis` default wave speed estimate for `FluxHLL()` (#1743) * make min_max_speed_davis default wave speed * fmt * exchange hll * exchange some min_max_speed_naive for min_max_speed_davis for some examples * fmt * add news entry * news * debug * revert unintended elixir changes * news entry * correct test vals * Update test vals * Exchange some tests * update test vals for threaded * test vals for fdsbp unstructured * fmt * tests for coverage --------- Co-authored-by: Hendrik Ranocha --- NEWS.md | 5 ++ .../elixir_eulergravity_convergence.jl | 2 +- ..._euler_source_terms_nonconforming_earth.jl | 2 +- .../elixir_euler_convergence.jl | 2 +- .../elixir_eulergravity_convergence.jl | 2 +- .../elixir_eulergravity_jeans_instability.jl | 2 +- .../elixir_eulergravity_sedov_blast_wave.jl | 2 +- .../elixir_eulergravity_convergence.jl | 2 +- ..._shallowwater_well_balanced_nonperiodic.jl | 4 +- .../elixir_eulergravity_convergence.jl | 2 +- .../elixir_shallowwater_dirichlet.jl | 4 +- src/equations/numerical_fluxes.jl | 16 +++- test/test_dgmulti_1d.jl | 10 +-- test/test_dgmulti_2d.jl | 82 +++++++----------- test/test_dgmulti_3d.jl | 71 ++++++--------- test/test_parabolic_3d.jl | 1 + test/test_special_elixirs.jl | 3 +- test/test_structured_2d.jl | 57 ++++++------ test/test_threaded.jl | 24 +++--- test/test_tree_1d_euler.jl | 8 +- test/test_tree_1d_eulergravity.jl | 10 +-- test/test_tree_1d_shallowwater.jl | 19 ++-- test/test_tree_2d_mhd.jl | 2 +- test/test_tree_2d_shallowwater.jl | 30 ++++++- test/test_tree_3d_euler.jl | 17 ++-- test/test_tree_3d_mhd.jl | 4 +- test/test_unstructured_2d.jl | 86 ++++++++----------- 27 files changed, 230 insertions(+), 239 deletions(-) diff --git a/NEWS.md b/NEWS.md index ecc91581e9a..d70504d8c85 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,9 @@ for human readability. #### Changed +- The default wave speed estimate used within `flux_hll` is now `min_max_speed_davis` + instead of `min_max_speed_naive`. + #### Deprecated #### Removed @@ -17,6 +20,7 @@ for human readability. Trixi.jl, but are moved to a dedicated repository: [TrixiShallowWater.jl](https://github.com/trixi-framework/TrixiShallowWater.jl). This includes all features related to wetting and drying, as well as the `ShallowWaterTwoLayerEquations1D` and `ShallowWaterTwoLayerEquations2D`. However, the basic shallow water equations are still part of Trixi.jl. We'll also be updating the TrixiShallowWater.jl documentation with instructions on how to use these relocated features in the future. + ## Changes in the v0.6 lifecycle #### Added @@ -27,6 +31,7 @@ for human readability. - Subcell (positivity) limiting support for nonlinear variables in 2D for `TreeMesh` - Added Lighthill-Whitham-Richards (LWR) traffic model + ## Changes when updating to v0.6 from v0.5.x #### Added diff --git a/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl index d55a59ca5ce..974466e3b3b 100644 --- a/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl @@ -10,7 +10,7 @@ gamma = 2.0 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 -solver_euler = DGSEM(polydeg, flux_hll) +solver_euler = DGSEM(polydeg, FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl index 28a300cd681..28cdec12da5 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl @@ -68,7 +68,7 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) boundary_conditions = Dict(:inside => boundary_condition, :outside => boundary_condition) -surface_flux = flux_hll +surface_flux = FluxHLL(min_max_speed_naive) # Note that a free stream is not preserved if N < 2 * N_geo, where N is the # polydeg of the solver and N_geo is the polydeg of the mesh. # However, the FSP error is negligible in this example. diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl index aabfce0f66b..4f44d7b12ac 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl @@ -8,7 +8,7 @@ equations = CompressibleEulerEquations2D(2.0) initial_condition = initial_condition_eoc_test_coupled_euler_gravity -solver = DGSEM(polydeg = 3, surface_flux = flux_hll) +solver = DGSEM(polydeg = 3, surface_flux = FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl index ce1d2cd05bd..49b98803577 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl @@ -10,7 +10,7 @@ gamma = 2.0 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 -solver_euler = DGSEM(polydeg, flux_hll) +solver_euler = DGSEM(polydeg, FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl index f081f6bb91a..7461198fbb2 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl @@ -66,7 +66,7 @@ gamma = 5 / 3 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 -solver_euler = DGSEM(polydeg, flux_hll) +solver_euler = DGSEM(polydeg, FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl index b7be2320228..bc7ceb97c8b 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl @@ -85,7 +85,7 @@ function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, end boundary_conditions = boundary_condition_sedov_self_gravity -surface_flux = flux_hll +surface_flux = FluxHLL(min_max_speed_naive) volume_flux = flux_chandrashekar polydeg = 3 basis = LobattoLegendreBasis(polydeg) diff --git a/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl b/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl index 98a9a5521a9..cd10315945a 100644 --- a/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl @@ -9,7 +9,7 @@ gamma = 2.0 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 -solver_euler = DGSEM(polydeg, flux_hll) +solver_euler = DGSEM(polydeg, FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl index e55fffc101e..9ed02c0e378 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl @@ -26,7 +26,9 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjordholm_etal), +solver = DGSEM(polydeg = 4, + surface_flux = (flux_hll, + flux_nonconservative_fjordholm_etal), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### diff --git a/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl index 21ef661d0b6..0a8c427bf8d 100644 --- a/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl @@ -10,7 +10,7 @@ equations_euler = CompressibleEulerEquations3D(gamma) initial_condition = initial_condition_eoc_test_coupled_euler_gravity polydeg = 3 -solver_euler = DGSEM(polydeg, flux_hll) +solver_euler = DGSEM(polydeg, FluxHLL(min_max_speed_naive)) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl index df1a69192ce..38e1279e220 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl @@ -30,7 +30,9 @@ boundary_condition = Dict(:OuterCircle => boundary_condition_constant) # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjordholm_etal), +solver = DGSEM(polydeg = 4, + surface_flux = (flux_hll, + flux_nonconservative_fjordholm_etal), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### diff --git a/src/equations/numerical_fluxes.jl b/src/equations/numerical_fluxes.jl index 87fcb412244..6794c71a32b 100644 --- a/src/equations/numerical_fluxes.jl +++ b/src/equations/numerical_fluxes.jl @@ -222,12 +222,12 @@ See [`FluxLaxFriedrichs`](@ref). const flux_lax_friedrichs = FluxLaxFriedrichs() """ - FluxHLL(min_max_speed=min_max_speed_naive) + FluxHLL(min_max_speed=min_max_speed_davis) Create an HLL (Harten, Lax, van Leer) numerical flux where the minimum and maximum wave speeds are estimated as `λ_min, λ_max = min_max_speed(u_ll, u_rr, orientation_or_normal_direction, equations)`, -defaulting to [`min_max_speed_naive`](@ref). +defaulting to [`min_max_speed_davis`](@ref). Original paper: - Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws @@ -237,7 +237,7 @@ struct FluxHLL{MinMaxSpeed} min_max_speed::MinMaxSpeed end -FluxHLL() = FluxHLL(min_max_speed_naive) +FluxHLL() = FluxHLL(min_max_speed_davis) """ min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations) @@ -246,10 +246,16 @@ FluxHLL() = FluxHLL(min_max_speed_naive) Simple and fast estimate(!) of the minimal and maximal wave speed of the Riemann problem with left and right states `u_ll, u_rr`, usually based only on the local wave speeds associated to `u_ll` and `u_rr`. +Slightly more diffusive than [`min_max_speed_davis`](@ref). - Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws [DOI: 10.1137/1025002](https://doi.org/10.1137/1025002) +See eq. (10.37) from +- Eleuterio F. Toro (2009) + Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction + [DOI: 10.1007/b79761](https://doi.org/10.1007/b79761) + See also [`FluxHLL`](@ref), [`min_max_speed_davis`](@ref), [`min_max_speed_einfeldt`](@ref). """ function min_max_speed_naive end @@ -266,6 +272,10 @@ left and right states `u_ll, u_rr`, usually based only on the local wave speeds Simplified Second-Order Godunov-Type Methods [DOI: 10.1137/0909030](https://doi.org/10.1137/0909030) +See eq. (10.38) from +- Eleuterio F. Toro (2009) + Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction + [DOI: 10.1007/b79761](https://doi.org/10.1007/b79761) See also [`FluxHLL`](@ref), [`min_max_speed_naive`](@ref), [`min_max_speed_einfeldt`](@ref). """ function min_max_speed_davis end diff --git a/test/test_dgmulti_1d.jl b/test/test_dgmulti_1d.jl index 0363086341f..e470de71efb 100644 --- a/test/test_dgmulti_1d.jl +++ b/test/test_dgmulti_1d.jl @@ -128,14 +128,12 @@ end @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), l2=[ - 9.146929180585711e-7, - 1.8997616878017292e-6, - 3.991417702211889e-6, + 9.146929178341782e-7, 1.8997616876521201e-6, + 3.991417701005622e-6, ], linf=[ - 1.7321089884614338e-6, - 3.3252888855805907e-6, - 6.5252787737613005e-6, + 1.7321089882393892e-6, 3.3252888869128583e-6, + 6.525278767988141e-6, ]) show(stdout, semi.solver.basis) show(stdout, MIME"text/plain"(), semi.solver.basis) diff --git a/test/test_dgmulti_2d.jl b/test/test_dgmulti_2d.jl index 892c8ed37f0..ab6b505e208 100644 --- a/test/test_dgmulti_2d.jl +++ b/test/test_dgmulti_2d.jl @@ -17,6 +17,7 @@ isdir(outdir) && rm(outdir, recursive = true) @trixi_testset "elixir_euler_weakform.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), cells_per_dimension=(4, 4), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), # division by 2.0 corresponds to normalization by the square root of the size of the domain l2=[ 0.0013536930300254945, @@ -44,6 +45,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), cells_per_dimension=(4, 4), approximation_type=SBP(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), # division by 2.0 corresponds to normalization by the square root of the size of the domain l2=[ 0.0074706882014934735, @@ -71,6 +73,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), cells_per_dimension=(4, 4), element_type=Quad(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), # division by 2.0 corresponds to normalization by the square root of the size of the domain l2=[ 0.00031892254415307093, @@ -184,16 +187,12 @@ end @trixi_testset "elixir_euler_bilinear.jl (Bilinear quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_bilinear.jl"), l2=[ - 1.0259435706215337e-5, - 9.014090233720625e-6, - 9.014090233223014e-6, - 2.738953587401793e-5, + 1.0259432774540821e-5, 9.014087689495575e-6, + 9.01408768888544e-6, 2.738953324859446e-5, ], linf=[ - 7.362609083649829e-5, - 6.874188055272512e-5, - 6.874188052830021e-5, - 0.0001912435192696904, + 7.362605996297233e-5, 6.874189724781488e-5, + 6.874189703509614e-5, 0.00019124355334110277, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -208,16 +207,12 @@ end @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), l2=[ - 1.720476068165337e-5, - 1.592168205710526e-5, - 1.592168205812963e-5, - 4.894094865697305e-5, + 1.7204593127904542e-5, 1.5921547179522804e-5, + 1.5921547180107928e-5, 4.894071422525737e-5, ], linf=[ - 0.00010525416930584619, - 0.00010003778091061122, - 0.00010003778085621029, - 0.00036426282101720275, + 0.00010525416937667842, 0.00010003778102718464, + 0.00010003778071832059, 0.0003642628211952825, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -232,6 +227,7 @@ end @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, GaussSBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), approximation_type=GaussSBP(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), l2=[ 3.4666312079259457e-6, 3.4392774480368986e-6, @@ -259,6 +255,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), element_type=Tri(), approximation_type=Polynomial(), volume_integral=VolumeIntegralWeakForm(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), l2=[ 7.905498158659466e-6, 8.731690809663625e-6, @@ -330,16 +327,12 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), # division by 2.0 corresponds to normalization by the square root of the size of the domain l2=[ - 0.0014986508075708323, - 0.001528523420746786, - 0.0015285234207473158, - 0.004846505183839211, - ] ./ 2.0, + 0.0007492755162295128, 0.0007641875305302599, + 0.0007641875305306243, 0.0024232389721009447, + ], linf=[ - 0.0015062108658376872, - 0.0019373508504645365, - 0.0019373508504538783, - 0.004742686826709086, + 0.0015060064614331736, 0.0019371156800773726, + 0.0019371156800769285, 0.004742431684202408, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -354,16 +347,12 @@ end @trixi_testset "elixir_euler_triangulate_pkg_mesh.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_triangulate_pkg_mesh.jl"), l2=[ - 2.344080455438114e-6, - 1.8610038753097983e-6, - 2.4095165666095305e-6, - 6.373308158814308e-6, + 2.344076909832665e-6, 1.8610002398709756e-6, + 2.4095132179484066e-6, 6.37330249340445e-6, ], linf=[ - 2.5099852761334418e-5, - 2.2683684021362893e-5, - 2.6180448559287584e-5, - 5.5752932611508044e-5, + 2.509979394305084e-5, 2.2683711321080935e-5, + 2.6180377720841363e-5, 5.575278031910713e-5, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -435,16 +424,12 @@ end "elixir_euler_rayleigh_taylor_instability.jl"), cells_per_dimension=(8, 8), tspan=(0.0, 0.2), l2=[ - 0.0709665896982514, - 0.005182828752164663, - 0.013832655585206478, - 0.03247013800580221, + 0.07097806723891838, 0.005168550941966817, + 0.013820912272220933, 0.03243357220022434, ], linf=[ - 0.4783963902824797, - 0.022527207050681054, - 0.040307056293369226, - 0.0852365428206836, + 0.4783395896753895, 0.02244629340135818, + 0.04023357731088538, 0.08515807256615027, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -604,16 +589,12 @@ end @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), l2=[ - 1.3333320340010056e-6, - 2.044834627970641e-6, - 2.044834627855601e-6, - 5.282189803559564e-6, + 1.333332033888785e-6, 2.044834627786368e-6, + 2.0448346278315884e-6, 5.282189803437435e-6, ], linf=[ - 2.7000151718858945e-6, - 3.988595028259212e-6, - 3.9885950273710336e-6, - 8.848583042286862e-6, + 2.7000151703315822e-6, 3.988595025372632e-6, + 3.9885950240403645e-6, 8.848583036513702e-6, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -628,6 +609,7 @@ end @trixi_testset "elixir_euler_fdsbp_periodic.jl (arbitrary reference domain)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), xmin=-200.0, xmax=100.0, #= parameters for reference interval =# + surface_flux=FluxHLL(min_max_speed_naive), l2=[ 1.333332034149886e-6, 2.0448346280892024e-6, @@ -659,6 +641,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), approximation_type=D, coordinates_min=(-3.0, -4.0), coordinates_max=(0.0, -1.0), + surface_flux=FluxHLL(min_max_speed_naive), l2=[ 0.07318831033918516, 0.10039910610067465, @@ -691,6 +674,7 @@ end global D = SummationByPartsOperators.couple_continuously(D_local, mesh_local) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), approximation_type=D, + surface_flux=FluxHLL(min_max_speed_naive), l2=[ 1.5440402410017893e-5, 1.4913189903083485e-5, diff --git a/test/test_dgmulti_3d.jl b/test/test_dgmulti_3d.jl index 3a1db255484..fa70b11447c 100644 --- a/test/test_dgmulti_3d.jl +++ b/test/test_dgmulti_3d.jl @@ -17,20 +17,15 @@ isdir(outdir) && rm(outdir, recursive = true) # 3d tet/hex tests @trixi_testset "elixir_euler_weakform.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain l2=[ - 0.0010029534292051608, - 0.0011682205957721673, - 0.001072975385793516, - 0.000997247778892257, - 0.0039364354651358294, - ] ./ sqrt(8), + 0.000354593110864001, 0.00041301573702385284, + 0.00037934556184883277, 0.0003525767114354012, + 0.0013917457634530887, + ], linf=[ - 0.003660737033303718, - 0.005625620600749226, - 0.0030566354814669516, - 0.0041580358824311325, - 0.019326660236036464, + 0.0036608123230692513, 0.005625540942772123, + 0.0030565781898950206, 0.004158099048202857, + 0.01932716837214299, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -74,6 +69,7 @@ end @trixi_testset "elixir_euler_weakform.jl (Hexahedral elements)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), element_type=Hex(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain l2=[ 0.00030580190715769566, @@ -102,18 +98,13 @@ end @trixi_testset "elixir_euler_curved.jl (Hex elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), l2=[ - 0.018354883045936066, - 0.024412704052042846, - 0.024408520416087945, - 0.01816314570880129, - 0.039342805507972006, + 0.01835488304593566, 0.024412704052042534, + 0.02440852041608929, 0.018163145708800853, + 0.03934280550797125, ], linf=[ - 0.14862225990775757, - 0.28952368161864683, - 0.2912054484817035, - 0.1456603133854122, - 0.3315354586775472, + 0.14862225990793032, 0.2895236816183626, 0.291205448481636, + 0.14566031338563246, 0.33153545867790246, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -129,18 +120,14 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), approximation_type=GaussSBP(), l2=[ - 0.002631131519508634, - 0.0029144224044954105, - 0.002913889110662827, - 0.002615140832314194, - 0.006881528610614373, + 0.0026311315195097097, 0.002914422404496567, + 0.0029138891106640368, 0.002615140832315232, + 0.006881528610616624, ], linf=[ - 0.020996114874140215, - 0.021314522450134543, - 0.021288322783006297, - 0.020273381695435244, - 0.052598740390024545, + 0.02099611487415931, 0.021314522450152307, + 0.021288322783027613, 0.020273381695449455, + 0.05259874039006007, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -154,20 +141,15 @@ end @trixi_testset "elixir_euler_weakform_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain l2=[ - 0.0010317074322517949, - 0.0012277090547035293, - 0.0011273991123913515, - 0.0010418496196130177, - 0.004058878478404962, - ] ./ sqrt(8), + 0.00036475807571383924, 0.00043404536371780537, + 0.0003985850214093045, 0.0003683451584072326, + 0.00143503620472638, + ], linf=[ - 0.003227752881827861, - 0.005620317864620361, - 0.0030514833972379307, - 0.003987027618439498, - 0.019282224709831652, + 0.0032278615418719347, 0.005620238272054934, + 0.0030514261010661237, 0.0039871165455998, + 0.019282771780667396, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -182,6 +164,7 @@ end @trixi_testset "elixir_euler_weakform_periodic.jl (Hexahedral elements)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), element_type=Hex(), + surface_integral=SurfaceIntegralWeakForm(FluxHLL(min_max_speed_naive)), # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain l2=[ 0.00034230612468547436, diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 1eaa9f51a56..863daeeaf35 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -400,6 +400,7 @@ end @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), initial_refinement_level=2, tspan=(0.0, 0.25), + surface_flux=FluxHLL(min_max_speed_naive), l2=[ 0.0001547509861140407, 0.015637861347119624, diff --git a/test/test_special_elixirs.jl b/test/test_special_elixirs.jl index ba670a6025e..277ade9bd5c 100644 --- a/test/test_special_elixirs.jl +++ b/test/test_special_elixirs.jl @@ -286,7 +286,8 @@ end equations = CompressibleEulerEquations1D(1.4) mesh = TreeMesh((-1.0,), (1.0,), initial_refinement_level = 3, n_cells_max = 10^4) - solver = DGSEM(3, flux_hll, VolumeIntegralFluxDifferencing(flux_ranocha)) + solver = DGSEM(3, FluxHLL(min_max_speed_naive), + VolumeIntegralFluxDifferencing(flux_ranocha)) initial_condition = (x, t, equations) -> begin rho = 2 + sinpi(k * sum(x)) v1 = 0.1 diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index f5fb169033a..64a1faf05b8 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -606,16 +606,12 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_rayleigh_taylor_instability.jl"), l2=[ - 0.06365630381017849, - 0.007166887387738937, - 0.002878708825497772, - 0.010247678114070121, + 0.06365630515019809, 0.007166887172039836, + 0.0028787103533600804, 0.010247678008197966, ], linf=[ - 0.4799214336153155, - 0.024595483032220266, - 0.02059808120543466, - 0.03190756362943725, + 0.47992143569849377, 0.02459548251933757, + 0.02059810091623976, 0.0319077000843877, ], cells_per_dimension=(8, 8), tspan=(0.0, 0.3)) @@ -659,14 +655,12 @@ end @trixi_testset "elixir_eulerpolytropic_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), l2=[ - 0.0016688820596537988, - 0.0025921681885685425, - 0.003280950351435014, + 0.00166898321776379, 0.00259202637930991, + 0.0032810744946276406, ], linf=[ - 0.010994679664394269, - 0.01331197845637, - 0.020080117011346488, + 0.010994883201888683, 0.013309526619369905, + 0.020080326611175536, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -678,18 +672,19 @@ end end end -@trixi_testset "elixir_eulerpolytropic_convergence.jl: HLL(Davis)" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), +@trixi_testset "elixir_eulerpolytropic_convergence.jl with FluxHLL(min_max_speed_naive)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulerpolytropic_convergence.jl"), solver=DGSEM(polydeg = 3, - surface_flux = FluxHLL(min_max_speed_davis), + surface_flux = FluxHLL(min_max_speed_naive), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)), l2=[ - 0.0016689832177644243, 0.0025920263793104445, - 0.003281074494629298, + 0.001668882059653298, 0.002592168188567654, + 0.0032809503514328307, ], linf=[ - 0.01099488320190023, 0.013309526619350365, - 0.02008032661117909, + 0.01099467966437917, 0.013311978456333584, + 0.020080117011337606, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -727,14 +722,12 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_isothermal_wave.jl"), l2=[ - 0.004998778491726366, - 0.004998916000294425, - 9.259136963058664e-17, + 0.004998778512795407, 0.004998916021367992, + 8.991558055435833e-17, ], linf=[ - 0.010001103673834888, - 0.010051165098399503, - 7.623942913643681e-16, + 0.010001103632831354, 0.010051165055185603, + 7.60697457718599e-16, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -749,14 +742,12 @@ end @trixi_testset "elixir_eulerpolytropic_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_wave.jl"), l2=[ - 0.23642682112204072, - 0.20904264390331334, - 8.174982691297391e-17, + 0.23642871172548174, 0.2090519382039672, + 8.778842676292274e-17, ], linf=[ - 0.4848250368349989, - 0.253350873815695, - 4.984552457753618e-16, + 0.4852276879687425, 0.25327870807625175, + 5.533921691832115e-16, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_threaded.jl b/test/test_threaded.jl index a8a1b1b425a..7365dcef21c 100644 --- a/test/test_threaded.jl +++ b/test/test_threaded.jl @@ -394,10 +394,10 @@ end "elixir_euler_curved.jl"), alg=RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()), l2=[ - 1.720476068165337e-5, - 1.592168205710526e-5, - 1.592168205812963e-5, - 4.894094865697305e-5, + 1.7204593127904542e-5, + 1.5921547179522804e-5, + 1.5921547180107928e-5, + 4.894071422525737e-5, ], linf=[ 0.00010525416930584619, @@ -420,16 +420,16 @@ end @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_euler_triangulate_pkg_mesh.jl"), l2=[ - 2.344080455438114e-6, - 1.8610038753097983e-6, - 2.4095165666095305e-6, - 6.373308158814308e-6, + 2.344076909832665e-6, + 1.8610002398709756e-6, + 2.4095132179484066e-6, + 6.37330249340445e-6, ], linf=[ - 2.5099852761334418e-5, - 2.2683684021362893e-5, - 2.6180448559287584e-5, - 5.5752932611508044e-5, + 2.509979394305084e-5, + 2.2683711321080935e-5, + 2.6180377720841363e-5, + 5.575278031910713e-5, ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_1d_euler.jl b/test/test_tree_1d_euler.jl index 39a1f6e30ba..f26500b411c 100644 --- a/test/test_tree_1d_euler.jl +++ b/test/test_tree_1d_euler.jl @@ -221,11 +221,11 @@ end @trixi_testset "elixir_euler_ec.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2=[0.07852272782240548, 0.10209790867523805, 0.293873048809011], + l2=[0.07855251823583848, 0.10213903748267686, 0.293985892532479], linf=[ - 0.19244768908604093, - 0.2515941686151897, - 0.7258000837553769, + 0.192621556068018, + 0.25184744005299536, + 0.7264977555504792, ], maxiters=10, surface_flux=flux_hll, diff --git a/test/test_tree_1d_eulergravity.jl b/test/test_tree_1d_eulergravity.jl index 9ab5b287d0b..17bc0c71a7a 100644 --- a/test/test_tree_1d_eulergravity.jl +++ b/test/test_tree_1d_eulergravity.jl @@ -13,14 +13,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), l2=[ - 0.0002170799126638106, - 0.0002913792848717502, - 0.0006112320856262327, + 0.00021708496949694728, 0.0002913795242132917, + 0.0006112500956552259, ], linf=[ - 0.0004977401033188222, - 0.0013594223337776157, - 0.002041891084400227, + 0.0004977733237385706, 0.0013594226727522418, + 0.0020418739554664, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_1d_shallowwater.jl b/test/test_tree_1d_shallowwater.jl index f9be63b87fd..41ad5c32bbd 100644 --- a/test/test_tree_1d_shallowwater.jl +++ b/test/test_tree_1d_shallowwater.jl @@ -143,17 +143,18 @@ end @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ - 0.0022758146627220154, - 0.015864082886204556, + 0.002275023323848826, + 0.015861093821754046, 4.436491725585346e-5, ], linf=[ - 0.008457195427364006, - 0.057201667446161064, + 0.008461451098266792, + 0.05722331401673486, 9.098379777405796e-5, ], tspan=(0.0, 0.025), - surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) + surface_flux=(flux_hll, + flux_nonconservative_fjordholm_etal)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -228,7 +229,7 @@ end 0.05720939349382359, 9.098379777405796e-5, ], - surface_flux=(FluxHydrostaticReconstruction(flux_hll, + surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), tspan=(0.0, 0.025)) @@ -255,7 +256,9 @@ end 3.469453422316143e-15, 3.844551077492042e-8, ], - tspan=(0.0, 0.25)) + tspan=(0.0, 0.25), + surface_flux=(FluxHLL(min_max_speed_naive), + flux_nonconservative_fjordholm_etal),) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -280,6 +283,8 @@ end 3.844551077492042e-8, ], tspan=(0.0, 0.25), + surface_flux=(FluxHLL(min_max_speed_naive), + flux_nonconservative_fjordholm_etal), boundary_condition=boundary_condition_slip_wall) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index 1f8458075aa..66b47138a44 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -183,7 +183,7 @@ end end end -@trixi_testset "elixir_mhd_orszag_tang.jl with flux_hll" begin +@trixi_testset "elixir_mhd_orszag_tang.jl with flux_hlle" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_orszag_tang.jl"), l2=[ 0.10806619664693064, diff --git a/test/test_tree_2d_shallowwater.jl b/test/test_tree_2d_shallowwater.jl index 93a8cb63667..01742644736 100644 --- a/test/test_tree_2d_shallowwater.jl +++ b/test/test_tree_2d_shallowwater.jl @@ -195,6 +195,33 @@ end end @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0018952610547425214, + 0.016943425162728183, + 0.017556784292859465, + 6.274146767717414e-5, + ], + linf=[ + 0.0151635341334182, + 0.07967467926956129, + 0.08400050790965174, + 0.0001819675955490041, + ], + tspan=(0.0, 0.025), + surface_flux=(flux_hll, + flux_nonconservative_fjordholm_etal)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl with FluxHLL(min_max_speed_naive)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ 0.0018957692481057034, @@ -209,7 +236,8 @@ end 0.0001819675955490041, ], tspan=(0.0, 0.025), - surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) + surface_flux=(FluxHLL(min_max_speed_naive), + flux_nonconservative_fjordholm_etal)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_tree_3d_euler.jl b/test/test_tree_3d_euler.jl index 02e657e001a..e9e2b82fec5 100644 --- a/test/test_tree_3d_euler.jl +++ b/test/test_tree_3d_euler.jl @@ -92,18 +92,14 @@ end @trixi_testset "elixir_euler_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), l2=[ - 0.0003637241020254405, - 0.0003955570866382718, - 0.0003955570866383613, - 0.00039555708663834417, - 0.0007811613481640202, + 0.0003637241020254673, 0.00039555708663848046, + 0.00039555708663832644, 0.0003955570866385083, + 0.0007811613481643962, ], linf=[ - 0.0024000660244674066, - 0.0029635410025339315, - 0.0029635410025292686, - 0.002963541002525938, - 0.007191437359396424, + 0.0024000660244567484, 0.002963541002521053, + 0.0029635410025201647, 0.002963541002522385, + 0.007191437359379549, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -462,6 +458,7 @@ end 2.397746252817731, ], maxiters=5, max_level=6, + surface_flux=FluxHLL(min_max_speed_naive), coverage_override=(maxiters = 2, initial_refinement_level = 1, base_level = 1, max_level = 3)) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_3d_mhd.jl b/test/test_tree_3d_mhd.jl index e75685f0b43..74107d462de 100644 --- a/test/test_tree_3d_mhd.jl +++ b/test/test_tree_3d_mhd.jl @@ -184,9 +184,9 @@ end end end -@trixi_testset "elixir_mhd_alfven_wave.jl with Orszag-Tang setup + flux_hll" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with Orszag-Tang setup + flux_hlle" begin # OBS! This setup does not make much sense and is only used to exercise all components of the - # flux_hll implementation + # flux_hlle implementation @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), l2=[ 0.004391143689111404, diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 04eb9f679aa..87d677e1623 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -17,16 +17,12 @@ isdir(outdir) && rm(outdir, recursive = true) @trixi_testset "elixir_euler_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_periodic.jl"), l2=[ - 0.00010978828464875207, - 0.00013010359527356914, - 0.00013010359527326057, - 0.0002987656724828824, + 0.0001099216141882387, 0.0001303795774982892, + 0.00013037957749794242, 0.0002993727892598759, ], linf=[ - 0.00638626102818618, - 0.009804042508242183, - 0.009804042508253286, - 0.02183139311614468, + 0.006407280810928562, 0.009836067015418948, + 0.009836067015398076, 0.021903519038095176, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -41,16 +37,12 @@ end @trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), l2=[ - 3.3937971107485363e-14, - 2.447586447887882e-13, - 1.4585205789296455e-13, - 4.716993468962946e-13, + 3.3937365073416665e-14, 2.44759188939065e-13, + 1.4585198700082895e-13, 4.716940764877479e-13, ], linf=[ - 8.804734719092266e-12, - 6.261270668606045e-11, - 2.93670088247211e-11, - 1.205400224080222e-10, + 8.804956763697191e-12, 6.261199891888225e-11, + 2.936639820205755e-11, 1.20543575121701e-10, ], tspan=(0.0, 0.1), atol=3.0e-13) @@ -78,7 +70,8 @@ end 0.29339040847600434, 0.5915610037764794, ], - tspan=(0.0, 0.25)) + tspan=(0.0, 0.25), + surface_flux=FluxHLL(min_max_speed_naive)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -407,15 +400,15 @@ end @trixi_testset "elixir_shallowwater_source_terms.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ - 0.0011197139793938152, - 0.015430259691310781, - 0.017081031802719724, + 0.001119678684752799, + 0.015429108794630785, + 0.01708275441241111, 5.089218476758271e-6, ], linf=[ - 0.014300809338967824, - 0.12783372461225184, - 0.17625472321992852, + 0.014299564388827513, + 0.12785126473870534, + 0.17626788561725526, 2.6407324614341476e-5, ], surface_flux=(FluxHydrostaticReconstruction(flux_hll, @@ -464,18 +457,19 @@ end @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ - 0.0011197139793938727, - 0.015430259691311309, - 0.017081031802719554, + 0.0011196786847528799, + 0.015429108794631075, + 0.017082754412411742, 5.089218476759981e-6, ], linf=[ - 0.014300809338967824, - 0.12783372461224918, - 0.17625472321993918, + 0.014299564388830177, + 0.12785126473870667, + 0.17626788561728546, 2.6407324614341476e-5, ], - surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), + surface_flux=(flux_hll, + flux_nonconservative_fjordholm_etal), tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -490,16 +484,12 @@ end @trixi_testset "elixir_shallowwater_dirichlet.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_dirichlet.jl"), l2=[ - 1.1577518608940115e-5, - 4.867189932537344e-13, - 4.647273240470541e-13, - 1.1577518608933468e-5, + 1.1577518608938916e-5, 4.859252379740366e-13, + 4.639600837197925e-13, 1.1577518608952174e-5, ], linf=[ - 8.394063878602864e-5, - 1.1469760027632646e-10, - 1.1146619484429974e-10, - 8.394063879602065e-5, + 8.3940638787805e-5, 1.1446362498574484e-10, + 1.1124515748367981e-10, 8.39406387962427e-5, ], tspan=(0.0, 2.0)) # Ensure that we do not have excessive memory allocations @@ -516,16 +506,12 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_wall_bc_shockcapturing.jl"), l2=[ - 0.04444388691670699, - 0.1527771788033111, - 0.1593763537203512, - 6.225080476986749e-8, + 0.0442113635677511, 0.1537465759364839, 0.16003586586203947, + 6.225080477067782e-8, ], linf=[ - 0.6526506870169639, - 1.980765893182952, - 2.4807635459119757, - 3.982097158683473e-7, + 0.6347820607387928, 2.0078125433846736, 2.530726684667019, + 3.982097165344811e-7, ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -609,12 +595,12 @@ end 1.0066867437607972e-13, 6.889210012578449e-14, 1.568290814572709e-13], - linf=[2.353373051988683e-10, - 2.801543719233024e-11, - 3.930469838486772e-11, + linf=[5.6139981552405516e-11, + 2.842849566864203e-11, + 1.8290174930157832e-11, 4.61017890529547e-11], tspan=(0.0, 0.1), - atol=1.0e-11) + atol=1.0e-10) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From c7693aaf06587de194147c9c70888c124ed2daf3 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 23 Feb 2024 13:47:12 +0100 Subject: [PATCH 25/27] set version to v0.7.0; closes #1726 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 6b27e6e9999..2fb8e196829 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.6.11-pre" +version = "0.7.0" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 27d91b3ceeb15e1079b815268738b365635c6cab Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 23 Feb 2024 13:47:49 +0100 Subject: [PATCH 26/27] set development version to v0.7.1-pre --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2fb8e196829..800c7b4c0fa 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.7.0" +version = "0.7.1-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" From 4ee60e7973ff78d553dad65f7f4760443891bdb6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 24 Feb 2024 05:57:09 +0100 Subject: [PATCH 27/27] CompatHelper: bump compat for Trixi to 0.7 for package benchmark, (keep existing compat) (#1853) Co-authored-by: CompatHelper Julia --- benchmark/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/Project.toml b/benchmark/Project.toml index e94144cfd15..51d271e65fc 100644 --- a/benchmark/Project.toml +++ b/benchmark/Project.toml @@ -8,4 +8,4 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" BenchmarkTools = "0.5, 0.7, 1.0" OrdinaryDiffEq = "5.65, 6" PkgBenchmark = "0.2.10" -Trixi = "0.4, 0.5, 0.6" +Trixi = "0.4, 0.5, 0.6, 0.7"