Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
575af7a
add geostrophic adjustment elixir
patrickersing Mar 7, 2025
92829a8
Add boundary conditions for fixed water height and momentum
patrickersing Apr 28, 2025
87565e3
Merge branch 'main' into geostrophic_adjustment
patrickersing Apr 28, 2025
a6f55c0
Use the new gravity parameter and correct boundary condition assignments
patrickersing Apr 28, 2025
df56ef5
fix gravity parameter in test_unit.jl
patrickersing Apr 28, 2025
a2bf1ac
switch to OrdinaryDiffEq subpackages in the new elixirs
patrickersing Apr 28, 2025
251fcd5
remove unnecessary lines in unit test
patrickersing Apr 28, 2025
cfbc207
Use Trixi.download instead of Base.download
patrickersing Apr 28, 2025
7bab2dd
increase iterations for coverage testing
patrickersing Apr 28, 2025
e24d587
apply formatter
patrickersing Apr 28, 2025
ab8fab7
specify maxiters for coverage overwrite
patrickersing Apr 28, 2025
8b66350
create equation specific constructor for the BCs
patrickersing Apr 28, 2025
02b99cf
fix tests
patrickersing Apr 28, 2025
da4c8b4
enforce correct output types for the boundary value function
patrickersing Apr 29, 2025
fd54bde
Apply suggestions from code review
patrickersing Apr 30, 2025
d34cd2c
apply suggestions from code review part 2
patrickersing Apr 30, 2025
cde6fd6
add BC in for SWE-1D together with moving-water steady state test cases
patrickersing May 1, 2025
6382f07
fix typos
patrickersing May 1, 2025
73de3c5
Merge branch 'main' into geostrophic_adjustment
patrickersing May 1, 2025
4c9e180
additional unit test to trigger ArgumentError for BoundaryConditionWa…
patrickersing May 1, 2025
65c4bf5
add news item
patrickersing May 1, 2025
befee41
Merge branch 'main' into geostrophic_adjustment
patrickersing May 2, 2025
93bd252
Apply changes from code review
patrickersing May 5, 2025
d3fd8ff
Apply changes from code review - part 2
patrickersing May 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ for human readability.
#### Added

- Experimental support for well-balanced mortars together with AMR [#45]
- New boundary conditions `BoundaryConditionWaterHeight` and `BoundaryConditionMomentum` now
available for the `ShallowWaterEquationsWetDry` to impose either the water height or the momentum
at the boundary. [#91]

#### Changed

Expand Down
184 changes: 184 additions & 0 deletions examples/tree_1d_dgsem/elixir_shallowwater_moving_water_shock.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@

using OrdinaryDiffEqSSPRK, OrdinaryDiffEqLowStorageRK
using Trixi
using TrixiShallowWater
using Roots

###############################################################################
# semidiscretization of the shallow water equations for a transonic moving water
# steady-state with a standing shock.

equations = ShallowWaterEquationsWetDry1D(gravity = 9.812, H0 = 3.25)

"""
inverse_transform(E, hv, sigma, b)

Inverse transformation from equilibrium variables (E, hv) to conservative variables (h, hv). Besides the
equilibrium variables, which are the total energy `E` and momentum `hv`, the function also depends
on the bottom topography `b` and the flow regime `sigma` (supersonic = 1 , sonic = 0 or subsonic = -1).

The implementation follows the procedure described in Section 2.1 of the paper:
- Sebastian Noelle, Yulong Xing and Chi-Wang Shu (2007)
High Order Well-balanced Finite Volume WENO Schemes for Shallow Water Equation with Moving Water
[DOI: 10.1016/j.jcp.2007.03.031](https://doi.org/10.1016/j.jcp.2007.03.031).
"""
function inverse_transform(E, hv, sigma, b)
# Extract the gravitational acceleration
g = equations.gravity

# Compute water height and specific energy at the sonic point
h_0 = 1 / g * (g * abs(hv))^(2 / 3)
phi_0 = 3 / 2 * (g * abs(hv))^(2 / 3)

# normalized total energy
E_hat = (E - g * b) / phi_0

# Check if the state is admissible and compute the water height
# as in equation (2.19) of the reference in the docstring.
if sigma == 0 && E_hat ≈ 1 # sonic state
h_hat = 1
elseif abs(sigma) == 1 && E_hat > 1 # supersonic / subsonic state
if sigma == 1 # supersonic
h_hat_init = 0.5 # needs to be < 1
else # subsonic
h_hat_init = 2.0 # needs to be > 1
end

# Setup the root finding problem.
f(h_hat) = E_hat - 2 / 3 * ((1 / (2 * h_hat^2)) + h_hat)
D(f) = h_hat -> Trixi.ForwardDiff.derivative(f, float(h_hat))

# Solve the root finding problem using Newton's method
h_hat = Roots.newton((f, D(f)), h_hat_init)
else
throw(error("The given state is not admissible: E_hat = $E_hat, sigma = $sigma"))
end

# Compute and return the water height `h` from the normalized water height `h_hat = h / h_0`.
return h_hat * h_0
end

"""
initial_condition_moving_water_transonic(x, t, equations::ShallowWaterEquationsWetDry1D)

Set the initial condition for a transonic moving water steady-state and a quadratic bottom
topography, to test the well-balancedness of the scheme.

The test parameters are taken from Section 4.1 of the paper:
- Sebastian Noelle, Yulong Xing and Chi-Wang Shu (2007)
High Order Well-balanced Finite Volume WENO Schemes for Shallow Water Equation with Moving Water
[DOI: 10.1016/j.jcp.2007.03.031](https://doi.org/10.1016/j.jcp.2007.03.031).
"""
function initial_condition_moving_water_shock(x, t,
equations::ShallowWaterEquationsWetDry1D)
# Extract the gravitational acceleration
g = equations.gravity

hv = 0.18 # momentum

# Set the total energy before and after the shock
if x[1] < 11.665504281554291
E = 3 / 2 * (g * 0.18)^(2 / 3) + g * 0.2
else
E = 0.18^2 / (2 * 0.33^2) + g * 0.33
end

# # Set the quadratic bottom topography function
if 8 <= x[1] <= 12
b = 0.2 - 0.05 * (x[1] - 10.0)^2
else
b = 0.0
end

# Set the sign function to label the flow regime (subsonic = -1, sonic = 0, supersonic = 1).
# A small tolerance is required to avoid numerical issues in the inverse_transform function
# close to the sonic point at x = 10.
tol = 1e-12
if x[1] <= 10.0 - tol || x[1] >= 11.665504281554291
sigma = -1 # subsonic
elseif 10 - tol < x[1] < 10.0 + tol
sigma = 0 # sonic
elseif 10 + tol <= x[1] < 11.665504281554291
sigma = 1 # supersonic
end

h = inverse_transform(E, hv, sigma, b)

return SVector(h, hv, b)
end

initial_condition = initial_condition_moving_water_shock

boundary_condition_inflow = BoundaryConditionMomentum(0.18, equations)
boundary_condition_outflow = BoundaryConditionDirichlet(initial_condition_moving_water_shock)

boundary_conditions = (x_neg = boundary_condition_inflow,
x_pos = boundary_condition_outflow)

###############################################################################
# Get the DG approximation space

volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal)
surface_flux = (FluxPlusDissipation(flux_wintermeyer_etal, DissipationLocalLaxFriedrichs()),
flux_nonconservative_wintermeyer_etal)

basis = LobattoLegendreBasis(3)

indicator_sc = IndicatorHennemannGassner(equations, basis,
alpha_max = 0.5,
alpha_min = 0.001,
alpha_smooth = true,
variable = waterheight)
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 non-periodic mesh

coordinates_min = 0.0
coordinates_max = 32.0 # This needs to be a multiple of 2 to match the corners of the bottom topography
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_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,
save_analysis = true)

alive_callback = AliveCallback(analysis_interval = analysis_interval)

save_solution = SaveSolutionCallback(interval = 1000,
save_initial_solution = true,
save_final_solution = true)

stepsize_callback = StepsizeCallback(cfl = 0.7)

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
155 changes: 155 additions & 0 deletions examples/tree_1d_dgsem/elixir_shallowwater_moving_water_subsonic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using OrdinaryDiffEqSSPRK, OrdinaryDiffEqLowStorageRK
using Trixi
using TrixiShallowWater
using Roots

###############################################################################
# semidiscretization of the shallow water equations for a subsonic moving water steady-state

equations = ShallowWaterEquationsWetDry1D(gravity = 9.812, H0 = 3.25)

"""
inverse_transform(E, hv, sigma, b)

Inverse transformation from equilibrium variables (E, hv) to conservative variables (h, hv). Besides the
equilibrium variables, which are the total energy `E` and momentum `hv`, the function also depends
on the bottom topography `b` and the flow regime `sigma` (supersonic = 1 , sonic = 0 or subsonic = -1).

The implementation follows the procedure described in Section 2.1 of the paper:
- Sebastian Noelle, Yulong Xing and Chi-Wang Shu (2007)
High Order Well-balanced Finite Volume WENO Schemes for Shallow Water Equation with Moving Water
[DOI: 10.1016/j.jcp.2007.03.031](https://doi.org/10.1016/j.jcp.2007.03.031).
"""
function inverse_transform(E, hv, sigma, b)
# Extract the gravitational acceleration
g = equations.gravity

# Compute water height and specific energy at the sonic point
h_0 = 1 / g * (g * abs(hv))^(2 / 3)
phi_0 = 3 / 2 * (g * abs(hv))^(2 / 3)

# normalized total energy
E_hat = (E - g * b) / phi_0

# Check if the state is admissible and compute the water height
# as in equation (2.19) of the reference in the docstring.
if sigma == 0 && E_hat ≈ 1 # sonic state
h_hat = 1
elseif abs(sigma) == 1 && E_hat > 1 # supersonic / subsonic state
# Pick an initial guess for the root finding problem based on the flow regime
if sigma == 1 # supersonic
h_hat_init = 0.5 # needs to be < 1
else # subsonic
h_hat_init = 2 # needs to be > 1
end

# Setup the root finding problem.
f(h_hat) = E_hat - 2 / 3 * ((1 / (2 * h_hat^2)) + h_hat)
D(f) = h_hat -> Trixi.ForwardDiff.derivative(f, float(h_hat))

# Solve the root finding problem using Newton's method
h_hat = Roots.newton((f, D(f)), h_hat_init)
else
throw(error("The given state is not admissible: E_hat = $E_hat, sigma = $sigma"))
end

# Compute and return the water height `h` from the normalized water height `h_hat = h / h_0`.
return h_hat * h_0
end

"""
initial_condition_moving_water_subsonic(x, t, equations::ShallowWaterEquations1D)

Set the initial condition for a subsonic moving water steady-state and quadratic bottom topography,
to test the well-balancedness of the scheme.

The test setup is taken from Section 4.1 of the paper:
- Sebastian Noelle, Yulong Xing and Chi-Wang Shu (2007)
High Order Well-balanced Finite Volume WENO Schemes for Shallow Water Equation with Moving Water
[DOI: 10.1016/j.jcp.2007.03.031](https://doi.org/10.1016/j.jcp.2007.03.031).
"""
function initial_condition_moving_water_subsonic(x, t,
equations::ShallowWaterEquationsWetDry1D)
# Set initial conditions
hv = 4.42 # momentum
E = 22.06605 # total energy

# Set the quadratic bottom topography function
if 8 <= x[1] <= 12
b = 0.2 - 0.05 * (x[1] - 10.0)^2
else
b = 0.0
end

sigma = -1 # sign function to label the flow regime (subsonic = -1, sonic = 0, supersonic = 1)

# Compute the water height using the inverse transformation
h = inverse_transform(E, hv, sigma, b)

return SVector(h, hv, b)
end

initial_condition = initial_condition_moving_water_subsonic

boundary_condition_inflow = BoundaryConditionMomentum(4.42, equations)
boundary_condition_outflow = BoundaryConditionWaterHeight(2.0, equations)

boundary_conditions = (x_neg = boundary_condition_inflow,
x_pos = boundary_condition_outflow)

###############################################################################
# Get the DG approximation space

volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal)
surface_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_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 = 0.0
coordinates_max = 32.0 # This needs to be a multiple of 2 to match the corners of the bottom topography
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_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,
save_analysis = true)

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
Loading
Loading