From c9cb2ea008e98244fc453d6702e11cb5fede831b Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 09:03:57 +0100 Subject: [PATCH 01/48] add equation SWEWetDry1D --- .JuliaFormatter.toml | 8 + Project.toml | 3 + src/TrixiShallowWater.jl | 14 +- src/equations/equations.jl | 13 + src/equations/shallow_water_wet_dry_1d.jl | 685 ++++++++++++++++++++++ 5 files changed, 718 insertions(+), 5 deletions(-) create mode 100644 .JuliaFormatter.toml create mode 100644 src/equations/equations.jl create mode 100644 src/equations/shallow_water_wet_dry_1d.jl diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..8518d20 --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,8 @@ +# Use SciML style: https://github.com/SciML/SciMLStyle +style = "sciml" + +# Python style alignment. See https://github.com/domluna/JuliaFormatter.jl/pull/732. +yas_style_nesting = true + +# Align struct fields for better readability of large struct definitions +align_struct_field = true diff --git a/Project.toml b/Project.toml index a2e8f3d..a03795b 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,9 @@ authors = ["Andrew R. Winters ", "Michael Schlottke- version = "0.1.0-pre" [deps] +MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" +Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" [compat] diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index b72b67e..e9561e7 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -1,10 +1,14 @@ module TrixiShallowWater - +# Decide between using Trixi: Trixi, import Trixi or using Trixi? using Trixi: Trixi +using MuladdMacro: @muladd +using StaticArrays: SVector +using Static: True, False + +include("equations/equations.jl") -# Write your package code here. -foo() = true -bar() = false -baz() = Trixi.examples_dir() +# export types/functions that define the public API of TrixiShallowWater.jl +export ShallowWaterEquationsWetDry1D +export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle end diff --git a/src/equations/equations.jl b/src/equations/equations.jl new file mode 100644 index 0000000..a84bff8 --- /dev/null +++ b/src/equations/equations.jl @@ -0,0 +1,13 @@ +# 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 + +#################################################################################################### +# Include files with actual implementations for different systems of equations. +# Numerical flux formulations that are independent of the specific system of equations + +include("shallow_water_wet_dry_1d.jl") +end # @muladd diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl new file mode 100644 index 0000000..dc3d9b4 --- /dev/null +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -0,0 +1,685 @@ +# 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""" + ShallowWaterEquationsWetDry1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing) + +Shallow water equations (SWE) in one space dimension. The equations are given by +```math +\begin{aligned} + \frac{\partial h}{\partial t} + \frac{\partial}{\partial x}(h v) &= 0 \\ + \frac{\partial}{\partial t}(h v) + \frac{\partial}{\partial x}\left(h v^2 + \frac{g}{2}h^2\right) + + g h \frac{\partial b}{\partial x} &= 0 +\end{aligned} +``` +The unknown quantities of the SWE are the water height ``h`` and the velocity ``v``. +The gravitational constant is denoted by `g` and the (possibly) variable bottom topography function ``b(x)``. +Conservative variable water height ``h`` is measured from the bottom topography ``b``, therefore one +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. + +In addition to the unknowns, Trixi.jl 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.jl's visualization tools will visualize the bottom topography by default. + +References for the SWE are many but a good introduction is available in Chapter 13 of the book: +- Randall J. LeVeque (2002) + Finite Volume Methods for Hyperbolic Problems + [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253) +""" +struct ShallowWaterEquationsWetDry1D{RealT <: Real} <: + Trixi.AbstractShallowWaterEquations{1, 3} + 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 ShallowWaterEquationsWetDry1D(; 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 + ShallowWaterEquationsWetDry1D(gravity_constant, H0, threshold_limiter, + threshold_wet) +end + +Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry1D) = True() +function Trixi.varnames(::typeof(Trixi.cons2cons), ::ShallowWaterEquationsWetDry1D) + ("h", "h_v", "b") +end +# Note, we use the total water height, H = h + b, as the first primitive variable for easier +# visualization and setting initial conditions +function Trixi.varnames(::typeof(Trixi.cons2prim), ::ShallowWaterEquationsWetDry1D) + ("H", "v", "b") +end + +# Set initial conditions at physical location `x` for time `t` +""" + initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) + +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 Trixi.initial_condition_convergence_test(x, t, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.initial_condition_convergence_test(x, t, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry1D) + +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). + +This manufactured solution source term is specifically designed for the bottom topography function +`b(x) = 2.0 + 0.5 * sin(sqrt(2.0)*pi*x[1])` +as defined in [`initial_condition_convergence_test`](@ref). +""" + +@inline function Trixi.source_terms_convergence_test(u, x, t, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.source_terms_convergence_test(u, x, t, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry1D) + +A weak blast wave discontinuity useful for testing, e.g., total energy conservation. +Note for the shallow water equations to the total energy acts as a mathematical entropy function. +""" +function Trixi.initial_condition_weak_blast_wave(x, t, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.initial_condition_weak_blast_wave(x, t, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function, + equations::ShallowWaterEquationsWetDry1D) + +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 Trixi.boundary_condition_slip_wall(u_inner, orientation_or_normal, + direction, + x, t, + surface_flux_function, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.boundary_condition_slip_wall(u_inner, orientation_or_normal, direction, + x, t, + surface_flux_function, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +# Calculate 1D flux for a single point +# Note, the bottom topography has no flux +@inline function Trixi.flux(u, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux(u, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, + eps(), eps())) +end + +""" + flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +Non-symmetric two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the bottom topography [`ShallowWaterEquationsWetDry1D`](@ref). + +Further details are available in the paper:#include("numerical_fluxes.jl") +- 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 Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +Non-symmetric two-point surface flux discretizing the nonconservative (source) term of +that contains the gradient of the bottom topography [`ShallowWaterEquationsWetDry1D`](@ref). + +This contains additional terms compared to [`flux_nonconservative_wintermeyer_etal`](@ref) +that account for possible discontinuities in the bottom topography function. +Thus, this flux should be used in general at interfaces. For flux differencing volume terms, +[`flux_nonconservative_wintermeyer_etal`](@ref) is analytically equivalent but slightly +cheaper. + +Further details for the original finite volume formulation are available in +- Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) + Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography + [DOI: 10.1016/j.jcp.2011.03.042](https://doi.org/10.1016/j.jcp.2011.03.042) +and for curvilinear 2D case in 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 Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. +The discretization uses the `hydrostatic_reconstruction_audusse_etal` on the conservative +variables. + +This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain +well-balanced for discontinuous bottom topographies [`ShallowWaterEquationsWetDry1D`](@ref). +Should be used together with [`FluxHydrostaticReconstruction`](@ref) and +[`hydrostatic_reconstruction_audusse_etal`](@ref) in the surface flux to ensure consistency. + +Further details on the hydrostatic reconstruction and its motivation can be found in +- Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) + A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows + [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) +""" +@inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, + orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + flux_nonconservative_chen_noelle(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +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::ShallowWaterEquationsWetDry1D) + + # 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::ShallowWaterEquationsWetDry1D) + +!!! 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 [`ShallowWaterEquationsWetDry1D`](@ref). + +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 Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + flux_fjordholm_etal(u_ll, u_rr, orientation, + equations::ShallowWaterEquationsWetDry1D) + +Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography +is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. +For well-balancedness in the volume flux use [`flux_wintermeyer_etal`](@ref). + +Details are available in Eq. (4.1) in the paper: +- Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) + Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography + [DOI: 10.1016/j.jcp.2011.03.042](https://doi.org/10.1016/j.jcp.2011.03.042) +""" +@inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +""" + flux_wintermeyer_etal(u_ll, u_rr, orientation, + equations::ShallowWaterEquationsWetDry1D) + +Total energy conservative (mathematical entropy for shallow water equations) split form. +When the bottom topography is nonzero this scheme will be well-balanced when used as a `volume_flux`. +The `surface_flux` should still use, e.g., [`flux_fjordholm_etal`](@ref). + +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 Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), eps())) +end + +""" + hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness +for a general bottom topography [`ShallowWaterEquationsWetDry1D`](@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. +Use in combination with the generic numerical flux routine [`FluxHydrostaticReconstruction`](@ref). + +Further details on this hydrostatic reconstruction and its motivation can be found in +- Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) + A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows + [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) +""" +@inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +""" + hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness +for a general bottom topography of the [`ShallowWaterEquationsWetDry1D`](@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::ShallowWaterEquationsWetDry1D) + # 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 `ShallowWaterEquationsWetDry1D` 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 Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.max_abs_speed_naive(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography +@inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry1D) + return (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), + eps())) +end + +# Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography +@inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry1D) + return (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +@inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +""" + min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +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::ShallowWaterEquationsWetDry1D) + # 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 Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +@inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, + eps(), eps())) +end + +@inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.max_abs_speeds(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +# Helper function to extract the velocity vector from the conservative variables +@inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.velocity(u, + Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, + eps(), eps())) +end + +# Convert conservative variables to primitive +@inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.cons2prim(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +# Convert conservative variables to entropy +# Note, only the first two are the entropy variables, the third entry still +# just carries the bottom topography values for convenience +@inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.cons2entropy(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +# Convert entropy variables to conservative +@inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry1D) + return Trixi.entropy2cons(w, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +# Convert primitive to conservative variables +@inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry1D) + return Trixi.prim2cons(prim, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +@inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.waterheight(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +@inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.pressure(u, + Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, + eps(), eps())) +end + +@inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.waterheight_pressure(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +""" + calc_wavespeed_roe(u_ll, u_rr, direction::Integer, + equations::ShallowWaterEquationsWetDry1D) + +Calculate Roe-averaged velocity `v_roe` and wavespeed `c_roe = sqrt{g * h_roe}` +See for instance equation (62) in +- Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) + High-order finite-volume methods for the shallow-water equations on the sphere + [DOI: 10.1016/j.jcp.2010.04.044](https://doi.org/10.1016/j.jcp.2010.04.044) +Or equation (9.17) in [this lecture notes](https://metaphor.ethz.ch/x/2019/hs/401-4671-00L/literature/mishra_hyperbolic_pdes.pdf). +""" +@inline function Trixi.calc_wavespeed_roe(u_ll, u_rr, direction::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.calc_wavespeed_roe(u_ll, u_rr, direction::Integer, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +# Entropy function for the shallow water equations is the total energy +@inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry1D) + Trixi.energy_total(cons, equations) +end + +# Calculate total energy for a conservative state `cons` +@inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry1D) + return Trixi.energy_total(cons, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), eps())) +end + +# Calculate kinetic energy for a conservative state `cons` +@inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.energy_kinetic(u, + Trixi.ShallowWaterEquations1D(equations.gravity, + equations.H0, eps(), + eps())) +end + +# Calculate potential energy for a conservative state `cons` +@inline function Trixi.energy_internal(cons, equations::ShallowWaterEquationsWetDry1D) + return Trixi.energy_total(cons, equations) - Trixi.energy_kinetic(cons, equations) +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. +@inline function Trixi.lake_at_rest_error(u, equations::ShallowWaterEquationsWetDry1D) + 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)) +end +end # @muladd From 6f23516cee63dfe30a180d4ec783ce7f95dfa15a Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 09:05:24 +0100 Subject: [PATCH 02/48] add tests and elixirs --- .../tree_1d_dgsem/elixir_shallowwater_ec.jl | 93 ++++ .../elixir_shallowwater_source_terms.jl | 60 +++ ...xir_shallowwater_source_terms_dirichlet.jl | 63 +++ .../elixir_shallowwater_well_balanced.jl | 88 ++++ ..._shallowwater_well_balanced_nonperiodic.jl | 77 ++++ test/runtests.jl | 4 +- test/test_tree_1d.jl | 27 ++ test/test_tree_1d_shallowwater_wet_dry.jl | 396 ++++++++++++++++++ test/test_trixi.jl | 238 +++++++++++ 9 files changed, 1043 insertions(+), 3 deletions(-) create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_ec.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl create mode 100644 test/test_tree_1d.jl create mode 100644 test/test_tree_1d_shallowwater_wet_dry.jl create mode 100644 test/test_trixi.jl diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl new file mode 100644 index 0000000..c976495 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl @@ -0,0 +1,93 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) + +# Initial condition with a truly discontinuous water height, velocity, and bottom +# topography function as an academic testcase for entropy conservation. +# The errors from the analysis callback are not important but `∑∂S/∂U ⋅ Uₜ` should +# be around machine roundoff. +# Works as intended for TreeMesh1D with `initial_refinement_level=4`. 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_ec_discontinuous_bottom(x, t, + equations::ShallowWaterEquationsWetDry1D) + # Set the background values + H = 4.25 + v = 0.0 + b = sin(x[1]) # arbitrary continuous function + + # Setup the discontinuous water height and velocity + if x[1] >= 0.125 && x[1] <= 0.25 + H = 5.0 + v = 0.1882 + end + + # Setup a discontinuous bottom topography + if x[1] >= -0.25 && x[1] <= -0.125 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + end + + return prim2cons(SVector(H, v, b), equations) +end + +initial_condition = initial_condition_ec_discontinuous_bottom + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 4, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = -1.0 +coordinates_max = 1.0 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 10_000) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 100 +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) + +stepsize_callback = StepsizeCallback(cfl = 3.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/tree_1d_dgsem/elixir_shallowwater_source_terms.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl new file mode 100644 index 0000000..1869a78 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl @@ -0,0 +1,60 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_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 = 200, + 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, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl new file mode 100644 index 0000000..e623077 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -0,0 +1,63 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +boundary_condition = BoundaryConditionDirichlet(initial_condition) + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_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 +coordinates_max = sqrt(2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition, + 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 = 200, + 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, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl new file mode 100644 index 0000000..39b8166 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl @@ -0,0 +1,88 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81, H0 = 3.25) + +# Setup a truly discontinuous bottom topography function for this academic +# testcase of well-balancedness. 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. +# Works as intended for TreeMesh1D with `initial_refinement_level=3`. 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_discontinuous_well_balancedness(x, t, + equations::ShallowWaterEquationsWetDry1D) + # Set the background values + H = equations.H0 + v = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography + if x[1] >= 0.5 && x[1] <= 0.75 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + end + + return prim2cons(SVector(H, v, b), equations) +end + +initial_condition = initial_condition_discontinuous_well_balancedness + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = -1.0 +coordinates_max = 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 solver + +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl new file mode 100644 index 0000000..e3bc3fc --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl @@ -0,0 +1,77 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 1.0, H0 = 3.0) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry1D) + # Set the background values + H = equations.H0 + v = 0.0 + + b = (1.5 / exp(0.5 * ((x[1] - 1.0)^2)) + 0.75 / exp(0.5 * ((x[1] + 1.0)^2))) + + return prim2cons(SVector(H, v, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +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), + 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 = false) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) + +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) + +############################################################################### +# 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/test/runtests.jl b/test/runtests.jl index 909d0e2..fb8e5ef 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,9 +11,7 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin @time if TRIXI_TEST == "all" - @test TrixiShallowWater.foo() == true - @test TrixiShallowWater.bar() == false - @test TrixiShallowWater.baz() isa String + include("test_tree_1d_shallowwater_wet_dry.jl") end @time if TRIXI_TEST == "all" || TRIXI_TEST == "upstream" diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl new file mode 100644 index 0000000..7d96552 --- /dev/null +++ b/test/test_tree_1d.jl @@ -0,0 +1,27 @@ +module TestExamplesTree1D + +using Test +using TrixiShallowWater + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_1d_dgsem") + +# Start with a clean environment: remove Trixi.jl output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +@testset "TreeMesh1D" begin +#! format: noindent + +# Run basic tests +@testset "Examples 1D" begin + # Shallow water + include("test_tree_1d_shallowwater_wet_dry.jl") +end + +# Clean up afterwards: delete Trixi.jl output directory +@test_nowarn rm(outdir, recursive = true) +end # TreeMesh1D + +end # module diff --git a/test/test_tree_1d_shallowwater_wet_dry.jl b/test/test_tree_1d_shallowwater_wet_dry.jl new file mode 100644 index 0000000..473bf05 --- /dev/null +++ b/test/test_tree_1d_shallowwater_wet_dry.jl @@ -0,0 +1,396 @@ +module TestExamples1DShallowWaterWetDry + +# TODO: TrixiShallowWater: move any wet/dry tests to new package + +using Test +using Trixi +using TrixiShallowWater + +# TODO: Right now this is a local copy of the file from Trixi.jl. How can I use @trixi_testset & +# @test_trixi_include from Trixi.jl? +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_1d_dgsem") + +@testset "Shallow Water Wet Dry" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[0.244729018751225, 0.8583565222389505, 0.07330427577586297], + linf=[ + 2.1635021283528504, + 3.8717508164234453, + 1.7711213427919539, + ], + 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_ec.jl with initial_condition_weak_blast_wave" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[ + 0.39464782107209717, + 2.03880864210846, + 4.1623084150546725e-10, + ], + linf=[ + 0.778905801278281, + 3.2409883402608273, + 7.419800190922032e-10, + ], + initial_condition=initial_condition_weak_blast_wave, + 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_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254829, + 1.4352935256803184e-14, + 0.10416666834254838, + ], + linf=[1.9999999999999996, 3.248036646353028e-14, 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_well_balanced.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254835, + 1.1891029971551825e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000018, 2.4019608337954543e-14, 2.0], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_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 + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254838, + 1.6657566141935285e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000004, 3.0610625110157164e-14, 2.0], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + 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: Activate test when Wet_Dry functionality is moved +# @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=[ + 0.0022363707373868713, + 0.01576799981934617, + 4.436491725585346e-5, + ], + linf=[ + 0.00893601803417754, + 0.05939797350246456, + 9.098379777405796e-5, + ], + 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_source_terms.jl with flux_hll" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0022758146627220154, + 0.015864082886204556, + 4.436491725585346e-5, + ], + linf=[ + 0.008457195427364006, + 0.057201667446161064, + 9.098379777405796e-5, + ], + 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 flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.005774284062933275, + 0.017408601639513584, + 4.43649172561843e-5, + ], + linf=[ + 0.01639116193303547, + 0.05102877460799604, + 9.098379777450205e-5, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + 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_source_terms_dirichlet.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022851099219788917, + 0.01560453773635554, + 4.43649172558535e-5, + ], + linf=[ + 0.008934615705174398, + 0.059403169140869405, + 9.098379777405796e-5, + ], + 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_source_terms_dirichlet.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022956052733432287, + 0.015540053559855601, + 4.43649172558535e-5, + ], + linf=[ + 0.008460440313118323, + 0.05720939349382359, + 9.098379777405796e-5, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + 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_well_balanced_nonperiodic.jl with Dirichlet boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.725964362045055e-8, + 5.0427180314307505e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551077492042e-8, + 3.469453422316143e-15, + 3.844551077492042e-8, + ], + 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_well_balanced_nonperiodic.jl with wall boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.7259643614361866e-8, + 3.5519018243195145e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551010878661e-8, + 9.846474508971374e-16, + 3.844551077492042e-8, + ], + tspan=(0.0, 0.25), + boundary_condition=boundary_condition_slip_wall) + # 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: Activate test when Wet_Dry functionality is moved +# @trixi_testset "elixir_shallowwater_shock_capturing.jl" begin +# @test_trixi_include(joinpath(EXAMPLES_DIR, +# "elixir_shallowwater_shock_capturing.jl"), +# l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], +# linf=[ +# 1.1209754279344226, +# 1.3230788645853582, +# 0.8646939843534251, +# ], +# 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 + +# TODO: Activate test when Wet_Dry functionality is moved +# @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 + +# TODO: Activate test when Wet_Dry functionality is moved +# @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 +end +end # module diff --git a/test/test_trixi.jl b/test/test_trixi.jl new file mode 100644 index 0000000..cebe216 --- /dev/null +++ b/test/test_trixi.jl @@ -0,0 +1,238 @@ +using Test: @test +import Trixi + +# Use a macro to avoid world age issues when defining new initial conditions etc. +# inside an elixir. +""" + @test_trixi_include(elixir; l2=nothing, linf=nothing, + atol=500*eps(), rtol=sqrt(eps()), + parameters...) + +Test Trixi by calling `trixi_include(elixir; parameters...)`. +By default, only the absence of error output is checked. +If `l2` or `linf` are specified, in addition the resulting L2/Linf errors +are compared approximately against these reference values, using `atol, rtol` +as absolute/relative tolerance. +""" +macro test_trixi_include(elixir, args...) + local l2 = get_kwarg(args, :l2, nothing) + local linf = get_kwarg(args, :linf, nothing) + local atol = get_kwarg(args, :atol, 500 * eps()) + local rtol = get_kwarg(args, :rtol, sqrt(eps())) + local skip_coverage = get_kwarg(args, :skip_coverage, false) + local coverage_override = expr_to_named_tuple(get_kwarg(args, :coverage_override, :())) + if !(:maxiters in keys(coverage_override)) + # maxiters in coverage_override defaults to 1 + coverage_override = (; coverage_override..., maxiters = 1) + end + + local cmd = string(Base.julia_cmd()) + local coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + + local kwargs = Pair{Symbol, Any}[] + for arg in args + if (arg.head == :(=) && + !(arg.args[1] in (:l2, :linf, :atol, :rtol, :coverage_override, :skip_coverage)) + && !(coverage && arg.args[1] in keys(coverage_override))) + push!(kwargs, Pair(arg.args...)) + end + end + + if coverage + for key in keys(coverage_override) + push!(kwargs, Pair(key, coverage_override[key])) + end + end + + if coverage && skip_coverage + return quote + if Trixi.mpi_isroot() + println("═"^100) + println("Skipping coverage test of ", $elixir) + println("═"^100) + println("\n\n") + end + end + end + + quote + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println($elixir) + + # if `maxiters` is set in tests, it is usually set to a small number to + # run only a few steps - ignore possible warnings coming from that + if any(==(:maxiters) ∘ first, $kwargs) + additional_ignore_content = [ + r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ SciMLBase .+\n", + r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ Trixi .+\n"] + else + additional_ignore_content = [] + end + + # evaluate examples in the scope of the module they're called from + @test_nowarn_mod trixi_include(@__MODULE__, $elixir; $kwargs...) additional_ignore_content + + # if present, compare l2 and linf errors against reference values + if !$coverage && (!isnothing($l2) || !isnothing($linf)) + l2_measured, linf_measured = analysis_callback(sol) + + if Trixi.mpi_isroot() && !isnothing($l2) + @test length($l2) == length(l2_measured) + for (l2_expected, l2_actual) in zip($l2, l2_measured) + @test isapprox(l2_expected, l2_actual, atol = $atol, rtol = $rtol) + end + end + + if Trixi.mpi_isroot() && !isnothing($linf) + @test length($linf) == length(linf_measured) + for (linf_expected, linf_actual) in zip($linf, linf_measured) + @test isapprox(linf_expected, linf_actual, atol = $atol, rtol = $rtol) + end + end + end + + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println("\n\n") + end +end + +# Get the first value assigned to `keyword` in `args` and return `default_value` +# if there are no assignments to `keyword` in `args`. +function get_kwarg(args, keyword, default_value) + val = default_value + for arg in args + if arg.head == :(=) && arg.args[1] == keyword + val = arg.args[2] + break + end + end + return val +end + +function expr_to_named_tuple(expr) + result = (;) + + for arg in expr.args + if arg.head != :(=) + error("Invalid expression") + end + result = (; result..., arg.args[1] => arg.args[2]) + end + return result +end + +# Modified version of `@test_nowarn` that prints the content of `stderr` when +# it is not empty and ignores module replacements. +macro test_nowarn_mod(expr, additional_ignore_content = String[]) + quote + let fname = tempname() + try + ret = open(fname, "w") do f + redirect_stderr(f) do + $(esc(expr)) + end + end + stderr_content = read(fname, String) + if !isempty(stderr_content) + println("Content of `stderr`:\n", stderr_content) + end + + # Patterns matching the following ones will be ignored. Additional patterns + # passed as arguments can also be regular expressions, so we just use the + # type `Any` for `ignore_content`. + ignore_content = Any[ + # We need to ignore steady state information reported by our callbacks + r"┌ Info: Steady state tolerance reached\n│ steady_state_callback .+\n└ t = .+\n", + # We also ignore our own compilation messages + "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n", + # TODO: Upstream (PlotUtils). This should be removed again once the + # deprecated stuff is fixed upstream. + "WARNING: importing deprecated binding Colors.RGB1 into Plots.\n", + "WARNING: importing deprecated binding Colors.RGB4 into Plots.\n", + r"┌ Warning: Keyword argument letter not supported with Plots.+\n└ @ Plots.+\n", + r"┌ Warning: `parse\(::Type, ::Coloarant\)` is deprecated.+\n│.+\n│.+\n└ @ Plots.+\n", + # TODO: Silence warning introduced by Flux v0.13.13. Should be properly fixed. + r"┌ Warning: Layer with Float32 parameters got Float64 input.+\n│.+\n│.+\n│.+\n└ @ Flux.+\n"] + append!(ignore_content, $additional_ignore_content) + for pattern in ignore_content + stderr_content = replace(stderr_content, pattern => "") + end + + # We also ignore simple module redefinitions for convenience. Thus, we + # check whether every line of `stderr_content` is of the form of a + # module replacement warning. + @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) + ret + finally + rm(fname, force = true) + end + end + end +end + +""" + @timed_testset "name of the testset" #= code to test #= + +Similar to `@testset`, but prints the name of the testset and its runtime +after execution. +""" +macro timed_testset(name, expr) + @assert name isa String + quote + local time_start = time_ns() + @testset $name $expr + local time_stop = time_ns() + if Trixi.mpi_isroot() + flush(stdout) + @info("Testset "*$name*" finished in " + *string(1.0e-9 * (time_stop - time_start))*" seconds.\n") + flush(stdout) + end + end +end + +""" + @trixi_testset "name of the testset" #= code to test #= + +Similar to `@testset`, but wraps the code inside a temporary module to avoid +namespace pollution. It also `include`s this file again to provide the +definition of `@test_trixi_include`. Moreover, it records the execution time +of the testset similarly to [`timed_testset`](@ref). +""" +macro trixi_testset(name, expr) + @assert name isa String + # TODO: `@eval` is evil + # We would like to use + # mod = gensym(name) + # ... + # module $mod + # to create new module names for every test set. However, this is not + # compatible with the dirty hack using `@eval` to get the mapping when + # loading structured, curvilinear meshes. Thus, we need to use a plain + # module name here. + quote + local time_start = time_ns() + @eval module TrixiTestModule + using Test + using Trixi + include(@__FILE__) + # We define `EXAMPLES_DIR` in (nearly) all test modules and use it to + # get the path to the elixirs to be tested. However, that's not required + # and we want to fail gracefully if it's not defined. + try + import ..EXAMPLES_DIR + catch + nothing + end + @testset $name $expr + end + local time_stop = time_ns() + if Trixi.mpi_isroot() + flush(stdout) + @info("Testset "*$name*" finished in " + *string(1.0e-9 * (time_stop - time_start))*" seconds.\n") + end + nothing + end +end From 49e1ef4af218d11bf46599892495c44332781263 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 11:10:08 +0100 Subject: [PATCH 03/48] add OrdinaryDiffEq as a test dependency --- test/Project.toml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/Project.toml b/test/Project.toml index fbc64c5..b337aa6 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,6 +1,18 @@ [deps] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" +OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" [compat] Trixi = "0.5, 0.6" +OrdinaryDiffEq = "6.49.1" + +[preferences.OrdinaryDiffEq] +PrecompileAutoSpecialize = false +PrecompileAutoSwitch = false +PrecompileDefaultSpecialize = false +PrecompileFunctionWrapperSpecialize = false +PrecompileLowStorage = false +PrecompileNoSpecialize = false +PrecompileNonStiff = false +PrecompileStiff = false From 83f321ad383ac575a5ca2f6bd83ccf90740de0ab Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 11:52:50 +0100 Subject: [PATCH 04/48] comment functions related to HR_chen_noelle --- src/TrixiShallowWater.jl | 3 +- src/equations/shallow_water_wet_dry_1d.jl | 263 +++++++++++----------- 2 files changed, 135 insertions(+), 131 deletions(-) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index e9561e7..e44cf50 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -9,6 +9,7 @@ include("equations/equations.jl") # export types/functions that define the public API of TrixiShallowWater.jl export ShallowWaterEquationsWetDry1D -export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle +# TODO: These function are currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl +#export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, min_max_speed_chen_noelle end diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index dc3d9b4..8937191 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -269,52 +269,53 @@ Further details on the hydrostatic reconstruction and its motivation can be foun eps())) end -""" - flux_nonconservative_chen_noelle(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - -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::ShallowWaterEquationsWetDry1D) - - # 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 +# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl +# """ +# flux_nonconservative_chen_noelle(u_ll, u_rr, +# orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) + +# 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::ShallowWaterEquationsWetDry1D) + +# # 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, @@ -412,65 +413,66 @@ Further details on this hydrostatic reconstruction and its motivation can be fou eps())) end -""" - hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - -A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness -for a general bottom topography of the [`ShallowWaterEquationsWetDry1D`](@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::ShallowWaterEquationsWetDry1D) - # 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 `ShallowWaterEquationsWetDry1D` 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 +# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl +# """ +# hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) + +# A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness +# for a general bottom topography of the [`ShallowWaterEquationsWetDry1D`](@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::ShallowWaterEquationsWetDry1D) +# # 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 `ShallowWaterEquationsWetDry1D` 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 @@ -512,37 +514,38 @@ end eps())) end -""" - min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) +# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl +# """ +# min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) -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. +# 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::ShallowWaterEquationsWetDry1D) - # Get the velocity quantities - v_ll = velocity(u_ll, equations) - v_rr = velocity(u_rr, equations) +# 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::ShallowWaterEquationsWetDry1D) +# # 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) +# # 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) +# 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))) +# λ_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 +# return λ_min, λ_max +# end # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, From 02c28846fe1cce3dd4f8b2c5e74d3674bc2adf5d Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 13:26:19 +0100 Subject: [PATCH 05/48] fix tests --- src/TrixiShallowWater.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index e44cf50..ca3748c 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -7,6 +7,8 @@ using Static: True, False include("equations/equations.jl") +baz() = Trixi.examples_dir() + # export types/functions that define the public API of TrixiShallowWater.jl export ShallowWaterEquationsWetDry1D # TODO: These function are currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl From b86c4ae5a793c20a554a18d72420b2cd71cb9ffd Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 17:01:59 +0100 Subject: [PATCH 06/48] fix tests #2 --- .github/workflows/ci.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8dc9958..230d63a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,19 +31,21 @@ concurrency: jobs: test: if: "!contains(github.event.head_commit.message, 'skip ci')" - name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + name: ${{ matrix.trixi_test }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: version: - - '1.8' + - '1.9' os: - ubuntu-latest - macOS-latest - windows-latest arch: - x64 + trixi_test: + - tree_part1 steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 @@ -53,7 +55,21 @@ jobs: - run: julia -e 'using InteractiveUtils; versioninfo(verbose=true)' - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 + #- uses: julia-actions/julia-runtest@v1 + - name: Run tests without coverage + uses: julia-actions/julia-runtest@v1 + with: + coverage: false + env: + PYTHON: "" + TRIXI_TEST: ${{ matrix.trixi_test }} + - name: Run tests with coverage + uses: julia-actions/julia-runtest@v1 + with: + coverage: true + env: + PYTHON: "" + TRIXI_TEST: ${{ matrix.trixi_test }} - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v3 with: From 9f49340f352fecf03ce163ebdf909084490af821 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 17:12:06 +0100 Subject: [PATCH 07/48] fix tests #3 --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index fb8e5ef..4a7f4f4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,7 +10,7 @@ const TRIXI_MPI_NPROCS = clamp(Sys.CPU_THREADS, 2, 3) const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin - @time if TRIXI_TEST == "all" + @time if TRIXI_TEST == "all" || TRIXI_TEST == "tree_part1" include("test_tree_1d_shallowwater_wet_dry.jl") end From df7d15e550766c8a27f8defbe3a07ab29b75f99a Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 18:00:45 +0100 Subject: [PATCH 08/48] fix tests 4 --- .github/workflows/ci.yml | 2 +- src/TrixiShallowWater.jl | 2 -- test/runtests.jl | 6 ++---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 230d63a..47e8b02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: arch: - x64 trixi_test: - - tree_part1 + - all steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index ca3748c..e44cf50 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -7,8 +7,6 @@ using Static: True, False include("equations/equations.jl") -baz() = Trixi.examples_dir() - # export types/functions that define the public API of TrixiShallowWater.jl export ShallowWaterEquationsWetDry1D # TODO: These function are currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl diff --git a/test/runtests.jl b/test/runtests.jl index 4a7f4f4..00acf9d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,13 +10,11 @@ const TRIXI_MPI_NPROCS = clamp(Sys.CPU_THREADS, 2, 3) const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin - @time if TRIXI_TEST == "all" || TRIXI_TEST == "tree_part1" + @time if TRIXI_TEST == "all" include("test_tree_1d_shallowwater_wet_dry.jl") end @time if TRIXI_TEST == "all" || TRIXI_TEST == "upstream" - @testset "baz()" begin - @test TrixiShallowWater.baz() isa String - end + end end From dba63bc1511dcad819372a603bc713cb9522050a Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 18:38:17 +0100 Subject: [PATCH 09/48] fix tests 5 --- .github/workflows/ci.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47e8b02..b5a6cfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ concurrency: jobs: test: if: "!contains(github.event.head_commit.message, 'skip ci')" - name: ${{ matrix.trixi_test }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -44,8 +44,6 @@ jobs: - windows-latest arch: - x64 - trixi_test: - - all steps: - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 @@ -60,16 +58,10 @@ jobs: uses: julia-actions/julia-runtest@v1 with: coverage: false - env: - PYTHON: "" - TRIXI_TEST: ${{ matrix.trixi_test }} - name: Run tests with coverage uses: julia-actions/julia-runtest@v1 with: coverage: true - env: - PYTHON: "" - TRIXI_TEST: ${{ matrix.trixi_test }} - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v3 with: From 5d5d29afffc677945c6c7bd2ebe2878489421ebf Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 18 Dec 2023 18:55:10 +0100 Subject: [PATCH 10/48] fix tests 6 --- .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 b5a6cfa..2558db3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: fail-fast: false matrix: version: - - '1.9' + - '1.8' os: - ubuntu-latest - macOS-latest From b58e902baf638041925b338b25b76a156ac2d9dc Mon Sep 17 00:00:00 2001 From: patrickersing Date: Tue, 19 Dec 2023 11:59:44 +0100 Subject: [PATCH 11/48] add unit tests and namespace conflict test --- src/equations/shallow_water_wet_dry_1d.jl | 19 -------- test/runtests.jl | 9 +++- test/test_unit.jl | 53 +++++++++++++++++++++++ 3 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 test/test_unit.jl diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 8937191..04bba57 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -627,25 +627,6 @@ end eps())) end -""" - calc_wavespeed_roe(u_ll, u_rr, direction::Integer, - equations::ShallowWaterEquationsWetDry1D) - -Calculate Roe-averaged velocity `v_roe` and wavespeed `c_roe = sqrt{g * h_roe}` -See for instance equation (62) in -- Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) - High-order finite-volume methods for the shallow-water equations on the sphere - [DOI: 10.1016/j.jcp.2010.04.044](https://doi.org/10.1016/j.jcp.2010.04.044) -Or equation (9.17) in [this lecture notes](https://metaphor.ethz.ch/x/2019/hs/401-4671-00L/literature/mishra_hyperbolic_pdes.pdf). -""" -@inline function Trixi.calc_wavespeed_roe(u_ll, u_rr, direction::Integer, - equations::ShallowWaterEquationsWetDry1D) - return Trixi.calc_wavespeed_roe(u_ll, u_rr, direction::Integer, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) -end - # Entropy function for the shallow water equations is the total energy @inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry1D) Trixi.energy_total(cons, equations) diff --git a/test/runtests.jl b/test/runtests.jl index 00acf9d..0da42f1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,4 @@ +using Trixi using TrixiShallowWater using Test @@ -12,9 +13,15 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin @time if TRIXI_TEST == "all" include("test_tree_1d_shallowwater_wet_dry.jl") + include("test_unit.jl") end @time if TRIXI_TEST == "all" || TRIXI_TEST == "upstream" - + @testset "Namespace conflicts" begin + # Test for namespace conflicts between TrixiShallowWater.jl and Trixi.jl + for name in names(Trixi) + @test !(name in names(TrixiShallowWater)) + end + end end end diff --git a/test/test_unit.jl b/test/test_unit.jl new file mode 100644 index 0000000..195e3bf --- /dev/null +++ b/test/test_unit.jl @@ -0,0 +1,53 @@ +module TestUnit + +using Test +using Trixi +using TrixiShallowWater + +include("test_trixi.jl") + +# Start with a clean environment: remove Trixi.jl output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +# Run various unit (= non-elixir-triggered) tests +@testset "Unit tests" begin +#! format: noindent + +@timed_testset "Shallow water conversion between conservative/entropy variables" begin + H, v, b = 3.5, 0.25, 0.4 + + let equations = ShallowWaterEquations1D(gravity_constant = 9.8) + cons_vars = Trixi.prim2cons(SVector(H, v, b), equations) + entropy_vars = Trixi.cons2entropy(cons_vars, equations) + @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) + + total_energy = Trixi.energy_total(cons_vars, equations) + @test total_energy ≈ Trixi.entropy(cons_vars, equations) + + # test tuple args + cons_vars = Trixi.prim2cons((H, v, b), equations) + entropy_vars = Trixi.cons2entropy(cons_vars, equations) + @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) + end +end + +@timed_testset "Connectivity with Trixi.jl" begin + u = SVector(SVector(1, 0.5, 0.0)) + orientation = 1 + equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) + equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.81) + + # We only need to check equivalence between the equation systems. The functionality is tested in + # Trixi.jl. We choose these specific ones to improve code coverage, as they are not tested in + # any elixirs. + @test min_max_speed_einfeldt(u, u, orientation, equations) == + min_max_speed_einfeldt(u, u, orientation, equations_trixi) + @test min_max_speed_davis(u, u, orientation, equations) == + min_max_speed_davis(u, u, orientation, equations_trixi) + @test max_abs_speed_naive(u, u, orientation, equations) == + max_abs_speed_naive(u, u, orientation, equations_trixi) +end +end + +end # module From d0eb6dd7eeed1e223c9fffc9b9b8c9f800a02a39 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Tue, 19 Dec 2023 13:05:32 +0100 Subject: [PATCH 12/48] update unit tests, comment wave speed estimates --- src/equations/shallow_water_wet_dry_1d.jl | 70 +++++++++++++---------- test/test_unit.jl | 36 ++++++------ 2 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 04bba57..fc22649 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -474,15 +474,17 @@ end # 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 Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - return Trixi.max_abs_speed_naive(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) -end +# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need +# equation specific wave speed estimates. +# # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation as the +# # maximum velocity magnitude plus the maximum speed of sound +# @inline function Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) +# return Trixi.max_abs_speed_naive(u_ll, u_rr, orientation, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, eps(), +# eps())) +# end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, @@ -505,14 +507,16 @@ end eps())) end -# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes -@inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) -end +# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need +# equation specific wave speed estimates. +# # Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +# @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) +# return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, eps(), +# eps())) +# end # TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl # """ @@ -547,22 +551,26 @@ end # return λ_min, λ_max # end +# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need +# equation specific wave speed estimates. # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes -@inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) -end +# @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) +# return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, eps(), +# eps())) +# end -@inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), eps())) -end +# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need +# equation specific wave speed estimates. +# @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, +# equations::ShallowWaterEquationsWetDry1D) +# return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, +# eps(), eps())) +# end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, diff --git a/test/test_unit.jl b/test/test_unit.jl index 195e3bf..a1474e3 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -17,7 +17,7 @@ isdir(outdir) && rm(outdir, recursive = true) @timed_testset "Shallow water conversion between conservative/entropy variables" begin H, v, b = 3.5, 0.25, 0.4 - let equations = ShallowWaterEquations1D(gravity_constant = 9.8) + let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) cons_vars = Trixi.prim2cons(SVector(H, v, b), equations) entropy_vars = Trixi.cons2entropy(cons_vars, equations) @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) @@ -32,22 +32,24 @@ isdir(outdir) && rm(outdir, recursive = true) end end -@timed_testset "Connectivity with Trixi.jl" begin - u = SVector(SVector(1, 0.5, 0.0)) - orientation = 1 - equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) - equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.81) - - # We only need to check equivalence between the equation systems. The functionality is tested in - # Trixi.jl. We choose these specific ones to improve code coverage, as they are not tested in - # any elixirs. - @test min_max_speed_einfeldt(u, u, orientation, equations) == - min_max_speed_einfeldt(u, u, orientation, equations_trixi) - @test min_max_speed_davis(u, u, orientation, equations) == - min_max_speed_davis(u, u, orientation, equations_trixi) - @test max_abs_speed_naive(u, u, orientation, equations) == - max_abs_speed_naive(u, u, orientation, equations_trixi) -end +# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need +# equation specific wave speed estimates. +# @timed_testset "Connectivity with Trixi.jl" begin +# u = SVector(SVector(1, 0.5, 0.0)) +# orientation = 1 +# equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) +# equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.81) + +# # We only need to check equivalence between the equation systems. The functionality is tested in +# # Trixi.jl. We choose these specific ones to improve code coverage, as they are not tested in +# # any elixirs. +# @test min_max_speed_einfeldt(u, u, orientation, equations) == +# min_max_speed_einfeldt(u, u, orientation, equations_trixi) +# @test min_max_speed_davis(u, u, orientation, equations) == +# min_max_speed_davis(u, u, orientation, equations_trixi) +# @test max_abs_speed_naive(u, u, orientation, equations) == +# max_abs_speed_naive(u, u, orientation, equations_trixi) +# end end end # module From 5fc8eec4e3ebfb3fb1a6860aeea4f136f3bd4721 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Tue, 19 Dec 2023 13:38:39 +0100 Subject: [PATCH 13/48] update unit test --- test/test_unit.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index a1474e3..448f8fc 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -24,7 +24,9 @@ isdir(outdir) && rm(outdir, recursive = true) total_energy = Trixi.energy_total(cons_vars, equations) @test total_energy ≈ Trixi.entropy(cons_vars, equations) - + @test total_energy ≈ + Trixi.energy_internal(cons_vars, equations) + + energy_kinetic(cons_vars, equations) # test tuple args cons_vars = Trixi.prim2cons((H, v, b), equations) entropy_vars = Trixi.cons2entropy(cons_vars, equations) From c02cbf60e0396aed8f64950577559dd3052b5a5c Mon Sep 17 00:00:00 2001 From: patrickersing Date: Thu, 21 Dec 2023 13:22:04 +0100 Subject: [PATCH 14/48] add compat bounds --- Project.toml | 3 +++ test/Project.toml | 1 + 2 files changed, 4 insertions(+) diff --git a/Project.toml b/Project.toml index a03795b..1ec3ece 100644 --- a/Project.toml +++ b/Project.toml @@ -10,5 +10,8 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" [compat] +MuladdMacro = "0.2.2" +Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" +StaticArrays = "1" Trixi = "0.5.17, 0.6" julia = "1.8" diff --git a/test/Project.toml b/test/Project.toml index b337aa6..cfac638 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,6 +4,7 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" [compat] +Test = "1" Trixi = "0.5, 0.6" OrdinaryDiffEq = "6.49.1" From 64b9bf37466ed8503b3f15f4ca63a2f28bbcd9b0 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Thu, 21 Dec 2023 13:53:57 +0100 Subject: [PATCH 15/48] add some comments --- examples/tree_1d_dgsem/elixir_shallowwater_ec.jl | 2 +- .../tree_1d_dgsem/elixir_shallowwater_source_terms.jl | 2 +- .../tree_1d_dgsem/elixir_shallowwater_well_balanced.jl | 2 +- .../elixir_shallowwater_well_balanced_nonperiodic.jl | 4 ++-- src/equations/shallow_water_wet_dry_1d.jl | 10 +++++++--- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl index c976495..8046736 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl @@ -5,7 +5,7 @@ using TrixiShallowWater ############################################################################### # Semidiscretization of the shallow water equations with a discontinuous -# bottom topography function +# bottom topography function for a fully wet configuration equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl index 1869a78..aded502 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl @@ -4,7 +4,7 @@ using Trixi using TrixiShallowWater ############################################################################### -# Semidiscretization of the shallow water equations +# Semidiscretization of the shallow water equations for a fully wet configuration equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl index 39b8166..e78a867 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl @@ -5,7 +5,7 @@ using TrixiShallowWater ############################################################################### # semidiscretization of the shallow water equations with a discontinuous -# bottom topography function +# bottom topography function for a fully wet configuration equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81, H0 = 3.25) 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 e3bc3fc..24c60c3 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl @@ -4,7 +4,7 @@ using Trixi using TrixiShallowWater ############################################################################### -# Semidiscretization of the shallow water equations +# Semidiscretization of the shallow water equations for a fully wet configuration equations = ShallowWaterEquationsWetDry1D(gravity_constant = 1.0, H0 = 3.0) @@ -31,7 +31,7 @@ solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjord volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### -# Get the TreeMesh and setup a periodic mesh +# Get the TreeMesh and setup a non-periodic mesh coordinates_min = 0.0 coordinates_max = sqrt(2.0) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index fc22649..e1d0fd2 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -93,6 +93,13 @@ function Trixi.varnames(::typeof(Trixi.cons2prim), ::ShallowWaterEquationsWetDry ("H", "v", "b") end +# TODO: Remove thresholds from ShallowWaterEquations1D after they have been moved + +# This equation set extends the basic ShallowWaterEquations1D from Trixi.jl with additional functionality +# for wet/dry transitions. Since many functions correspond to the fully wet case, we make use of the +# exisiting functionality and introduce a number of wrapper functions, that dispatch to the +# ShallowWaterEquations1D. + # Set initial conditions at physical location `x` for time `t` """ initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) @@ -321,9 +328,6 @@ end flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) -!!! 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 [`ShallowWaterEquationsWetDry1D`](@ref). From 6b585b9296b27554032ddd30886d7f35349df6ed Mon Sep 17 00:00:00 2001 From: patrickersing Date: Wed, 10 Jan 2024 09:22:14 +0100 Subject: [PATCH 16/48] clean some comments, remove wave speed estimates --- src/equations/equations.jl | 1 - src/equations/shallow_water_wet_dry_1d.jl | 44 ----------------------- test/test_unit.jl | 19 ---------- 3 files changed, 64 deletions(-) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index a84bff8..4d31451 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -7,7 +7,6 @@ #################################################################################################### # Include files with actual implementations for different systems of equations. -# Numerical flux formulations that are independent of the specific system of equations include("shallow_water_wet_dry_1d.jl") end # @muladd diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index e1d0fd2..bace4da 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -478,18 +478,6 @@ end # return u_ll_star, u_rr_star # end -# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need -# equation specific wave speed estimates. -# # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation as the -# # maximum velocity magnitude plus the maximum speed of sound -# @inline function Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) -# return Trixi.max_abs_speed_naive(u_ll, u_rr, orientation, -# Trixi.ShallowWaterEquations1D(equations.gravity, -# equations.H0, eps(), -# eps())) -# end - # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, @@ -511,17 +499,6 @@ end eps())) end -# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need -# equation specific wave speed estimates. -# # Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes -# @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) -# return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, -# Trixi.ShallowWaterEquations1D(equations.gravity, -# equations.H0, eps(), -# eps())) -# end - # TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl # """ # min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, @@ -555,27 +532,6 @@ end # return λ_min, λ_max # end -# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need -# equation specific wave speed estimates. -# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes -# @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) -# return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, -# Trixi.ShallowWaterEquations1D(equations.gravity, -# equations.H0, eps(), -# eps())) -# end - -# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need -# equation specific wave speed estimates. -# @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) -# return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, -# Trixi.ShallowWaterEquations1D(equations.gravity, -# equations.H0, -# eps(), eps())) -# end - @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, Trixi.ShallowWaterEquations1D(equations.gravity, diff --git a/test/test_unit.jl b/test/test_unit.jl index 448f8fc..9517443 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -33,25 +33,6 @@ isdir(outdir) && rm(outdir, recursive = true) @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) end end - -# TODO: Probably can be removed. Since we dispatch to ShallowWaterEquations1D we don't need -# equation specific wave speed estimates. -# @timed_testset "Connectivity with Trixi.jl" begin -# u = SVector(SVector(1, 0.5, 0.0)) -# orientation = 1 -# equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) -# equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.81) - -# # We only need to check equivalence between the equation systems. The functionality is tested in -# # Trixi.jl. We choose these specific ones to improve code coverage, as they are not tested in -# # any elixirs. -# @test min_max_speed_einfeldt(u, u, orientation, equations) == -# min_max_speed_einfeldt(u, u, orientation, equations_trixi) -# @test min_max_speed_davis(u, u, orientation, equations) == -# min_max_speed_davis(u, u, orientation, equations_trixi) -# @test max_abs_speed_naive(u, u, orientation, equations) == -# max_abs_speed_naive(u, u, orientation, equations_trixi) -# end end end # module From 9ffdc275a7ca75c2f5cd6998216c2857b21e5641 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 12 Jan 2024 17:57:22 +0100 Subject: [PATCH 17/48] comment unused lines --- src/equations/shallow_water_wet_dry_1d.jl | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index bace4da..57313ff 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -539,12 +539,12 @@ end eps())) end -# Helper function to extract the velocity vector from the conservative variables -@inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) - return Trixi.velocity(u, - Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, - eps(), eps())) -end +# # Helper function to extract the velocity vector from the conservative variables +# @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) +# return Trixi.velocity(u, +# Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, +# eps(), eps())) +# end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) @@ -576,24 +576,24 @@ end equations.H0, eps(), eps())) end -@inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) - return Trixi.waterheight(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) -end +# @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) +# return Trixi.waterheight(u, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, eps(), eps())) +# end -@inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) - return Trixi.pressure(u, - Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, - eps(), eps())) -end +# @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) +# return Trixi.pressure(u, +# Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, +# eps(), eps())) +# end -@inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) - return Trixi.waterheight_pressure(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) -end +# @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) +# return Trixi.waterheight_pressure(u, +# Trixi.ShallowWaterEquations1D(equations.gravity, +# equations.H0, eps(), +# eps())) +# end # Entropy function for the shallow water equations is the total energy @inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry1D) From 5fc3c36f693e9e4f648acc98ce1b76194141d981 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 15 Jan 2024 09:33:35 +0100 Subject: [PATCH 18/48] include examples folder for coverage test --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0295b0..2d4787d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,8 @@ jobs: with: coverage: true - uses: julia-actions/julia-processcoverage@v1 + with: + directories: src, examples - uses: codecov/codecov-action@v3 with: files: lcov.info From aa21b7fbcf9cfbd97f0948ad55c837c0a8df5f5e Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 15 Jan 2024 09:33:52 +0100 Subject: [PATCH 19/48] add upstream tests --- test/runtests.jl | 3 +++ test/test_upstream.jl | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 test/test_upstream.jl diff --git a/test/runtests.jl b/test/runtests.jl index 0da42f1..8a0e590 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,5 +23,8 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @test !(name in names(TrixiShallowWater)) end end + + # Run upstream tests for each mesh and dimension to test compatibility with Trixi.jl + include("test_upstream.jl") end end diff --git a/test/test_upstream.jl b/test/test_upstream.jl new file mode 100644 index 0000000..56c9850 --- /dev/null +++ b/test/test_upstream.jl @@ -0,0 +1,51 @@ +module TestExamplesUpstream + +using Test +using TrixiShallowWater + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples") + +# Start with a clean environment: remove output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +# Run upstream tests for each mesh and dimension to test compatibility with Trixi.jl +@testset "Upstream tests" begin +#! format: noindent + +# Run tests for TreeMesh +@testset "TreeMesh" begin + # Shallow water wet/dry 1D + @trixi_testset "1D-Test: elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "tree_1d_dgsem", + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.7259643614361866e-8, + 3.5519018243195145e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551010878661e-8, + 9.846474508971374e-16, + 3.844551077492042e-8, + ], + tspan=(0.0, 0.25), + boundary_condition=boundary_condition_slip_wall) + # 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 output directory +@test_nowarn rm(outdir, recursive = true) +end # Upstream tests + +end # module From 00247c4a1af0f80ce9fc26834cec5a8ad6571d5c Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 15 Jan 2024 09:46:01 +0100 Subject: [PATCH 20/48] fix ci --- .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 2d4787d..de6f84c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: coverage: true - uses: julia-actions/julia-processcoverage@v1 with: - directories: src, examples + directories: src,examples - uses: codecov/codecov-action@v3 with: files: lcov.info From d256bc72604dcf18bb39384320c90b135fe551f1 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 19 Jan 2024 13:10:21 +0100 Subject: [PATCH 21/48] Adjust comment --- src/TrixiShallowWater.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index e44cf50..7cfe6da 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -1,5 +1,7 @@ module TrixiShallowWater -# Decide between using Trixi: Trixi, import Trixi or using Trixi? +# We decided to import only Trixi.jl and qualify symbols explicitly with e.g. `Trixi.function_name`. +# For more information, see +# https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi: Trixi using MuladdMacro: @muladd using StaticArrays: SVector From 8184d681910c912aed2b0b9ccb51fd820c7bde04 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 19 Jan 2024 16:37:30 +0100 Subject: [PATCH 22/48] remove comments --- test/test_tree_1d_shallowwater_wet_dry.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/test_tree_1d_shallowwater_wet_dry.jl b/test/test_tree_1d_shallowwater_wet_dry.jl index 473bf05..e2cec1a 100644 --- a/test/test_tree_1d_shallowwater_wet_dry.jl +++ b/test/test_tree_1d_shallowwater_wet_dry.jl @@ -1,13 +1,9 @@ module TestExamples1DShallowWaterWetDry -# TODO: TrixiShallowWater: move any wet/dry tests to new package - using Test using Trixi using TrixiShallowWater -# TODO: Right now this is a local copy of the file from Trixi.jl. How can I use @trixi_testset & -# @test_trixi_include from Trixi.jl? include("test_trixi.jl") EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_1d_dgsem") From cd95eab6647c0e33b19a42bf4a33b842cf358026 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 10:24:38 +0100 Subject: [PATCH 23/48] do using Trixi instead of using Trixi : Trixi --- src/TrixiShallowWater.jl | 2 +- test/test_tree_1d.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 7cfe6da..3286603 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -2,7 +2,7 @@ module TrixiShallowWater # We decided to import only Trixi.jl and qualify symbols explicitly with e.g. `Trixi.function_name`. # For more information, see # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 -using Trixi: Trixi +using Trixi using MuladdMacro: @muladd using StaticArrays: SVector using Static: True, False diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index 7d96552..cfe94ff 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -1,6 +1,7 @@ module TestExamplesTree1D using Test +using Trixi using TrixiShallowWater include("test_trixi.jl") From 1c6dceecf41e3968011916b2f02cc75c78d96e46 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 10:53:44 +0100 Subject: [PATCH 24/48] update swe-1d --- src/equations/shallow_water_wet_dry_1d.jl | 112 +++++++--------------- 1 file changed, 35 insertions(+), 77 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 57313ff..8f4c84a 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -84,12 +84,12 @@ function ShallowWaterEquationsWetDry1D(; gravity_constant, H0 = zero(gravity_con end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry1D) = True() -function Trixi.varnames(::typeof(Trixi.cons2cons), ::ShallowWaterEquationsWetDry1D) +function Trixi.varnames(::typeof(cons2cons), ::ShallowWaterEquationsWetDry1D) ("h", "h_v", "b") end # Note, we use the total water height, H = h + b, as the first primitive variable for easier # visualization and setting initial conditions -function Trixi.varnames(::typeof(Trixi.cons2prim), ::ShallowWaterEquationsWetDry1D) +function Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry1D) ("H", "v", "b") end @@ -112,10 +112,7 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_convergence_test(x, t, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -133,10 +130,7 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.source_terms_convergence_test(u, x, t, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -148,10 +142,7 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_weak_blast_wave(x, t, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -176,10 +167,7 @@ For details see Section 9.2.5 of the book: return Trixi.boundary_condition_slip_wall(u_inner, orientation_or_normal, direction, x, t, surface_flux_function, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Calculate 1D flux for a single point @@ -187,8 +175,7 @@ end @inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux(u, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, - eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -208,10 +195,7 @@ Further details are available in the paper:#include("numerical_fluxes.jl") orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -241,10 +225,7 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end """ @@ -270,10 +251,7 @@ Further details on the hydrostatic reconstruction and its motivation can be foun equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl @@ -345,10 +323,8 @@ For further details see: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -367,9 +343,8 @@ Details are available in Eq. (4.1) in the paper: @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -389,9 +364,8 @@ Further details are available in Theorem 1 of the paper: @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), eps())) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -411,10 +385,8 @@ Further details on this hydrostatic reconstruction and its motivation can be fou @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, equations::ShallowWaterEquationsWetDry1D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end # TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl @@ -479,24 +451,19 @@ end # end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography -@inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, +@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry1D) - return (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, - eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography -@inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, +@inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry1D) - return (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) + return (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl @@ -534,23 +501,20 @@ end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # # Helper function to extract the velocity vector from the conservative variables # @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) # return Trixi.velocity(u, -# Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, +# ShallowWaterEquations1D(equations.gravity, equations.H0, # eps(), eps())) # end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2prim(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Convert conservative variables to entropy @@ -558,39 +522,36 @@ end # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2entropy(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry1D) return Trixi.entropy2cons(w, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Convert primitive to conservative variables @inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry1D) return Trixi.prim2cons(prim, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) # return Trixi.waterheight(u, -# Trixi.ShallowWaterEquations1D(equations.gravity, +# ShallowWaterEquations1D(equations.gravity, # equations.H0, eps(), eps())) # end # @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) # return Trixi.pressure(u, -# Trixi.ShallowWaterEquations1D(equations.gravity, equations.H0, +# ShallowWaterEquations1D(equations.gravity, equations.H0, # eps(), eps())) # end # @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) # return Trixi.waterheight_pressure(u, -# Trixi.ShallowWaterEquations1D(equations.gravity, +# ShallowWaterEquations1D(equations.gravity, # equations.H0, eps(), # eps())) # end @@ -603,16 +564,13 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_total(cons, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_kinetic(u, - Trixi.ShallowWaterEquations1D(equations.gravity, - equations.H0, eps(), - eps())) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end # Calculate potential energy for a conservative state `cons` From c99ee93093494c40aaf6ba8c23cfba4c307a694a Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 11:07:26 +0100 Subject: [PATCH 25/48] add swe-2d --- .../elixir_shallowwater_source_terms.jl | 59 ++ .../elixir_shallowwater_well_balanced.jl | 124 +++ .../tree_2d_dgsem/elixir_shallowwater_ec.jl | 120 +++ .../elixir_shallowwater_source_terms.jl | 60 ++ ...xir_shallowwater_source_terms_dirichlet.jl | 63 ++ .../tree_2d_dgsem/elixir_shallowwater_wall.jl | 83 ++ .../elixir_shallowwater_well_balanced.jl | 120 +++ .../elixir_shallowwater_well_balanced_wall.jl | 123 +++ .../elixir_shallowwater_dirichlet.jl | 81 ++ .../elixir_shallowwater_ec.jl | 124 +++ .../elixir_shallowwater_source_terms.jl | 67 ++ .../elixir_shallowwater_well_balanced.jl | 124 +++ src/TrixiShallowWater.jl | 6 +- src/equations/equations.jl | 1 + src/equations/shallow_water_wet_dry_2d.jl | 731 ++++++++++++++++++ 15 files changed, 1883 insertions(+), 3 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl create mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_ec.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_wall.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl create mode 100644 src/equations/shallow_water_wet_dry_2d.jl diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl new file mode 100644 index 0000000..20656cf --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -0,0 +1,59 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (0.0, 0.0) +coordinates_max = (sqrt(2.0), sqrt(2.0)) + +cells_per_dimension = (8, 8) + +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + +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 = 100 +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, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 2.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/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl new file mode 100644 index 0000000..11c8d68 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -0,0 +1,124 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function (set in the initial conditions) + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 3.0) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +# Note, this routine is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_discontinuous_well_balancedness` below. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# This setup a structured periodic mesh + +coordinates_min = (-2.0, -2.0) +coordinates_max = (2.0, 2.0) + +cells_per_dimension = (4, 4) + +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, 100.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Workaround to set a discontinuous bottom topography for debugging and testing. + +# alternative version of the initial conditinon used to setup a truly discontinuous +# bottom topography function for this academic testcase. +# 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 +# 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_well_balancedness(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_well_balancedness(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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/tree_2d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl new file mode 100644 index 0000000..56f0e16 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl @@ -0,0 +1,120 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +# Note, this initial condition is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_ec_discontinuous_bottom` below. +initial_condition = initial_condition_weak_blast_wave + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 4, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 2, + n_cells_max = 10_000) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 2.0) +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 +# bottom topography function and initial condition for this academic testcase of entropy conservation. +# The errors from the analysis callback are not important but `∑∂S/∂U ⋅ Uₜ` should be around machine roundoff +# 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 TreeMesh2D with initial_refinement_level=2. +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 4.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 5.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_ec_discontinuous_bottom(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 = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(dt = 0.2, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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/tree_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl new file mode 100644 index 0000000..a159acb --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -0,0 +1,60 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test # MMS EOC test + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_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 = 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 = 200, + 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, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl new file mode 100644 index 0000000..013895f --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -0,0 +1,63 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +boundary_condition = BoundaryConditionDirichlet(initial_condition) + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_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 = 10_000, + periodicity = false) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition, + 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 = 200, + 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, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_wall.jl b/examples/tree_2d_dgsem/elixir_shallowwater_wall.jl new file mode 100644 index 0000000..14bb8c9 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_wall.jl @@ -0,0 +1,83 @@ +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 3.25) + +# An initial condition with a bottom topography and a perturbation in the waterheight to test +# boundary_condition_slip_wall +function initial_condition_perturbation(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + + # Bottom topography + b = 1.5 * exp(-0.5 * ((x[1])^2 + (x[2])^2)) + # Waterheight perturbation + H = H + 0.5 * exp(-10.0 * ((x[1])^2 + (x[2])^2)) + + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_perturbation + +boundary_condition = boundary_condition_slip_wall + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a non-periodic 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_condition) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.25) +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 = 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) + +############################################################################### +# 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.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl new file mode 100644 index 0000000..54b0aa2 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -0,0 +1,120 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 3.25) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +# Note, this routine is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_discontinuous_well_balancedness` below. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 2, + n_cells_max = 10_000) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 100.0) +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 +# bottom topography function for this academic testcase of well-balancedness. +# 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 +# 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 TreeMesh2D with initial_refinement_level=2. +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_well_balancedness(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl new file mode 100644 index 0000000..d92008e --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl @@ -0,0 +1,123 @@ +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 3.25) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +# Note, this routine is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_discontinuous_well_balancedness` below. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +boundary_condition = boundary_condition_slip_wall + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 2, + 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, 100.0) +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 +# bottom topography function for this academic testcase of well-balancedness. +# 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 +# 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 TreeMesh2D with initial_refinement_level=2. +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_well_balancedness(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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_dirichlet.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl new file mode 100644 index 0000000..c987d98 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl @@ -0,0 +1,81 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a continuous +# bottom topography function (set in the initial conditions) + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 1.0, H0 = 3.0) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +boundary_condition_constant = BoundaryConditionDirichlet(initial_condition) +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), + 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) +default_mesh_file = joinpath(@__DIR__, "mesh_outer_circle.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition) + +############################################################################### +# ODE solvers, callbacks, etc. + +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) + +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) + +############################################################################### +# run the simulation + +# use a Runge-Kutta method with automatic (error based) time step size control +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-11, reltol = 1.0e-11, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl new file mode 100644 index 0000000..1415335 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl @@ -0,0 +1,124 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +# Note, this initial condition is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_ec_discontinuous_bottom` below. +initial_condition = initial_condition_weak_blast_wave + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +solver = DGSEM(polydeg = 6, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# This setup is for the curved, split form entropy conservation testing (needs periodic BCs) + +# Get the unstructured quad mesh from a file (downloads the file if not available locally) +default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 2.0) +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 +# bottom topography function and initial condition for this academic testcase of entropy conservation. +# The errors from the analysis callback are not important but `∑∂S/∂U ⋅ Uₜ` should be around machine roundoff +# 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_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 3.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 4.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_ec_discontinuous_bottom(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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_source_terms.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl new file mode 100644 index 0000000..95342b5 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -0,0 +1,67 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a periodic +# bottom topography function (set in the initial conditions) + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_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) +default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, 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 = 100 +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) + +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_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl new file mode 100644 index 0000000..e0b76c6 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -0,0 +1,124 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function (set in the initial conditions) + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 3.0) + +# An initial condition with constant total water height and zero velocities to test well-balancedness. +# Note, this routine is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_discontinuous_well_balancedness` below. +function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_well_balancedness + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_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) +default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Workaround to set a discontinuous bottom topography for debugging and testing. + +# alternative version of the initial conditinon used to setup a truly discontinuous +# bottom topography function for this academic testcase. +# 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 +# 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_well_balancedness(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_well_balancedness(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.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/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 3286603..3e8e339 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -10,8 +10,8 @@ using Static: True, False include("equations/equations.jl") # export types/functions that define the public API of TrixiShallowWater.jl -export ShallowWaterEquationsWetDry1D -# TODO: These function are currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl -#export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, min_max_speed_chen_noelle +export ShallowWaterEquationsWetDry1D, ShallowWaterEquationsWetDry2D + +export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, min_max_speed_chen_noelle end diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 4d31451..9fb8148 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -9,4 +9,5 @@ # Include files with actual implementations for different systems of equations. include("shallow_water_wet_dry_1d.jl") +include("shallow_water_wet_dry_2d.jl") end # @muladd diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl new file mode 100644 index 0000000..9fef63f --- /dev/null +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -0,0 +1,731 @@ +# 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""" + ShallowWaterEquationsWetDry2D(; gravity, H0 = 0, threshold_limiter = nothing, threshold_wet = nothing) + +Shallow water equations (SWE) in two space dimensions. The equations are given by +```math +\begin{aligned} + \frac{\partial h}{\partial t} + \frac{\partial}{\partial x}(h v_1) + + \frac{\partial}{\partial y}(h v_2) &= 0 \\ + \frac{\partial}{\partial t}(h v_1) + \frac{\partial}{\partial x}\left(h v_1^2 + \frac{g}{2}h^2\right) + + \frac{\partial}{\partial y}(h v_1 v_2) + g h \frac{\partial b}{\partial x} &= 0 \\ + \frac{\partial}{\partial t}(h v_2) + \frac{\partial}{\partial x}(h v_1 v_2) + + \frac{\partial}{\partial y}\left(h v_2^2 + \frac{g}{2}h^2\right) + g h \frac{\partial b}{\partial y} &= 0. +\end{aligned} +``` +The unknown quantities of the SWE are the water height ``h`` and the velocities ``\mathbf{v} = (v_1, v_2)^T``. +The gravitational constant is denoted by `g` and the (possibly) variable bottom topography function ``b(x,y)``. +Conservative variable water height ``h`` is measured from the bottom topography ``b``, therefore one +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. + +In addition to the unknowns, TrixiShallowWater.jl 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.jl's visualization tools will visualize the bottom topography by default. + +References for the SWE are many but a good introduction is available in Chapter 13 of the book: +- Randall J. LeVeque (2002) + Finite Volume Methods for Hyperbolic Problems + [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253) +""" +struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: Trixi.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 +# 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 ShallowWaterEquationsWetDry2D(; 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 + ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, threshold_wet) +end + +Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry2D) = True() +Trixi.varnames(::typeof(cons2cons), ::ShallowWaterEquationsWetDry2D) = ("h", "h_v1", "h_v2", "b") +# Note, we use the total water height, H = h + b, as the first primitive variable for easier +# visualization and setting initial conditions +Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry2D) = ("H", "v1", "v2", "b") + +# Set initial conditions at physical location `x` for time `t` +""" + initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) + +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 Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) + return Trixi.initial_condition_convergence_test(x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry2D) + +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). + +This manufactured solution source term is specifically designed for the bottom topography function +`b(x,y) = 2 + 0.5 * sin(sqrt(2)*pi*x) + 0.5 * sin(sqrt(2)*pi*y)` +as defined in [`initial_condition_convergence_test`](@ref). +""" +@inline function Trixi.source_terms_convergence_test(u, x, t, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.source_terms_convergence_test(u, x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry2D) + +A weak blast wave discontinuity useful for testing, e.g., total energy conservation. +Note for the shallow water equations to the total energy acts as a mathematical entropy function. +""" +function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry2D) + return Trixi.initial_condition_weak_blast_wave(x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function, + equations::ShallowWaterEquationsWetDry2D) +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::ShallowWaterEquationsWetDry2D) + Trixi.boundary_condition_slip_wall(u_inner, normal_direction::AbstractVector, + x, t, + surface_flux_function, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + boundary_condition_slip_wall(u_inner, orientation, direction, x, t, + surface_flux_function, equations::ShallowWaterEquationsWetDry2D) + +Should be used together with [`TreeMesh`](@ref). +""" +@inline function Trixi.boundary_condition_slip_wall(u_inner, orientation, + direction, x, t, + surface_flux_function, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.boundary_condition_slip_wall(u_inner, orientation, + direction, x, t, + surface_flux_function, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Calculate 1D flux for a single point +# Note, the bottom topography has no flux +@inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) + Trixi.flux(u, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) +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 Trixi.flux(u, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux(u, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + flux_nonconservative_wintermeyer_etal(u_ll, u_rr, + normal_direction_ll ::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +Non-symmetric two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the bottom topography [`ShallowWaterEquationsWetDry2D`](@ref). + +On curvilinear meshes, this nonconservative flux depends on both the +contravariant vector (normal direction) at the current node and the averaged +one. This is different from numerical fluxes used to discretize conservative +terms. + +Further details are available in 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 Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + flux_nonconservative_fjordholm_etal(u_ll, u_rr, + normal_direction_ll ::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +Non-symmetric two-point surface flux discretizing the nonconservative (source) term of +that contains the gradient of the bottom topography [`ShallowWaterEquationsWetDry2D`](@ref). + +On curvilinear meshes, this nonconservative flux depends on both the +contravariant vector (normal direction) at the current node and the averaged +one. This is different from numerical fluxes used to discretize conservative +terms. + +This contains additional terms compared to [`flux_nonconservative_wintermeyer_etal`](@ref) +that account for possible discontinuities in the bottom topography function. +Thus, this flux should be used in general at interfaces. For flux differencing volume terms, +[`flux_nonconservative_wintermeyer_etal`](@ref) is analytically equivalent but slightly +cheaper. + +Further details for the original finite volume formulation are available in +- Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) + Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography + [DOI: 10.1016/j.jcp.2011.03.042](https://doi.org/10.1016/j.jcp.2011.03.042) +and for curvilinear 2D case in 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 Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) +end + +""" + hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) + +A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness +for a general bottom topography [`ShallowWaterEquationsWetDry2D`](@ref). The reconstructed solution states +`u_ll_star` and `u_rr_star` variables are used to evaluate the surface numerical flux at the interface. +Use in combination with the generic numerical flux routine [`FluxHydrostaticReconstruction`](@ref). + +Further details for the hydrostatic reconstruction and its motivation can be found in +- Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) + A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows + [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) +""" +@inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + + +""" + hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + +A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness +for a general bottom topography of the [`ShallowWaterEquationsWetDry2D`](@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::ShallowWaterEquationsWetDry2D) + # 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 `ShallowWaterEquationsWetDry2D` 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::ShallowWaterEquationsWetDry2D) + flux_nonconservative_audusse_etal(u_ll, u_rr, + normal_direction_ll ::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. +The discretization uses the `hydrostatic_reconstruction_audusse_etal` on the conservative +variables. + +This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain +well-balanced for discontinuous bottom topographies [`ShallowWaterEquationsWetDry2D`](@ref). +Should be used together with [`FluxHydrostaticReconstruction`](@ref) and +[`hydrostatic_reconstruction_audusse_etal`](@ref) in the surface flux to ensure consistency. + +Further details for the hydrostatic reconstruction and its motivation can be found in +- Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) + A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows + [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) +""" +@inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# TODO: TrixiShallowWater: move wet/dry specific routine +""" + flux_nonconservative_chen_noelle(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + flux_nonconservative_chen_noelle(u_ll, u_rr, + normal_direction_ll ::AbstractVector, + normal_direction_average ::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + # 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::ShallowWaterEquationsWetDry2D) + # 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::ShallowWaterEquationsWetDry2D) + flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +!!! 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 [`ShallowWaterEquationsWetDry2D`](@ref). + +On curvilinear meshes, this nonconservative flux depends on both the +contravariant vector (normal direction) at the current node and the averaged +one. This is different from numerical fluxes used to discretize conservative +terms. + +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 Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + flux_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) + +Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography +is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. +For well-balancedness in the volume flux use [`flux_wintermeyer_etal`](@ref). + +Details are available in Eq. (4.1) in the paper: +- Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) + Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography + [DOI: 10.1016/j.jcp.2011.03.042](https://doi.org/10.1016/j.jcp.2011.03.042) +""" +@inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + flux_wintermeyer_etal(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) + +Total energy conservative (mathematical entropy for shallow water equations) split form. +When the bottom topography is nonzero this scheme will be well-balanced when used as a `volume_flux`. +The `surface_flux` should still use, e.g., [`flux_fjordholm_etal`](@ref). + +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 Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography +@inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) + return (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography +@inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) + return (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, + ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +""" + min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + 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::ShallowWaterEquationsWetDry2D) + 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 + +# Convert conservative variables to primitive +@inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.cons2prim(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Convert conservative variables to entropy +# Note, only the first three are the entropy variables, the fourth entry still +# just carries the bottom topography values for convenience +@inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.cons2entropy(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Convert entropy variables to conservative +@inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry2D) + return Trixi.entropy2cons(w, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Convert primitive to conservative variables +@inline function prim2cons(prim, equations::ShallowWaterEquationsWetDry2D) + return Trixi.prim2cons(prim, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.waterheight(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.pressure(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +@inline function waterheight_pressure(u, equations::ShallowWaterEquationsWetDry2D) + return waterheight(u, equations) * pressure(u, equations) +end + + + +# Entropy function for the shallow water equations is the total energy +@inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry2D) + Trixi.energy_total(cons, equations) +end + +# Calculate total energy for a conservative state `cons` +@inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry2D) + Trixi.energy_total +end + +# Calculate kinetic energy for a conservative state `cons` +@inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry2D) + Trixi.energy_kinetic(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + +# Calculate potential energy for a conservative state `cons` +@inline function energy_internal(cons, equations::ShallowWaterEquationsWetDry2D) + return energy_total(cons, equations) - energy_kinetic(cons, equations) +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 +@inline function Trixi.lake_at_rest_error(u, equations::ShallowWaterEquationsWetDry2D) + 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)) +end +end # @muladd From b612cc14e45dc3dfc333cd28df15d3d4fe414a6b Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 16:46:12 +0100 Subject: [PATCH 26/48] add wet/dry functionality, tests and examples --- Project.toml | 1 + .../elixir_shallowwater_conical_island.jl | 113 +++++ .../elixir_shallowwater_parabolic_bowl.jl | 118 +++++ ...ixir_shallowwater_well_balanced_wet_dry.jl | 206 +++++++++ .../elixir_shallowwater_beach.jl | 122 ++++++ .../elixir_shallowwater_parabolic_bowl.jl | 118 +++++ .../elixir_shallowwater_shock_capturing.jl | 117 +++++ ...ixir_shallowwater_well_balanced_wet_dry.jl | 171 ++++++++ .../elixir_shallowwater_conical_island.jl | 116 +++++ .../elixir_shallowwater_parabolic_bowl.jl | 121 +++++ ...ixir_shallowwater_well_balanced_wet_dry.jl | 205 +++++++++ .../elixir_shallowwater_ec_shockcapturing.jl | 129 ++++++ ...ixir_shallowwater_three_mound_dam_break.jl | 139 ++++++ ...xir_shallowwater_wall_bc_shockcapturing.jl | 100 +++++ src/TrixiShallowWater.jl | 14 +- src/callbacks_stage/callbacks_stage.jl | 9 + .../positivity_shallow_water.jl | 87 ++++ .../positivity_shallow_water_dg1d.jl | 87 ++++ .../positivity_shallow_water_dg2d.jl | 89 ++++ src/equations/numerical_fluxes.jl | 31 ++ src/equations/shallow_water_wet_dry_1d.jl | 366 ++++++++-------- src/equations/shallow_water_wet_dry_2d.jl | 302 ++++++++----- src/solvers/indicators.jl | 85 ++++ src/solvers/indicators_1d.jl | 115 +++++ src/solvers/indicators_2d.jl | 116 +++++ test/runtests.jl | 7 +- test/test_structured_2d.jl | 148 +++++++ test/test_tree_1d_shallowwater_wet_dry.jl | 182 ++++---- test/test_tree_2d_shallowwater_wet_dry.jl | 356 +++++++++++++++ test/test_unstructured_2d.jl | 414 ++++++++++++++++++ test/test_upstream.jl | 3 +- 31 files changed, 3808 insertions(+), 379 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl create mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl create mode 100644 examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_beach.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl create mode 100644 examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl create mode 100644 examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl create mode 100644 examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl create mode 100644 src/callbacks_stage/callbacks_stage.jl create mode 100644 src/callbacks_stage/positivity_shallow_water.jl create mode 100644 src/callbacks_stage/positivity_shallow_water_dg1d.jl create mode 100644 src/callbacks_stage/positivity_shallow_water_dg2d.jl create mode 100644 src/equations/numerical_fluxes.jl create mode 100644 src/solvers/indicators.jl create mode 100644 src/solvers/indicators_1d.jl create mode 100644 src/solvers/indicators_2d.jl create mode 100644 test/test_structured_2d.jl create mode 100644 test/test_tree_2d_shallowwater_wet_dry.jl create mode 100644 test/test_unstructured_2d.jl diff --git a/Project.toml b/Project.toml index 1ec3ece..ca24444 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Andrew R. Winters ", "Michael Schlottke- version = "0.1.0-pre" [deps] +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl new file mode 100644 index 0000000..6696130 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -0,0 +1,113 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 1.4) + +""" + initial_condition_conical_island(x, t, equations::ShallowWaterEquationsWetDry2D) + +Initial condition for the [`ShallowWaterEquationsWetDry2D`](@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::ShallowWaterEquationsWetDry2D) + # 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 ShallowWaterEquationsWetDry 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 new file mode 100644 index 0000000..1d90985 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -0,0 +1,118 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +""" + initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + 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 ShallowWaterEquationsWetDry 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 new file mode 100644 index 0000000..7d4d4c1 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -0,0 +1,206 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater +using Printf: @printf, @sprintf + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.812) + +""" + initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + 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 ShallowWaterEquationsWetDry 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::ShallowWaterEquationsWetDry2D) + 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 new file mode 100644 index 0000000..84cb809 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl @@ -0,0 +1,122 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.812) + +""" + initial_condition_beach(x, t, equations:: ShallowWaterEquationsWetDry1D) +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::ShallowWaterEquationsWetDry1D) + 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 ShallowWaterEquationsWetDry 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 new file mode 100644 index 0000000..5f40bc4 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -0,0 +1,118 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.81) + +""" + initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquationsWetDry1D) + +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::ShallowWaterEquationsWetDry1D) + 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 ShallowWaterEquationsWetDry 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_shock_capturing.jl b/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl new file mode 100644 index 0000000..bbb65d0 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl @@ -0,0 +1,117 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.812, H0 = 1.75) + +# Initial condition with a truly discontinuous velocity and bottom topography. +# Works as intended for TreeMesh1D with `initial_refinement_level=3`. 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_stone_throw_discontinuous_bottom(x, t, + equations::ShallowWaterEquationsWetDry1D) + + # Calculate primitive variables + + # flat lake + H = equations.H0 + + # Discontinuous velocity + v = 0.0 + if x[1] >= -0.75 && x[1] <= 0.0 + v = -1.0 + elseif x[1] >= 0.0 && x[1] <= 0.75 + v = 1.0 + end + + b = (1.5 / exp(0.5 * ((x[1] - 1.0)^2)) + + 0.75 / exp(0.5 * ((x[1] + 1.0)^2))) + + # Force a discontinuous bottom topography + if x[1] >= -1.5 && x[1] <= 0.0 + b = 0.5 + end + + return prim2cons(SVector(H, v, b), equations) +end + +initial_condition = initial_condition_stone_throw_discontinuous_bottom + +boundary_condition = boundary_condition_slip_wall + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal) +basis = LobattoLegendreBasis(4) + +indicator_sc = IndicatorHennemannGassner(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 [-3, 3] + +coordinates_min = -3.0 +coordinates_max = 3.0 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition) + +############################################################################### +# ODE solver + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + lake_at_rest_error)) + +# Enable in-situ visualization with a new plot generated every 50 time steps +# and we explicitly pass that the plot data will be one-dimensional +# visualization = VisualizationCallback(interval=50, plot_data_creator=PlotData1D) + +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)#, +# visualization) + +############################################################################### +# run the simulation + +# use a Runge-Kutta method with automatic (error based) time step size control +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-7, reltol = 1.0e-7, + ode_default_options()..., 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 new file mode 100644 index 0000000..3f11b47 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -0,0 +1,171 @@ + +using OrdinaryDiffEq +using Trixi +using Printf: @printf, @sprintf +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.812) + +""" + initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquationsWetDry1D) + +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::ShallowWaterEquationsWetDry1D) + 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 ShallowWaterEquationsWetDry 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::ShallowWaterEquationsWetDry1D) + 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 new file mode 100644 index 0000000..b688e59 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -0,0 +1,116 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 1.4) + +""" + initial_condition_conical_island(x, t, equations::ShallowWaterEquationsWetDry2D) + +Initial condition for the [`ShallowWaterEquationsWetDry2D`](@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::ShallowWaterEquationsWetDry2D) + # 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 ShallowWaterEquationsWetDry 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 new file mode 100644 index 0000000..1aae708 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -0,0 +1,121 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +""" + initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + 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 ShallowWaterEquationsWetDry 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) +basis = LobattoLegendreBasis(3) + +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_well_balanced_wet_dry.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl new file mode 100644 index 0000000..8135e28 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -0,0 +1,205 @@ + +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater +using Printf: @printf, @sprintf + +############################################################################### +# Semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.812) + +""" + initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + 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 ShallowWaterEquationsWetDry 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::ShallowWaterEquationsWetDry2D) + 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_ec_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl new file mode 100644 index 0000000..2b550c6 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl @@ -0,0 +1,129 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81) + +# Note, this initial condition is used to compute errors in the analysis callback but the initialization is +# overwritten by `initial_condition_ec_discontinuous_bottom` below. +initial_condition = initial_condition_weak_blast_wave + +############################################################################### +# Get the DG approximation space + +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +polydeg = 6 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorHennemannGassner(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) + +############################################################################### +# This setup is for the curved, split form entropy conservation testing (needs periodic BCs) + +# Get the unstructured quad mesh from a file (downloads the file if not available locally) +default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 2.0) +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 +# bottom topography function and initial condition for this academic testcase of entropy conservation. +# The errors from the analysis callback are not important but `∑∂S/∂U ⋅ Uₜ` should be around machine roundoff +# 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_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquationsWetDry2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 3.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 4.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, 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_ec_discontinuous_bottom(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 = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +stepsize_callback = StepsizeCallback(cfl = 3.0) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + 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_three_mound_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl new file mode 100644 index 0000000..54e93b5 --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl @@ -0,0 +1,139 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.81, H0 = 1.875, + threshold_limiter = 1e-12, threshold_wet = 1e-14) + +""" + initial_condition_three_mounds(x, t, equations::ShallowWaterEquationsWetDry2D) + +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::ShallowWaterEquationsWetDry2D) + + # 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 ShallowWaterEquationsWetDry 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::ShallowWaterEquationsWetDry2D) + # 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) + +default_meshfile = joinpath(@__DIR__, "mesh_three_mound.mesh") + +isfile(default_meshfile) || + download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", + default_meshfile) + +meshfile = default_meshfile + +mesh = UnstructuredMesh2D(meshfile) + +# 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_wall_bc_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl new file mode 100644 index 0000000..c7b80be --- /dev/null +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl @@ -0,0 +1,100 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi +using TrixiShallowWater + +############################################################################### +# semidiscretization of the shallow water equations with a continuous +# bottom topography function + +equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.812, H0 = 2.0) + +function initial_condition_stone_throw(x, t, equations::ShallowWaterEquationsWetDry2D) + # Set up polar coordinates + inicenter = SVector(0.15, 0.15) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Calculate primitive variables + H = equations.H0 + v1 = r < 0.6 ? 2.0 : 0.0 + v2 = r < 0.6 ? -2.0 : 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + + return prim2cons(SVector(H, v1, v2, b), equations) +end + +initial_condition = initial_condition_stone_throw + +boundary_condition = Dict(:OuterCircle => boundary_condition_slip_wall) + +############################################################################### +# Get the DG approximation space + +surface_flux = (FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +polydeg = 6 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.waterheight) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) + +############################################################################### +# Get the unstructured quad mesh from a file (downloads the file if not available locally) + +default_mesh_file = joinpath(@__DIR__, "mesh_outer_circle.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition) + +############################################################################### +# ODE solvers, callbacks, etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +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) + +############################################################################### +# 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, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 3e8e339..45fd00e 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -1,17 +1,29 @@ module TrixiShallowWater +# TODO: rewrite this # We decided to import only Trixi.jl and qualify symbols explicitly with e.g. `Trixi.function_name`. # For more information, see # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi +# Import additional symbols that are not export by Trixi +import Trixi: get_node_vars, set_node_vars! using MuladdMacro: @muladd using StaticArrays: SVector using Static: True, False +using LinearAlgebra: norm include("equations/equations.jl") +include("equations/numerical_fluxes.jl") +include("callbacks_stage/callbacks_stage.jl") +include("solvers/indicators.jl") # export types/functions that define the public API of TrixiShallowWater.jl export ShallowWaterEquationsWetDry1D, ShallowWaterEquationsWetDry2D -export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, min_max_speed_chen_noelle +export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, + min_max_speed_chen_noelle, + flux_hll_chen_noelle + +export PositivityPreservingLimiterShallowWater +export IndicatorHennemannGassnerShallowWater end diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl new file mode 100644 index 0000000..ddc596a --- /dev/null +++ b/src/callbacks_stage/callbacks_stage.jl @@ -0,0 +1,9 @@ +# 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 + +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 new file mode 100644 index 0000000..6145762 --- /dev/null +++ b/src/callbacks_stage/positivity_shallow_water.jl @@ -0,0 +1,87 @@ +# 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 + +""" + 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::Trixi.AbstractSemidiscretization, + t) + u = Trixi.wrap_array(u_ode, semi) + Trixi.@trixi_timeit Trixi.timer() "positivity-preserving limiter" limiter_shallow_water!(u, + limiter!.variables, + Trixi.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{ShallowWaterEquationsWetDry1D, + ShallowWaterEquationsWetDry2D}, + 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{ShallowWaterEquationsWetDry1D, + ShallowWaterEquationsWetDry2D}, + 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 new file mode 100644 index 0000000..3494662 --- /dev/null +++ b/src/callbacks_stage/positivity_shallow_water_dg1d.jl @@ -0,0 +1,87 @@ +# 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 + +function limiter_shallow_water!(u, threshold::Real, variable, + mesh::Trixi.AbstractMesh{1}, + equations::ShallowWaterEquationsWetDry1D, + dg::DGSEM, cache) + @unpack weights = dg.basis + + Trixi.@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 + Trixi.@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 new file mode 100644 index 0000000..812f453 --- /dev/null +++ b/src/callbacks_stage/positivity_shallow_water_dg2d.jl @@ -0,0 +1,89 @@ +# 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 + +function limiter_shallow_water!(u, threshold::Real, variable, + mesh::Trixi.AbstractMesh{2}, + equations::ShallowWaterEquationsWetDry2D, dg::DGSEM, + cache) + @unpack weights = dg.basis + + Trixi.@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 + Trixi.@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/numerical_fluxes.jl b/src/equations/numerical_fluxes.jl new file mode 100644 index 0000000..7aae0f8 --- /dev/null +++ b/src/equations/numerical_fluxes.jl @@ -0,0 +1,31 @@ +# 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 + +# This file contains general numerical fluxes that are not specific to certain equations + +# 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) +end diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 8f4c84a..1416a7b 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -93,8 +93,6 @@ function Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry1D) ("H", "v", "b") end -# TODO: Remove thresholds from ShallowWaterEquations1D after they have been moved - # This equation set extends the basic ShallowWaterEquations1D from Trixi.jl with additional functionality # for wet/dry transitions. Since many functions correspond to the fully wet case, we make use of the # exisiting functionality and introduce a number of wrapper functions, that dispatch to the @@ -112,7 +110,8 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_convergence_test(x, t, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -130,7 +129,8 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.source_terms_convergence_test(u, x, t, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -142,7 +142,8 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_weak_blast_wave(x, t, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -164,10 +165,22 @@ For details see Section 9.2.5 of the book: x, t, surface_flux_function, equations::ShallowWaterEquationsWetDry1D) - return Trixi.boundary_condition_slip_wall(u_inner, orientation_or_normal, direction, - x, t, - surface_flux_function, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + # This can not be dispatched, when Flux Hydrostactic reconstruction is used + # create the "external" boundary solution state + u_boundary = SVector(u_inner[1], + -u_inner[2], + u_inner[3]) + + # calculate the boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation_or_normal, + equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation_or_normal, + equations) + end + + return flux end # Calculate 1D flux for a single point @@ -195,7 +208,8 @@ Further details are available in the paper:#include("numerical_fluxes.jl") orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -225,7 +239,8 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end """ @@ -251,56 +266,56 @@ Further details on the hydrostatic reconstruction and its motivation can be foun equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end -# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl -# """ -# flux_nonconservative_chen_noelle(u_ll, u_rr, -# orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) +""" + flux_nonconservative_chen_noelle(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) -# Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. -# The discretization uses the `hydrostatic_reconstruction_chen_noelle` on the conservative -# variables. +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. +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::ShallowWaterEquationsWetDry1D) +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::ShallowWaterEquationsWetDry1D) -# # Pull the water height and bottom topography on the left -# h_ll, _, b_ll = u_ll -# h_rr, _, b_rr = u_rr + # 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 + 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)) + 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) + # 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] + # 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 + 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, @@ -324,7 +339,7 @@ For further details see: equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.H0)) end """ @@ -344,7 +359,7 @@ Details are available in Eq. (4.1) in the paper: equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.H0)) end """ @@ -365,7 +380,7 @@ Further details are available in Theorem 1 of the paper: equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.H0)) end """ @@ -386,130 +401,138 @@ Further details on this hydrostatic reconstruction and its motivation can be fou equations::ShallowWaterEquationsWetDry1D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, ShallowWaterEquations1D(equations.gravity, - equations.H0)) -end - -# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl -# """ -# hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) - -# A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness -# for a general bottom topography of the [`ShallowWaterEquationsWetDry1D`](@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::ShallowWaterEquationsWetDry1D) -# # 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 `ShallowWaterEquationsWetDry1D` 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 + equations.H0)) +end + +""" + hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + +A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness +for a general bottom topography of the [`ShallowWaterEquationsWetDry1D`](@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::ShallowWaterEquationsWetDry1D) + # 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 `ShallowWaterEquationsWetDry1D` 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 # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry1D) - return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations::ShallowWaterEquationsWetDry1D) + return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry1D) + equations::ShallowWaterEquationsWetDry1D) return (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, equations.H0)) end -# TODO: This function is currently exported by Trixi.jl. Needs to be uncommented when removed from Trixi.jl -# """ -# min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, -# equations::ShallowWaterEquationsWetDry1D) +""" + min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) -# 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. +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::ShallowWaterEquationsWetDry1D) -# # Get the velocity quantities -# v_ll = velocity(u_ll, equations) -# v_rr = velocity(u_rr, equations) +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) +""" +# Since FluxHLL is dispatched on ShallowWaterEquations1D, we also need to dispatch this wave speed +# estimate on ShallowWaterEquations1D. +@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return min_max_speed_chen_noelle(u_ll, u_rr, orientation, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end -# # Calculate the wave celerity on the left and right -# h_ll = waterheight(u_ll, equations) -# h_rr = waterheight(u_rr, equations) +@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) -# a_ll = sqrt(equations.gravity * h_ll) -# a_rr = sqrt(equations.gravity * h_rr) + # Calculate the wave celerity on the left and right + h_ll = Trixi.waterheight(u_ll, equations) + h_rr = Trixi.waterheight(u_rr, equations) -# λ_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))) + a_ll = sqrt(equations.gravity * h_ll) + a_rr = sqrt(equations.gravity * h_rr) -# return λ_min, λ_max -# end + λ_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 @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end -# # Helper function to extract the velocity vector from the conservative variables -# @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) -# return Trixi.velocity(u, -# ShallowWaterEquations1D(equations.gravity, equations.H0, -# eps(), eps())) -# end +# Helper function to extract the velocity vector from the conservative variables +@inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.velocity(u, + ShallowWaterEquations1D(equations.gravity, equations.H0)) +end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) @@ -537,24 +560,22 @@ end ShallowWaterEquations1D(equations.gravity, equations.H0)) end -# @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) -# return Trixi.waterheight(u, -# ShallowWaterEquations1D(equations.gravity, -# equations.H0, eps(), eps())) -# end +@inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.waterheight(u, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end -# @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) -# return Trixi.pressure(u, -# ShallowWaterEquations1D(equations.gravity, equations.H0, -# eps(), eps())) -# end +@inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.pressure(u, + ShallowWaterEquations1D(equations.gravity, equations.H0)) +end -# @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) -# return Trixi.waterheight_pressure(u, -# ShallowWaterEquations1D(equations.gravity, -# equations.H0, eps(), -# eps())) -# end +@inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) + return Trixi.waterheight_pressure(u, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end # Entropy function for the shallow water equations is the total energy @inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry1D) @@ -570,7 +591,8 @@ end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_kinetic(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + ShallowWaterEquations1D(equations.gravity, + equations.H0)) end # Calculate potential energy for a conservative state `cons` diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 9fef63f..67148da 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -53,9 +53,8 @@ References for the SWE are many but a good introduction is available in Chapter Finite Volume Methods for Hyperbolic Problems [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253) """ -struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: Trixi.AbstractShallowWaterEquations{2, 4} - # TODO: TrixiShallowWater: where should the `threshold_limiter` and `threshold_wet` live? - # how to "properly" export these constants across the two packages? +struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: + Trixi.AbstractShallowWaterEquations{2, 4} gravity::RealT # gravitational constant H0::RealT # constant "lake-at-rest" total water height # `threshold_limiter` used in `PositivityPreservingLimiterShallowWater` on water height, @@ -74,7 +73,8 @@ end # well-balancedness test cases. # Strict default values for thresholds that performed well in many numerical experiments function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_constant), - threshold_limiter = nothing, threshold_wet = nothing) + threshold_limiter = nothing, + threshold_wet = nothing) T = promote_type(typeof(gravity_constant), typeof(H0)) if threshold_limiter === nothing threshold_limiter = 500 * eps(T) @@ -82,14 +82,17 @@ function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_con if threshold_wet === nothing threshold_wet = 5 * eps(T) end - ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, threshold_wet) + ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, + threshold_wet) end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry2D) = True() -Trixi.varnames(::typeof(cons2cons), ::ShallowWaterEquationsWetDry2D) = ("h", "h_v1", "h_v2", "b") +Trixi.varnames(::typeof(cons2cons), ::ShallowWaterEquationsWetDry2D) = ("h", "h_v1", + "h_v2", "b") # Note, we use the total water height, H = h + b, as the first primitive variable for easier # visualization and setting initial conditions -Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry2D) = ("H", "v1", "v2", "b") +Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry2D) = ("H", "v1", "v2", + "b") # Set initial conditions at physical location `x` for time `t` """ @@ -99,8 +102,11 @@ 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 Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) - return Trixi.initial_condition_convergence_test(x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) +function Trixi.initial_condition_convergence_test(x, t, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.initial_condition_convergence_test(x, t, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -115,8 +121,10 @@ This manufactured solution source term is specifically designed for the bottom t as defined in [`initial_condition_convergence_test`](@ref). """ @inline function Trixi.source_terms_convergence_test(u, x, t, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.source_terms_convergence_test(u, x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations::ShallowWaterEquationsWetDry2D) + return Trixi.source_terms_convergence_test(u, x, t, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -125,8 +133,11 @@ end A weak blast wave discontinuity useful for testing, e.g., total energy conservation. Note for the shallow water equations to the total energy acts as a mathematical entropy function. """ -function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry2D) - return Trixi.initial_condition_weak_blast_wave(x, t, ShallowWaterEquations2D(equations.gravity, equations.H0)) +function Trixi.initial_condition_weak_blast_wave(x, t, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.initial_condition_weak_blast_wave(x, t, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -141,14 +152,27 @@ For details see Section 9.2.5 of the book: 1st edition ISBN 0471987662 """ -@inline function boundary_condition_slip_wall(u_inner, normal_direction::AbstractVector, - x, t, - surface_flux_function, - equations::ShallowWaterEquationsWetDry2D) - Trixi.boundary_condition_slip_wall(u_inner, normal_direction::AbstractVector, - x, t, - surface_flux_function, - ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.boundary_condition_slip_wall(u_inner, + normal_direction::AbstractVector, + x, t, + surface_flux_function, + equations::ShallowWaterEquationsWetDry2D) + # normalize the outward pointing direction + normal = normal_direction / norm(normal_direction) + + # compute the normal velocity + u_normal = normal[1] * u_inner[2] + normal[2] * u_inner[3] + + # create the "external" boundary solution state + u_boundary = SVector(u_inner[1], + u_inner[2] - 2.0 * u_normal * normal[1], + u_inner[3] - 2.0 * u_normal * normal[2], + u_inner[4]) + + # calculate the boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + + return flux end """ @@ -158,26 +182,39 @@ end Should be used together with [`TreeMesh`](@ref). """ @inline function Trixi.boundary_condition_slip_wall(u_inner, orientation, - direction, x, t, - surface_flux_function, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.boundary_condition_slip_wall(u_inner, orientation, - direction, x, t, - surface_flux_function, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + direction, x, t, + surface_flux_function, + equations::ShallowWaterEquationsWetDry2D) + ## get the appropriate normal vector from the orientation + if orientation == 1 + u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4]) + else # orientation == 2 + u_boundary = SVector(u_inner[1], u_inner[2], -u_inner[3], u_inner[4]) + end + + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end + + return flux end # Calculate 1D flux for a single point # Note, the bottom topography has no flux -@inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) - Trixi.flux(u, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux(u, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux(u, orientation, ShallowWaterEquations2D(equations.gravity, equations.H0)) 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 Trixi.flux(u, normal_direction::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) - Trixi.flux(u, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux(u, normal_direction, + ShallowWaterEquations2D(equations.gravity, equations.H0)) end """ @@ -202,20 +239,23 @@ Further details are available in the paper: 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 Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end @inline function Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + normal_direction_ll, + normal_direction_average, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -250,20 +290,23 @@ and for curvilinear 2D case in the paper: 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 Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, - ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end @inline function Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + normal_direction_ll, + normal_direction_average, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -281,12 +324,12 @@ Further details for the hydrostatic reconstruction and its motivation can be fou [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) """ @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - equations::ShallowWaterEquationsWetDry2D) + equations::ShallowWaterEquationsWetDry2D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end - """ hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) @@ -371,22 +414,25 @@ Further details for the hydrostatic reconstruction and its motivation can be fou A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows [DOI: 10.1137/S1064827503431090](https://doi.org/10.1137/S1064827503431090) """ -@inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer, ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end @inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + normal_direction_ll, + normal_direction_average, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end -# TODO: TrixiShallowWater: move wet/dry specific routine """ flux_nonconservative_chen_noelle(u_ll, u_rr, orientation::Integer, @@ -513,20 +559,23 @@ For further details see: curvilinear meshes [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) """ -@inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, - ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end @inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + normal_direction_ll, + normal_direction_average, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -543,15 +592,16 @@ Details are available in Eq. (4.1) in the paper: [DOI: 10.1016/j.jcp.2011.03.042](https://doi.org/10.1016/j.jcp.2011.03.042) """ @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, ShallowWaterEquations2D(equations.gravity, equations.H0)) end @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -569,30 +619,36 @@ Further details are available in Theorem 1 of the paper: [DOI: 10.1016/j.jcp.2017.03.036](https://doi.org/10.1016/j.jcp.2017.03.036) """ @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end -@inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) - return Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, + normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry2D) + orientation_or_normal_direction, + equations::ShallowWaterEquationsWetDry2D) return (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + orientation_or_normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry2D) + equations::ShallowWaterEquationsWetDry2D) return (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end """ @@ -613,11 +669,20 @@ the reference below. The definition of the wave speeds are given in Equation (2. A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ +# Since FluxHLL is dispatched on ShallowWaterEquations1D, we also need to dispatch this wave speed +# estimate on ShallowWaterEquations1D. @inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) - h_ll = waterheight(u_ll, equations) + return min_max_speed_chen_noelle(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquations2D) + h_ll = Trixi.waterheight(u_ll, equations) v1_ll, v2_ll = velocity(u_ll, equations) - h_rr = waterheight(u_rr, equations) + h_rr = Trixi.waterheight(u_rr, equations) v1_rr, v2_rr = velocity(u_rr, equations) a_ll = sqrt(equations.gravity * h_ll) @@ -636,9 +701,16 @@ end @inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) - h_ll = waterheight(u_ll, equations) + return min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquations2D) + h_ll = Trixi.waterheight(u_ll, equations) v1_ll, v2_ll = velocity(u_ll, equations) - h_rr = waterheight(u_rr, equations) + h_rr = Trixi.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] @@ -655,6 +727,17 @@ end return λ_min, λ_max end +@inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.max_abs_speeds(u, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +# Helper function to extract the velocity vector from the conservative variables +@inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.velocity(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) +end + # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.cons2prim(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) @@ -664,33 +747,35 @@ end # Note, only the first three are the entropy variables, the fourth entry still # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.cons2entropy(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.cons2entropy(u, + ShallowWaterEquations2D(equations.gravity, equations.H0)) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry2D) - return Trixi.entropy2cons(w, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.entropy2cons(w, + ShallowWaterEquations2D(equations.gravity, equations.H0)) end # Convert primitive to conservative variables -@inline function prim2cons(prim, equations::ShallowWaterEquationsWetDry2D) - return Trixi.prim2cons(prim, ShallowWaterEquations2D(equations.gravity, equations.H0)) +@inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry2D) + return Trixi.prim2cons(prim, + ShallowWaterEquations2D(equations.gravity, equations.H0)) end @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.waterheight(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.waterheight(u, + ShallowWaterEquations2D(equations.gravity, equations.H0)) end @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.pressure(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) end -@inline function waterheight_pressure(u, equations::ShallowWaterEquationsWetDry2D) - return waterheight(u, equations) * pressure(u, equations) +@inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry2D) + return Trixi.waterheight(u, equations) * Trixi.pressure(u, equations) end - - # Entropy function for the shallow water equations is the total energy @inline function Trixi.entropy(cons, equations::ShallowWaterEquationsWetDry2D) Trixi.energy_total(cons, equations) @@ -698,7 +783,7 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry2D) - Trixi.energy_total + Trixi.energy_total(cons, ShallowWaterEquations2D(equations.gravity, equations.H0)) end # Calculate kinetic energy for a conservative state `cons` @@ -707,16 +792,13 @@ end end # Calculate potential energy for a conservative state `cons` -@inline function energy_internal(cons, equations::ShallowWaterEquationsWetDry2D) +@inline function Trixi.energy_internal(cons, equations::ShallowWaterEquationsWetDry2D) return energy_total(cons, equations) - energy_kinetic(cons, equations) 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 @inline function Trixi.lake_at_rest_error(u, equations::ShallowWaterEquationsWetDry2D) h, _, _, b = u diff --git a/src/solvers/indicators.jl b/src/solvers/indicators.jl new file mode 100644 index 0000000..270595f --- /dev/null +++ b/src/solvers/indicators.jl @@ -0,0 +1,85 @@ +# 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 + +""" + 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} <: + Trixi.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::Trixi.AbstractShallowWaterEquations, + basis; + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable) + alpha_max, alpha_min = promote(alpha_max, alpha_min) + cache = Trixi.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"), + ] + Trixi.summary_box(io, "IndicatorHennemannGassnerShallowWater", setup) + end +end + +include("indicators_1d.jl") +include("indicators_2d.jl") +end # @muladd diff --git a/src/solvers/indicators_1d.jl b/src/solvers/indicators_1d.jl new file mode 100644 index 0000000..b8766fa --- /dev/null +++ b/src/solvers/indicators_1d.jl @@ -0,0 +1,115 @@ +# 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 + +# 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. +function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, + 3}, + mesh, + equations::ShallowWaterEquationsWetDry1D, + 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 + + Trixi.@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 + Trixi.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 + Trixi.apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) + end + + return alpha +end +end # @muladd diff --git a/src/solvers/indicators_2d.jl b/src/solvers/indicators_2d.jl new file mode 100644 index 0000000..6622d24 --- /dev/null +++ b/src/solvers/indicators_2d.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 + +# 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. +function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, + 4}, + mesh, + equations::ShallowWaterEquationsWetDry2D, + 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 + + Trixi.@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 + Trixi.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 + Trixi.apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) + end + + return alpha +end +end # @muladd diff --git a/test/runtests.jl b/test/runtests.jl index 8a0e590..f3de815 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,6 +13,9 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin @time if TRIXI_TEST == "all" include("test_tree_1d_shallowwater_wet_dry.jl") + include("test_tree_2d_shallowwater_wet_dry.jl") + include("test_unstructured_2d.jl") + include("test_structured_2d.jl") include("test_unit.jl") end @@ -23,8 +26,8 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @test !(name in names(TrixiShallowWater)) end end - + # Run upstream tests for each mesh and dimension to test compatibility with Trixi.jl - include("test_upstream.jl") + include("test_upstream.jl") end end diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl new file mode 100644 index 0000000..6312471 --- /dev/null +++ b/test/test_structured_2d.jl @@ -0,0 +1,148 @@ +module TestExamplesStructuredMesh2D + +using Test +using Trixi +using TrixiShallowWater + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "structured_2d_dgsem") + +# Start with a clean environment: remove TrixiShallowWater.jl output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +@testset "StructuredMesh2D" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0017285599436729316, + 0.025584610912606776, + 0.028373834961180594, + 6.274146767730866e-5, + ], + linf=[ + 0.012972309788264802, + 0.108283714215621, + 0.15831585777928936, + 0.00018196759554722775, + ], + 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_shallowwater_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.7920927046419308, + 9.92129670988898e-15, + 1.0118635033124588e-14, + 0.7920927046419308, + ], + linf=[ + 2.408429868800133, + 5.5835419986809516e-14, + 5.448874313931364e-14, + 2.4084298688001335, + ], + 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_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 +end + +# Clean up afterwards: delete TrixiShallowWater.jl output directory +@test_nowarn rm(outdir, recursive = true) + +end # module diff --git a/test/test_tree_1d_shallowwater_wet_dry.jl b/test/test_tree_1d_shallowwater_wet_dry.jl index e2cec1a..2435fa4 100644 --- a/test/test_tree_1d_shallowwater_wet_dry.jl +++ b/test/test_tree_1d_shallowwater_wet_dry.jl @@ -118,32 +118,31 @@ end end end -# TODO: Activate test when Wet_Dry functionality is moved -# @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_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"), @@ -319,74 +318,71 @@ end end end -# TODO: Activate test when Wet_Dry functionality is moved -# @trixi_testset "elixir_shallowwater_shock_capturing.jl" begin -# @test_trixi_include(joinpath(EXAMPLES_DIR, -# "elixir_shallowwater_shock_capturing.jl"), -# l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], -# linf=[ -# 1.1209754279344226, -# 1.3230788645853582, -# 0.8646939843534251, -# ], -# 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_shallowwater_shock_capturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_shock_capturing.jl"), + l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], + linf=[ + 1.1209754279344226, + 1.3230788645853582, + 0.8646939843534251, + ], + 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 -# TODO: Activate test when Wet_Dry functionality is moved -# @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_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 -# TODO: Activate test when Wet_Dry functionality is moved -# @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_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 end end # module diff --git a/test/test_tree_2d_shallowwater_wet_dry.jl b/test/test_tree_2d_shallowwater_wet_dry.jl new file mode 100644 index 0000000..50cf0e6 --- /dev/null +++ b/test/test_tree_2d_shallowwater_wet_dry.jl @@ -0,0 +1,356 @@ +module TestExamples2DShallowWaterWetDry + +using Test +using Trixi +using TrixiShallowWater + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_2d_dgsem") + +@testset "Shallow Water Wet Dry" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[ + 0.991181203601035, + 0.734130029040644, + 0.7447696147162621, + 0.5875351036989047, + ], + linf=[ + 2.0117744577945413, + 2.9962317608172127, + 2.6554999727293653, + 3.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_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.9130579602987144, + 1.0602847041965408e-14, + 1.082225645390032e-14, + 0.9130579602987147, + ], + linf=[ + 2.113062037615659, + 4.6613606802974e-14, + 5.4225772771633196e-14, + 2.1130620376156584, + ], + 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_well_balanced_wall.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_wall.jl"), + l2=[ + 0.9130579602987144, + 1.0602847041965408e-14, + 1.082225645390032e-14, + 0.9130579602987147, + ], + linf=[ + 2.113062037615659, + 4.6613606802974e-14, + 5.4225772771633196e-14, + 2.1130620376156584, + ], + 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_well_balanced.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.9130579602987147, + 9.68729463970494e-15, + 9.694538537436981e-15, + 0.9130579602987147, + ], + linf=[ + 2.1130620376156584, + 2.3875905654916432e-14, + 2.2492839032269154e-14, + 2.1130620376156584, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_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 + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.9130579602987146, + 1.0323158914614244e-14, + 1.0276096319430528e-14, + 0.9130579602987147, + ], + linf=[ + 2.11306203761566, + 4.063916419044386e-14, + 3.694484044448245e-14, + 2.1130620376156584, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + 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 + +@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=[ + 0.001868474306068482, + 0.01731687445878443, + 0.017649083171490863, + 6.274146767717023e-5, + ], + linf=[ + 0.016962486402209986, + 0.08768628853889782, + 0.09038488750767648, + 0.0001819675955490041, + ], + 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_source_terms_dirichlet.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0018746929418489125, + 0.017332321628469628, + 0.01634953679145536, + 6.274146767717023e-5, + ], + linf=[ + 0.016262353691956388, + 0.08726160620859424, + 0.09043621801418844, + 0.0001819675955490041, + ], + 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_source_terms.jl with flux_hll" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0018957692481057034, + 0.016943229710439864, + 0.01755623297390675, + 6.274146767717414e-5, + ], + linf=[ + 0.015156105797771602, + 0.07964811135780492, + 0.0839787097210376, + 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 flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.002471853426064005, + 0.05619168608950033, + 0.11844727575152562, + 6.274146767730281e-5, + ], + linf=[ + 0.014332922987500218, + 0.2141204806174546, + 0.5392313755637872, + 0.0001819675955490041, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + 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 + +@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=[ + 0.13517233723296504, + 0.20010876311162215, + 0.20010876311162223, + 2.719538414346464e-7, + ], + linf=[ + 0.5303607982988336, + 0.5080989745682338, + 0.5080989745682352, + 1.1301675764130437e-6, + ], + 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_unstructured_2d.jl b/test/test_unstructured_2d.jl new file mode 100644 index 0000000..79e491f --- /dev/null +++ b/test/test_unstructured_2d.jl @@ -0,0 +1,414 @@ +module TestExamplesUnstructuredMesh2D + +using Test +using Trixi +using TrixiShallowWater + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "unstructured_2d_dgsem") + +# Start with a clean environment: remove Trixi.jl output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +@testset "UnstructuredMesh2D" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[ + 0.6106939484178353, + 0.48586236867426724, + 0.48234490854514356, + 0.29467422718511727, + ], + linf=[ + 2.775979948281604, + 3.1721242154451548, + 3.5713448319601393, + 2.052861364219655, + ], + 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_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 1.2164292510839076, + 2.6118925543469468e-12, + 1.1636046671473883e-12, + 1.2164292510839079, + ], + linf=[ + 1.5138512282315846, + 4.998482888288039e-11, + 2.0246214978154587e-11, + 1.513851228231574, + ], + 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_well_balanced.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 1.2164292510839085, + 1.2643106818778908e-12, + 7.46884905098358e-13, + 1.2164292510839079, + ], + linf=[ + 1.513851228231562, + 1.6287765844373185e-11, + 6.8766999132716964e-12, + 1.513851228231574, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.2)) + # 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_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 1.2164292510839083, + 2.590643638636187e-12, + 1.0945471514840143e-12, + 1.2164292510839079, + ], + linf=[ + 1.5138512282315792, + 5.0276441977281156e-11, + 1.9816934589292803e-11, + 1.513851228231574, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + 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 + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0011197623982310795, + 0.04456344888447023, + 0.014317376629669337, + 5.089218476758975e-6, + ], + linf=[ + 0.007835284004819698, + 0.3486891284278597, + 0.11242778979399048, + 2.6407324614119432e-5, + ], + 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_source_terms.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0011197139793938152, + 0.015430259691310781, + 0.017081031802719724, + 5.089218476758271e-6, + ], + linf=[ + 0.014300809338967824, + 0.12783372461225184, + 0.17625472321992852, + 2.6407324614341476e-5, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + 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_source_terms.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0011196687776346434, + 0.044562672453443995, + 0.014306265289763618, + 5.089218476759981e-6, + ], + linf=[ + 0.007825021762002393, + 0.348550815397918, + 0.1115517935018282, + 2.6407324614341476e-5, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + 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_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, + 5.089218476759981e-6, + ], + linf=[ + 0.014300809338967824, + 0.12783372461224918, + 0.17625472321993918, + 2.6407324614341476e-5, + ], + 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) + 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_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, + ], + linf=[ + 8.394063878602864e-5, + 1.1469760027632646e-10, + 1.1146619484429974e-10, + 8.394063879602065e-5, + ], + tspan=(0.0, 2.0)) + # 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_bc_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_wall_bc_shockcapturing.jl"), + l2=[ + 0.04444388691670699, + 0.1527771788033111, + 0.1593763537203512, + 6.225080476986749e-8, + ], + linf=[ + 0.6526506870169639, + 1.980765893182952, + 2.4807635459119757, + 3.982097158683473e-7, + ], + 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_shallowwater_ec_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_ec_shockcapturing.jl"), + l2=[ + 0.6124656312639043, + 0.504371951785709, + 0.49180896200746366, + 0.29467422718511727, + ], + linf=[ + 2.7639232436274392, + 3.3985508653311767, + 3.3330308209196224, + 2.052861364219655, + ], + 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_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 + +# TODO: activate when twolayer equations are available +# @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 +end + +# Clean up afterwards: delete Trixi.jl output directory +@test_nowarn rm(outdir, recursive = true) + +end # module diff --git a/test/test_upstream.jl b/test/test_upstream.jl index 56c9850..1b534a5 100644 --- a/test/test_upstream.jl +++ b/test/test_upstream.jl @@ -20,7 +20,7 @@ isdir(outdir) && rm(outdir, recursive = true) # Shallow water wet/dry 1D @trixi_testset "1D-Test: elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "tree_1d_dgsem", - "elixir_shallowwater_well_balanced_nonperiodic.jl"), + "elixir_shallowwater_well_balanced_nonperiodic.jl"), l2=[ 1.7259643614361866e-8, 3.5519018243195145e-16, @@ -42,6 +42,7 @@ isdir(outdir) && rm(outdir, recursive = true) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + # TODO: add upstream tests in 2D and positivity-preserving tests end # Clean up afterwards: delete output directory From c47527e3d0c602df76a5f202a13754a1f3862765 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 17:07:32 +0100 Subject: [PATCH 27/48] add unit tests --- test/test_unit.jl | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 9517443..6771ba7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -14,11 +14,20 @@ isdir(outdir) && rm(outdir, recursive = true) @testset "Unit tests" begin #! format: noindent +@timed_testset "Printing indicators/controllers" begin + # OBS! Constructing indicators/controllers using the parameters below doesn't make sense. It's + # just useful to run basic tests of `show` methods. + + indicator_hg_swe = IndicatorHennemannGassnerShallowWater(1.0, 0.0, true, "variable", + "cache") + @test_nowarn show(stdout, indicator_hg_swe) +end + @timed_testset "Shallow water conversion between conservative/entropy variables" begin - H, v, b = 3.5, 0.25, 0.4 + H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) - cons_vars = Trixi.prim2cons(SVector(H, v, b), equations) + cons_vars = Trixi.prim2cons(SVector(H, v1, b), equations) entropy_vars = Trixi.cons2entropy(cons_vars, equations) @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) @@ -28,10 +37,24 @@ isdir(outdir) && rm(outdir, recursive = true) Trixi.energy_internal(cons_vars, equations) + energy_kinetic(cons_vars, equations) # test tuple args - cons_vars = Trixi.prim2cons((H, v, b), equations) + cons_vars = Trixi.prim2cons((H, v1, b), equations) entropy_vars = Trixi.cons2entropy(cons_vars, equations) @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) end + + let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, v2, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) + + total_energy = energy_total(cons_vars, equations) + @test total_energy ≈ entropy(cons_vars, equations) + + # test tuple args + cons_vars = prim2cons((H, v1, v2, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) + end end end From 7eeb2ab306bf869098d7f2f82d943a4326dc7c29 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 17:15:27 +0100 Subject: [PATCH 28/48] Update comments in test files --- src/TrixiShallowWater.jl | 2 +- test/test_tree_1d.jl | 4 ++-- test/test_unit.jl | 5 ++++- test/test_unstructured_2d.jl | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 45fd00e..04d8066 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -4,7 +4,7 @@ module TrixiShallowWater # For more information, see # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi -# Import additional symbols that are not export by Trixi +# Import additional symbols that are not exported by Trixi import Trixi: get_node_vars, set_node_vars! using MuladdMacro: @muladd using StaticArrays: SVector diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index cfe94ff..c87b027 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -8,7 +8,7 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_1d_dgsem") -# Start with a clean environment: remove Trixi.jl output directory if it exists +# Start with a clean environment: remove TrixiShallowWater.jl output directory if it exists outdir = "out" isdir(outdir) && rm(outdir, recursive = true) @@ -21,7 +21,7 @@ isdir(outdir) && rm(outdir, recursive = true) include("test_tree_1d_shallowwater_wet_dry.jl") end -# Clean up afterwards: delete Trixi.jl output directory +# Clean up afterwards: delete TrixiShallowWater.jl output directory @test_nowarn rm(outdir, recursive = true) end # TreeMesh1D diff --git a/test/test_unit.jl b/test/test_unit.jl index 6771ba7..2d9d94d 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -6,7 +6,7 @@ using TrixiShallowWater include("test_trixi.jl") -# Start with a clean environment: remove Trixi.jl output directory if it exists +# Start with a clean environment: remove TrixiShallowWater.jl output directory if it exists outdir = "out" isdir(outdir) && rm(outdir, recursive = true) @@ -58,4 +58,7 @@ end end end +# Clean up afterwards: delete TrixiShallowWater.jl output directory +@test_nowarn rm(outdir, recursive = true) + end # module diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 79e491f..2496db2 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -8,7 +8,7 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "unstructured_2d_dgsem") -# Start with a clean environment: remove Trixi.jl output directory if it exists +# Start with a clean environment: remove TrixiShallowWater.jl output directory if it exists outdir = "out" isdir(outdir) && rm(outdir, recursive = true) @@ -408,7 +408,7 @@ end # end end -# Clean up afterwards: delete Trixi.jl output directory +# Clean up afterwards: delete TrixiShallowWater.jl output directory @test_nowarn rm(outdir, recursive = true) end # module From 2c55e2928562423f3bba83a20f5b2d204fdce59e Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 22 Jan 2024 17:20:42 +0100 Subject: [PATCH 29/48] add upstream tests --- test/test_upstream.jl | 80 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/test/test_upstream.jl b/test/test_upstream.jl index 1b534a5..be732f3 100644 --- a/test/test_upstream.jl +++ b/test/test_upstream.jl @@ -18,7 +18,7 @@ isdir(outdir) && rm(outdir, recursive = true) # Run tests for TreeMesh @testset "TreeMesh" begin # Shallow water wet/dry 1D - @trixi_testset "1D-Test: elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin + @trixi_testset "TreeMesh1D: elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "tree_1d_dgsem", "elixir_shallowwater_well_balanced_nonperiodic.jl"), l2=[ @@ -43,6 +43,84 @@ isdir(outdir) && rm(outdir, recursive = true) end end # TODO: add upstream tests in 2D and positivity-preserving tests + + # Shallow water wet/dry 2D + # TreeMesh2D + @trixi_testset "TreeMesh2D: 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 + # Unstructured2D + @trixi_testset "Unstructured2D: elixir_shallowwater_wall_bc_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_wall_bc_shockcapturing.jl"), + l2=[ + 0.04444388691670699, + 0.1527771788033111, + 0.1593763537203512, + 6.225080476986749e-8, + ], + linf=[ + 0.6526506870169639, + 1.980765893182952, + 2.4807635459119757, + 3.982097158683473e-7, + ], + 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 + # Structured2D + @trixi_testset "Structured2D: 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 end # Clean up afterwards: delete output directory From 9ab42089e1d42abd369e3cf049dd2279113eb263 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Tue, 23 Jan 2024 09:44:15 +0100 Subject: [PATCH 30/48] update comments --- src/TrixiShallowWater.jl | 3 ++- src/equations/shallow_water_wet_dry_2d.jl | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 04d8066..a6ca0ab 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -1,6 +1,7 @@ module TrixiShallowWater # TODO: rewrite this -# We decided to import only Trixi.jl and qualify symbols explicitly with e.g. `Trixi.function_name`. +# While we do using Trixi.jl to extend a method from Trixi.jl symbols need to be qualified explicitly +# e.g. `Trixi.function_name`. # For more information, see # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 67148da..0d9f287 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -94,6 +94,11 @@ Trixi.varnames(::typeof(cons2cons), ::ShallowWaterEquationsWetDry2D) = ("h", "h_ Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry2D) = ("H", "v1", "v2", "b") +# This equation set extends the basic ShallowWaterEquations2D from Trixi.jl with additional +# functionality for wet/dry transitions. Since many functions correspond to the fully wet case, we +# make use of the exisiting functionality and introduce a number of wrapper functions, that dispatch +# to the ShallowWaterEquations2D. + # Set initial conditions at physical location `x` for time `t` """ initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) From 698690949545757608d36d8fe9e188b6525a0a1f Mon Sep 17 00:00:00 2001 From: patrickersing Date: Wed, 31 Jan 2024 15:18:28 +0100 Subject: [PATCH 31/48] fix typos --- src/equations/shallow_water_wet_dry_1d.jl | 2 +- src/equations/shallow_water_wet_dry_2d.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 1416a7b..105d16e 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -95,7 +95,7 @@ end # This equation set extends the basic ShallowWaterEquations1D from Trixi.jl with additional functionality # for wet/dry transitions. Since many functions correspond to the fully wet case, we make use of the -# exisiting functionality and introduce a number of wrapper functions, that dispatch to the +# existing functionality and introduce a number of wrapper functions, that dispatch to the # ShallowWaterEquations1D. # Set initial conditions at physical location `x` for time `t` diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 0d9f287..b6c1df4 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -96,7 +96,7 @@ Trixi.varnames(::typeof(cons2prim), ::ShallowWaterEquationsWetDry2D) = ("H", "v1 # This equation set extends the basic ShallowWaterEquations2D from Trixi.jl with additional # functionality for wet/dry transitions. Since many functions correspond to the fully wet case, we -# make use of the exisiting functionality and introduce a number of wrapper functions, that dispatch +# make use of the existing functionality and introduce a number of wrapper functions, that dispatch # to the ShallowWaterEquations2D. # Set initial conditions at physical location `x` for time `t` From 39395781ae0118b7f6e1602a6683cdc99f62cf43 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Wed, 31 Jan 2024 15:35:56 +0100 Subject: [PATCH 32/48] add Downloads pkg, apply formatter --- Project.toml | 1 + test/test_upstream.jl | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index ca24444..a78a90d 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Andrew R. Winters ", "Michael Schlottke- version = "0.1.0-pre" [deps] +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" diff --git a/test/test_upstream.jl b/test/test_upstream.jl index be732f3..4eabcea 100644 --- a/test/test_upstream.jl +++ b/test/test_upstream.jl @@ -47,7 +47,8 @@ isdir(outdir) && rm(outdir, recursive = true) # Shallow water wet/dry 2D # TreeMesh2D @trixi_testset "TreeMesh2D: elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_conical_island.jl"), l2=[ 0.0459315416430658, 0.1644534881916991, @@ -98,7 +99,8 @@ isdir(outdir) && rm(outdir, recursive = true) end # Structured2D @trixi_testset "Structured2D: elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_conical_island.jl"), l2=[ 0.04593154164306353, 0.1644534881916908, From f3d54901aa4d38479249e9fa8b9d074541a81673 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Thu, 1 Feb 2024 09:14:31 +0100 Subject: [PATCH 33/48] move downloads dependency to test project.toml --- Project.toml | 1 - test/Project.toml | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a78a90d..ca24444 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,6 @@ authors = ["Andrew R. Winters ", "Michael Schlottke- version = "0.1.0-pre" [deps] -Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" diff --git a/test/Project.toml b/test/Project.toml index cfac638..0522218 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,11 +2,13 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" [compat] Test = "1" Trixi = "0.5, 0.6" OrdinaryDiffEq = "6.49.1" +Downloads = "1" [preferences.OrdinaryDiffEq] PrecompileAutoSpecialize = false From 49c61b13543d2872655cb1116a1c91d98b5a89d4 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 23 Feb 2024 15:48:22 +0100 Subject: [PATCH 34/48] Update Trixi version to 0.7 --- Project.toml | 2 +- test/Project.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index ca24444..e391cce 100644 --- a/Project.toml +++ b/Project.toml @@ -14,5 +14,5 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" MuladdMacro = "0.2.2" Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" StaticArrays = "1" -Trixi = "0.5.17, 0.6" +Trixi = "0.7" julia = "1.8" diff --git a/test/Project.toml b/test/Project.toml index 0522218..7cd9a14 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -6,7 +6,7 @@ Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" [compat] Test = "1" -Trixi = "0.5, 0.6" +Trixi = "0.7" OrdinaryDiffEq = "6.49.1" Downloads = "1" From ff74d1227c173d47417c41bee4b6983728e1302f Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 23 Feb 2024 16:07:05 +0100 Subject: [PATCH 35/48] fix formatter to older version --- .github/workflows/FormatCheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 1310d5d..b025346 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -26,7 +26,7 @@ jobs: # # julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version = "0.13.0"))' 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(".")' - name: Format check run: | From 6f0ab5643f75a35449f27b82ab89a62b89d3e16a Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 23 Feb 2024 16:23:37 +0100 Subject: [PATCH 36/48] add Printf to Project.toml --- Project.toml | 2 ++ test/Project.toml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Project.toml b/Project.toml index e391cce..23caf26 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] MuladdMacro = "0.2.2" @@ -16,3 +17,4 @@ Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" StaticArrays = "1" Trixi = "0.7" julia = "1.8" +Printf = "1" diff --git a/test/Project.toml b/test/Project.toml index 7cd9a14..d3420ab 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -3,12 +3,14 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] Test = "1" Trixi = "0.7" OrdinaryDiffEq = "6.49.1" Downloads = "1" +Printf = "1" [preferences.OrdinaryDiffEq] PrecompileAutoSpecialize = false From 60d4ed0d7379764409f11e1332c9c4e35736aaa6 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 23 Feb 2024 18:33:26 +0100 Subject: [PATCH 37/48] Change wavespeed estimate to fix tests with hll fluxes --- test/test_tree_1d_shallowwater_wet_dry.jl | 12 +++++++++--- test/test_tree_2d_shallowwater_wet_dry.jl | 3 ++- test/test_unit.jl | 3 --- test/test_unstructured_2d.jl | 14 ++++++++++---- test/test_upstream.jl | 11 +++++++---- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/test/test_tree_1d_shallowwater_wet_dry.jl b/test/test_tree_1d_shallowwater_wet_dry.jl index 2435fa4..66398a5 100644 --- a/test/test_tree_1d_shallowwater_wet_dry.jl +++ b/test/test_tree_1d_shallowwater_wet_dry.jl @@ -180,7 +180,8 @@ end 9.098379777405796e-5, ], 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 @@ -255,7 +256,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)) @@ -282,7 +283,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 @@ -307,6 +310,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) @@ -385,4 +390,5 @@ end end end end + end # module diff --git a/test/test_tree_2d_shallowwater_wet_dry.jl b/test/test_tree_2d_shallowwater_wet_dry.jl index 50cf0e6..fe8113f 100644 --- a/test/test_tree_2d_shallowwater_wet_dry.jl +++ b/test/test_tree_2d_shallowwater_wet_dry.jl @@ -236,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_unit.jl b/test/test_unit.jl index 2d9d94d..8583b80 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -58,7 +58,4 @@ end end end -# Clean up afterwards: delete TrixiShallowWater.jl output directory -@test_nowarn rm(outdir, recursive = true) - end # module diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 2496db2..c2ca180 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -161,7 +161,7 @@ end 0.17625472321992852, 2.6407324614341476e-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)) @@ -218,7 +218,8 @@ end 0.17625472321993918, 2.6407324614341476e-5, ], - surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), + surface_flux=(FluxHLL(min_max_speed_naive), + flux_nonconservative_fjordholm_etal), tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -244,7 +245,9 @@ end 1.1146619484429974e-10, 8.394063879602065e-5, ], - tspan=(0.0, 2.0)) + tspan=(0.0, 2.0), + 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 @@ -270,7 +273,10 @@ end 2.4807635459119757, 3.982097158683473e-7, ], - tspan=(0.0, 0.05)) + tspan=(0.0, 0.05), + surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_upstream.jl b/test/test_upstream.jl index 4eabcea..34b354b 100644 --- a/test/test_upstream.jl +++ b/test/test_upstream.jl @@ -47,7 +47,7 @@ isdir(outdir) && rm(outdir, recursive = true) # Shallow water wet/dry 2D # TreeMesh2D @trixi_testset "TreeMesh2D: elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, + @test_trixi_include(joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_shallowwater_conical_island.jl"), l2=[ 0.0459315416430658, @@ -73,7 +73,7 @@ isdir(outdir) && rm(outdir, recursive = true) end # Unstructured2D @trixi_testset "Unstructured2D: elixir_shallowwater_wall_bc_shockcapturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, + @test_trixi_include(joinpath(EXAMPLES_DIR, "unstructured_2d_dgsem", "elixir_shallowwater_wall_bc_shockcapturing.jl"), l2=[ 0.04444388691670699, @@ -87,7 +87,10 @@ isdir(outdir) && rm(outdir, recursive = true) 2.4807635459119757, 3.982097158683473e-7, ], - tspan=(0.0, 0.05)) + tspan=(0.0, 0.05), + surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -99,7 +102,7 @@ isdir(outdir) && rm(outdir, recursive = true) end # Structured2D @trixi_testset "Structured2D: elixir_shallowwater_conical_island.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, + @test_trixi_include(joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_shallowwater_conical_island.jl"), l2=[ 0.04593154164306353, From 26f7b89ad5720272569a99754d2dc0a7df8d653e Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 26 Feb 2024 10:23:53 +0100 Subject: [PATCH 38/48] add unit tests, remove unused function --- src/equations/shallow_water_wet_dry_1d.jl | 12 ++------ src/equations/shallow_water_wet_dry_2d.jl | 21 ++------------ test/test_unit.jl | 34 +++++++++++++++++------ 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 105d16e..3754b9d 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -483,7 +483,7 @@ end """ min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) + 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 @@ -494,15 +494,7 @@ Further details on this hydrostatic reconstruction and its motivation can be fou A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -# Since FluxHLL is dispatched on ShallowWaterEquations1D, we also need to dispatch this wave speed -# estimate on ShallowWaterEquations1D. -@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry1D) - return min_max_speed_chen_noelle(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) -end - +# Since FluxHLL is dispatched on ShallowWaterEquations1D this is only used by the ShallowWaterEquations1D. @inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations1D) # Get the velocity quantities diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index b6c1df4..94dc714 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -658,9 +658,9 @@ end """ min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) + equations::ShallowWaterEquations2D) min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) + 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 @@ -674,15 +674,7 @@ the reference below. The definition of the wave speeds are given in Equation (2. A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -# Since FluxHLL is dispatched on ShallowWaterEquations1D, we also need to dispatch this wave speed -# estimate on ShallowWaterEquations1D. -@inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquationsWetDry2D) - return min_max_speed_chen_noelle(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) -end - +# Since FluxHLL is dispatched on ShallowWaterEquations1D this is only used by the ShallowWaterEquations2D. @inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquations2D) h_ll = Trixi.waterheight(u_ll, equations) @@ -704,13 +696,6 @@ end return λ_min, λ_max end -@inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquationsWetDry2D) - return min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) -end - @inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquations2D) h_ll = Trixi.waterheight(u_ll, equations) diff --git a/test/test_unit.jl b/test/test_unit.jl index 8583b80..d7fcd2a 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -27,19 +27,19 @@ end H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) - cons_vars = Trixi.prim2cons(SVector(H, v1, b), equations) - entropy_vars = Trixi.cons2entropy(cons_vars, equations) - @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) + cons_vars = prim2cons(SVector(H, v1, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - total_energy = Trixi.energy_total(cons_vars, equations) - @test total_energy ≈ Trixi.entropy(cons_vars, equations) + total_energy = energy_total(cons_vars, equations) + @test total_energy ≈ entropy(cons_vars, equations) @test total_energy ≈ - Trixi.energy_internal(cons_vars, equations) + + energy_internal(cons_vars, equations) + energy_kinetic(cons_vars, equations) # test tuple args - cons_vars = Trixi.prim2cons((H, v1, b), equations) - entropy_vars = Trixi.cons2entropy(cons_vars, equations) - @test cons_vars ≈ Trixi.entropy2cons(entropy_vars, equations) + cons_vars = prim2cons((H, v1, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) @@ -56,6 +56,22 @@ end @test cons_vars ≈ entropy2cons(entropy_vars, equations) end end + +@timed_testset "Consistency check for waterheight_pressure" begin + H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 + + let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, b), equations) + @test waterheight_pressure(cons_vars, equations) ≈ + Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) + end + + let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, v2, b), equations) + @test waterheight_pressure(cons_vars, equations) ≈ + Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) + end +end end end # module From e3007aec5370135e8fdf5ad8a4c8bbd9076221a6 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Mon, 26 Feb 2024 10:29:43 +0100 Subject: [PATCH 39/48] apply formatter --- test/test_unit.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index d7fcd2a..ad0dbb0 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -63,13 +63,13 @@ end let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) cons_vars = prim2cons(SVector(H, v1, b), equations) @test waterheight_pressure(cons_vars, equations) ≈ - Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) + Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) end let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) cons_vars = prim2cons(SVector(H, v1, v2, b), equations) @test waterheight_pressure(cons_vars, equations) ≈ - Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) + Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) end end end From 77f44c650f95e4bc7bcbd284ecd2f60f6b9d0609 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Tue, 27 Feb 2024 09:31:49 +0100 Subject: [PATCH 40/48] Change comments according to code review, add compat bound for LinearAlgebra --- Project.toml | 1 + examples/tree_1d_dgsem/elixir_shallowwater_beach.jl | 1 + src/TrixiShallowWater.jl | 10 +++++----- src/callbacks_stage/positivity_shallow_water.jl | 6 +++--- src/equations/numerical_fluxes.jl | 2 +- src/solvers/indicators.jl | 3 ++- src/solvers/indicators_1d.jl | 10 +++++----- src/solvers/indicators_2d.jl | 10 +++++----- 8 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Project.toml b/Project.toml index 23caf26..6ea3d75 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] +LinearAlgebra = "1" MuladdMacro = "0.2.2" Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" StaticArrays = "1" diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl index 84cb809..4a87144 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl @@ -10,6 +10,7 @@ equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.812) """ initial_condition_beach(x, t, equations:: ShallowWaterEquationsWetDry1D) + 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 diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index a6ca0ab..0ff7d48 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -1,11 +1,11 @@ module TrixiShallowWater -# TODO: rewrite this -# While we do using Trixi.jl to extend a method from Trixi.jl symbols need to be qualified explicitly -# e.g. `Trixi.function_name`. + +# While `using Trixi` makes all exported symbols available, in order to extend a method from the +# `Trixi.jl` module, symbols need to be explicitly qualified with `Trixi.function_name`. # For more information, see # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi -# Import additional symbols that are not exported by Trixi +# Import additional symbols that are not exported by Trixi.jl import Trixi: get_node_vars, set_node_vars! using MuladdMacro: @muladd using StaticArrays: SVector @@ -17,7 +17,7 @@ include("equations/numerical_fluxes.jl") include("callbacks_stage/callbacks_stage.jl") include("solvers/indicators.jl") -# export types/functions that define the public API of TrixiShallowWater.jl +# Export types/functions that define the public API of TrixiShallowWater.jl export ShallowWaterEquationsWetDry1D, ShallowWaterEquationsWetDry2D export hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, diff --git a/src/callbacks_stage/positivity_shallow_water.jl b/src/callbacks_stage/positivity_shallow_water.jl index 6145762..17b8388 100644 --- a/src/callbacks_stage/positivity_shallow_water.jl +++ b/src/callbacks_stage/positivity_shallow_water.jl @@ -10,8 +10,8 @@ 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. +using the defined `threshold_limiter` from the [`ShallowWaterEquationsWetDry1D`](@ref) struct +or the [`ShallowWaterEquationsWetDry2D`](@ref) struct to determine the minimal acceptable values. The order of the `variables` is important and might have a strong influence on the robustness. @@ -19,7 +19,7 @@ As opposed to the standard version of the [`PositivityPreservingLimiterZhangShu` 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 +`ShallowWaterEquationsWetDry` 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. diff --git a/src/equations/numerical_fluxes.jl b/src/equations/numerical_fluxes.jl index 7aae0f8..098bc69 100644 --- a/src/equations/numerical_fluxes.jl +++ b/src/equations/numerical_fluxes.jl @@ -10,7 +10,7 @@ # 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`. +# for `min_max_speed_chen_noelle` in `shallow_water_wet_dry_1d.jl` or `shallow_water_wet_dry_2d.jl`. function min_max_speed_chen_noelle end diff --git a/src/solvers/indicators.jl b/src/solvers/indicators.jl index 270595f..0ac2a5a 100644 --- a/src/solvers/indicators.jl +++ b/src/solvers/indicators.jl @@ -38,7 +38,8 @@ 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 +# It modifies the shock-capturing indicator to use full FV method in dry elements +# or partially dry elements containing a wet/dry transition. function IndicatorHennemannGassnerShallowWater(equations::Trixi.AbstractShallowWaterEquations, basis; alpha_max = 0.5, diff --git a/src/solvers/indicators_1d.jl b/src/solvers/indicators_1d.jl index b8766fa..8a9f47d 100644 --- a/src/solvers/indicators_1d.jl +++ b/src/solvers/indicators_1d.jl @@ -5,7 +5,7 @@ @muladd begin #! format: noindent -# Modified indicator for ShallowWaterEquations1D to apply full FV method on cells +# Modified indicator for ShallowWaterEquationsWetDry1D to apply full FV method on elements # containing some "dry" LGL nodes. That is, if an element is partially "wet" then it becomes a # full FV element. function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, @@ -31,15 +31,15 @@ function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{ # 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. + # FV method is used in partially wet elements 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 + # Overall idea is to increase robustness when computing the velocity on (nearly) dry elements 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 + # Here, the impact of the threshold on the number of elements 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 + # Well-balancedness of the scheme on partially wet elements 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 diff --git a/src/solvers/indicators_2d.jl b/src/solvers/indicators_2d.jl index 6622d24..1e36414 100644 --- a/src/solvers/indicators_2d.jl +++ b/src/solvers/indicators_2d.jl @@ -5,7 +5,7 @@ @muladd begin #! format: noindent -# Modified indicator for ShallowWaterEquations2D to apply full FV method on cells +# Modified indicator for ShallowWaterEquationsWetDry2D to apply full FV method on elements # containing some "dry" LGL nodes. That is, if an element is partially "wet" then it becomes a # full FV element. function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, @@ -31,15 +31,15 @@ function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{ # 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. + # FV method is used in partially wet elements 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 + # Overall idea is to increase robustness when computing the velocity on (nearly) dry elements 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 + # Here, the impact of the threshold on the number of elements 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 + # Well-balancedness of the scheme on partially wet elements 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 From 92f2fdde25425999ed967e88dffc6ba1a21c05f9 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Thu, 29 Feb 2024 09:25:59 +0100 Subject: [PATCH 41/48] reorganize single test files for each mesh type --- test/runtests.jl | 10 +- test/test_tree_1d.jl | 383 ++++++++++++++++- test/test_tree_1d_shallowwater_wet_dry.jl | 394 ------------------ ...hallowwater_wet_dry.jl => test_tree_2d.jl} | 11 +- 4 files changed, 390 insertions(+), 408 deletions(-) delete mode 100644 test/test_tree_1d_shallowwater_wet_dry.jl rename test/{test_tree_2d_shallowwater_wet_dry.jl => test_tree_2d.jl} (97%) diff --git a/test/runtests.jl b/test/runtests.jl index f3de815..d501312 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,18 +2,14 @@ using Trixi using TrixiShallowWater using Test -# We run tests in parallel with CI jobs setting the `TRIXI_TEST` environment +# We run tests with CI jobs setting the `TRIXI_TEST` environment # variable to determine the subset of tests to execute. -# By default, we just run the threaded tests since they are relatively cheap -# and test a good amount of different functionality. const TRIXI_TEST = get(ENV, "TRIXI_TEST", "all") -const TRIXI_MPI_NPROCS = clamp(Sys.CPU_THREADS, 2, 3) -const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time @testset "TrixiShallowWater.jl tests" begin @time if TRIXI_TEST == "all" - include("test_tree_1d_shallowwater_wet_dry.jl") - include("test_tree_2d_shallowwater_wet_dry.jl") + include("test_tree_1d.jl") + include("test_tree_2d.jl") include("test_unstructured_2d.jl") include("test_structured_2d.jl") include("test_unit.jl") diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index c87b027..e5a1dee 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -15,14 +15,387 @@ isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh1D" begin #! format: noindent -# Run basic tests -@testset "Examples 1D" begin - # Shallow water - include("test_tree_1d_shallowwater_wet_dry.jl") +@trixi_testset "elixir_shallowwater_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[0.244729018751225, 0.8583565222389505, 0.07330427577586297], + linf=[ + 2.1635021283528504, + 3.8717508164234453, + 1.7711213427919539, + ], + 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_ec.jl with initial_condition_weak_blast_wave" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), + l2=[ + 0.39464782107209717, + 2.03880864210846, + 4.1623084150546725e-10, + ], + linf=[ + 0.778905801278281, + 3.2409883402608273, + 7.419800190922032e-10, + ], + initial_condition=initial_condition_weak_blast_wave, + 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_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254829, + 1.4352935256803184e-14, + 0.10416666834254838, + ], + linf=[1.9999999999999996, 3.248036646353028e-14, 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_well_balanced.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254835, + 1.1891029971551825e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000018, 2.4019608337954543e-14, 2.0], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_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 + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254838, + 1.6657566141935285e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000004, 3.0610625110157164e-14, 2.0], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + 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 + +@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=[ + 0.0022363707373868713, + 0.01576799981934617, + 4.436491725585346e-5, + ], + linf=[ + 0.00893601803417754, + 0.05939797350246456, + 9.098379777405796e-5, + ], + 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_source_terms.jl with flux_hll" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0022758146627220154, + 0.015864082886204556, + 4.436491725585346e-5, + ], + linf=[ + 0.008457195427364006, + 0.057201667446161064, + 9.098379777405796e-5, + ], + tspan=(0.0, 0.025), + 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 + 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 flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.005774284062933275, + 0.017408601639513584, + 4.43649172561843e-5, + ], + linf=[ + 0.01639116193303547, + 0.05102877460799604, + 9.098379777450205e-5, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + 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_source_terms_dirichlet.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022851099219788917, + 0.01560453773635554, + 4.43649172558535e-5, + ], + linf=[ + 0.008934615705174398, + 0.059403169140869405, + 9.098379777405796e-5, + ], + 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_source_terms_dirichlet.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022956052733432287, + 0.015540053559855601, + 4.43649172558535e-5, + ], + linf=[ + 0.008460440313118323, + 0.05720939349382359, + 9.098379777405796e-5, + ], + surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + 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_well_balanced_nonperiodic.jl with Dirichlet boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.725964362045055e-8, + 5.0427180314307505e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551077492042e-8, + 3.469453422316143e-15, + 3.844551077492042e-8, + ], + 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 + 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_well_balanced_nonperiodic.jl with wall boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.7259643614361866e-8, + 3.5519018243195145e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551010878661e-8, + 9.846474508971374e-16, + 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) + 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_shock_capturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_shock_capturing.jl"), + l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], + linf=[ + 1.1209754279344226, + 1.3230788645853582, + 0.8646939843534251, + ], + 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_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 +end # TreeMesh1D + # Clean up afterwards: delete TrixiShallowWater.jl output directory @test_nowarn rm(outdir, recursive = true) -end # TreeMesh1D end # module diff --git a/test/test_tree_1d_shallowwater_wet_dry.jl b/test/test_tree_1d_shallowwater_wet_dry.jl deleted file mode 100644 index 66398a5..0000000 --- a/test/test_tree_1d_shallowwater_wet_dry.jl +++ /dev/null @@ -1,394 +0,0 @@ -module TestExamples1DShallowWaterWetDry - -using Test -using Trixi -using TrixiShallowWater - -include("test_trixi.jl") - -EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_1d_dgsem") - -@testset "Shallow Water Wet Dry" begin -#! format: noindent - -@trixi_testset "elixir_shallowwater_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2=[0.244729018751225, 0.8583565222389505, 0.07330427577586297], - linf=[ - 2.1635021283528504, - 3.8717508164234453, - 1.7711213427919539, - ], - 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_ec.jl with initial_condition_weak_blast_wave" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2=[ - 0.39464782107209717, - 2.03880864210846, - 4.1623084150546725e-10, - ], - linf=[ - 0.778905801278281, - 3.2409883402608273, - 7.419800190922032e-10, - ], - initial_condition=initial_condition_weak_blast_wave, - 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_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2=[ - 0.10416666834254829, - 1.4352935256803184e-14, - 0.10416666834254838, - ], - linf=[1.9999999999999996, 3.248036646353028e-14, 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_well_balanced.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2=[ - 0.10416666834254835, - 1.1891029971551825e-14, - 0.10416666834254838, - ], - linf=[2.0000000000000018, 2.4019608337954543e-14, 2.0], - surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, - hydrostatic_reconstruction_audusse_etal), - flux_nonconservative_audusse_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 - -@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2=[ - 0.10416666834254838, - 1.6657566141935285e-14, - 0.10416666834254838, - ], - linf=[2.0000000000000004, 3.0610625110157164e-14, 2.0], - surface_flux=(flux_wintermeyer_etal, - flux_nonconservative_ersing_etal), - volume_flux=(flux_wintermeyer_etal, - 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 - -@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=[ - 0.0022363707373868713, - 0.01576799981934617, - 4.436491725585346e-5, - ], - linf=[ - 0.00893601803417754, - 0.05939797350246456, - 9.098379777405796e-5, - ], - 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_source_terms.jl with flux_hll" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2=[ - 0.0022758146627220154, - 0.015864082886204556, - 4.436491725585346e-5, - ], - linf=[ - 0.008457195427364006, - 0.057201667446161064, - 9.098379777405796e-5, - ], - tspan=(0.0, 0.025), - 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 - 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 flux_nonconservative_ersing_etal" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2=[ - 0.005774284062933275, - 0.017408601639513584, - 4.43649172561843e-5, - ], - linf=[ - 0.01639116193303547, - 0.05102877460799604, - 9.098379777450205e-5, - ], - surface_flux=(flux_wintermeyer_etal, - flux_nonconservative_ersing_etal), - volume_flux=(flux_wintermeyer_etal, - flux_nonconservative_ersing_etal), - 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_source_terms_dirichlet.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_source_terms_dirichlet.jl"), - l2=[ - 0.0022851099219788917, - 0.01560453773635554, - 4.43649172558535e-5, - ], - linf=[ - 0.008934615705174398, - 0.059403169140869405, - 9.098379777405796e-5, - ], - 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_source_terms_dirichlet.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_source_terms_dirichlet.jl"), - l2=[ - 0.0022956052733432287, - 0.015540053559855601, - 4.43649172558535e-5, - ], - linf=[ - 0.008460440313118323, - 0.05720939349382359, - 9.098379777405796e-5, - ], - surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), - hydrostatic_reconstruction_audusse_etal), - flux_nonconservative_audusse_etal), - 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_well_balanced_nonperiodic.jl with Dirichlet boundary" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_well_balanced_nonperiodic.jl"), - l2=[ - 1.725964362045055e-8, - 5.0427180314307505e-16, - 1.7259643530442137e-8, - ], - linf=[ - 3.844551077492042e-8, - 3.469453422316143e-15, - 3.844551077492042e-8, - ], - 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 - 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_well_balanced_nonperiodic.jl with wall boundary" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_well_balanced_nonperiodic.jl"), - l2=[ - 1.7259643614361866e-8, - 3.5519018243195145e-16, - 1.7259643530442137e-8, - ], - linf=[ - 3.844551010878661e-8, - 9.846474508971374e-16, - 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) - 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_shock_capturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_shallowwater_shock_capturing.jl"), - l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], - linf=[ - 1.1209754279344226, - 1.3230788645853582, - 0.8646939843534251, - ], - 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_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 -end - -end # module diff --git a/test/test_tree_2d_shallowwater_wet_dry.jl b/test/test_tree_2d.jl similarity index 97% rename from test/test_tree_2d_shallowwater_wet_dry.jl rename to test/test_tree_2d.jl index fe8113f..e0c324c 100644 --- a/test/test_tree_2d_shallowwater_wet_dry.jl +++ b/test/test_tree_2d.jl @@ -8,7 +8,11 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(TrixiShallowWater, "examples", "tree_2d_dgsem") -@testset "Shallow Water Wet Dry" begin +# Start with a clean environment: remove TrixiShallowWater.jl output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive = true) + +@testset "TreeMesh2D" begin #! format: noindent @trixi_testset "elixir_shallowwater_ec.jl" begin @@ -352,6 +356,9 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end -end +end # TreeMesh2D + +# Clean up afterwards: delete TrixiShallowWater.jl output directory +@test_nowarn rm(outdir, recursive = true) end # module From 0fc33bc6d0b7a51cdacc81dd936bd37830e161a1 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Thu, 29 Feb 2024 10:20:58 +0100 Subject: [PATCH 42/48] Add own flux hll and wave speed estimates; add unit tests --- src/equations/shallow_water_wet_dry_1d.jl | 46 ++++++++++++-- src/equations/shallow_water_wet_dry_2d.jl | 71 +++++++++++++++++++-- test/test_unit.jl | 76 +++++++++++++++++++++++ 3 files changed, 183 insertions(+), 10 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 3754b9d..eadd4db 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -477,8 +477,24 @@ end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry1D) - return (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + λ_min, λ_max = numflux.min_max_speed(u_ll, u_rr, orientation_or_normal_direction, + equations) + + if λ_min >= 0 && λ_max >= 0 + return flux(u_ll, orientation_or_normal_direction, equations) + elseif λ_max <= 0 && λ_min <= 0 + return flux(u_rr, orientation_or_normal_direction, equations) + else + f_ll = flux(u_ll, orientation_or_normal_direction, equations) + f_rr = flux(u_rr, orientation_or_normal_direction, equations) + inv_λ_max_minus_λ_min = inv(λ_max - λ_min) + factor_ll = λ_max * inv_λ_max_minus_λ_min + factor_rr = λ_min * inv_λ_max_minus_λ_min + factor_diss = λ_min * λ_max * inv_λ_max_minus_λ_min + diss = u_rr - u_ll + return factor_ll * f_ll - factor_rr * f_rr + + factor_diss * SVector(diss[1], diss[2], zero(eltype(u_ll))) + end end """ @@ -494,9 +510,8 @@ Further details on this hydrostatic reconstruction and its motivation can be fou A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -# Since FluxHLL is dispatched on ShallowWaterEquations1D this is only used by the ShallowWaterEquations1D. @inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations1D) + equations::ShallowWaterEquationsWetDry1D) # Get the velocity quantities v_ll = velocity(u_ll, equations) v_rr = velocity(u_rr, equations) @@ -520,6 +535,29 @@ end equations.H0)) end +# Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end + +@inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry1D) + return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, + ShallowWaterEquations1D(equations.gravity, + equations.H0)) +end + # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.velocity(u, diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 94dc714..cdd1723 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -651,9 +651,24 @@ end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry2D) - return (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + λ_min, λ_max = numflux.min_max_speed(u_ll, u_rr, orientation_or_normal_direction, + equations) + + if λ_min >= 0 && λ_max >= 0 + return flux(u_ll, orientation_or_normal_direction, equations) + elseif λ_max <= 0 && λ_min <= 0 + return flux(u_rr, orientation_or_normal_direction, equations) + else + f_ll = flux(u_ll, orientation_or_normal_direction, equations) + f_rr = flux(u_rr, orientation_or_normal_direction, equations) + inv_λ_max_minus_λ_min = inv(λ_max - λ_min) + factor_ll = λ_max * inv_λ_max_minus_λ_min + factor_rr = λ_min * inv_λ_max_minus_λ_min + factor_diss = λ_min * λ_max * inv_λ_max_minus_λ_min + diss = u_rr - u_ll + return factor_ll * f_ll - factor_rr * f_rr + + factor_diss * SVector(diss[1], diss[2], diss[3], zero(eltype(u_ll))) + end end """ @@ -674,9 +689,8 @@ the reference below. The definition of the wave speeds are given in Equation (2. A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -# Since FluxHLL is dispatched on ShallowWaterEquations1D this is only used by the ShallowWaterEquations2D. @inline function min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterEquations2D) + equations::ShallowWaterEquationsWetDry2D) h_ll = Trixi.waterheight(u_ll, equations) v1_ll, v2_ll = velocity(u_ll, equations) h_rr = Trixi.waterheight(u_rr, equations) @@ -697,7 +711,7 @@ the reference below. The definition of the wave speeds are given in Equation (2. end @inline function min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector, - equations::ShallowWaterEquations2D) + equations::ShallowWaterEquationsWetDry2D) h_ll = Trixi.waterheight(u_ll, equations) v1_ll, v2_ll = velocity(u_ll, equations) h_rr = Trixi.waterheight(u_rr, equations) @@ -723,6 +737,51 @@ end equations.H0)) end +# Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + +@inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, + normal_direction::AbstractVector, + equations::ShallowWaterEquationsWetDry2D) + return Trixi.min_max_speed_einfeldt(u_ll, u_rr, normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) +end + # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.velocity(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) diff --git a/test/test_unit.jl b/test/test_unit.jl index ad0dbb0..9e78a0d 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -72,6 +72,82 @@ end Trixi.waterheight(cons_vars, equations) * pressure(cons_vars, equations) end end + +# Test consistency of the wrapper functions for the wave speed estimates +@timed_testset "Consistency check for wave speed estimates of the SWE" begin + let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) + equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.8) + u_rr = SVector(1.2, 0.3, 0.7) + u_ll = SVector(0.25, 0.1, 0.4) + orientation = 1 + + @test min_max_speed_naive(u_ll, u_rr, orientation, + equations) == + min_max_speed_naive(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_davis(u_ll, u_rr, orientation, + equations) == + min_max_speed_davis(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_einfeldt(u_ll, u_rr, orientation, + equations) == + min_max_speed_einfeldt(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_naive(u_ll, u_rr, orientation, + equations) == + min_max_speed_naive(u_ll, u_rr, orientation, + equations_trixi) + end + + let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) + equations_trixi = ShallowWaterEquations2D(gravity_constant = 9.8) + u_rr = SVector(1.2, 0.3, 0.2, 0.7) + u_ll = SVector(0.25, 0.1, 0.3, 0.4) + orientations = [1, 2] + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + + for orientation in orientations + @test min_max_speed_naive(u_ll, u_rr, orientation, + equations) == + min_max_speed_naive(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_davis(u_ll, u_rr, orientation, + equations) == + min_max_speed_davis(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_einfeldt(u_ll, u_rr, orientation, + equations) == + min_max_speed_einfeldt(u_ll, u_rr, orientation, + equations_trixi) + @test min_max_speed_naive(u_ll, u_rr, orientation, + equations) == + min_max_speed_naive(u_ll, u_rr, orientation, + equations_trixi) + end + + for normal_direction in normal_directions + @test min_max_speed_naive(u_ll, u_rr, normal_direction, + equations) == + min_max_speed_naive(u_ll, u_rr, normal_direction, + equations_trixi) + @test min_max_speed_davis(u_ll, u_rr, normal_direction, + equations) == + min_max_speed_davis(u_ll, u_rr, normal_direction, + equations_trixi) + @test min_max_speed_einfeldt(u_ll, u_rr, normal_direction, + equations) == + min_max_speed_einfeldt(u_ll, u_rr, normal_direction, + equations_trixi) + @test min_max_speed_naive(u_ll, u_rr, normal_direction, + equations) == + min_max_speed_naive(u_ll, u_rr, normal_direction, + equations_trixi) + end + end end +end # Unit tests end # module From 276990a641d5e020cead93f0520679b12f2a43a3 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 1 Mar 2024 07:51:22 +0100 Subject: [PATCH 43/48] remove unnecessary qualifier --- src/equations/shallow_water_wet_dry_2d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index cdd1723..e498c6b 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -639,17 +639,17 @@ end end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography -@inline function (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, +@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry2D) - return (dissipation::Trixi.DissipationLocalLaxFriedrichs)(u_ll, u_rr, + return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, ShallowWaterEquations2D(equations.gravity, equations.H0)) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography -@inline function (numflux::Trixi.FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, +@inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquationsWetDry2D) λ_min, λ_max = numflux.min_max_speed(u_ll, u_rr, orientation_or_normal_direction, equations) From 9cc7904ddc549bd5d38ed3786fd062dc7538ccaf Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 1 Mar 2024 07:58:18 +0100 Subject: [PATCH 44/48] apply formatter --- src/equations/shallow_water_wet_dry_2d.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index e498c6b..3a8ea8e 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -640,17 +640,17 @@ end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry2D) - return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations::ShallowWaterEquationsWetDry2D) + return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + ShallowWaterEquations2D(equations.gravity, + equations.H0)) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @inline function (numflux::FluxHLL)(u_ll, u_rr, orientation_or_normal_direction, - equations::ShallowWaterEquationsWetDry2D) + equations::ShallowWaterEquationsWetDry2D) λ_min, λ_max = numflux.min_max_speed(u_ll, u_rr, orientation_or_normal_direction, equations) From 033bb482329cf08517bc127cd976613ba2ec4885 Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 8 Mar 2024 11:15:19 +0100 Subject: [PATCH 45/48] Apply changes from code review and introduce new field equations.swe_trixi --- .github/workflows/FormatCheck.yml | 2 + src/TrixiShallowWater.jl | 2 +- src/equations/shallow_water_wet_dry_1d.jl | 77 +++++++---------- src/equations/shallow_water_wet_dry_2d.jl | 100 +++++++++------------- test/test_unit.jl | 26 +++--- 5 files changed, 88 insertions(+), 119 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index b025346..8ecb87a 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -25,6 +25,8 @@ jobs: # This will use the latest version by default but you can set the version like so: # # julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version = "0.13.0"))' + # + # TODO: remove version restriction once formatting has sorted itself out run: | julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.45"))' julia -e 'using JuliaFormatter; format(".")' diff --git a/src/TrixiShallowWater.jl b/src/TrixiShallowWater.jl index 0ff7d48..c065f79 100644 --- a/src/TrixiShallowWater.jl +++ b/src/TrixiShallowWater.jl @@ -6,7 +6,7 @@ module TrixiShallowWater # https://github.com/trixi-framework/TrixiShallowWater.jl/pull/10#discussion_r1433720559 using Trixi # Import additional symbols that are not exported by Trixi.jl -import Trixi: get_node_vars, set_node_vars! +using Trixi: get_node_vars, set_node_vars! using MuladdMacro: @muladd using StaticArrays: SVector using Static: True, False diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index eadd4db..f6f97a2 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -62,6 +62,8 @@ struct ShallowWaterEquationsWetDry1D{RealT <: Real} <: # before calculating the numerical flux. # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT + # Standard shallow water equations for dispatch on Trixi.jl functions + swe_trixi::typeof(ShallowWaterEquations1D(gravity_constant=1.0)) end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -79,8 +81,11 @@ function ShallowWaterEquationsWetDry1D(; gravity_constant, H0 = zero(gravity_con if threshold_wet === nothing threshold_wet = 5 * eps(T) end + # Construct standard SWE for dispatch + swe_trixi = ShallowWaterEquations1D(gravity_constant=gravity_constant, H0 = H0) + ShallowWaterEquationsWetDry1D(gravity_constant, H0, threshold_limiter, - threshold_wet) + threshold_wet, swe_trixi) end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry1D) = True() @@ -110,8 +115,7 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_convergence_test(x, t, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -129,8 +133,7 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.source_terms_convergence_test(u, x, t, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -142,8 +145,7 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_weak_blast_wave(x, t, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -188,7 +190,7 @@ end @inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux(u, orientation, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end """ @@ -208,8 +210,7 @@ Further details are available in the paper:#include("numerical_fluxes.jl") orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -239,8 +240,7 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -266,8 +266,7 @@ Further details on the hydrostatic reconstruction and its motivation can be foun equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -338,8 +337,7 @@ For further details see: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -358,8 +356,7 @@ Details are available in Eq. (4.1) in the paper: @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -379,8 +376,7 @@ Further details are available in Theorem 1 of the paper: @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -400,8 +396,7 @@ Further details on this hydrostatic reconstruction and its motivation can be fou @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, equations::ShallowWaterEquationsWetDry1D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -470,8 +465,7 @@ end equations::ShallowWaterEquationsWetDry1D) return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @@ -531,43 +525,39 @@ end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.velocity(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2prim(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert conservative variables to entropy @@ -575,36 +565,34 @@ end # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2entropy(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry1D) return Trixi.entropy2cons(w, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert primitive to conservative variables @inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry1D) return Trixi.prim2cons(prim, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.waterheight(u, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.pressure(u, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.waterheight_pressure(u, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Entropy function for the shallow water equations is the total energy @@ -615,14 +603,13 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_total(cons, - ShallowWaterEquations1D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_kinetic(u, - ShallowWaterEquations1D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Calculate potential energy for a conservative state `cons` diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 3a8ea8e..1fa5804 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -65,6 +65,8 @@ struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: # before calculating the numerical flux. # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT + # Standard shallow water equations for dispatch on Trixi.jl functions + swe_trixi::typeof(ShallowWaterEquations2D(gravity_constant=1.0)) end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -82,8 +84,11 @@ function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_con if threshold_wet === nothing threshold_wet = 5 * eps(T) end + # Construct standard SWE for dispatch + swe_trixi = ShallowWaterEquations2D(gravity_constant=gravity_constant, H0 = H0) + ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, - threshold_wet) + threshold_wet, swe_trixi) end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry2D) = True() @@ -110,8 +115,7 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.initial_condition_convergence_test(x, t, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -128,8 +132,7 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.source_terms_convergence_test(u, x, t, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -141,8 +144,7 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.initial_condition_weak_blast_wave(x, t, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -211,7 +213,7 @@ end # Note, the bottom topography has no flux @inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) - Trixi.flux(u, orientation, ShallowWaterEquations2D(equations.gravity, equations.H0)) + Trixi.flux(u, orientation, equations.swe_trixi) end # Calculate 1D flux for a single point in the normal direction @@ -219,7 +221,7 @@ end @inline function Trixi.flux(u, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) Trixi.flux(u, normal_direction, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end """ @@ -248,8 +250,7 @@ Further details are available in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, @@ -259,8 +260,7 @@ end return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -299,8 +299,7 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, @@ -310,8 +309,7 @@ end Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -331,8 +329,7 @@ Further details for the hydrostatic reconstruction and its motivation can be fou @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, equations::ShallowWaterEquationsWetDry2D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -423,8 +420,7 @@ Further details for the hydrostatic reconstruction and its motivation can be fou orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, @@ -434,8 +430,7 @@ end return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -568,8 +563,7 @@ For further details see: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, @@ -579,8 +573,7 @@ end Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -599,14 +592,13 @@ Details are available in Eq. (4.1) in the paper: @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end """ @@ -626,16 +618,14 @@ Further details are available in Theorem 1 of the paper: @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @@ -644,8 +634,7 @@ end equations::ShallowWaterEquationsWetDry2D) return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @@ -733,63 +722,56 @@ end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.max_abs_speeds(u, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, normal_direction, - ShallowWaterEquations2D(equations.gravity, - equations.H0)) + equations.swe_trixi) end # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.velocity(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.velocity(u, equations.swe_trixi) end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.cons2prim(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.cons2prim(u, equations.swe_trixi) end # Convert conservative variables to entropy @@ -797,28 +779,28 @@ end # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.cons2entropy(u, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry2D) return Trixi.entropy2cons(w, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end # Convert primitive to conservative variables @inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry2D) return Trixi.prim2cons(prim, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.waterheight(u, - ShallowWaterEquations2D(equations.gravity, equations.H0)) + equations.swe_trixi) end @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.pressure(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + return Trixi.pressure(u, equations.swe_trixi) end @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry2D) @@ -832,12 +814,12 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry2D) - Trixi.energy_total(cons, ShallowWaterEquations2D(equations.gravity, equations.H0)) + Trixi.energy_total(cons, equations.swe_trixi) end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry2D) - Trixi.energy_kinetic(u, ShallowWaterEquations2D(equations.gravity, equations.H0)) + Trixi.energy_kinetic(u, equations.swe_trixi) end # Calculate potential energy for a conservative state `cons` diff --git a/test/test_unit.jl b/test/test_unit.jl index 9e78a0d..e6a189e 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -76,7 +76,6 @@ end # Test consistency of the wrapper functions for the wave speed estimates @timed_testset "Consistency check for wave speed estimates of the SWE" begin let equations = ShallowWaterEquationsWetDry1D(gravity_constant = 9.8) - equations_trixi = ShallowWaterEquations1D(gravity_constant = 9.8) u_rr = SVector(1.2, 0.3, 0.7) u_ll = SVector(0.25, 0.1, 0.4) orientation = 1 @@ -84,23 +83,22 @@ end @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_davis(u_ll, u_rr, orientation, equations) == min_max_speed_davis(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_einfeldt(u_ll, u_rr, orientation, equations) == min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) end let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) - equations_trixi = ShallowWaterEquations2D(gravity_constant = 9.8) u_rr = SVector(1.2, 0.3, 0.2, 0.7) u_ll = SVector(0.25, 0.1, 0.3, 0.4) orientations = [1, 2] @@ -113,38 +111,38 @@ end @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_davis(u_ll, u_rr, orientation, equations) == min_max_speed_davis(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_einfeldt(u_ll, u_rr, orientation, equations) == min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations_trixi) + equations.swe_trixi) end for normal_direction in normal_directions @test min_max_speed_naive(u_ll, u_rr, normal_direction, equations) == min_max_speed_naive(u_ll, u_rr, normal_direction, - equations_trixi) + equations.swe_trixi) @test min_max_speed_davis(u_ll, u_rr, normal_direction, equations) == min_max_speed_davis(u_ll, u_rr, normal_direction, - equations_trixi) + equations.swe_trixi) @test min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations) == min_max_speed_einfeldt(u_ll, u_rr, normal_direction, - equations_trixi) + equations.swe_trixi) @test min_max_speed_naive(u_ll, u_rr, normal_direction, equations) == min_max_speed_naive(u_ll, u_rr, normal_direction, - equations_trixi) + equations.swe_trixi) end end end From 595caf23e509dd873adacae5e4fa117ad23f1aba Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 8 Mar 2024 11:23:41 +0100 Subject: [PATCH 46/48] apply formatter --- src/equations/shallow_water_wet_dry_1d.jl | 4 ++-- src/equations/shallow_water_wet_dry_2d.jl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index f6f97a2..3190e7d 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -63,7 +63,7 @@ struct ShallowWaterEquationsWetDry1D{RealT <: Real} <: # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT # Standard shallow water equations for dispatch on Trixi.jl functions - swe_trixi::typeof(ShallowWaterEquations1D(gravity_constant=1.0)) + swe_trixi::typeof(ShallowWaterEquations1D(gravity_constant = 1.0)) end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -82,7 +82,7 @@ function ShallowWaterEquationsWetDry1D(; gravity_constant, H0 = zero(gravity_con threshold_wet = 5 * eps(T) end # Construct standard SWE for dispatch - swe_trixi = ShallowWaterEquations1D(gravity_constant=gravity_constant, H0 = H0) + swe_trixi = ShallowWaterEquations1D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry1D(gravity_constant, H0, threshold_limiter, threshold_wet, swe_trixi) diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index 1fa5804..a357851 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -66,7 +66,7 @@ struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT # Standard shallow water equations for dispatch on Trixi.jl functions - swe_trixi::typeof(ShallowWaterEquations2D(gravity_constant=1.0)) + swe_trixi::typeof(ShallowWaterEquations2D(gravity_constant = 1.0)) end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -85,7 +85,7 @@ function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_con threshold_wet = 5 * eps(T) end # Construct standard SWE for dispatch - swe_trixi = ShallowWaterEquations2D(gravity_constant=gravity_constant, H0 = H0) + swe_trixi = ShallowWaterEquations2D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, threshold_wet, swe_trixi) From 8e14bba5d8e509fdc2570b64973862a7939d720f Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 8 Mar 2024 13:37:22 +0100 Subject: [PATCH 47/48] Update name and type assignment of swe_trixi -> basic_swe --- src/equations/shallow_water_wet_dry_1d.jl | 58 ++++++++--------- src/equations/shallow_water_wet_dry_2d.jl | 76 +++++++++++------------ test/test_unit.jl | 24 +++---- 3 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index 3190e7d..b734f95 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -63,7 +63,7 @@ struct ShallowWaterEquationsWetDry1D{RealT <: Real} <: # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT # Standard shallow water equations for dispatch on Trixi.jl functions - swe_trixi::typeof(ShallowWaterEquations1D(gravity_constant = 1.0)) + basic_swe::ShallowWaterEquations1D{RealT} end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -82,10 +82,10 @@ function ShallowWaterEquationsWetDry1D(; gravity_constant, H0 = zero(gravity_con threshold_wet = 5 * eps(T) end # Construct standard SWE for dispatch - swe_trixi = ShallowWaterEquations1D(gravity_constant = gravity_constant, H0 = H0) + basic_swe = ShallowWaterEquations1D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry1D(gravity_constant, H0, threshold_limiter, - threshold_wet, swe_trixi) + threshold_wet, basic_swe) end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry1D) = True() @@ -115,7 +115,7 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_convergence_test(x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -133,7 +133,7 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.source_terms_convergence_test(u, x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -145,7 +145,7 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry1D) return Trixi.initial_condition_weak_blast_wave(x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -190,7 +190,7 @@ end @inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux(u, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -210,7 +210,7 @@ Further details are available in the paper:#include("numerical_fluxes.jl") orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -240,7 +240,7 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -266,7 +266,7 @@ Further details on the hydrostatic reconstruction and its motivation can be foun equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -337,7 +337,7 @@ For further details see: orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -356,7 +356,7 @@ Details are available in Eq. (4.1) in the paper: @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -376,7 +376,7 @@ Further details are available in Theorem 1 of the paper: @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end """ @@ -396,7 +396,7 @@ Further details on this hydrostatic reconstruction and its motivation can be fou @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, equations::ShallowWaterEquationsWetDry1D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - equations.swe_trixi) + equations.basic_swe) end """ @@ -465,7 +465,7 @@ end equations::ShallowWaterEquationsWetDry1D) return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - equations.swe_trixi) + equations.basic_swe) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @@ -525,39 +525,39 @@ end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.max_abs_speeds(u, - equations.swe_trixi) + equations.basic_swe) end # Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry1D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.velocity(u, - equations.swe_trixi) + equations.basic_swe) end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2prim(u, - equations.swe_trixi) + equations.basic_swe) end # Convert conservative variables to entropy @@ -565,34 +565,34 @@ end # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.cons2entropy(u, - equations.swe_trixi) + equations.basic_swe) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry1D) return Trixi.entropy2cons(w, - equations.swe_trixi) + equations.basic_swe) end # Convert primitive to conservative variables @inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry1D) return Trixi.prim2cons(prim, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.waterheight(u, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.pressure(u, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.waterheight_pressure(u, - equations.swe_trixi) + equations.basic_swe) end # Entropy function for the shallow water equations is the total energy @@ -603,13 +603,13 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_total(cons, - equations.swe_trixi) + equations.basic_swe) end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry1D) return Trixi.energy_kinetic(u, - equations.swe_trixi) + equations.basic_swe) end # Calculate potential energy for a conservative state `cons` diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index a357851..cc30f91 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -66,7 +66,7 @@ struct ShallowWaterEquationsWetDry2D{RealT <: Real} <: # Default is 5*eps() which in double precision is ≈1e-15. threshold_wet::RealT # Standard shallow water equations for dispatch on Trixi.jl functions - swe_trixi::typeof(ShallowWaterEquations2D(gravity_constant = 1.0)) + basic_swe::ShallowWaterEquations2D{RealT} end # Allow for flexibility to set the gravitational constant within an elixir depending on the @@ -85,10 +85,10 @@ function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_con threshold_wet = 5 * eps(T) end # Construct standard SWE for dispatch - swe_trixi = ShallowWaterEquations2D(gravity_constant = gravity_constant, H0 = H0) + basic_swe = ShallowWaterEquations2D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter, - threshold_wet, swe_trixi) + threshold_wet, basic_swe) end Trixi.have_nonconservative_terms(::ShallowWaterEquationsWetDry2D) = True() @@ -115,7 +115,7 @@ A smooth initial condition used for convergence tests in combination with function Trixi.initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.initial_condition_convergence_test(x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -132,7 +132,7 @@ as defined in [`initial_condition_convergence_test`](@ref). @inline function Trixi.source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.source_terms_convergence_test(u, x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -144,7 +144,7 @@ Note for the shallow water equations to the total energy acts as a mathematical function Trixi.initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquationsWetDry2D) return Trixi.initial_condition_weak_blast_wave(x, t, - equations.swe_trixi) + equations.basic_swe) end """ @@ -213,7 +213,7 @@ end # Note, the bottom topography has no flux @inline function Trixi.flux(u, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) - Trixi.flux(u, orientation, equations.swe_trixi) + Trixi.flux(u, orientation, equations.basic_swe) end # Calculate 1D flux for a single point in the normal direction @@ -221,7 +221,7 @@ end @inline function Trixi.flux(u, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) Trixi.flux(u, normal_direction, - equations.swe_trixi) + equations.basic_swe) end """ @@ -250,7 +250,7 @@ Further details are available in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, @@ -260,7 +260,7 @@ end return Trixi.flux_nonconservative_wintermeyer_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - equations.swe_trixi) + equations.basic_swe) end """ @@ -299,7 +299,7 @@ and for curvilinear 2D case in the paper: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, @@ -309,7 +309,7 @@ end Trixi.flux_nonconservative_fjordholm_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - equations.swe_trixi) + equations.basic_swe) end """ @@ -329,7 +329,7 @@ Further details for the hydrostatic reconstruction and its motivation can be fou @inline function Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, equations::ShallowWaterEquationsWetDry2D) return Trixi.hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, - equations.swe_trixi) + equations.basic_swe) end """ @@ -420,7 +420,7 @@ Further details for the hydrostatic reconstruction and its motivation can be fou orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, @@ -430,7 +430,7 @@ end return Trixi.flux_nonconservative_audusse_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - equations.swe_trixi) + equations.basic_swe) end """ @@ -563,7 +563,7 @@ For further details see: orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, @@ -573,7 +573,7 @@ end Trixi.flux_nonconservative_ersing_etal(u_ll, u_rr, normal_direction_ll, normal_direction_average, - equations.swe_trixi) + equations.basic_swe) end """ @@ -592,13 +592,13 @@ Details are available in Eq. (4.1) in the paper: @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) Trixi.flux_fjordholm_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_fjordholm_etal(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end """ @@ -618,14 +618,14 @@ Further details are available in Theorem 1 of the paper: @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.flux_wintermeyer_etal(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end # Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography @@ -634,7 +634,7 @@ end equations::ShallowWaterEquationsWetDry2D) return (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, orientation_or_normal_direction, - equations.swe_trixi) + equations.basic_swe) end # Specialized `FluxHLL` to avoid spurious dissipation in the bottom topography @@ -722,56 +722,56 @@ end @inline function Trixi.max_abs_speeds(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.max_abs_speeds(u, - equations.swe_trixi) + equations.basic_swe) end # Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_naive(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function Trixi.min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_davis(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_davis(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, equations::ShallowWaterEquationsWetDry2D) return Trixi.min_max_speed_einfeldt(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end # Helper function to extract the velocity vector from the conservative variables @inline function Trixi.velocity(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.velocity(u, equations.swe_trixi) + return Trixi.velocity(u, equations.basic_swe) end # Convert conservative variables to primitive @inline function Trixi.cons2prim(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.cons2prim(u, equations.swe_trixi) + return Trixi.cons2prim(u, equations.basic_swe) end # Convert conservative variables to entropy @@ -779,28 +779,28 @@ end # just carries the bottom topography values for convenience @inline function Trixi.cons2entropy(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.cons2entropy(u, - equations.swe_trixi) + equations.basic_swe) end # Convert entropy variables to conservative @inline function Trixi.entropy2cons(w, equations::ShallowWaterEquationsWetDry2D) return Trixi.entropy2cons(w, - equations.swe_trixi) + equations.basic_swe) end # Convert primitive to conservative variables @inline function Trixi.prim2cons(prim, equations::ShallowWaterEquationsWetDry2D) return Trixi.prim2cons(prim, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.waterheight(u, equations::ShallowWaterEquationsWetDry2D) return Trixi.waterheight(u, - equations.swe_trixi) + equations.basic_swe) end @inline function Trixi.pressure(u, equations::ShallowWaterEquationsWetDry2D) - return Trixi.pressure(u, equations.swe_trixi) + return Trixi.pressure(u, equations.basic_swe) end @inline function Trixi.waterheight_pressure(u, equations::ShallowWaterEquationsWetDry2D) @@ -814,12 +814,12 @@ end # Calculate total energy for a conservative state `cons` @inline function Trixi.energy_total(cons, equations::ShallowWaterEquationsWetDry2D) - Trixi.energy_total(cons, equations.swe_trixi) + Trixi.energy_total(cons, equations.basic_swe) end # Calculate kinetic energy for a conservative state `cons` @inline function Trixi.energy_kinetic(u, equations::ShallowWaterEquationsWetDry2D) - Trixi.energy_kinetic(u, equations.swe_trixi) + Trixi.energy_kinetic(u, equations.basic_swe) end # Calculate potential energy for a conservative state `cons` diff --git a/test/test_unit.jl b/test/test_unit.jl index e6a189e..9d77370 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -83,19 +83,19 @@ end @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_davis(u_ll, u_rr, orientation, equations) == min_max_speed_davis(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_einfeldt(u_ll, u_rr, orientation, equations) == min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end let equations = ShallowWaterEquationsWetDry2D(gravity_constant = 9.8) @@ -111,38 +111,38 @@ end @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_davis(u_ll, u_rr, orientation, equations) == min_max_speed_davis(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_einfeldt(u_ll, u_rr, orientation, equations) == min_max_speed_einfeldt(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_naive(u_ll, u_rr, orientation, equations) == min_max_speed_naive(u_ll, u_rr, orientation, - equations.swe_trixi) + equations.basic_swe) end for normal_direction in normal_directions @test min_max_speed_naive(u_ll, u_rr, normal_direction, equations) == min_max_speed_naive(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_davis(u_ll, u_rr, normal_direction, equations) == min_max_speed_davis(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations) == min_max_speed_einfeldt(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) @test min_max_speed_naive(u_ll, u_rr, normal_direction, equations) == min_max_speed_naive(u_ll, u_rr, normal_direction, - equations.swe_trixi) + equations.basic_swe) end end end From 42cf9eeb711b87eaee5b28401b115e2ae99229ff Mon Sep 17 00:00:00 2001 From: patrickersing Date: Fri, 8 Mar 2024 14:46:16 +0100 Subject: [PATCH 48/48] add comment about duplication of g and H0 --- src/equations/shallow_water_wet_dry_1d.jl | 4 +++- src/equations/shallow_water_wet_dry_2d.jl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/equations/shallow_water_wet_dry_1d.jl b/src/equations/shallow_water_wet_dry_1d.jl index b734f95..095041d 100644 --- a/src/equations/shallow_water_wet_dry_1d.jl +++ b/src/equations/shallow_water_wet_dry_1d.jl @@ -81,7 +81,9 @@ function ShallowWaterEquationsWetDry1D(; gravity_constant, H0 = zero(gravity_con if threshold_wet === nothing threshold_wet = 5 * eps(T) end - # Construct standard SWE for dispatch + # Construct the standard SWE for dispatch. Even though the `basic_swe` already store the + # gravity constant and the total water height, we store an extra copy in + # `ShallowWaterEquationsWetDry1D` for convenience. basic_swe = ShallowWaterEquations1D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry1D(gravity_constant, H0, threshold_limiter, diff --git a/src/equations/shallow_water_wet_dry_2d.jl b/src/equations/shallow_water_wet_dry_2d.jl index cc30f91..a9edf53 100644 --- a/src/equations/shallow_water_wet_dry_2d.jl +++ b/src/equations/shallow_water_wet_dry_2d.jl @@ -84,7 +84,9 @@ function ShallowWaterEquationsWetDry2D(; gravity_constant, H0 = zero(gravity_con if threshold_wet === nothing threshold_wet = 5 * eps(T) end - # Construct standard SWE for dispatch + # Construct the standard SWE for dispatch. Even though the `basic_swe` already store the + # gravity constant and the total water height, we store an extra copy in + # `ShallowWaterEquationsWetDry2D` for convenience. basic_swe = ShallowWaterEquations2D(gravity_constant = gravity_constant, H0 = H0) ShallowWaterEquationsWetDry2D(gravity_constant, H0, threshold_limiter,