From 03c95db6ffafc633f9c8bfd99009e02ecf0681af Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 12 Jan 2022 15:02:22 +0100 Subject: [PATCH 001/423] Add first version of VolumeIntegralStaggeredGrid with (new) data structure --- .../elixir_euler_ec_staggered_grid.jl | 60 ++++ src/Trixi.jl | 1 + src/solvers/dg.jl | 28 ++ src/solvers/dgsem_tree/dg_2d.jl | 265 ++++++++++++++++++ 4 files changed, 354 insertions(+) create mode 100644 examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl b/examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl new file mode 100644 index 0000000000..e5a34ab7a0 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl @@ -0,0 +1,60 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_weak_blast_wave + +volume_flux = flux_ranocha +solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, + volume_integral=VolumeIntegralStaggeredGrid(0.5; volume_flux_dg=volume_flux, + volume_flux_fv=volume_flux)) + +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, + periodicity=true) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_condition_periodic) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.4) +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=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/src/Trixi.jl b/src/Trixi.jl index 895023c0f6..842886eb4b 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -174,6 +174,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, + VolumeIntegralStaggeredGrid, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, MortarL2 diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 86cbac1ee6..84dd9ddb0e 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -142,6 +142,34 @@ function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralPureLGLFi end +struct VolumeIntegralStaggeredGrid{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral + volume_flux_dg::VolumeFluxDG + volume_flux_fv::VolumeFluxFV + indicator::Indicator +end + +function VolumeIntegralStaggeredGrid(indicator; volume_flux_dg=flux_ranocha, + volume_flux_fv=flux_lax_friedrichs) + VolumeIntegralStaggeredGrid{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( + volume_flux_dg, volume_flux_fv, indicator) +end + +function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralStaggeredGrid) + @nospecialize integral # reduce precompilation time + + if get(io, :compact, false) + show(io, integral) + else + setup = [ + "volume flux dg" => integral.volume_flux_dg, + "volume flux fv" => integral.volume_flux_fv, + "indicator" => integral.indicator + ] + summary_box(io, "VolumeIntegralStaggeredGrid", setup) + end +end + + function get_element_variables!(element_variables, u, mesh, equations, volume_integral::VolumeIntegralShockCapturingHG, dg, cache) # call the indicator to get up-to-date values for IO diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5215db6edc..d43d9a9886 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -78,6 +78,38 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMe return (; fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded) end + +function create_cache(mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, equations, + volume_integral::VolumeIntegralStaggeredGrid, dg::DG, uEltype) + error("VolumeIntegralStaggeredGrid only defined for TreeMesh") +end + + +function create_cache(mesh::TreeMesh{2}, equations, + volume_integral::VolumeIntegralStaggeredGrid, dg::DG, uEltype) + + have_nonconservative_terms(equations) !== Val(false) && error("VolumeIntegralStaggeredGrid only defined for no nonconservative terms.") + + cache = create_cache(mesh, equations, + VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), + dg, uEltype) + + # old structure of staggered grid fluxes + # FluxType = SVector{nvariables(equations), uEltype} + # fstaggered_threaded = [Vector{FluxType}(undef, nnodes(dg) - 1) for _ in 1:Threads.nthreads()] + + A3dp1_x = Array{uEltype, 3} + A3dp1_y = Array{uEltype, 3} + + fstaggered1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + fstaggered1_R_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + fstaggered2_L_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + fstaggered2_R_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + + return (; cache..., fstaggered1_L_threaded, fstaggered2_L_threaded, fstaggered1_R_threaded, fstaggered2_R_threaded) +end + + # The methods below are specialized on the mortar type # and called from the basic `create_cache` method at the top. function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, @@ -490,6 +522,239 @@ end end +function calc_volume_integral!(du, u, + mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, + nonconservative_terms, equations, + volume_integral::VolumeIntegralStaggeredGrid, + dg::DGSEM, cache) + error("VolumeIntegralStaggeredGrid only defined for TreeMesh") +end + + +function calc_volume_integral!(du, u, + mesh::TreeMesh{2}, + nonconservative_terms, equations, + volume_integral::VolumeIntegralStaggeredGrid, + dg::DGSEM, cache) + @threaded for element in eachelement(dg, cache) + staggered_grid_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, dg, cache) + end +end + +@inline function staggered_grid_kernel!(du, u, + element, mesh::TreeMesh{2}, + nonconservative_terms, equations, + volume_integral, dg::DGSEM, cache, alpha=true) + # true * [some floating point value] == [exactly the same floating point value] + # This can (hopefully) be optimized away due to constant propagation. + @unpack inverse_weights = dg.basis + @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral + + # high-order dg fluxes + @unpack fstaggered1_L_threaded, fstaggered2_L_threaded, fstaggered1_R_threaded, fstaggered2_R_threaded = cache + + fstaggered1_L = fstaggered1_L_threaded[Threads.threadid()] + fstaggered2_L = fstaggered2_L_threaded[Threads.threadid()] + fstaggered1_R = fstaggered1_R_threaded[Threads.threadid()] + fstaggered2_R = fstaggered2_R_threaded[Threads.threadid()] + calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + + # low-order fv fluxes + @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache + + fstar1_L = fstar1_L_threaded[Threads.threadid()] + fstar2_L = fstar2_L_threaded[Threads.threadid()] + fstar1_R = fstar1_R_threaded[Threads.threadid()] + fstar2_R = fstar2_R_threaded[Threads.threadid()] + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + + + # Calculate blending factor alpha_blending + alpha_blending = volume_integral.indicator + + + # Calculate volume integral contribution + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + du[v, i, j, element] += ( (1 - alpha_blending) * + (inverse_weights[i] * (fstaggered1_L[v, i+1, j] - fstaggered1_R[v, i, j]) + + inverse_weights[j] * (fstaggered2_L[v, i, j+1] - fstaggered2_R[v, i, j])) ) + + ( alpha_blending * + (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) ) + + end + end + + # ----------------------------------------------------------------------------------------------- + # old version of calculation with fstaggered as Vector of SVectors + # (only for one "line", in x or y direction) + # @unpack fstaggered_threaded = cache + + # fstaggered = fstaggered_threaded[Threads.threadid()] + + # # x + # for j in eachnode(dg) + # # compute local high-order flux + # local_fluxes_1!(fstaggered, u, nonconservative_terms, equations, volume_flux_dg, dg, j, element) + + # # update volume contribution in locally conservative form + # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[1] * fstaggered[1], equations, dg, 1, j, element) + # for i in 2:nnodes(dg)-1 + # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[i] * (fstaggered[i] - fstaggered[i-1]), equations, dg, i, j, element) + # end + # add_to_node_vars!(du, -(1 - alpha_blending) * inverse_weights[end] * fstaggered[end], equations, dg, nnodes(dg), j, element) + # end + + # # y + # for i in eachnode(dg) + # # compute local high-order fluxes + # local_fluxes_2!(fstaggered, u, nonconservative_terms, equations, volume_flux_dg, dg, i, element) + + # # update volume contribution in locally conservative form + # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[1] * fstaggered[1], equations, dg, i, 1, element) + # for j in 2:nnodes(dg)-1 + # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[j] * (fstaggered[j] - fstaggered[j-1]), equations, dg, i, j, element) + # end + # add_to_node_vars!(du, -(1 - alpha_blending) * inverse_weights[end] * fstaggered[end], equations, dg, i, nnodes(dg), element) + # end + + return nothing +end + + +# calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u, mesh, +# nonconservative_terms, equations, volume_flux_dg, dg, element, cache) +# +# Calculate the staggered grid volume fluxes inside the elements (**without non-conservative terms**). +# +# # Arguments +# - `fstaggered1_L::AbstractArray{<:Real, 3}` +# - `fstaggered1_R::AbstractArray{<:Real, 3}` +# - `fstaggered2_L::AbstractArray{<:Real, 3}` +# - `fstaggered2_R::AbstractArray{<:Real, 3}` +@inline function calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u::AbstractArray{<:Any,4}, + mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, + volume_flux, dg::DGSEM, element, cache) + + @unpack weights, derivative_split = dg.basis + + fstaggered1_L[:, 1, :] .= zero(eltype(fstaggered1_L)) + fstaggered1_L[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1_L)) + fstaggered1_R[:, 1, :] .= zero(eltype(fstaggered1_R)) + fstaggered1_R[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1_R)) + + for j in eachnode(dg) + local_fluxes_1!(fstaggered1_L, fstaggered1_R, u, + nonconservative_terms, equations, + volume_flux, dg, j, element) + end + + fstaggered2_L[:, :, 1 ] .= zero(eltype(fstaggered2_L)) + fstaggered2_L[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2_L)) + fstaggered2_R[:, :, 1 ] .= zero(eltype(fstaggered2_R)) + fstaggered2_R[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2_R)) + + for i in eachnode(dg) + local_fluxes_2!(fstaggered2_L, fstaggered2_R, u, + nonconservative_terms, equations, + volume_flux, dg, i, element) + end + + return nothing +end + + +@inline function local_fluxes_1!(fstaggered_L, fstaggered_R, u::AbstractArray{<:Any,4}, + nonconservative_terms::Val{false}, equations, + volume_flux, dg::DGSEM, j, element) + @unpack weights, derivative_split = dg.basis + + for i in 2:nnodes(dg) + fstaggered_L[:, i, j] .= zero(eltype(fstaggered_L)) + fstaggered_R[:, i, j] .= zero(eltype(fstaggered_R)) + for iip in i:nnodes(dg) + uiip = get_node_vars(u, equations, dg, iip, j, element) + for iim in 1:i-1 + uiim = get_node_vars(u, equations, dg, iim, j, element) + flux = volume_flux(uiim, uiip, 1, equations) + multiply_add_to_node_vars!(fstaggered_L, weights[iim] * derivative_split[iim, iip], flux, equations, dg, i, j) + multiply_add_to_node_vars!(fstaggered_R, weights[iim] * derivative_split[iim, iip], flux, equations, dg, i, j) + end + end + end + + return nothing +end + + +@inline function local_fluxes_2!(fstaggered_L, fstaggered_R, u::AbstractArray{<:Any,4}, + nonconservative_terms::Val{false}, equations, + volume_flux, dg::DGSEM, i, element) + @unpack weights, derivative_split = dg.basis + for j in 2:nnodes(dg) + fstaggered_L[:, i, j] .= zero(eltype(fstaggered_L)) + fstaggered_R[:, i, j] .= zero(eltype(fstaggered_R)) + for jjp in j:nnodes(dg) + ujjp = get_node_vars(u, equations, dg, i, jjp, element) + for jjm in 1:j-1 + ujjm = get_node_vars(u, equations, dg, i, jjm, element) + flux = volume_flux(ujjm, ujjp, 2, equations) + multiply_add_to_node_vars!(fstaggered_L, weights[jjm] * derivative_split[jjm, jjp], flux, equations, dg, i, j) + multiply_add_to_node_vars!(fstaggered_R, weights[jjm] * derivative_split[jjm, jjp], flux, equations, dg, i, j) + end + end + end + + return nothing +end + +# functions local_fluxes_1! and local_fluxes_2! for old data structure +# @inline function local_fluxes_1!(fluxes, u::AbstractArray{<:Any,4}, +# nonconservative_terms::Val{false}, equations, +# volume_flux, dg::DGSEM, j, element) +# @unpack weights, derivative_split = dg.basis + +# for i in eachindex(fluxes) +# flux1 = zero(eltype(fluxes)) +# for iip in i+1:nnodes(dg) +# uiip = get_node_vars(u, equations, dg, iip, j, element) +# for iim in 1:i +# uiim = get_node_vars(u, equations, dg, iim, j, element) +# flux1 += weights[iim] * derivative_split[iim,iip] * volume_flux(uiim, uiip, 1, equations) +# end +# end +# fluxes[i] = flux1 +# end + +# return nothing +# end + +# @inline function local_fluxes_2!(fluxes, u::AbstractArray{<:Any,4}, +# nonconservative_terms::Val{false}, equations, +# volume_flux, dg::DGSEM, i, element) +# @unpack weights, derivative_split = dg.basis + +# for j in eachindex(fluxes) +# flux2 = zero(eltype(fluxes)) +# for jjp in j+1:nnodes(dg) +# ujjp = get_node_vars(u, equations, dg, i, jjp, element) +# for jjm in 1:j +# ujjm = get_node_vars(u, equations, dg, i, jjm, element) +# flux2 += weights[jjm] * derivative_split[jjm,jjp] * volume_flux(ujjm, ujjp, 2, equations) +# end +# end +# fluxes[j] = flux2 +# end + +# return nothing +# end + + function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) @unpack interfaces = cache From 80049d5dfb335f916809a202cd618a8473385da1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 13 Jan 2022 19:46:52 +0100 Subject: [PATCH 002/423] Implement recursive calculation; remove L and R arrays --- src/solvers/dgsem_tree/dg_2d.jl | 108 +++++++++----------------------- 1 file changed, 29 insertions(+), 79 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index d43d9a9886..1f94dfcafd 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -101,12 +101,10 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} - fstaggered1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] - fstaggered1_R_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] - fstaggered2_L_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - fstaggered2_R_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + fstaggered1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_L_threaded, fstaggered2_L_threaded, fstaggered1_R_threaded, fstaggered2_R_threaded) + return (; cache..., fstaggered1_threaded, fstaggered2_threaded) end @@ -553,13 +551,11 @@ end @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral # high-order dg fluxes - @unpack fstaggered1_L_threaded, fstaggered2_L_threaded, fstaggered1_R_threaded, fstaggered2_R_threaded = cache + @unpack fstaggered1_threaded, fstaggered2_threaded = cache - fstaggered1_L = fstaggered1_L_threaded[Threads.threadid()] - fstaggered2_L = fstaggered2_L_threaded[Threads.threadid()] - fstaggered1_R = fstaggered1_R_threaded[Threads.threadid()] - fstaggered2_R = fstaggered2_R_threaded[Threads.threadid()] - calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u, mesh, + fstaggered1 = fstaggered1_threaded[Threads.threadid()] + fstaggered2 = fstaggered2_threaded[Threads.threadid()] + calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # low-order fv fluxes @@ -581,8 +577,8 @@ end for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += ( (1 - alpha_blending) * - (inverse_weights[i] * (fstaggered1_L[v, i+1, j] - fstaggered1_R[v, i, j]) + - inverse_weights[j] * (fstaggered2_L[v, i, j+1] - fstaggered2_R[v, i, j])) ) + + (inverse_weights[i] * (fstaggered1[v, i+1, j] - fstaggered1[v, i, j]) + + inverse_weights[j] * (fstaggered2[v, i, j+1] - fstaggered2[v, i, j])) ) + ( alpha_blending * (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) ) @@ -627,92 +623,46 @@ end end -# calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u, mesh, +# calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, # nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # # Calculate the staggered grid volume fluxes inside the elements (**without non-conservative terms**). # # # Arguments -# - `fstaggered1_L::AbstractArray{<:Real, 3}` -# - `fstaggered1_R::AbstractArray{<:Real, 3}` -# - `fstaggered2_L::AbstractArray{<:Real, 3}` -# - `fstaggered2_R::AbstractArray{<:Real, 3}` -@inline function calcflux_staggered!(fstaggered1_L, fstaggered2_L, fstaggered1_R, fstaggered2_R, u::AbstractArray{<:Any,4}, +# - `fstaggered1::AbstractArray{<:Real, 3}` +# - `fstaggered2::AbstractArray{<:Real, 3}` +@inline function calcflux_staggered!(fstaggered1, fstaggered2, u::AbstractArray{<:Any,4}, mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis - fstaggered1_L[:, 1, :] .= zero(eltype(fstaggered1_L)) - fstaggered1_L[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1_L)) - fstaggered1_R[:, 1, :] .= zero(eltype(fstaggered1_R)) - fstaggered1_R[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1_R)) + fstaggered1[:, 1, :] .= zero(eltype(fstaggered1)) + fstaggered1[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1)) - for j in eachnode(dg) - local_fluxes_1!(fstaggered1_L, fstaggered1_R, u, - nonconservative_terms, equations, - volume_flux, dg, j, element) - end - - fstaggered2_L[:, :, 1 ] .= zero(eltype(fstaggered2_L)) - fstaggered2_L[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2_L)) - fstaggered2_R[:, :, 1 ] .= zero(eltype(fstaggered2_R)) - fstaggered2_R[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2_R)) - - for i in eachnode(dg) - local_fluxes_2!(fstaggered2_L, fstaggered2_R, u, - nonconservative_terms, equations, - volume_flux, dg, i, element) - end - - return nothing -end - - -@inline function local_fluxes_1!(fstaggered_L, fstaggered_R, u::AbstractArray{<:Any,4}, - nonconservative_terms::Val{false}, equations, - volume_flux, dg::DGSEM, j, element) - @unpack weights, derivative_split = dg.basis + fstaggered2[:, :, 1 ] .= zero(eltype(fstaggered2)) + fstaggered2[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2)) - for i in 2:nnodes(dg) - fstaggered_L[:, i, j] .= zero(eltype(fstaggered_L)) - fstaggered_R[:, i, j] .= zero(eltype(fstaggered_R)) - for iip in i:nnodes(dg) - uiip = get_node_vars(u, equations, dg, iip, j, element) - for iim in 1:i-1 - uiim = get_node_vars(u, equations, dg, iim, j, element) - flux = volume_flux(uiim, uiip, 1, equations) - multiply_add_to_node_vars!(fstaggered_L, weights[iim] * derivative_split[iim, iip], flux, equations, dg, i, j) - multiply_add_to_node_vars!(fstaggered_R, weights[iim] * derivative_split[iim, iip], flux, equations, dg, i, j) - end + for j in eachnode(dg), i in 1:nnodes(dg)-1 + for v in eachvariable(equations) + fstaggered1[v, i+1, j] = fstaggered1[v, i, j] + fstaggered2[v, j, i+1] = fstaggered2[v, j, i] end - end - - return nothing -end - -@inline function local_fluxes_2!(fstaggered_L, fstaggered_R, u::AbstractArray{<:Any,4}, - nonconservative_terms::Val{false}, equations, - volume_flux, dg::DGSEM, i, element) - @unpack weights, derivative_split = dg.basis - for j in 2:nnodes(dg) - fstaggered_L[:, i, j] .= zero(eltype(fstaggered_L)) - fstaggered_R[:, i, j] .= zero(eltype(fstaggered_R)) - for jjp in j:nnodes(dg) - ujjp = get_node_vars(u, equations, dg, i, jjp, element) - for jjm in 1:j-1 - ujjm = get_node_vars(u, equations, dg, i, jjm, element) - flux = volume_flux(ujjm, ujjp, 2, equations) - multiply_add_to_node_vars!(fstaggered_L, weights[jjm] * derivative_split[jjm, jjp], flux, equations, dg, i, j) - multiply_add_to_node_vars!(fstaggered_R, weights[jjm] * derivative_split[jjm, jjp], flux, equations, dg, i, j) - end + uij = get_node_vars(u, equations, dg, i, j, element) + uji = get_node_vars(u, equations, dg, j, i, element) + for ii in eachnode(dg) + uiij = get_node_vars(u, equations, dg, ii, j, element) + ujii = get_node_vars(u, equations, dg, j, ii, element) + multiply_add_to_node_vars!(fstaggered1, weights[i] * derivative_split[i, ii], volume_flux(uij, uiij, 1, equations), equations, dg, i+1, j) + multiply_add_to_node_vars!(fstaggered2, weights[i] * derivative_split[i, ii], volume_flux(uji, ujii, 2, equations), equations, dg, j, i+1) end end return nothing end + # functions local_fluxes_1! and local_fluxes_2! for old data structure # @inline function local_fluxes_1!(fluxes, u::AbstractArray{<:Any,4}, # nonconservative_terms::Val{false}, equations, From 034a4f7d318f064ca19bf11eb4ff4b80a123649c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 14 Jan 2022 14:04:10 +0100 Subject: [PATCH 003/423] Implement some first suggestions --- src/solvers/dg.jl | 13 ++- src/solvers/dgsem_tree/dg_2d.jl | 138 +++++++------------------------- 2 files changed, 42 insertions(+), 109 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 84dd9ddb0e..e5c568a0ba 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -142,14 +142,23 @@ function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralPureLGLFi end +""" + VolumeIntegralStaggeredGrid + +A shock-capturing volume integral type for DG methods based on a subcell blending approach +with a low-order FV method. + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" struct VolumeIntegralStaggeredGrid{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG volume_flux_fv::VolumeFluxFV indicator::Indicator end -function VolumeIntegralStaggeredGrid(indicator; volume_flux_dg=flux_ranocha, - volume_flux_fv=flux_lax_friedrichs) +function VolumeIntegralStaggeredGrid(indicator; volume_flux_dg, + volume_flux_fv) VolumeIntegralStaggeredGrid{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( volume_flux_dg, volume_flux_fv, indicator) end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 1f94dfcafd..4dca6d80c5 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -79,12 +79,6 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMe end -function create_cache(mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, equations, - volume_integral::VolumeIntegralStaggeredGrid, dg::DG, uEltype) - error("VolumeIntegralStaggeredGrid only defined for TreeMesh") -end - - function create_cache(mesh::TreeMesh{2}, equations, volume_integral::VolumeIntegralStaggeredGrid, dg::DG, uEltype) @@ -94,10 +88,6 @@ function create_cache(mesh::TreeMesh{2}, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) - # old structure of staggered grid fluxes - # FluxType = SVector{nvariables(equations), uEltype} - # fstaggered_threaded = [Vector{FluxType}(undef, nnodes(dg) - 1) for _ in 1:Threads.nthreads()] - A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -520,15 +510,6 @@ end end -function calc_volume_integral!(du, u, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, - nonconservative_terms, equations, - volume_integral::VolumeIntegralStaggeredGrid, - dg::DGSEM, cache) - error("VolumeIntegralStaggeredGrid only defined for TreeMesh") -end - - function calc_volume_integral!(du, u, mesh::TreeMesh{2}, nonconservative_terms, equations, @@ -586,39 +567,6 @@ end end end - # ----------------------------------------------------------------------------------------------- - # old version of calculation with fstaggered as Vector of SVectors - # (only for one "line", in x or y direction) - # @unpack fstaggered_threaded = cache - - # fstaggered = fstaggered_threaded[Threads.threadid()] - - # # x - # for j in eachnode(dg) - # # compute local high-order flux - # local_fluxes_1!(fstaggered, u, nonconservative_terms, equations, volume_flux_dg, dg, j, element) - - # # update volume contribution in locally conservative form - # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[1] * fstaggered[1], equations, dg, 1, j, element) - # for i in 2:nnodes(dg)-1 - # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[i] * (fstaggered[i] - fstaggered[i-1]), equations, dg, i, j, element) - # end - # add_to_node_vars!(du, -(1 - alpha_blending) * inverse_weights[end] * fstaggered[end], equations, dg, nnodes(dg), j, element) - # end - - # # y - # for i in eachnode(dg) - # # compute local high-order fluxes - # local_fluxes_2!(fstaggered, u, nonconservative_terms, equations, volume_flux_dg, dg, i, element) - - # # update volume contribution in locally conservative form - # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[1] * fstaggered[1], equations, dg, i, 1, element) - # for j in 2:nnodes(dg)-1 - # add_to_node_vars!(du, (1 - alpha_blending) * inverse_weights[j] * (fstaggered[j] - fstaggered[j-1]), equations, dg, i, j, element) - # end - # add_to_node_vars!(du, -(1 - alpha_blending) * inverse_weights[end] * fstaggered[end], equations, dg, i, nnodes(dg), element) - # end - return nothing end @@ -631,31 +579,49 @@ end # # Arguments # - `fstaggered1::AbstractArray{<:Real, 3}` # - `fstaggered2::AbstractArray{<:Real, 3}` -@inline function calcflux_staggered!(fstaggered1, fstaggered2, u::AbstractArray{<:Any,4}, +@inline function calcflux_staggered!(fstaggered1, fstaggered2, u, mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis + # x fstaggered1[:, 1, :] .= zero(eltype(fstaggered1)) fstaggered1[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1)) + for j in eachnode(dg) + for i in 1:nnodes(dg)-1 + for v in eachvariable(equations) + fstaggered1[v, i+1, j] = fstaggered1[v, i, j] + end + + u_node = get_node_vars(u, equations, dg, i, j, element) + for ii in eachnode(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + + flux1 = volume_flux(u_node, u_node_ii, 1, equations) + multiply_add_to_node_vars!(fstaggered1, weights[i] * derivative_split[i, ii], flux1, equations, dg, i+1, j) + end + end + end + + # y fstaggered2[:, :, 1 ] .= zero(eltype(fstaggered2)) fstaggered2[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2)) - for j in eachnode(dg), i in 1:nnodes(dg)-1 - for v in eachvariable(equations) - fstaggered1[v, i+1, j] = fstaggered1[v, i, j] - fstaggered2[v, j, i+1] = fstaggered2[v, j, i] - end + for i in eachnode(dg) + for j in 1:nnodes(dg)-1 + for v in eachvariable(equations) + fstaggered2[v, i, j+1] = fstaggered2[v, i, j] + end - uij = get_node_vars(u, equations, dg, i, j, element) - uji = get_node_vars(u, equations, dg, j, i, element) - for ii in eachnode(dg) - uiij = get_node_vars(u, equations, dg, ii, j, element) - ujii = get_node_vars(u, equations, dg, j, ii, element) - multiply_add_to_node_vars!(fstaggered1, weights[i] * derivative_split[i, ii], volume_flux(uij, uiij, 1, equations), equations, dg, i+1, j) - multiply_add_to_node_vars!(fstaggered2, weights[i] * derivative_split[i, ii], volume_flux(uji, ujii, 2, equations), equations, dg, j, i+1) + u_node = get_node_vars(u, equations, dg, i, j, element) + for jj in eachnode(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + + flux2 = volume_flux(u_node, u_node_jj, 2, equations) + multiply_add_to_node_vars!(fstaggered2, weights[j] * derivative_split[j, jj], flux2, equations, dg, i, j+1) + end end end @@ -663,48 +629,6 @@ end end -# functions local_fluxes_1! and local_fluxes_2! for old data structure -# @inline function local_fluxes_1!(fluxes, u::AbstractArray{<:Any,4}, -# nonconservative_terms::Val{false}, equations, -# volume_flux, dg::DGSEM, j, element) -# @unpack weights, derivative_split = dg.basis - -# for i in eachindex(fluxes) -# flux1 = zero(eltype(fluxes)) -# for iip in i+1:nnodes(dg) -# uiip = get_node_vars(u, equations, dg, iip, j, element) -# for iim in 1:i -# uiim = get_node_vars(u, equations, dg, iim, j, element) -# flux1 += weights[iim] * derivative_split[iim,iip] * volume_flux(uiim, uiip, 1, equations) -# end -# end -# fluxes[i] = flux1 -# end - -# return nothing -# end - -# @inline function local_fluxes_2!(fluxes, u::AbstractArray{<:Any,4}, -# nonconservative_terms::Val{false}, equations, -# volume_flux, dg::DGSEM, i, element) -# @unpack weights, derivative_split = dg.basis - -# for j in eachindex(fluxes) -# flux2 = zero(eltype(fluxes)) -# for jjp in j+1:nnodes(dg) -# ujjp = get_node_vars(u, equations, dg, i, jjp, element) -# for jjm in 1:j -# ujjm = get_node_vars(u, equations, dg, i, jjm, element) -# flux2 += weights[jjm] * derivative_split[jjm,jjp] * volume_flux(ujjm, ujjp, 2, equations) -# end -# end -# fluxes[j] = flux2 -# end - -# return nothing -# end - - function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) @unpack interfaces = cache From 6a346f9b4875d2148e434f4aa38b4ae16384821c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 14 Jan 2022 14:21:58 +0100 Subject: [PATCH 004/423] Implement some more suggestions --- src/solvers/dgsem_tree/dg_2d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4dca6d80c5..df3f4e23ab 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -524,7 +524,7 @@ end @inline function staggered_grid_kernel!(du, u, element, mesh::TreeMesh{2}, - nonconservative_terms, equations, + nonconservative_terms::Val{false}, equations, volume_integral, dg::DGSEM, cache, alpha=true) # true * [some floating point value] == [exactly the same floating point value] # This can (hopefully) be optimized away due to constant propagation. @@ -574,7 +574,7 @@ end # calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, # nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # -# Calculate the staggered grid volume fluxes inside the elements (**without non-conservative terms**). +# Calculate the staggered volume fluxes inside the elements (**without non-conservative terms**). # # # Arguments # - `fstaggered1::AbstractArray{<:Real, 3}` @@ -620,7 +620,7 @@ end u_node_jj = get_node_vars(u, equations, dg, i, jj, element) flux2 = volume_flux(u_node, u_node_jj, 2, equations) - multiply_add_to_node_vars!(fstaggered2, weights[j] * derivative_split[j, jj], flux2, equations, dg, i, j+1) + multiply_add_to_node_vars!(fstaggered2, weights[j] * derivative_split[j, jj], flux2, equations, dg, i, j+1) end end end From a70744fa334a52fed3722be1f8b921555d19e39d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 18 Jan 2022 11:31:49 +0100 Subject: [PATCH 005/423] Add volume flux precomputation (using symmetry) --- src/solvers/dgsem_tree/dg_2d.jl | 77 +++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index df3f4e23ab..a483375411 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -90,11 +90,13 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} + A3d = Array{uEltype, 3} fstaggered1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_threaded, fstaggered2_threaded) + return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded) end @@ -584,45 +586,64 @@ end volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded = cache - # x + flux_temp = flux_temp_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fstaggered_(0,1) = f_0 + w_0 * FVol_0, + # fstaggered_(j,j+1) = fstaggered_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of the `volume_flux` to save half of the possible two-poitn flux + # computations. + for ii in (i+1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + flux1 = volume_flux(u_node, u_node_ii, 1, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1, equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, equations, dg, ii, j) + end + end + + # FV-form flux `fstaggered` in x direction fstaggered1[:, 1, :] .= zero(eltype(fstaggered1)) fstaggered1[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1)) - for j in eachnode(dg) - for i in 1:nnodes(dg)-1 - for v in eachvariable(equations) - fstaggered1[v, i+1, j] = fstaggered1[v, i, j] - end + for j in eachnode(dg), i in 1:nnodes(dg)-1, v in eachvariable(equations) + fstaggered1[v, i+1, j] = fstaggered1[v, i, j] + weights[i] * flux_temp[v, i, j] + end - u_node = get_node_vars(u, equations, dg, i, j, element) - for ii in eachnode(dg) - u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + # Split form volume flux in in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) - flux1 = volume_flux(u_node, u_node_ii, 1, equations) - multiply_add_to_node_vars!(fstaggered1, weights[i] * derivative_split[i, ii], flux1, equations, dg, i+1, j) - end + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + for jj in (j+1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + flux2 = volume_flux(u_node, u_node_jj, 2, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2, equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, equations, dg, i, jj) end end - # y + # FV-form flux `fstaggered` in y direction fstaggered2[:, :, 1 ] .= zero(eltype(fstaggered2)) fstaggered2[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2)) - for i in eachnode(dg) - for j in 1:nnodes(dg)-1 - for v in eachvariable(equations) - fstaggered2[v, i, j+1] = fstaggered2[v, i, j] - end - - u_node = get_node_vars(u, equations, dg, i, j, element) - for jj in eachnode(dg) - u_node_jj = get_node_vars(u, equations, dg, i, jj, element) - - flux2 = volume_flux(u_node, u_node_jj, 2, equations) - multiply_add_to_node_vars!(fstaggered2, weights[j] * derivative_split[j, jj], flux2, equations, dg, i, j+1) - end - end + for j in 1:nnodes(dg)-1, i in eachnode(dg), v in eachvariable(equations) + fstaggered2[v, i, j+1] = fstaggered2[v, i, j] + weights[j] * flux_temp[v, i, j] end return nothing From 6334999eac1a84b7a45e6abc832b31e996b870cb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 1 Feb 2022 11:22:20 +0100 Subject: [PATCH 006/423] Implement suggestions --- src/solvers/dg.jl | 2 ++ src/solvers/dgsem_tree/dg_2d.jl | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index e5c568a0ba..a205a1c429 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -150,6 +150,8 @@ with a low-order FV method. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. + +See also: [`VolumeIntegralShockCapturingHG`](@ref) """ struct VolumeIntegralStaggeredGrid{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index a483375411..870cfa6625 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -533,7 +533,7 @@ end @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral - # high-order dg fluxes + # high-order DG fluxes @unpack fstaggered1_threaded, fstaggered2_threaded = cache fstaggered1 = fstaggered1_threaded[Threads.threadid()] @@ -541,7 +541,7 @@ end calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - # low-order fv fluxes + # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache fstar1_L = fstar1_L_threaded[Threads.threadid()] @@ -625,7 +625,7 @@ end fstaggered1[v, i+1, j] = fstaggered1[v, i, j] + weights[i] * flux_temp[v, i, j] end - # Split form volume flux in in orientation 2: y direction + # Split form volume flux in orientation 2: y direction flux_temp .= zero(eltype(flux_temp)) for j in eachnode(dg), i in eachnode(dg) From 05534fb12eef682f7e7271e24bb02bc1cf5fe4d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 9 Feb 2022 12:13:18 +0100 Subject: [PATCH 007/423] Try RK with Trixi's structure (adding indicator is problem) --- src/Trixi.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 48 +++++-- src/solvers/dgsem_tree/indicators.jl | 35 +++++ src/solvers/dgsem_tree/indicators_2d.jl | 66 +++++++++ src/time_integration/methods_SSP.jl | 173 +++++++++++++++++++++++ src/time_integration/time_integration.jl | 1 + 6 files changed, 315 insertions(+), 10 deletions(-) create mode 100644 src/time_integration/methods_SSP.jl diff --git a/src/Trixi.jl b/src/Trixi.jl index 842886eb4b..b7008579f3 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -174,7 +174,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralStaggeredGrid, + VolumeIntegralStaggeredGrid, IndicatorIDP, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, MortarL2 diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 870cfa6625..7c1511751b 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -96,7 +96,13 @@ function create_cache(mesh::TreeMesh{2}, equations, fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded) + # TODO: flux_antidiffusive needs to be saved for all elements at once. Here we don't have nelements since we don't have the normal cache... + A4dp1_x = Array{uEltype, 4} + A4dp1_y = Array{uEltype, 4} + # flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, )) for _ in 1:Threads.nthreads()] + # flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements()) for _ in 1:Threads.nthreads()] + + return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded, )#flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) end @@ -517,6 +523,12 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralStaggeredGrid, dg::DGSEM, cache) + + # A4dp1_x = Array{uEltype, 4} + # A4dp1_y = Array{uEltype, 4} + # flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, cache)) for _ in 1:Threads.nthreads()] + # flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements(dg, cache)) for _ in 1:Threads.nthreads()] + # cache = (cache..., flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) @threaded for element in eachelement(dg, cache) staggered_grid_kernel!(du, u, element, mesh, nonconservative_terms, equations, @@ -553,19 +565,22 @@ end # Calculate blending factor alpha_blending - alpha_blending = volume_integral.indicator + # @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache + + # flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] + # flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] + # calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1_L, fstar2_L, u, mesh, + # nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - du[v, i, j, element] += ( (1 - alpha_blending) * - (inverse_weights[i] * (fstaggered1[v, i+1, j] - fstaggered1[v, i, j]) + - inverse_weights[j] * (fstaggered2[v, i, j+1] - fstaggered2[v, i, j])) ) + - ( alpha_blending * - (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + - inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) ) - + du[v, i, j, element] += (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) + # ( (1 - alpha_blending) * + # (inverse_weights[i] * (fstaggered1[v, i+1, j] - fstaggered1[v, i, j]) + + # inverse_weights[j] * (fstaggered2[v, i, j+1] - fstaggered2[v, i, j])) ) end end @@ -649,6 +664,21 @@ end return nothing end +function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, dg, element, cache) + @unpack inverse_weights = dg.basis + inverse_jacobian = cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + flux_antidiffusive1[v, i, j, element] = inverse_jacobian * inverse_weights[i] * (fstaggered1[v, i, j] - fstar1[v, i, j]) + flux_antidiffusive2[v, i, j, element] = inverse_jacobian * inverse_weights[j] * (fstaggered2[v, i, j] - fstar2[v, i, j]) + end + end + + return nothing +end + function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 3f70a75a57..236c1f4835 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -151,6 +151,41 @@ const IndicatorLoehner = IndicatorLöhner end +""" + IndicatorIDP + +Indicator used for subcell shock-capturing used by Rueda-Ramírez, Pazner, Gassner. +""" +struct IndicatorIDP{Variable, Cache} <: AbstractIndicator + # alpha_max::RealT + # alpha_min::RealT + # alpha_smooth::Bool + variable::Variable + cache::Cache +end + +# this method is used when the indicator is constructed as for shock-capturing volume integrals +function IndicatorIDP(equations::AbstractEquations, basis; + # alpha_max=0.5, + # alpha_min=0.001, + # alpha_smooth=true, + variable) + # alpha_max, alpha_min = promote(alpha_max, alpha_min) + cache = create_cache(IndicatorIDP, equations, basis) + IndicatorIDP{typeof(variable), typeof(cache)}(variable, cache) +end + +function Base.show(io::IO, indicator::IndicatorIDP) + @nospecialize indicator # reduce precompilation time + + print(io, "IndicatorIDP(") + 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 + struct IndicatorMax{Variable, Cache<:NamedTuple} <: AbstractIndicator variable::Variable diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 60230948c4..d7a6dd4f58 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -190,6 +190,72 @@ function (löhner::IndicatorLöhner)(u::AbstractArray{<:Any,4}, end +# this method is used when the indicator is constructed as for shock-capturing volume integrals +function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) + + A = Array{real(basis), ndims(equations)} + var_max_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + var_min_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + P_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + P_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + alpha_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + alpha_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + + alpha_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + alpha_prov_threaded = similar(alpha_threaded) + + indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + + # modal_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + # modal_tmp1_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + + return (; var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, + alpha_plus_threaded, alpha_minus_threaded, alpha_threaded, alpha_prov_threaded, + indicator_threaded) +end + +function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, + mesh, equations, dg::DGSEM, + element, cache; + kwargs...) + @unpack var_max_threaded, var_min_threaded, indicator_threaded = indicator_IDP.cache + + var_max = var_max_threaded[Threads.threadid()] + var_min = var_min_threaded[Threads.threadid()] + indicator = indicator_threaded[Threads.threadid()] + + # 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) + indicator[i, j] = indicator_IDP.variable(u_local, equations) + end + + # Calculate max and min of variable at Gauss-Lobatto nodes + var_max[1, 1], var_min[1, 1] = extrema((indicator[1, 1], indicator[1, 2], indicator[2, 1])) + var_max[1, nnodes(dg)], var_min[1, nnodes(dg)] = extrema((indicator[1, nnodes(dg)], indicator[1, nnodes(dg)-1], indicator[2, nnodes(dg)])) + var_max[nnodes(dg), 1], var_min[nnodes(dg), 1] = extrema((indicator[nnodes(dg), 1], indicator[nnodes(dg), 2], indicator[nnodes(dg)-1, 1])) + var_max[nnodes(dg), nnodes(dg)], var_min[nnodes(dg), nnodes(dg)] = extrema((indicator[nnodes(dg), nnodes(dg)], indicator[nnodes(dg)-1, nnodes(dg)], indicator[nnodes(dg), nnodes(dg)-1])) + for i in 2:nnodes(dg)-1 + var_max[i, 1], var_min[i, 1] = extrema((indicator[i, 1], indicator[i, 2], indicator[i+1, 1], indicator[i-1, 1])) + var_max[1, i], var_min[1, i] = extrema((indicator[1, i], indicator[2, i], indicator[1, i+1], indicator[1, i-1])) + var_max[i, nnodes(dg)], var_min[i, nnodes(dg)] = extrema((indicator[i, nnodes(dg)], indicator[i, nnodes(dg)-1], indicator[i+1, nnodes(dg)], indicator[i-1, nnodes(dg)])) + var_max[nnodes(dg), i], var_min[nnodes(dg), i] = extrema((indicator[nnodes(dg), i], indicator[nnodes(dg)-1, i], indicator[nnodes(dg), i+1], indicator[nnodes(dg), i-1])) + end + for j in 2:nnodes(dg)-1, i in 2:nnodes(dg)-1 + var_max[i, j], var_min[i, j] = extrema((indicator[i, j], indicator[i, j-1], indicator[i, j+1], indicator[i+1, j], indicator[i-1, j])) + end + + @unpack P_plus_threaded, P_minus_threaded = indicator_IDP.cache + P_plus = P_plus_threaded[Threads.threadid()] + P_minus = P_minus_threaded[Threads.threadid()] + + @unpack alpha_threaded = indicator_IDP.cache + alpha = alpha_threaded[Threads.threadid()] + + + return alpha +end + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl new file mode 100644 index 0000000000..2af163f8d4 --- /dev/null +++ b/src/time_integration/methods_SSP.jl @@ -0,0 +1,173 @@ +# 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 + + +abstract type SimpleAlgorithmSSP end + + +""" + SSPRK33_ShuOsher() + +""" +struct SSPRK33_ShuOsher <: SimpleAlgorithmSSP + + function SSPRK33_ShuOsher() + new() + end +end + + +# This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L1 +mutable struct SimpleIntegratorSSPOptions{Callback} + callback::Callback # callbacks; used in Trixi + adaptive::Bool # whether the algorithm is adaptive; ignored + dtmax::Float64 # ignored + maxiters::Int # maximal numer of time steps + tstops::Vector{Float64} # tstops from https://diffeq.sciml.ai/v6.8/basics/common_solver_opts/#Output-Control-1; ignored +end + +function SimpleIntegratorSSPOptions(callback, tspan; maxiters=typemax(Int), kwargs...) + SimpleIntegratorSSPOptions{typeof(callback)}( + callback, false, Inf, maxiters, [last(tspan)]) +end + +# This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 +# This implements the interface components described at +# https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 +# which are used in Trixi. +mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, Alg, SimpleIntegratorSSPOptions} + u::uType # + du::uType + u_tmp::uType + t::RealT + dt::RealT # current time step + dtcache::RealT # ignored + iter::Int # current number of time steps (iteration) + p::Params # will be the semidiscretization from Trixi + sol::Sol # faked + alg::Alg + opts::SimpleIntegratorSSPOptions + finalstep::Bool # added for convenience +end + +# Forward integrator.destats.naccept to integrator.iter (see GitHub PR#771) +function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) + if field === :destats + return (naccept = getfield(integrator, :iter),) + end + # general fallback + return getfield(integrator, field) +end + +""" + solve_IDP() + +The following structures and methods provide a implementation of the +SSP Runge-Kutta method of + + Shu, Osher (1988) Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes, eq. 2.18. +""" +function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) + alg = SSPRK33_ShuOsher() + + u = copy(ode.u0) + du = similar(u) + u_tmp = similar(u) + t = first(ode.tspan) + iter = 0 + integrator = SimpleIntegratorSSP(u, du, u_tmp, t, dt, zero(dt), iter, ode.p, + (prob=ode,), alg, + SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) + + if callback isa CallbackSet + for cb in callback.continuous_callbacks + error("unsupported") + end + for cb in callback.discrete_callbacks + cb.initialize(cb, integrator.u, integrator.t, integrator) + end + elseif !isnothing(callback) + error("unsupported") + end + + solve!(integrator) +end + +function solve!(integrator::SimpleIntegratorSSP) + @unpack prob = integrator.sol + @unpack alg = integrator + t_end = last(prob.tspan) + callbacks = integrator.opts.callback + + integrator.finalstep = false + @trixi_timeit timer() "main loop" while !integrator.finalstep + if isnan(integrator.dt) + error("time step size `dt` is NaN") + end + + # if the next iteration would push the simulation beyond the end time, set dt accordingly + if integrator.t + integrator.dt > t_end || isapprox(integrator.t + integrator.dt, t_end) + integrator.dt = t_end - integrator.t + terminate!(integrator) + end + + prob.f(integrator.du, integrator.u, integrator.p, integrator.t) + integrator.u_tmp = integrator.u + integrator.dt * integrator.du + + prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + integrator.dt) + integrator.u_tmp = 3/4 * integrator.u + 1/4 * integrator.u_tmp + 1/4 * integrator.dt * integrator.du + + prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + 1/2 * integrator.dt) + integrator.u = 1/3 * integrator.u + 2/3 * integrator.u_tmp + 2/3 * integrator.dt * integrator.du + + @unpack alpha_threaded = integrator.p.solver.volume_integral.indicator.cache + + # calcalpha_blending!(alpha_blending, volume_integral.indicator(u, mesh, equations, dg, element, cache) + + integrator.iter += 1 + integrator.t += integrator.dt + + # handle callbacks + if callbacks isa CallbackSet + for cb in callbacks.discrete_callbacks + if cb.condition(integrator.u, integrator.t, integrator) + cb.affect!(integrator) + end + end + end + + # respect maximum number of iterations + if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep + @warn "Interrupted. Larger maxiters is needed." + terminate!(integrator) + end + end + + return TimeIntegratorSolution((first(prob.tspan), integrator.t), + (prob.u0, integrator.u), + integrator.sol.prob) +end + +# get a cache where the RHS can be stored +get_du(integrator::SimpleIntegratorSSP) = integrator.du +get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_tmp,) + +# some algorithms from DiffEq like FSAL-ones need to be informed when a callback has modified u +u_modified!(integrator::SimpleIntegratorSSP, ::Bool) = false + +# used by adaptive timestepping algorithms in DiffEq +function set_proposed_dt!(integrator::SimpleIntegratorSSP, dt) + integrator.dt = dt +end + +# stop the time integration +function terminate!(integrator::SimpleIntegratorSSP) + integrator.finalstep = true + empty!(integrator.opts.tstops) +end + + +end # @muladd \ No newline at end of file diff --git a/src/time_integration/time_integration.jl b/src/time_integration/time_integration.jl index 9b0c7c7783..131731d452 100644 --- a/src/time_integration/time_integration.jl +++ b/src/time_integration/time_integration.jl @@ -15,6 +15,7 @@ end include("methods_2N.jl") include("methods_3Sstar.jl") +include("methods_SSP.jl") end # @muladd From ebbb1c7d1f22af337362214dfd0d9a872529e175 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 10 Feb 2022 18:38:36 +0100 Subject: [PATCH 008/423] Add indicator_IDP --- .../elixir_euler_blast_wave_sc_subcell.jl | 90 +++++++++++++++++++ ...euler_ec_shockcapturing_subcell_SSPRK3.jl} | 27 +++--- src/solvers/dgsem_tree/dg_2d.jl | 80 +++++++++++------ src/solvers/dgsem_tree/indicators_2d.jl | 79 ++++++++++++---- src/time_integration/methods_SSP.jl | 23 ++++- 5 files changed, 242 insertions(+), 57 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl rename examples/tree_2d_dgsem/{elixir_euler_ec_staggered_grid.jl => elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl} (67%) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..78f443f2e3 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -0,0 +1,90 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +A medium blast wave taken from +- Sebastian Hennemann, Gregor J. 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) +""" +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorIDP(equations, basis; + variable=density_pressure) +volume_integral = VolumeIntegralStaggeredGrid(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=10_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 12.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +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_euler_ec_staggered_grid.jl b/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl similarity index 67% rename from examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl rename to examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl index e5a34ab7a0..8e13f7f2ac 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_staggered_grid.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl @@ -8,10 +8,13 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralStaggeredGrid(0.5; volume_flux_dg=volume_flux, - volume_flux_fv=volume_flux)) +indicator_sc = IndicatorIDP(equations, basis; variable=density) +volume_integral=VolumeIntegralStaggeredGrid(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=volume_flux) +solver = DGSEM(basis, flux_ranocha, volume_integral) coordinates_min = (-2.0, -2.0) coordinates_max = ( 2.0, 2.0) @@ -36,25 +39,27 @@ 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_solution = SaveSolutionCallback(interval=10, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval=analysis_interval) + stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, +callbacks = CallbackSet(summary_callback, save_solution, 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 +# Trixi.solve(ode, Trixi.CarpenterKennedy2N43(); +# dt=0.01, callback=callbacks) +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +sol = Trixi.solve_IDP(ode, semi; + dt=0.01, # 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/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 7c1511751b..9d22aedbec 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -30,6 +30,8 @@ function create_cache(mesh::TreeMesh{2}, equations, cache = (;cache..., create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) cache = (;cache..., create_cache(mesh, equations, dg.mortar, uEltype)...) + cache = (;cache..., create_cache(cache, equations, dg, uEltype)...) + return cache end @@ -96,12 +98,6 @@ function create_cache(mesh::TreeMesh{2}, equations, fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - # TODO: flux_antidiffusive needs to be saved for all elements at once. Here we don't have nelements since we don't have the normal cache... - A4dp1_x = Array{uEltype, 4} - A4dp1_y = Array{uEltype, 4} - # flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, )) for _ in 1:Threads.nthreads()] - # flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements()) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded, )#flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) end @@ -523,12 +519,6 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralStaggeredGrid, dg::DGSEM, cache) - - # A4dp1_x = Array{uEltype, 4} - # A4dp1_y = Array{uEltype, 4} - # flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, cache)) for _ in 1:Threads.nthreads()] - # flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements(dg, cache)) for _ in 1:Threads.nthreads()] - # cache = (cache..., flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) @threaded for element in eachelement(dg, cache) staggered_grid_kernel!(du, u, element, mesh, nonconservative_terms, equations, @@ -550,9 +540,10 @@ end fstaggered1 = fstaggered1_threaded[Threads.threadid()] fstaggered2 = fstaggered2_threaded[Threads.threadid()] + @trixi_timeit timer() "calculation fstaggered" begin calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - + end # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -560,27 +551,26 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] + @trixi_timeit timer() "calculation fstar" begin calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - + end # Calculate blending factor alpha_blending - # @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache - - # flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] - # flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] - # calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1_L, fstar2_L, u, mesh, - # nonconservative_terms, equations, dg, element, cache) - + @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache + flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] + flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] + @trixi_timeit timer() "calculation flux_antidiffusive" begin + calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1_L, fstar2_L, u, mesh, + nonconservative_terms, equations, dg, element, cache) + end # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) - # ( (1 - alpha_blending) * - # (inverse_weights[i] * (fstaggered1[v, i+1, j] - fstaggered1[v, i, j]) + - # inverse_weights[j] * (fstaggered2[v, i, j+1] - fstaggered2[v, i, j])) ) + end end @@ -667,12 +657,48 @@ end function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) @unpack inverse_weights = dg.basis - inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - flux_antidiffusive1[v, i, j, element] = inverse_jacobian * inverse_weights[i] * (fstaggered1[v, i, j] - fstar1[v, i, j]) - flux_antidiffusive2[v, i, j, element] = inverse_jacobian * inverse_weights[j] * (fstaggered2[v, i, j] - fstar2[v, i, j]) + flux_antidiffusive1[v, i, j, element] = (fstaggered1[v, i, j] - fstar1[v, i, j]) + flux_antidiffusive2[v, i, j, element] = (fstaggered2[v, i, j] - fstar2[v, i, j]) + end + end + + flux_antidiffusive1[:, 1, :, element] .= zero(eltype(flux_antidiffusive1)) + flux_antidiffusive1[:, nnodes(dg)+1, :, element] .= zero(eltype(flux_antidiffusive1)) + + flux_antidiffusive2[:, :, 1, element] .= zero(eltype(flux_antidiffusive2)) + flux_antidiffusive2[:, :, nnodes(dg)+1, element] .= zero(eltype(flux_antidiffusive2)) + + return nothing +end + +function antidiffusive_stage!(u, u_old, dt, ode) + @unpack mesh, equations, solver = ode + @unpack inverse_weights = solver.basis + @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache + + @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = ode.cache + + u_old_ode = reshape(u_old, nvariables(equations), ntuple(_ -> nnodes(solver), ndims(equations))..., nelements(solver, ode.cache)) + u_ode = reshape(u, nvariables(equations), ntuple(_ -> nnodes(solver), ndims(equations))..., nelements(solver, ode.cache)) + + @threaded for element in eachelement(solver, ode.cache) + inverse_jacobian = -ode.cache.elements.inverse_jacobian[element] + + alpha1, alpha2 = ode.solver.volume_integral.indicator(u_ode, u_old_ode, mesh, equations, solver, dt, element, ode.cache) + + flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] + flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] + + # Calculate volume integral contribution + for j in eachnode(solver), i in eachnode(solver) + for v in eachvariable(equations) + u_ode[v, i, j, element] += dt * inverse_jacobian * + (inverse_weights[i] * (1 - alpha1[i+1, j]) * (flux_antidiffusive1[v, i+1, j, element] - flux_antidiffusive1[v, i, j, element]) + + inverse_weights[j] * (1 - alpha2[i, j+1]) * (flux_antidiffusive2[v, i, j+1, element] - flux_antidiffusive2[v, i, j, element]) ) + end end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index d7a6dd4f58..059efa7836 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -201,8 +201,9 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] alpha_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - alpha_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - alpha_prov_threaded = similar(alpha_threaded) + alpha1_threaded = [A(undef, nnodes(basis)+1, nnodes(basis), ) for _ in 1:Threads.nthreads()] + alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] + alpha_prov_threaded = [A(undef, nnodes(basis), nnodes(basis), ) for _ in 1:Threads.nthreads()] indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] @@ -210,32 +211,35 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas # modal_tmp1_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] return (; var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, - alpha_plus_threaded, alpha_minus_threaded, alpha_threaded, alpha_prov_threaded, + alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, alpha_prov_threaded, indicator_threaded) end -function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, +function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, mesh, equations, dg::DGSEM, - element, cache; + dt, element, cache; kwargs...) - @unpack var_max_threaded, var_min_threaded, indicator_threaded = indicator_IDP.cache + @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache + @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache - var_max = var_max_threaded[Threads.threadid()] - var_min = var_min_threaded[Threads.threadid()] - indicator = indicator_threaded[Threads.threadid()] + @unpack alpha_prov_threaded, alpha1_threaded, alpha2_threaded = indicator_IDP.cache # Calculate indicator variables at Gauss-Lobatto nodes + indicator = indicator_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) + u_local = get_node_vars(u_old, equations, dg, i, j, element) indicator[i, j] = indicator_IDP.variable(u_local, equations) end # Calculate max and min of variable at Gauss-Lobatto nodes + var_max = var_max_threaded[Threads.threadid()] + var_min = var_min_threaded[Threads.threadid()] + # corners var_max[1, 1], var_min[1, 1] = extrema((indicator[1, 1], indicator[1, 2], indicator[2, 1])) var_max[1, nnodes(dg)], var_min[1, nnodes(dg)] = extrema((indicator[1, nnodes(dg)], indicator[1, nnodes(dg)-1], indicator[2, nnodes(dg)])) var_max[nnodes(dg), 1], var_min[nnodes(dg), 1] = extrema((indicator[nnodes(dg), 1], indicator[nnodes(dg), 2], indicator[nnodes(dg)-1, 1])) var_max[nnodes(dg), nnodes(dg)], var_min[nnodes(dg), nnodes(dg)] = extrema((indicator[nnodes(dg), nnodes(dg)], indicator[nnodes(dg)-1, nnodes(dg)], indicator[nnodes(dg), nnodes(dg)-1])) - for i in 2:nnodes(dg)-1 + for i in 2:nnodes(dg)-1 # first colomn/row, last colomn/row var_max[i, 1], var_min[i, 1] = extrema((indicator[i, 1], indicator[i, 2], indicator[i+1, 1], indicator[i-1, 1])) var_max[1, i], var_min[1, i] = extrema((indicator[1, i], indicator[2, i], indicator[1, i+1], indicator[1, i-1])) var_max[i, nnodes(dg)], var_min[i, nnodes(dg)] = extrema((indicator[i, nnodes(dg)], indicator[i, nnodes(dg)-1], indicator[i+1, nnodes(dg)], indicator[i-1, nnodes(dg)])) @@ -245,15 +249,60 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, var_max[i, j], var_min[i, j] = extrema((indicator[i, j], indicator[i, j-1], indicator[i, j+1], indicator[i+1, j], indicator[i-1, j])) end - @unpack P_plus_threaded, P_minus_threaded = indicator_IDP.cache + # Calculate P_plus and P_minus P_plus = P_plus_threaded[Threads.threadid()] P_minus = P_minus_threaded[Threads.threadid()] + flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] + flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] - @unpack alpha_threaded = indicator_IDP.cache - alpha = alpha_threaded[Threads.threadid()] + @unpack inverse_weights = dg.basis + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + val_flux1_local = inverse_jacobian * inverse_weights[i] * indicator_IDP.variable(get_node_vars(flux_antidiffusive1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = inverse_jacobian * inverse_weights[i] * indicator_IDP.variable(get_node_vars(flux_antidiffusive1, equations, dg, i+1, j, element), equations) + val_flux2_local = inverse_jacobian * inverse_weights[j] * indicator_IDP.variable(get_node_vars(flux_antidiffusive2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = inverse_jacobian * inverse_weights[j] * indicator_IDP.variable(get_node_vars(flux_antidiffusive2, equations, dg, i, j+1, element), equations) + + P_plus[i, j] = dt * ((max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1)) + + (max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1))) + P_minus[i, j] = dt * ((min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1)) + + (min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1))) + end + # Calculate alpha_plus and alpha_minus + alpha_plus = alpha_plus_threaded[Threads.threadid()] + alpha_minus = alpha_plus_threaded[Threads.threadid()] + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + var = indicator_IDP.variable(u_local, equations) + alpha_plus[i, j] = 1 - min(1.0, max(0.0, (var_max[i, j] - var) / P_plus[i, j])) + alpha_minus[i, j] = 1 - min(1.0, max(0.0, (var_min[i, j] - var) / P_minus[i, j])) + isnan(alpha_plus[i, j]) && (alpha_plus[i, j] = 0.0) + isnan(alpha_minus[i, j]) && (alpha_minus[i, j] = 0.0) + # TODO: Added max(0.0, ...) and last two lines to make sure alpha_plus/minus is not -Inf, Inf or NaN + end - return alpha + # Calculate alpha_prov + alpha_prov = alpha_prov_threaded[Threads.threadid()] + for j in eachnode(dg), i in eachnode(dg) + alpha_prov[i, j] = max(alpha_plus[i, j], alpha_minus[i, j]) + end + + # Calculate alpha1 and alpha2 + alpha1 = alpha1_threaded[Threads.threadid()] + alpha2 = alpha2_threaded[Threads.threadid()] + for j in eachnode(dg), i in 2:nnodes(dg) + alpha1[i, j] = max(alpha_prov[i-1, j], alpha_prov[i, j]) + end + for j in 2:nnodes(dg), i in eachnode(dg) + alpha2[i, j] = max(alpha_prov[i, j-1], alpha_prov[i, j]) + end + alpha1[1, :] .= 0 + alpha1[nnodes(dg)+1, :] .= 0 + alpha2[:, 1] .= 0 + alpha2[:, nnodes(dg)+1] .= 0 + + return alpha1, alpha2 end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 2af163f8d4..4cf663d44c 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -62,6 +62,15 @@ function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) return getfield(integrator, field) end +function create_cache(cache, equations, dg, uEltype) + A4dp1_x = Array{uEltype, 4} + A4dp1_y = Array{uEltype, 4} + flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, cache)) for _ in 1:Threads.nthreads()] + flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements(dg, cache)) for _ in 1:Threads.nthreads()] + + return (; flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) +end + """ solve_IDP() @@ -71,6 +80,7 @@ SSP Runge-Kutta method of Shu, Osher (1988) Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes, eq. 2.18. """ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) + # TODO: Maybe add alg to dependency alg = SSPRK33_ShuOsher() u = copy(ode.u0) @@ -114,18 +124,23 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end + @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) integrator.u_tmp = integrator.u + integrator.dt * integrator.du + end + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u, integrator.dt, integrator.p) + @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + integrator.dt) integrator.u_tmp = 3/4 * integrator.u + 1/4 * integrator.u_tmp + 1/4 * integrator.dt * integrator.du + end + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, 3/4 * integrator.u + 1/4 * integrator.u_tmp, 1/4 * integrator.dt, integrator.p) + @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + 1/2 * integrator.dt) integrator.u = 1/3 * integrator.u + 2/3 * integrator.u_tmp + 2/3 * integrator.dt * integrator.du - - @unpack alpha_threaded = integrator.p.solver.volume_integral.indicator.cache - - # calcalpha_blending!(alpha_blending, volume_integral.indicator(u, mesh, equations, dg, element, cache) + end + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, 1/3 * integrator.u + 2/3 * integrator.u_tmp, 2/3 * integrator.dt, integrator.p) integrator.iter += 1 integrator.t += integrator.dt From cb62e5902dc9bd87d2f4dfc1898364626070942e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 10 Feb 2022 18:46:09 +0100 Subject: [PATCH 009/423] Clean function create_cache() --- src/solvers/dgsem_tree/dg_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 9d22aedbec..4c0ad825a4 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -98,7 +98,7 @@ function create_cache(mesh::TreeMesh{2}, equations, fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded, )#flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) + return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded, ) end From 73cb4829ec900295e4759abb34fd56d6896cf6cf Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Feb 2022 14:01:40 +0100 Subject: [PATCH 010/423] Fix some mistakes with the indicator --- .../elixir_euler_blast_wave_sc_subcell.jl | 6 +- ..._euler_ec_shockcapturing_subcell_SSPRK3.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 27 +++-- src/solvers/dgsem_tree/indicators_2d.jl | 104 ++++++++++-------- 4 files changed, 80 insertions(+), 59 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 78f443f2e3..5d4a7035bc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_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); +sol = Trixi.solve_IDP(ode, semi; + 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_euler_ec_shockcapturing_subcell_SSPRK3.jl b/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl index 8e13f7f2ac..353dfd197e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl @@ -11,7 +11,7 @@ initial_condition = initial_condition_weak_blast_wave polydeg = 3 basis = LobattoLegendreBasis(polydeg) volume_flux = flux_ranocha -indicator_sc = IndicatorIDP(equations, basis; variable=density) +indicator_sc = IndicatorIDP(equations, basis; variable=Trixi.density) volume_integral=VolumeIntegralStaggeredGrid(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=volume_flux) solver = DGSEM(basis, flux_ranocha, volume_integral) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4c0ad825a4..cb29bfe78b 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -654,8 +654,8 @@ end return nothing end -function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, dg, element, cache) +@inline function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, dg, element, cache) @unpack inverse_weights = dg.basis for j in eachnode(dg), i in eachnode(dg) @@ -674,30 +674,33 @@ function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstag return nothing end -function antidiffusive_stage!(u, u_old, dt, ode) - @unpack mesh, equations, solver = ode +@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, ode) + mesh, equations, solver, cache = mesh_equations_solver_cache(ode) @unpack inverse_weights = solver.basis @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache - @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = ode.cache + @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache - u_old_ode = reshape(u_old, nvariables(equations), ntuple(_ -> nnodes(solver), ndims(equations))..., nelements(solver, ode.cache)) - u_ode = reshape(u, nvariables(equations), ntuple(_ -> nnodes(solver), ndims(equations))..., nelements(solver, ode.cache)) + u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) + u = wrap_array(u_ode, mesh, equations, solver, cache) @threaded for element in eachelement(solver, ode.cache) - inverse_jacobian = -ode.cache.elements.inverse_jacobian[element] + inverse_jacobian = -cache.elements.inverse_jacobian[element] - alpha1, alpha2 = ode.solver.volume_integral.indicator(u_ode, u_old_ode, mesh, equations, solver, dt, element, ode.cache) + @trixi_timeit timer() "alpha calculation" alpha = ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] # Calculate volume integral contribution + # Note: flux_antidiffusive1[v, i, xi, element] = flux_antidiffusive2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) for v in eachvariable(equations) - u_ode[v, i, j, element] += dt * inverse_jacobian * - (inverse_weights[i] * (1 - alpha1[i+1, j]) * (flux_antidiffusive1[v, i+1, j, element] - flux_antidiffusive1[v, i, j, element]) + - inverse_weights[j] * (1 - alpha2[i, j+1]) * (flux_antidiffusive2[v, i, j+1, element] - flux_antidiffusive2[v, i, j, element]) ) + u[v, i, j, element] += (1.0 - alpha[i, j]) * dt * inverse_jacobian * + (inverse_weights[i] * (flux_antidiffusive1[v, i+1, j, element] - + flux_antidiffusive1[v, i, j, element]) + + inverse_weights[j] * (flux_antidiffusive2[v, i, j+1, element] - + flux_antidiffusive2[v, i, j, element]) ) end end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 059efa7836..17f8792721 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -194,10 +194,14 @@ end function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) A = Array{real(basis), ndims(equations)} + indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + var_max_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] var_min_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + P_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] P_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + alpha_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] alpha_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] @@ -205,24 +209,21 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] alpha_prov_threaded = [A(undef, nnodes(basis), nnodes(basis), ) for _ in 1:Threads.nthreads()] - indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - - # modal_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - # modal_tmp1_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] + alpha_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] # TODO: Save for all elements - return (; var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, + return (; indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, alpha_prov_threaded, - indicator_threaded) + alpha_threaded) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, - mesh, equations, dg::DGSEM, - dt, element, cache; - kwargs...) + mesh, equations, dg::DGSEM, + dt, element, cache; + kwargs...) @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache - @unpack alpha_prov_threaded, alpha1_threaded, alpha2_threaded = indicator_IDP.cache + @unpack alpha_prov_threaded, alpha1_threaded, alpha2_threaded, alpha_threaded = indicator_IDP.cache # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] @@ -234,19 +235,26 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac # Calculate max and min of variable at Gauss-Lobatto nodes var_max = var_max_threaded[Threads.threadid()] var_min = var_min_threaded[Threads.threadid()] - # corners - var_max[1, 1], var_min[1, 1] = extrema((indicator[1, 1], indicator[1, 2], indicator[2, 1])) - var_max[1, nnodes(dg)], var_min[1, nnodes(dg)] = extrema((indicator[1, nnodes(dg)], indicator[1, nnodes(dg)-1], indicator[2, nnodes(dg)])) - var_max[nnodes(dg), 1], var_min[nnodes(dg), 1] = extrema((indicator[nnodes(dg), 1], indicator[nnodes(dg), 2], indicator[nnodes(dg)-1, 1])) - var_max[nnodes(dg), nnodes(dg)], var_min[nnodes(dg), nnodes(dg)] = extrema((indicator[nnodes(dg), nnodes(dg)], indicator[nnodes(dg)-1, nnodes(dg)], indicator[nnodes(dg), nnodes(dg)-1])) - for i in 2:nnodes(dg)-1 # first colomn/row, last colomn/row - var_max[i, 1], var_min[i, 1] = extrema((indicator[i, 1], indicator[i, 2], indicator[i+1, 1], indicator[i-1, 1])) - var_max[1, i], var_min[1, i] = extrema((indicator[1, i], indicator[2, i], indicator[1, i+1], indicator[1, i-1])) - var_max[i, nnodes(dg)], var_min[i, nnodes(dg)] = extrema((indicator[i, nnodes(dg)], indicator[i, nnodes(dg)-1], indicator[i+1, nnodes(dg)], indicator[i-1, nnodes(dg)])) - var_max[nnodes(dg), i], var_min[nnodes(dg), i] = extrema((indicator[nnodes(dg), i], indicator[nnodes(dg)-1, i], indicator[nnodes(dg), i+1], indicator[nnodes(dg), i-1])) - end - for j in 2:nnodes(dg)-1, i in 2:nnodes(dg)-1 - var_max[i, j], var_min[i, j] = extrema((indicator[i, j], indicator[i, j-1], indicator[i, j+1], indicator[i+1, j], indicator[i-1, j])) + + for j in eachnode(dg), i in eachnode(dg) + var_min[i, j] = indicator[i, j] + var_max[i, j] = indicator[i, j] + if j > 1 + var_min[i, j] = min(var_min[i, j], indicator[i, j-1]) + var_max[i, j] = max(var_max[i, j], indicator[i, j-1]) + end + if j < nnodes(dg) + var_min[i, j] = min(var_min[i, j], indicator[i, j+1]) + var_max[i, j] = max(var_max[i, j], indicator[i, j+1]) + end + if i > 1 + var_min[i, j] = min(var_min[i, j], indicator[i-1, j]) + var_max[i, j] = max(var_max[i, j], indicator[i-1, j]) + end + if i < nnodes(dg) + var_min[i, j] = min(var_min[i, j], indicator[i+1, j]) + var_max[i, j] = max(var_max[i, j], indicator[i+1, j]) + end end # Calculate P_plus and P_minus @@ -258,28 +266,33 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac @unpack inverse_weights = dg.basis inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - val_flux1_local = inverse_jacobian * inverse_weights[i] * indicator_IDP.variable(get_node_vars(flux_antidiffusive1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = inverse_jacobian * inverse_weights[i] * indicator_IDP.variable(get_node_vars(flux_antidiffusive1, equations, dg, i+1, j, element), equations) - val_flux2_local = inverse_jacobian * inverse_weights[j] * indicator_IDP.variable(get_node_vars(flux_antidiffusive2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = inverse_jacobian * inverse_weights[j] * indicator_IDP.variable(get_node_vars(flux_antidiffusive2, equations, dg, i, j+1, element), equations) - - P_plus[i, j] = dt * ((max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1)) + - (max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1))) - P_minus[i, j] = dt * ((min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1)) + - (min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1))) + # Note: Boundaries of flux_antidiffusive1/2 are constant 0, so they make no difference here. + val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(flux_antidiffusive1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(flux_antidiffusive1, equations, dg, i+1, j, element), equations) + val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(flux_antidiffusive2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(flux_antidiffusive2, equations, dg, i, j+1, element), equations) + + P_plus[i, j] = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + P_minus[i, j] = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) end # Calculate alpha_plus and alpha_minus alpha_plus = alpha_plus_threaded[Threads.threadid()] - alpha_minus = alpha_plus_threaded[Threads.threadid()] + alpha_minus = alpha_minus_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) var = indicator_IDP.variable(u_local, equations) - alpha_plus[i, j] = 1 - min(1.0, max(0.0, (var_max[i, j] - var) / P_plus[i, j])) - alpha_minus[i, j] = 1 - min(1.0, max(0.0, (var_min[i, j] - var) / P_minus[i, j])) - isnan(alpha_plus[i, j]) && (alpha_plus[i, j] = 0.0) - isnan(alpha_minus[i, j]) && (alpha_minus[i, j] = 0.0) - # TODO: Added max(0.0, ...) and last two lines to make sure alpha_plus/minus is not -Inf, Inf or NaN + + frac_plus = (var_max[i, j] - var) / P_plus[i, j] + frac_minus = (var_min[i, j] - var) / P_minus[i, j] + # min(Int, NaN) seems to be Int. To avoid this, set fraction to 1.0 if NaN + isnan(frac_plus) && (frac_plus = 1.0) + isnan(frac_minus) && (frac_minus = 1.0) + + alpha_plus[i, j] = 1 - min(1.0, max(0.0, frac_plus)) + alpha_minus[i, j] = 1 - min(1.0, max(0.0, frac_minus)) end # Calculate alpha_prov @@ -297,12 +310,17 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac for j in 2:nnodes(dg), i in eachnode(dg) alpha2[i, j] = max(alpha_prov[i, j-1], alpha_prov[i, j]) end - alpha1[1, :] .= 0 - alpha1[nnodes(dg)+1, :] .= 0 - alpha2[:, 1] .= 0 - alpha2[:, nnodes(dg)+1] .= 0 + alpha1[1, :] .= zero(eltype(alpha1)) + alpha1[nnodes(dg)+1, :] .= zero(eltype(alpha1)) + alpha2[:, 1] .= zero(eltype(alpha2)) + alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) - return alpha1, alpha2 + alpha = alpha_threaded[Threads.threadid()] + for j in eachnode(dg), i in eachnode(dg) + alpha[i, j] = max(alpha1[i, j], alpha1[i+1, j], alpha2[i, j], alpha2[i, j+1]) + end + + return alpha end From 6698e33f24300a77ef79973fad5f5f631f9ddb74 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Feb 2022 14:19:12 +0100 Subject: [PATCH 011/423] Rename volume integral to `VolumeIntegralShockCapturingSubcell` --- .../elixir_euler_blast_wave_sc_subcell.jl | 6 +- ...SPRK3.jl => elixir_euler_ec_sc_subcell.jl} | 5 +- src/Trixi.jl | 2 +- src/solvers/dg.jl | 14 +-- src/solvers/dgsem_tree/dg_2d.jl | 86 +++++++++---------- 5 files changed, 55 insertions(+), 58 deletions(-) rename examples/tree_2d_dgsem/{elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl => elixir_euler_ec_sc_subcell.jl} (92%) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 5d4a7035bc..5e3f49eb24 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -40,9 +40,9 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; variable=density_pressure) -volume_integral = VolumeIntegralStaggeredGrid(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralShockCapturingSubcell(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl similarity index 92% rename from examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl rename to examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl index 353dfd197e..d5e50aa162 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_shockcapturing_subcell_SSPRK3.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl @@ -12,8 +12,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) volume_flux = flux_ranocha indicator_sc = IndicatorIDP(equations, basis; variable=Trixi.density) -volume_integral=VolumeIntegralStaggeredGrid(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=volume_flux) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=volume_flux) solver = DGSEM(basis, flux_ranocha, volume_integral) coordinates_min = (-2.0, -2.0) @@ -61,5 +61,4 @@ callbacks = CallbackSet(summary_callback, save_solution, sol = Trixi.solve_IDP(ode, semi; dt=0.01, # solve needs some value here but it will be overwritten by the stepsize_callback save_everystep=false, callback=callbacks); - summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index b7008579f3..55456c73e3 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -174,7 +174,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralStaggeredGrid, IndicatorIDP, + VolumeIntegralShockCapturingSubcell, IndicatorIDP, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, MortarL2 diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index a205a1c429..c9a9c2fb23 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -143,7 +143,7 @@ end """ - VolumeIntegralStaggeredGrid + VolumeIntegralShockCapturingSubcell A shock-capturing volume integral type for DG methods based on a subcell blending approach with a low-order FV method. @@ -153,19 +153,19 @@ with a low-order FV method. See also: [`VolumeIntegralShockCapturingHG`](@ref) """ -struct VolumeIntegralStaggeredGrid{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral +struct VolumeIntegralShockCapturingSubcell{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG volume_flux_fv::VolumeFluxFV indicator::Indicator end -function VolumeIntegralStaggeredGrid(indicator; volume_flux_dg, - volume_flux_fv) - VolumeIntegralStaggeredGrid{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( +function VolumeIntegralShockCapturingSubcell(indicator; volume_flux_dg, + volume_flux_fv) + VolumeIntegralShockCapturingSubcell{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( volume_flux_dg, volume_flux_fv, indicator) end -function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralStaggeredGrid) +function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) @nospecialize integral # reduce precompilation time if get(io, :compact, false) @@ -176,7 +176,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralStaggered "volume flux fv" => integral.volume_flux_fv, "indicator" => integral.indicator ] - summary_box(io, "VolumeIntegralStaggeredGrid", setup) + summary_box(io, "VolumeIntegralShockCapturingSubcell", setup) end end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index cb29bfe78b..d4c996065c 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -82,9 +82,7 @@ end function create_cache(mesh::TreeMesh{2}, equations, - volume_integral::VolumeIntegralStaggeredGrid, dg::DG, uEltype) - - have_nonconservative_terms(equations) !== Val(false) && error("VolumeIntegralStaggeredGrid only defined for no nonconservative terms.") + volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), @@ -94,11 +92,11 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_y = Array{uEltype, 3} A3d = Array{uEltype, 3} - fstaggered1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] - fstaggered2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + fhat1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - return (; cache..., fstaggered1_threaded, fstaggered2_threaded, flux_temp_threaded, ) + return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) end @@ -517,33 +515,32 @@ end function calc_volume_integral!(du, u, mesh::TreeMesh{2}, nonconservative_terms, equations, - volume_integral::VolumeIntegralStaggeredGrid, + volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) @threaded for element in eachelement(dg, cache) - staggered_grid_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral, dg, cache) + subcell_DG_FV_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, dg, cache) end end -@inline function staggered_grid_kernel!(du, u, - element, mesh::TreeMesh{2}, - nonconservative_terms::Val{false}, equations, - volume_integral, dg::DGSEM, cache, alpha=true) +@inline function subcell_DG_FV_kernel!(du, u, + element, mesh::TreeMesh{2}, + nonconservative_terms::Val{false}, equations, + volume_integral, dg::DGSEM, cache, alpha=true) # true * [some floating point value] == [exactly the same floating point value] # This can (hopefully) be optimized away due to constant propagation. @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral # high-order DG fluxes - @unpack fstaggered1_threaded, fstaggered2_threaded = cache + @unpack fhat1_threaded, fhat2_threaded = cache + + fhat1 = fhat1_threaded[Threads.threadid()] + fhat2 = fhat2_threaded[Threads.threadid()] + calcflux_fhat!(fhat1, fhat2, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - fstaggered1 = fstaggered1_threaded[Threads.threadid()] - fstaggered2 = fstaggered2_threaded[Threads.threadid()] - @trixi_timeit timer() "calculation fstaggered" begin - calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - end # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -562,14 +559,14 @@ end flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] @trixi_timeit timer() "calculation flux_antidiffusive" begin - calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1_L, fstar2_L, u, mesh, + calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) end # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - du[v, i, j, element] += (inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + - inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j])) + du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j]) end end @@ -578,17 +575,18 @@ end end -# calcflux_staggered!(fstaggered1, fstaggered2, u, mesh, +# calcflux_fhat!(fhat1, fhat2, u, mesh, # nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # -# Calculate the staggered volume fluxes inside the elements (**without non-conservative terms**). +# Calculate the FV-form staggered volume fluxes `fhat` inside the elements +# (**without non-conservative terms**). # # # Arguments -# - `fstaggered1::AbstractArray{<:Real, 3}` -# - `fstaggered2::AbstractArray{<:Real, 3}` -@inline function calcflux_staggered!(fstaggered1, fstaggered2, u, - mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, - volume_flux, dg::DGSEM, element, cache) +# - `fhat1::AbstractArray{<:Real, 3}` +# - `fhat2::AbstractArray{<:Real, 3}` +@inline function calcflux_fhat!(fhat1, fhat2, u, + mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, + volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis @unpack flux_temp_threaded = cache @@ -596,8 +594,8 @@ end flux_temp = flux_temp_threaded[Threads.threadid()] # The FV-form fluxes are calculated in a recursive manner, i.e.: - # fstaggered_(0,1) = f_0 + w_0 * FVol_0, - # fstaggered_(j,j+1) = fstaggered_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # fhat_(0,1) = f_0 + w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated @@ -622,12 +620,12 @@ end end end - # FV-form flux `fstaggered` in x direction - fstaggered1[:, 1, :] .= zero(eltype(fstaggered1)) - fstaggered1[:, nnodes(dg)+1, :] .= zero(eltype(fstaggered1)) + # FV-form flux `fhat` in x direction + fhat1[:, 1, :] .= zero(eltype(fhat1)) + fhat1[:, nnodes(dg)+1, :] .= zero(eltype(fhat1)) for j in eachnode(dg), i in 1:nnodes(dg)-1, v in eachvariable(equations) - fstaggered1[v, i+1, j] = fstaggered1[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1[v, i+1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] end # Split form volume flux in orientation 2: y direction @@ -643,25 +641,25 @@ end end end - # FV-form flux `fstaggered` in y direction - fstaggered2[:, :, 1 ] .= zero(eltype(fstaggered2)) - fstaggered2[:, :, nnodes(dg)+1] .= zero(eltype(fstaggered2)) + # FV-form flux `fhat` in y direction + fhat2[:, :, 1 ] .= zero(eltype(fhat2)) + fhat2[:, :, nnodes(dg)+1] .= zero(eltype(fhat2)) for j in 1:nnodes(dg)-1, i in eachnode(dg), v in eachvariable(equations) - fstaggered2[v, i, j+1] = fstaggered2[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2[v, i, j+1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] end return nothing end -@inline function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fstaggered1, fstaggered2, fstar1, fstar2, u, mesh, +@inline function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) @unpack inverse_weights = dg.basis for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - flux_antidiffusive1[v, i, j, element] = (fstaggered1[v, i, j] - fstar1[v, i, j]) - flux_antidiffusive2[v, i, j, element] = (fstaggered2[v, i, j] - fstar2[v, i, j]) + flux_antidiffusive1[v, i, j, element] = (fhat1[v, i, j] - fstar1[v, i, j]) + flux_antidiffusive2[v, i, j, element] = (fhat2[v, i, j] - fstar2[v, i, j]) end end From 946cb31d0f0faab097d555d13812b26ad2adf32e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Feb 2022 15:17:19 +0100 Subject: [PATCH 012/423] Use interface alphas for calculation --- src/solvers/dgsem_tree/dg_2d.jl | 11 +++++------ src/solvers/dgsem_tree/indicators_2d.jl | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index d4c996065c..270e640cfb 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -685,7 +685,7 @@ end @threaded for element in eachelement(solver, ode.cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] - @trixi_timeit timer() "alpha calculation" alpha = ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) + @trixi_timeit timer() "alpha calculation" alpha1, alpha2 = ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] @@ -694,11 +694,10 @@ end # Note: flux_antidiffusive1[v, i, xi, element] = flux_antidiffusive2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) for v in eachvariable(equations) - u[v, i, j, element] += (1.0 - alpha[i, j]) * dt * inverse_jacobian * - (inverse_weights[i] * (flux_antidiffusive1[v, i+1, j, element] - - flux_antidiffusive1[v, i, j, element]) + - inverse_weights[j] * (flux_antidiffusive2[v, i, j+1, element] - - flux_antidiffusive2[v, i, j, element]) ) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * ((1.0 - alpha1[i+1, j]) * flux_antidiffusive1[v, i+1, j, element] - + (1.0 - alpha1[i, j]) * flux_antidiffusive1[v, i, j, element]) + + inverse_weights[j] * ((1.0 - alpha2[i, j+1]) * flux_antidiffusive2[v, i, j+1, element] - + (1.0 - alpha2[i, j]) * flux_antidiffusive2[v, i, j, element]) ) end end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 17f8792721..e2dde992a0 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -285,14 +285,16 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac u_local = get_node_vars(u, equations, dg, i, j, element) var = indicator_IDP.variable(u_local, equations) - frac_plus = (var_max[i, j] - var) / P_plus[i, j] - frac_minus = (var_min[i, j] - var) / P_minus[i, j] - # min(Int, NaN) seems to be Int. To avoid this, set fraction to 1.0 if NaN - isnan(frac_plus) && (frac_plus = 1.0) - isnan(frac_minus) && (frac_minus = 1.0) - - alpha_plus[i, j] = 1 - min(1.0, max(0.0, frac_plus)) - alpha_minus[i, j] = 1 - min(1.0, max(0.0, frac_minus)) + if abs(var_max[i, j] - var) < sqrt(eps()) + alpha_plus[i, j] = 0.0 + alpha_minus[i, j] = 0.0 + else + frac_plus = (var_max[i, j] - var) / P_plus[i, j] + frac_minus = (var_min[i, j] - var) / P_minus[i, j] + + alpha_plus[i, j] = 1 - min(1.0, max(0.0, frac_plus)) + alpha_minus[i, j] = 1 - min(1.0, max(0.0, frac_minus)) + end end # Calculate alpha_prov @@ -320,7 +322,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha[i, j] = max(alpha1[i, j], alpha1[i+1, j], alpha2[i, j], alpha2[i, j+1]) end - return alpha + return alpha1, alpha2 end From 038b0ed0cea5c27b40a4f44120640be949c7b2c0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Feb 2022 16:33:25 +0100 Subject: [PATCH 013/423] Use alpha_prov as not threaded to save everything --- examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl | 3 ++- src/solvers/dgsem_tree/dg_2d.jl | 2 ++ src/solvers/dgsem_tree/indicators_2d.jl | 9 +++------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl index d5e50aa162..696e0003dd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl @@ -48,8 +48,9 @@ alive_callback = AliveCallback(analysis_interval=analysis_interval) stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, save_solution, +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + save_solution, stepsize_callback) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 270e640cfb..5e8ccdedd7 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -30,6 +30,8 @@ function create_cache(mesh::TreeMesh{2}, equations, cache = (;cache..., create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) cache = (;cache..., create_cache(mesh, equations, dg.mortar, uEltype)...) + # TODO: Just defined for VolumeIntegralShockCapturingSubcell. + # It adds flux_antidiffusive, which should save data for alle element cache = (;cache..., create_cache(cache, equations, dg, uEltype)...) return cache diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index e2dde992a0..3196ee0248 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -207,13 +207,11 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha1_threaded = [A(undef, nnodes(basis)+1, nnodes(basis), ) for _ in 1:Threads.nthreads()] alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] - alpha_prov_threaded = [A(undef, nnodes(basis), nnodes(basis), ) for _ in 1:Threads.nthreads()] - alpha_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] # TODO: Save for all elements + alpha_prov = A(undef, nnodes(basis), nnodes(basis), ) # TODO: Save for all elements return (; indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, - alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, alpha_prov_threaded, - alpha_threaded) + alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, alpha_prov) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -223,7 +221,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache - @unpack alpha_prov_threaded, alpha1_threaded, alpha2_threaded, alpha_threaded = indicator_IDP.cache + @unpack alpha_prov, alpha1_threaded, alpha2_threaded = indicator_IDP.cache # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] @@ -298,7 +296,6 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end # Calculate alpha_prov - alpha_prov = alpha_prov_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) alpha_prov[i, j] = max(alpha_plus[i, j], alpha_minus[i, j]) end From e6175a3b2b3d222820d985074db26063be942fd7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Feb 2022 16:56:13 +0100 Subject: [PATCH 014/423] Update docstring --- src/solvers/dgsem_tree/dg_2d.jl | 4 ++-- src/time_integration/methods_SSP.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5e8ccdedd7..099984e6eb 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -578,9 +578,9 @@ end # calcflux_fhat!(fhat1, fhat2, u, mesh, -# nonconservative_terms, equations, volume_flux_dg, dg, element, cache) +# nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # -# Calculate the FV-form staggered volume fluxes `fhat` inside the elements +# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element # (**without non-conservative terms**). # # # Arguments diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 4cf663d44c..ea7b5a2f7d 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -185,4 +185,4 @@ function terminate!(integrator::SimpleIntegratorSSP) end -end # @muladd \ No newline at end of file +end # @muladd From 957d8283bdb2fcdc5861caf39a1e436ab84bc77a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 17 Feb 2022 11:13:19 +0100 Subject: [PATCH 015/423] Implement first suggestions --- src/solvers/dg.jl | 7 ++-- src/solvers/dgsem_tree/dg_2d.jl | 5 +-- src/solvers/dgsem_tree/indicators.jl | 10 +++++- src/time_integration/methods_SSP.jl | 50 ++++++++++++++++------------ 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index c9a9c2fb23..04df284f53 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -143,10 +143,13 @@ end """ - VolumeIntegralShockCapturingSubcell + VolumeIntegralShockCapturingSubcell(indicator; + volume_flux_dg, volume_flux_fv) A shock-capturing volume integral type for DG methods based on a subcell blending approach -with a low-order FV method. +with a low-order FV method from the preprint paper +- Rueda-Ramíreza, Pazner, Gassner (2022) + "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 099984e6eb..9fa6b1693e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -550,20 +550,17 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calculation fstar" begin calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - end # Calculate blending factor alpha_blending @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] - @trixi_timeit timer() "calculation flux_antidiffusive" begin calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) - end + # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 236c1f4835..c694aefe6b 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -154,7 +154,15 @@ end """ IndicatorIDP -Indicator used for subcell shock-capturing used by Rueda-Ramírez, Pazner, Gassner. +Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturingSubcell`](@ref) proposed by +- Rueda-Ramírez, Pazner, Gassner (2022) + "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" +- Pazner (2020) + "Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting" + [arXiv:2004.08503](https://doi.org/10.1016/j.cma.2021.113876) + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. """ struct IndicatorIDP{Variable, Cache} <: AbstractIndicator # alpha_max::RealT diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index ea7b5a2f7d..43d8b0af04 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -9,15 +9,15 @@ abstract type SimpleAlgorithmSSP end """ - SSPRK33_ShuOsher() + SimpleSSPRK33() -""" -struct SSPRK33_ShuOsher <: SimpleAlgorithmSSP +The third-order SSP Runge-Kutta method of + Shu, Osher (1988) Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes, eq. 2.18. - function SSPRK33_ShuOsher() - new() - end -end +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +struct SimpleSSPRK33 <: SimpleAlgorithmSSP end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L1 @@ -42,6 +42,7 @@ mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, Alg, SimpleI u::uType # du::uType u_tmp::uType + u_old::uType t::RealT dt::RealT # current time step dtcache::RealT # ignored @@ -72,23 +73,25 @@ function create_cache(cache, equations, dg, uEltype) end """ - solve_IDP() + solve_IDP(ode, semi; dt, callbacks, kwargs...) -The following structures and methods provide a implementation of the -SSP Runge-Kutta method of +The following structures and methods provide a implementation of the third-order SSP Runge-Kutta +method [`SimpleSSPRK33`](@ref). - Shu, Osher (1988) Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes, eq. 2.18. +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. """ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) # TODO: Maybe add alg to dependency - alg = SSPRK33_ShuOsher() + alg = SimpleSSPRK33() u = copy(ode.u0) du = similar(u) u_tmp = similar(u) + u_old = similar(u) t = first(ode.tspan) iter = 0 - integrator = SimpleIntegratorSSP(u, du, u_tmp, t, dt, zero(dt), iter, ode.p, + integrator = SimpleIntegratorSSP(u, du, u_tmp, u_old, t, dt, zero(dt), iter, ode.p, (prob=ode,), alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) @@ -125,22 +128,25 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u, integrator.p, integrator.t) - integrator.u_tmp = integrator.u + integrator.dt * integrator.du + prob.f(integrator.du, integrator.u, integrator.p, integrator.t) + @. integrator.u_old = integrator.u + @. integrator.u_tmp = integrator.u_old + integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u, integrator.dt, integrator.p) + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u_old, integrator.dt, integrator.p) @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + integrator.dt) - integrator.u_tmp = 3/4 * integrator.u + 1/4 * integrator.u_tmp + 1/4 * integrator.dt * integrator.du + prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + integrator.dt) + @. integrator.u_old = 3/4 * integrator.u + 1/4 * integrator.u_tmp + @. integrator.u_tmp = integrator.u_old + 1/4 * integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, 3/4 * integrator.u + 1/4 * integrator.u_tmp, 1/4 * integrator.dt, integrator.p) + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u_old, 1/4 * integrator.dt, integrator.p) @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + 1/2 * integrator.dt) - integrator.u = 1/3 * integrator.u + 2/3 * integrator.u_tmp + 2/3 * integrator.dt * integrator.du + prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + 1/2 * integrator.dt) + @. integrator.u_old = 1/3 * integrator.u + 2/3 * integrator.u_tmp + @. integrator.u = integrator.u_old + 2/3 * integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, 1/3 * integrator.u + 2/3 * integrator.u_tmp, 2/3 * integrator.dt, integrator.p) + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, integrator.u_old, 2/3 * integrator.dt, integrator.p) integrator.iter += 1 integrator.t += integrator.dt From 09bb45159e2b4ac898554b8f33d2c42fc275c05f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 17 Feb 2022 15:18:38 +0100 Subject: [PATCH 016/423] Use container for antidifussive fluxes --- src/solvers/dgsem_tree/containers_2d.jl | 57 +++++++++++++++++++++++++ src/solvers/dgsem_tree/dg_2d.jl | 27 +++++------- src/time_integration/methods_SSP.jl | 15 +++---- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index bcbd3e671e..6752a2472d 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1248,6 +1248,63 @@ function init_mpi_mortars!(mpi_mortars, elements, mesh::TreeMesh2D) end +# Container data structure (structure-of-arrays style) for FCT-type antidiffusive fluxes +# (i, j+1) +# | +# flux2(i, j+1) +# | +# (i+1, j) ---flux1(i-1, j)--- (i, j) ---flux1(i, j)--- (i+1, j) +# | +# flux2(i, j-1) +# | +# (i, j-1) +mutable struct ContainerFCT2D{uEltype<:Real} + antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] + # internal `resize!`able storage + _antidiffusive_flux1::Vector{uEltype} + _antidiffusive_flux2::Vector{uEltype} +end + +function ContainerFCT2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real + nan_uEltype = convert(uEltype, NaN) + + # Initialize fields with defaults + _antidiffusive_flux1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), + (n_variables, n_nodes+1, n_nodes, capacity)) + + _antidiffusive_flux2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), + (n_variables, n_nodes, n_nodes+1, capacity)) + + return ContainerFCT2D{uEltype}(antidiffusive_flux1, antidiffusive_flux2, + _antidiffusive_flux1, _antidiffusive_flux2) +end + +nvariables(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 1) +nnodes(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 3) + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(fluxes::ContainerFCT2D, capacity) + n_nodes = nnodes(fluxes) + n_variables = nvariables(fluxes) + + @unpack _antidiffusive_flux1, _antidiffusive_flux2 = fluxes + + resize!(_antidiffusive_flux1, n_variables * (n_nodes+1) * n_nodes * capacity) + fluxes.antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), + (n_variables, n_nodes+1, n_nodes, capacity)) + resize!(_antidiffusive_flux2, n_variables * n_nodes * (n_nodes+1) * capacity) + fluxes.antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), + (n_variables, n_nodes, n_nodes+1, capacity)) + + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 9fa6b1693e..dffa29fe1a 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -30,10 +30,6 @@ function create_cache(mesh::TreeMesh{2}, equations, cache = (;cache..., create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) cache = (;cache..., create_cache(mesh, equations, dg.mortar, uEltype)...) - # TODO: Just defined for VolumeIntegralShockCapturingSubcell. - # It adds flux_antidiffusive, which should save data for alle element - cache = (;cache..., create_cache(cache, equations, dg, uEltype)...) - return cache end @@ -98,7 +94,9 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) + ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) + + return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded, ContainerFCT2D) end @@ -554,11 +552,9 @@ end nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # Calculate blending factor alpha_blending - @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] - flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] - calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution @@ -676,7 +672,7 @@ end @unpack inverse_weights = solver.basis @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache - @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -686,17 +682,14 @@ end @trixi_timeit timer() "alpha calculation" alpha1, alpha2 = ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) - flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] - flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] - # Calculate volume integral contribution # Note: flux_antidiffusive1[v, i, xi, element] = flux_antidiffusive2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * ((1.0 - alpha1[i+1, j]) * flux_antidiffusive1[v, i+1, j, element] - - (1.0 - alpha1[i, j]) * flux_antidiffusive1[v, i, j, element]) + - inverse_weights[j] * ((1.0 - alpha2[i, j+1]) * flux_antidiffusive2[v, i, j+1, element] - - (1.0 - alpha2[i, j]) * flux_antidiffusive2[v, i, j, element]) ) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * ((1.0 - alpha1[i+1, j]) * antidiffusive_flux1[v, i+1, j, element] - + (1.0 - alpha1[i, j]) * antidiffusive_flux1[v, i, j, element]) + + inverse_weights[j] * ((1.0 - alpha2[i, j+1]) * antidiffusive_flux2[v, i, j+1, element] - + (1.0 - alpha2[i, j]) * antidiffusive_flux2[v, i, j, element]) ) end end end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 43d8b0af04..4d4dee1a61 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -63,15 +63,6 @@ function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) return getfield(integrator, field) end -function create_cache(cache, equations, dg, uEltype) - A4dp1_x = Array{uEltype, 4} - A4dp1_y = Array{uEltype, 4} - flux_antidiffusive1_threaded = A4dp1_x[A4dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg), nelements(dg, cache)) for _ in 1:Threads.nthreads()] - flux_antidiffusive2_threaded = A4dp1_y[A4dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1, nelements(dg, cache)) for _ in 1:Threads.nthreads()] - - return (; flux_antidiffusive1_threaded, flux_antidiffusive2_threaded) -end - """ solve_IDP(ode, semi; dt, callbacks, kwargs...) @@ -95,6 +86,9 @@ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) (prob=ode,), alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) + # Resize antidiffusive fluxes + resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) + if callback isa CallbackSet for cb in callback.continuous_callbacks error("unsupported") @@ -127,6 +121,9 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end + # Resize antidiffusive fluxes, TODO: Only necessary after every AMR step. + resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) + @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) @. integrator.u_old = integrator.u From 9dec56d221b2f15b37302110ac464e39bd345ef6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 17 Feb 2022 15:26:27 +0100 Subject: [PATCH 017/423] Clean up code --- src/solvers/dg.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 04df284f53..31b04df3ad 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -148,7 +148,7 @@ end A shock-capturing volume integral type for DG methods based on a subcell blending approach with a low-order FV method from the preprint paper -- Rueda-Ramíreza, Pazner, Gassner (2022) +- Rueda-Ramírez, Pazner, Gassner (2022) "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" !!! warning "Experimental implementation" diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 3196ee0248..58d5c6f4c9 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -219,7 +219,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac dt, element, cache; kwargs...) @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache - @unpack flux_antidiffusive1_threaded, flux_antidiffusive2_threaded = cache + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @unpack alpha_prov, alpha1_threaded, alpha2_threaded = indicator_IDP.cache From 382729b266080b299ab2e9a63f745c4dc832ed20 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 18 Feb 2022 18:56:35 +0100 Subject: [PATCH 018/423] Add element- and timestep-based plot feature for alphas --- .../elixir_euler_blast_wave_sc_subcell.jl | 11 ++-- .../elixir_euler_ec_sc_subcell.jl | 7 ++- src/solvers/dg.jl | 7 +++ src/solvers/dgsem_tree/containers_2d.jl | 61 ++++++++++++++++--- src/solvers/dgsem_tree/dg_2d.jl | 18 +++--- src/solvers/dgsem_tree/indicators.jl | 5 ++ src/solvers/dgsem_tree/indicators_2d.jl | 41 +++++++------ src/time_integration/methods_SSP.jl | 21 +++++++ 8 files changed, 129 insertions(+), 42 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 5e3f49eb24..eb3626370a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - variable=density_pressure) + variable=Trixi.density) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -58,7 +58,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 12.5) +tspan = (0.0, 2.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -68,12 +68,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=100, +save_solution = SaveSolutionCallback(interval=20, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl=0.2) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -88,3 +88,6 @@ sol = Trixi.solve_IDP(ode, semi; 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 + +using Plots +plot(indicator_sc.cache.alpha_mean_per_timestep, legend=false, ylabel="mean(alpha)", xlabel="timestep") diff --git a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl index 696e0003dd..f3a939ab4a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl @@ -39,7 +39,7 @@ summary_callback = SummaryCallback() analysis_interval = 100 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=10, +save_solution = SaveSolutionCallback(interval=5, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) @@ -60,6 +60,9 @@ callbacks = CallbackSet(summary_callback, # dt=0.01, callback=callbacks) # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks sol = Trixi.solve_IDP(ode, semi; - dt=0.01, # solve needs some value here but it will be overwritten by the stepsize_callback + 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 + +using Plots +plot(indicator_sc.cache.alpha_mean_per_timestep, legend=false, ylabel="mean(alpha)", xlabel="timestep", ylims=(0, 1)) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 31b04df3ad..fb037a9719 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -191,6 +191,13 @@ function get_element_variables!(element_variables, u, mesh, equations, get_element_variables!(element_variables, volume_integral.indicator, volume_integral) end +function get_element_variables!(element_variables, u, mesh, equations, + volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + # call the indicator to get up-to-date values for IO + volume_integral.indicator(u, u, mesh, equations, dg, 0.0, 1, cache) + get_element_variables!(element_variables, volume_integral.indicator, volume_integral) +end + abstract type AbstractSurfaceIntegral end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 6752a2472d..759f018b6a 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1249,15 +1249,15 @@ end # Container data structure (structure-of-arrays style) for FCT-type antidiffusive fluxes -# (i, j+1) -# | -# flux2(i, j+1) -# | -# (i+1, j) ---flux1(i-1, j)--- (i, j) ---flux1(i, j)--- (i+1, j) -# | -# flux2(i, j-1) -# | -# (i, j-1) +# (i, j+1) +# | +# flux2(i, j+1) +# | +# (i-1, j) ---flux1(i, j)--- (i, j) ---flux1(i+1, j)--- (i+1, j) +# | +# flux2(i, j) +# | +# (i, j-1) mutable struct ContainerFCT2D{uEltype<:Real} antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] @@ -1306,5 +1306,48 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) return nothing end +mutable struct ContainerShockCapturingIndicator{uEltype<:Real} + alpha::Array{uEltype, 3} # [i, j, elements] + # internal `resize!`able storage + _alpha::Vector{uEltype} + + alpha_max::Vector{uEltype} # [elements] + alpha_mean::Vector{uEltype} # [elements] +end + +function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) where uEltype<:Real + nan_uEltype = convert(uEltype, NaN) + + # Initialize fields with defaults + _alpha = fill(nan_uEltype, n_nodes * n_nodes * capacity) + alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + + alpha_max = fill(nan_uEltype, capacity) + alpha_mean = fill(nan_uEltype, capacity) + + return ContainerShockCapturingIndicator{uEltype}(alpha, _alpha, alpha_max, alpha_mean) +end + +nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) + n_nodes = nnodes(indicator) + + @unpack _alpha, alpha, alpha_max, alpha_mean = indicator + + resize!(_alpha, n_nodes * n_nodes * capacity) + indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + + resize!(alpha_max, capacity) + resize!(alpha_mean, capacity) + + return nothing +end + end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index dffa29fe1a..ab7228179d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -647,22 +647,22 @@ end return nothing end -@inline function calcflux_antidiffusive!(flux_antidiffusive1, flux_antidiffusive2, fhat1, fhat2, fstar1, fstar2, u, mesh, +@inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) @unpack inverse_weights = dg.basis for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - flux_antidiffusive1[v, i, j, element] = (fhat1[v, i, j] - fstar1[v, i, j]) - flux_antidiffusive2[v, i, j, element] = (fhat2[v, i, j] - fstar2[v, i, j]) + antidiffusive_flux1[v, i, j, element] = (fhat1[v, i, j] - fstar1[v, i, j]) + antidiffusive_flux2[v, i, j, element] = (fhat2[v, i, j] - fstar2[v, i, j]) end end - flux_antidiffusive1[:, 1, :, element] .= zero(eltype(flux_antidiffusive1)) - flux_antidiffusive1[:, nnodes(dg)+1, :, element] .= zero(eltype(flux_antidiffusive1)) + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) - flux_antidiffusive2[:, :, 1, element] .= zero(eltype(flux_antidiffusive2)) - flux_antidiffusive2[:, :, nnodes(dg)+1, element] .= zero(eltype(flux_antidiffusive2)) + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) return nothing end @@ -680,10 +680,10 @@ end @threaded for element in eachelement(solver, ode.cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] - @trixi_timeit timer() "alpha calculation" alpha1, alpha2 = ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) + alpha1, alpha2 = @trixi_timeit timer() "alpha calculation" ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) # Calculate volume integral contribution - # Note: flux_antidiffusive1[v, i, xi, element] = flux_antidiffusive2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * ((1.0 - alpha1[i+1, j]) * antidiffusive_flux1[v, i+1, j, element] - diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index c694aefe6b..1fdd57accf 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -16,6 +16,11 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end +function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) + element_variables[:indicator_shock_capturing_max] = indicator.cache.ContainerShockCapturingIndicator.alpha_max + element_variables[:indicator_shock_capturing_mean] = indicator.cache.ContainerShockCapturingIndicator.alpha_mean + return nothing +end """ diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 58d5c6f4c9..a14d26c706 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -208,10 +208,17 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha1_threaded = [A(undef, nnodes(basis)+1, nnodes(basis), ) for _ in 1:Threads.nthreads()] alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] - alpha_prov = A(undef, nnodes(basis), nnodes(basis), ) # TODO: Save for all elements + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) + + # TODO: Nice way to set a maximal length? (typemax(Int)=maxiter is too big) + # Maybe resize it if too many timesteps + alpha_max_per_timestep = zeros(real(basis), 5_000) + alpha_mean_per_timestep = zeros(real(basis), 5_000) return (; indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, - alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, alpha_prov) + alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, + ContainerShockCapturingIndicator, + alpha_max_per_timestep, alpha_mean_per_timestep) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -221,7 +228,8 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - @unpack alpha_prov, alpha1_threaded, alpha2_threaded = indicator_IDP.cache + @unpack alpha1_threaded, alpha2_threaded = indicator_IDP.cache + @unpack alpha, alpha_max, alpha_mean = indicator_IDP.cache.ContainerShockCapturingIndicator # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] @@ -258,17 +266,15 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac # Calculate P_plus and P_minus P_plus = P_plus_threaded[Threads.threadid()] P_minus = P_minus_threaded[Threads.threadid()] - flux_antidiffusive1 = flux_antidiffusive1_threaded[Threads.threadid()] - flux_antidiffusive2 = flux_antidiffusive2_threaded[Threads.threadid()] @unpack inverse_weights = dg.basis inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - # Note: Boundaries of flux_antidiffusive1/2 are constant 0, so they make no difference here. - val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(flux_antidiffusive1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(flux_antidiffusive1, equations, dg, i+1, j, element), equations) - val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(flux_antidiffusive2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(flux_antidiffusive2, equations, dg, i, j+1, element), equations) + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) + val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) P_plus[i, j] = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) @@ -295,29 +301,28 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end end - # Calculate alpha_prov + # Calculate alpha at nodes for j in eachnode(dg), i in eachnode(dg) - alpha_prov[i, j] = max(alpha_plus[i, j], alpha_minus[i, j]) + alpha[i, j, element] = max(alpha_plus[i, j], alpha_minus[i, j]) end # Calculate alpha1 and alpha2 alpha1 = alpha1_threaded[Threads.threadid()] alpha2 = alpha2_threaded[Threads.threadid()] for j in eachnode(dg), i in 2:nnodes(dg) - alpha1[i, j] = max(alpha_prov[i-1, j], alpha_prov[i, j]) + alpha1[i, j] = max(alpha[i-1, j, element], alpha[i, j, element]) end for j in 2:nnodes(dg), i in eachnode(dg) - alpha2[i, j] = max(alpha_prov[i, j-1], alpha_prov[i, j]) + alpha2[i, j] = max(alpha[i, j-1, element], alpha[i, j, element]) end alpha1[1, :] .= zero(eltype(alpha1)) alpha1[nnodes(dg)+1, :] .= zero(eltype(alpha1)) alpha2[:, 1] .= zero(eltype(alpha2)) alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) - alpha = alpha_threaded[Threads.threadid()] - for j in eachnode(dg), i in eachnode(dg) - alpha[i, j] = max(alpha1[i, j], alpha1[i+1, j], alpha2[i, j], alpha2[i, j+1]) - end + # Calculate maximal alpha per element + alpha_max[element] = max(alpha_max[element], maximum(alpha1)) + alpha_mean[element] += 1/3 * 1/(nnodes(dg)^2) * sum(alpha1) return alpha1, alpha2 end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 4d4dee1a61..4bff038fd7 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -88,6 +88,13 @@ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) # Resize antidiffusive fluxes resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) + # Resize alpha, alpha_max, alpha_mean + resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, + nelements(integrator.p.solver, integrator.p.cache)) + + # Reset alpha_max, alpha_mean + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max .= 0.0 + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean .= 0.0 if callback isa CallbackSet for cb in callback.continuous_callbacks @@ -119,10 +126,18 @@ function solve!(integrator::SimpleIntegratorSSP) if integrator.t + integrator.dt > t_end || isapprox(integrator.t + integrator.dt, t_end) integrator.dt = t_end - integrator.t terminate!(integrator) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) end # Resize antidiffusive fluxes, TODO: Only necessary after every AMR step. resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) + # Resize alpha, alpha_max, alpha_mean + resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) + + # Reset alpha_max and alpha_mean + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max .= 0.0 + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean .= 0.0 @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) @@ -145,6 +160,12 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, integrator.u_old, 2/3 * integrator.dt, integrator.p) + integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep[integrator.iter+1] = + maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max) + integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = + 1/length(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean) * + sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean) + integrator.iter += 1 integrator.t += integrator.dt From 251f276d364eebf5c3f002c2487756b80da823a6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 21 Feb 2022 11:16:09 +0100 Subject: [PATCH 019/423] Implement code to support AMR --- ...kelvin_helmholtz_instability_sc_subcell.jl | 101 ++++++++++++++++++ src/solvers/dgsem_tree/containers_2d.jl | 16 +-- src/solvers/dgsem_tree/dg_2d.jl | 16 +-- src/solvers/dgsem_tree/indicators.jl | 4 +- src/solvers/dgsem_tree/indicators_2d.jl | 13 ++- src/time_integration/methods_SSP.jl | 53 +++++---- 6 files changed, 161 insertions(+), 42 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl new file mode 100644 index 0000000000..d1f969685e --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -0,0 +1,101 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorIDP(equations, basis; + alpha_max=0.2, + alpha_min=0.0001, + variable=Trixi.density) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=volume_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.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=50, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +amr_indicator = IndicatorHennemannGassner(semi, + alpha_max=1.0, + alpha_min=0.0001, + alpha_smooth=false, + variable=Trixi.density) +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level=4, + med_level=0, med_threshold=0.0003, # med_level = current level + max_level=7, max_threshold=0.03) +amr_callback = AMRCallback(semi, amr_controller, + interval=1, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + +stepsize_callback = StepsizeCallback(cfl=0.1) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + amr_callback, + stepsize_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve_IDP(ode, semi, + 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/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 759f018b6a..17bf0e9a56 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1311,8 +1311,8 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} # internal `resize!`able storage _alpha::Vector{uEltype} - alpha_max::Vector{uEltype} # [elements] - alpha_mean::Vector{uEltype} # [elements] + alpha_max_per_element::Vector{uEltype} # [elements] + alpha_mean_per_element::Vector{uEltype} # [elements] end function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) where uEltype<:Real @@ -1322,10 +1322,10 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) w _alpha = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) - alpha_max = fill(nan_uEltype, capacity) - alpha_mean = fill(nan_uEltype, capacity) + alpha_max_per_element = fill(nan_uEltype, capacity) + alpha_mean_per_element = fill(nan_uEltype, capacity) - return ContainerShockCapturingIndicator{uEltype}(alpha, _alpha, alpha_max, alpha_mean) + return ContainerShockCapturingIndicator{uEltype}(alpha, _alpha, alpha_max_per_element, alpha_mean_per_element) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1338,13 +1338,13 @@ nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) n_nodes = nnodes(indicator) - @unpack _alpha, alpha, alpha_max, alpha_mean = indicator + @unpack _alpha, alpha, alpha_max_per_element, alpha_mean_per_element = indicator resize!(_alpha, n_nodes * n_nodes * capacity) indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) - resize!(alpha_max, capacity) - resize!(alpha_mean, capacity) + resize!(alpha_max_per_element, capacity) + resize!(alpha_mean_per_element, capacity) return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ab7228179d..3f05dbbb4f 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -653,8 +653,8 @@ end for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = (fhat1[v, i, j] - fstar1[v, i, j]) - antidiffusive_flux2[v, i, j, element] = (fhat2[v, i, j] - fstar2[v, i, j]) + antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] end end @@ -670,7 +670,6 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, ode) mesh, equations, solver, cache = mesh_equations_solver_cache(ode) @unpack inverse_weights = solver.basis - @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @@ -685,11 +684,14 @@ end # Calculate volume integral contribution # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) + alpha_flux1 = (1.0 - alpha1[i, j]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) + for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * ((1.0 - alpha1[i+1, j]) * antidiffusive_flux1[v, i+1, j, element] - - (1.0 - alpha1[i, j]) * antidiffusive_flux1[v, i, j, element]) + - inverse_weights[j] * ((1.0 - alpha2[i, j+1]) * antidiffusive_flux2[v, i, j+1, element] - - (1.0 - alpha2[i, j]) * antidiffusive_flux2[v, i, j, element]) ) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) end end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 1fdd57accf..22c08dab03 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -17,8 +17,8 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, end function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) - element_variables[:indicator_shock_capturing_max] = indicator.cache.ContainerShockCapturingIndicator.alpha_max - element_variables[:indicator_shock_capturing_mean] = indicator.cache.ContainerShockCapturingIndicator.alpha_mean + element_variables[:indicator_shock_capturing_max] = indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element + element_variables[:indicator_shock_capturing_mean] = indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index a14d26c706..0c4c53bc3c 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -210,10 +210,9 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) - # TODO: Nice way to set a maximal length? (typemax(Int)=maxiter is too big) - # Maybe resize it if too many timesteps - alpha_max_per_timestep = zeros(real(basis), 5_000) - alpha_mean_per_timestep = zeros(real(basis), 5_000) + # TODO: Nicer way to set a length? + alpha_max_per_timestep = zeros(real(basis), 200) + alpha_mean_per_timestep = zeros(real(basis), 200) return (; indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, @@ -229,7 +228,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @unpack alpha1_threaded, alpha2_threaded = indicator_IDP.cache - @unpack alpha, alpha_max, alpha_mean = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] @@ -321,8 +320,8 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) # Calculate maximal alpha per element - alpha_max[element] = max(alpha_max[element], maximum(alpha1)) - alpha_mean[element] += 1/3 * 1/(nnodes(dg)^2) * sum(alpha1) + alpha_max_per_element[element] = max(alpha_max_per_element[element], maximum(alpha1)) + alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * sum(alpha1) return alpha1, alpha2 end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 4bff038fd7..c20fa3b493 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -88,13 +88,13 @@ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) # Resize antidiffusive fluxes resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha, alpha_max, alpha_mean + # Resize alpha, alpha_max_per_element, alpha_mean_per_element resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) - # Reset alpha_max, alpha_mean - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max .= 0.0 - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean .= 0.0 + # Reset alpha_max_per_element, alpha_mean_per_element + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element .= 0.0 + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element .= 0.0 if callback isa CallbackSet for cb in callback.continuous_callbacks @@ -126,18 +126,11 @@ function solve!(integrator::SimpleIntegratorSSP) if integrator.t + integrator.dt > t_end || isapprox(integrator.t + integrator.dt, t_end) integrator.dt = t_end - integrator.t terminate!(integrator) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) end - # Resize antidiffusive fluxes, TODO: Only necessary after every AMR step. - resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha, alpha_max, alpha_mean - resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) - - # Reset alpha_max and alpha_mean - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max .= 0.0 - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean .= 0.0 + # Reset alpha_max_per_element and alpha_mean_per_element + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element .= 0.0 + integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element .= 0.0 @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) @@ -160,11 +153,17 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, integrator.u_old, 2/3 * integrator.dt, integrator.p) + if integrator.iter == length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) + new_length = length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) + 200 + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, new_length) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, new_length) + end + integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max) + maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element) integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = - 1/length(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean) * - sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean) + 1/length(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element) * + sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element) integrator.iter += 1 integrator.t += integrator.dt @@ -192,7 +191,7 @@ end # get a cache where the RHS can be stored get_du(integrator::SimpleIntegratorSSP) = integrator.du -get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_tmp,) +get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_tmp, integrator.u_old) # some algorithms from DiffEq like FSAL-ones need to be informed when a callback has modified u u_modified!(integrator::SimpleIntegratorSSP, ::Bool) = false @@ -206,6 +205,24 @@ end function terminate!(integrator::SimpleIntegratorSSP) integrator.finalstep = true empty!(integrator.opts.tstops) + + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) +end + +# used for AMR +function Base.resize!(integrator::SimpleIntegratorSSP, new_size) + resize!(integrator.u, new_size) + resize!(integrator.du, new_size) + resize!(integrator.u_tmp, new_size) + resize!(integrator.u_old, new_size) + + # Resize antidiffusive fluxes + resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) + # Resize alpha, alpha_max_per_element, alpha_mean_per_element + resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, + nelements(integrator.p.solver, integrator.p.cache)) + end From 1b8eab669ece27254ca02f2290ffebaccf89cb19 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 22 Feb 2022 14:53:30 +0100 Subject: [PATCH 020/423] Add alpha_maxIDP --- ...r_kelvin_helmholtz_instability_sc_subcell.jl | 3 +-- src/solvers/dgsem_tree/indicators.jl | 17 +++++------------ src/solvers/dgsem_tree/indicators_2d.jl | 6 ++++++ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index d1f969685e..9b5513b546 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,8 +37,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - alpha_max=0.2, - alpha_min=0.0001, + alpha_maxIDP=1.0, variable=Trixi.density) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=volume_flux) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 22c08dab03..4ae6788798 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -169,23 +169,18 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{Variable, Cache} <: AbstractIndicator - # alpha_max::RealT - # alpha_min::RealT - # alpha_smooth::Bool +struct IndicatorIDP{RealT<:Real, Variable, Cache} <: AbstractIndicator + alpha_maxIDP::RealT variable::Variable cache::Cache end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; - # alpha_max=0.5, - # alpha_min=0.001, - # alpha_smooth=true, + alpha_maxIDP=1.0, variable) - # alpha_max, alpha_min = promote(alpha_max, alpha_min) cache = create_cache(IndicatorIDP, equations, basis) - IndicatorIDP{typeof(variable), typeof(cache)}(variable, cache) + IndicatorIDP{typeof(alpha_maxIDP), typeof(variable), typeof(cache)}(alpha_maxIDP, variable, cache) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -193,9 +188,7 @@ function Base.show(io::IO, indicator::IndicatorIDP) print(io, "IndicatorIDP(") 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, ", alpha_maxIDP=", indicator.alpha_maxIDP) print(io, ")") end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 0c4c53bc3c..9e24cea7e7 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -305,6 +305,12 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha[i, j, element] = max(alpha_plus[i, j], alpha_minus[i, j]) end + # Clip the maximum amount of FV allowed + @unpack alpha_maxIDP = indicator_IDP + for j in eachnode(dg), i in eachnode(dg) + alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + end + # Calculate alpha1 and alpha2 alpha1 = alpha1_threaded[Threads.threadid()] alpha2 = alpha2_threaded[Threads.threadid()] From 888821193c6409f8342564edce21780710f455ec Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 22 Feb 2022 17:40:26 +0100 Subject: [PATCH 021/423] Fix mean calculation --- src/solvers/dgsem_tree/indicators_2d.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 9e24cea7e7..844536aacc 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -325,9 +325,11 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha2[:, 1] .= zero(eltype(alpha2)) alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) - # Calculate maximal alpha per element - alpha_max_per_element[element] = max(alpha_max_per_element[element], maximum(alpha1)) - alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * sum(alpha1) + # Calculate maximum and mean alpha per element + for j in eachnode(dg), i in eachnode(dg) + alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) + alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] + end return alpha1, alpha2 end From 6035d30f0deef726bd79b9ef998adb9ba07e02f8 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 25 Feb 2022 15:45:37 +0100 Subject: [PATCH 022/423] Improve efficiency of alpha calculation --- src/solvers/dgsem_tree/dg_2d.jl | 39 +++++----- src/solvers/dgsem_tree/indicators_2d.jl | 94 ++++++++++--------------- src/time_integration/methods_SSP.jl | 3 +- 3 files changed, 60 insertions(+), 76 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 3f05dbbb4f..7bb2a4ec28 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -527,9 +527,7 @@ end @inline function subcell_DG_FV_kernel!(du, u, element, mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, - volume_integral, dg::DGSEM, cache, alpha=true) - # true * [some floating point value] == [exactly the same floating point value] - # This can (hopefully) be optimized away due to constant propagation. + volume_integral, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral @@ -538,8 +536,8 @@ end fhat1 = fhat1_threaded[Threads.threadid()] fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + @trixi_timeit timer() "high-order flux" calcflux_fhat!(fhat1, fhat2, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -548,14 +546,14 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + @trixi_timeit timer() "low-order flux" calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # Calculate blending factor alpha_blending @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, dg, element, cache) + @trixi_timeit timer() "antidiffusive flux" calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) @@ -589,7 +587,7 @@ end flux_temp = flux_temp_threaded[Threads.threadid()] # The FV-form fluxes are calculated in a recursive manner, i.e.: - # fhat_(0,1) = f_0 + w_0 * FVol_0, + # fhat_(0,1) = w_0 * FVol_0, # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). @@ -658,28 +656,33 @@ end end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) + for i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux1[v, 1, i, element] = zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[v, nnodes(dg)+1, i, element] = zero(eltype(antidiffusive_flux1)) - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[v, i, 1, element] = zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[v, i, nnodes(dg)+1, element] = zero(eltype(antidiffusive_flux2)) + end + end return nothing end -@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, ode) - mesh, equations, solver, cache = mesh_equations_solver_cache(ode) +@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack inverse_weights = solver.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + # @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) - @threaded for element in eachelement(solver, ode.cache) + @threaded for element in eachelement(solver, semi.cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] - alpha1, alpha2 = @trixi_timeit timer() "alpha calculation" ode.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) + alpha1, alpha2 = @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) # Calculate volume integral contribution # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 844536aacc..da51827206 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -199,12 +199,6 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas var_max_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] var_min_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - P_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - P_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - - alpha_plus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - alpha_minus_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - alpha1_threaded = [A(undef, nnodes(basis)+1, nnodes(basis), ) for _ in 1:Threads.nthreads()] alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] @@ -214,8 +208,7 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) - return (; indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, - alpha_plus_threaded, alpha_minus_threaded, alpha1_threaded, alpha2_threaded, + return (; indicator_threaded, var_max_threaded, var_min_threaded, alpha1_threaded, alpha2_threaded, ContainerShockCapturingIndicator, alpha_max_per_timestep, alpha_mean_per_timestep) end @@ -224,12 +217,17 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac mesh, equations, dg::DGSEM, dt, element, cache; kwargs...) - @unpack indicator_threaded, var_max_threaded, var_min_threaded, P_plus_threaded, P_minus_threaded, alpha_plus_threaded, alpha_minus_threaded = indicator_IDP.cache + @unpack indicator_threaded, var_max_threaded, var_min_threaded = indicator_IDP.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @unpack alpha1_threaded, alpha2_threaded = indicator_IDP.cache @unpack alpha, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack inverse_weights = dg.basis + inverse_jacobian = cache.elements.inverse_jacobian[element] + + @unpack alpha_maxIDP = indicator_IDP + # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) @@ -237,11 +235,11 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac indicator[i, j] = indicator_IDP.variable(u_local, equations) end - # Calculate max and min of variable at Gauss-Lobatto nodes var_max = var_max_threaded[Threads.threadid()] var_min = var_min_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) + # Calculate max and min of variable at Gauss-Lobatto nodes var_min[i, j] = indicator[i, j] var_max[i, j] = indicator[i, j] if j > 1 @@ -262,53 +260,41 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end end - # Calculate P_plus and P_minus - P_plus = P_plus_threaded[Threads.threadid()] - P_minus = P_minus_threaded[Threads.threadid()] - - @unpack inverse_weights = dg.basis - inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) - val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) - - P_plus[i, j] = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) - P_minus[i, j] = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - end - - # Calculate alpha_plus and alpha_minus - alpha_plus = alpha_plus_threaded[Threads.threadid()] - alpha_minus = alpha_minus_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) var = indicator_IDP.variable(u_local, equations) - - if abs(var_max[i, j] - var) < sqrt(eps()) - alpha_plus[i, j] = 0.0 - alpha_minus[i, j] = 0.0 + if abs(var_max[i, j] - var) < sqrt(eps()) || abs(var_min[i, j] - var) < sqrt(eps()) + alpha[i, j, element] = 0.0 else - frac_plus = (var_max[i, j] - var) / P_plus[i, j] - frac_minus = (var_min[i, j] - var) / P_minus[i, j] - - alpha_plus[i, j] = 1 - min(1.0, max(0.0, frac_plus)) - alpha_minus[i, j] = 1 - min(1.0, max(0.0, frac_minus)) + # Calculate P_plus and P_minus + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) + val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) + + P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + + # Calculate alpha_plus and alpha_minus + frac_plus = (var_max[i, j] - var) / P_plus + frac_minus = (var_min[i, j] - var) / P_minus + + alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) + alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha_plus, alpha_minus) + + # Clip the maximum amount of FV allowed + alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) end - end - # Calculate alpha at nodes - for j in eachnode(dg), i in eachnode(dg) - alpha[i, j, element] = max(alpha_plus[i, j], alpha_minus[i, j]) - end - - # Clip the maximum amount of FV allowed - @unpack alpha_maxIDP = indicator_IDP - for j in eachnode(dg), i in eachnode(dg) - alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + # Calculate maximum and mean alpha per element + alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) + alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] end # Calculate alpha1 and alpha2 @@ -325,12 +311,6 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha2[:, 1] .= zero(eltype(alpha2)) alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) - # Calculate maximum and mean alpha per element - for j in eachnode(dg), i in eachnode(dg) - alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) - alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] - end - return alpha1, alpha2 end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index c20fa3b493..ef58327dee 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -4,7 +4,8 @@ # See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. @muladd begin - +# Abstract base type for time integration schemes of explicit strong stabilitypreserving (SSP) +# Runge-Kutta (RK) methods. They are high-order time discretizations that guarantee the TVD property. abstract type SimpleAlgorithmSSP end From 4566f1e5f4a886711f9fd1659b41f3e1f7518a7b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 7 Mar 2022 13:02:42 +0100 Subject: [PATCH 023/423] Calculate alphas for all elements at once --- src/solvers/dg.jl | 2 +- src/solvers/dgsem_tree/containers_2d.jl | 17 +- src/solvers/dgsem_tree/dg_2d.jl | 14 +- src/solvers/dgsem_tree/indicators_2d.jl | 213 +++++++++++++++--------- 4 files changed, 154 insertions(+), 92 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index fb037a9719..fe05368086 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -194,7 +194,7 @@ end function get_element_variables!(element_variables, u, mesh, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) # call the indicator to get up-to-date values for IO - volume_integral.indicator(u, u, mesh, equations, dg, 0.0, 1, cache) + volume_integral.indicator(u, u, mesh, equations, dg, 0.0, cache) get_element_variables!(element_variables, volume_integral.indicator, volume_integral) end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 17bf0e9a56..f020be59ee 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1308,8 +1308,13 @@ end mutable struct ContainerShockCapturingIndicator{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, elements] + alpha1::Array{uEltype, 3} + alpha2::Array{uEltype, 3} # internal `resize!`able storage _alpha::Vector{uEltype} + _alpha1::Vector{uEltype} + _alpha2::Vector{uEltype} + alpha_max_per_element::Vector{uEltype} # [elements] alpha_mean_per_element::Vector{uEltype} # [elements] @@ -1321,11 +1326,15 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) w # Initialize fields with defaults _alpha = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + _alpha1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) + alpha1 = unsafe_wrap(Array, pointer(_alpha), (n_nodes+1, n_nodes, capacity)) + _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) + alpha2 = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes+1, capacity)) alpha_max_per_element = fill(nan_uEltype, capacity) alpha_mean_per_element = fill(nan_uEltype, capacity) - return ContainerShockCapturingIndicator{uEltype}(alpha, _alpha, alpha_max_per_element, alpha_mean_per_element) + return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, _alpha, _alpha1, _alpha2, alpha_max_per_element, alpha_mean_per_element) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1338,10 +1347,14 @@ nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) n_nodes = nnodes(indicator) - @unpack _alpha, alpha, alpha_max_per_element, alpha_mean_per_element = indicator + @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, alpha_max_per_element, alpha_mean_per_element = indicator resize!(_alpha, n_nodes * n_nodes * capacity) indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + resize!(_alpha1, (n_nodes + 1) * n_nodes * capacity) + indicator.alpha1 = unsafe_wrap(Array, pointer(_alpha1), (n_nodes + 1, n_nodes, capacity)) + resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) + indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) resize!(alpha_max_per_element, capacity) resize!(alpha_mean_per_element, capacity) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 7bb2a4ec28..a857dd6214 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -674,23 +674,23 @@ end @unpack inverse_weights = solver.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - # @unpack alpha1_threaded, alpha2_threaded = solver.volume_integral.indicator.cache u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) + @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) + @unpack alpha1, alpha2 = semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(solver, semi.cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] - alpha1, alpha2 = @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, element, cache) - # Calculate volume integral contribution # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} for j in eachnode(solver), i in eachnode(solver) - alpha_flux1 = (1.0 - alpha1[i, j]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index da51827206..f405bea479 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -199,119 +199,168 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas var_max_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] var_min_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - alpha1_threaded = [A(undef, nnodes(basis)+1, nnodes(basis), ) for _ in 1:Threads.nthreads()] - alpha2_threaded = [A(undef, nnodes(basis), nnodes(basis)+1, ) for _ in 1:Threads.nthreads()] - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) # TODO: Nicer way to set a length? alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) - return (; indicator_threaded, var_max_threaded, var_min_threaded, alpha1_threaded, alpha2_threaded, + return (; indicator_threaded, var_max_threaded, var_min_threaded, ContainerShockCapturingIndicator, alpha_max_per_timestep, alpha_mean_per_timestep) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, mesh, equations, dg::DGSEM, - dt, element, cache; + dt, cache; kwargs...) @unpack indicator_threaded, var_max_threaded, var_min_threaded = indicator_IDP.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - @unpack alpha1_threaded, alpha2_threaded = indicator_IDP.cache - @unpack alpha, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha1, alpha2, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator @unpack inverse_weights = dg.basis - inverse_jacobian = cache.elements.inverse_jacobian[element] @unpack alpha_maxIDP = indicator_IDP - # Calculate indicator variables at Gauss-Lobatto nodes - indicator = indicator_threaded[Threads.threadid()] - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u_old, equations, dg, i, j, element) - indicator[i, j] = indicator_IDP.variable(u_local, equations) + # Construct cell -> element mapping for easier algorithm implementation + c2e = zeros(Int, length(mesh.tree)) + for element in eachelement(dg, cache) + c2e[cache.elements.cell_ids[element]] = element end - var_max = var_max_threaded[Threads.threadid()] - var_min = var_min_threaded[Threads.threadid()] + @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - # Calculate max and min of variable at Gauss-Lobatto nodes - var_min[i, j] = indicator[i, j] - var_max[i, j] = indicator[i, j] - if j > 1 - var_min[i, j] = min(var_min[i, j], indicator[i, j-1]) - var_max[i, j] = max(var_max[i, j], indicator[i, j-1]) - end - if j < nnodes(dg) - var_min[i, j] = min(var_min[i, j], indicator[i, j+1]) - var_max[i, j] = max(var_max[i, j], indicator[i, j+1]) - end - if i > 1 - var_min[i, j] = min(var_min[i, j], indicator[i-1, j]) - var_max[i, j] = max(var_max[i, j], indicator[i-1, j]) - end - if i < nnodes(dg) - var_min[i, j] = min(var_min[i, j], indicator[i+1, j]) - var_max[i, j] = max(var_max[i, j], indicator[i+1, j]) + cell_id = cache.elements.cell_ids[element] + + # Calculate indicator variables at Gauss-Lobatto nodes + indicator = indicator_threaded[Threads.threadid()] + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u_old, equations, dg, i, j, element) + indicator[i, j] = indicator_IDP.variable(u_local, equations) end - end - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - var = indicator_IDP.variable(u_local, equations) - if abs(var_max[i, j] - var) < sqrt(eps()) || abs(var_min[i, j] - var) < sqrt(eps()) - alpha[i, j, element] = 0.0 - else - # Calculate P_plus and P_minus - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) - val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) - - P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) - P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - - # Calculate alpha_plus and alpha_minus - frac_plus = (var_max[i, j] - var) / P_plus - frac_minus = (var_min[i, j] - var) / P_minus - - alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) - alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha_plus, alpha_minus) - - # Clip the maximum amount of FV allowed - alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + var_max = var_max_threaded[Threads.threadid()] + var_min = var_min_threaded[Threads.threadid()] + + for j in eachnode(dg), i in eachnode(dg) + # Calculate max and min of variable at Gauss-Lobatto nodes + var_min[i, j] = indicator[i, j] + var_max[i, j] = indicator[i, j] + if i > 1 + var_min[i, j] = min(var_min[i, j], indicator[i-1, j]) + var_max[i, j] = max(var_max[i, j], indicator[i-1, j]) + elseif has_neighbor(mesh.tree, cell_id, 1) + neighbor_cell_id = mesh.tree.neighbor_ids[1, cell_id] + if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor + u_local = get_node_vars(u_old, equations, dg, nnodes(dg), j, c2e[neighbor_cell_id]) + var_neighbor = indicator_IDP.variable(u_local, equations) + else # Higher level neighbor TODO: interpolate values + u_local = get_node_vars(u_old, equations, dg, nnodes(dg), j, c2e[neighbor_cell_id + 2]) + var_neighbor = indicator_IDP.variable(u_local, equations) + end + var_min[i, j] = min(var_min[i, j], var_neighbor) + var_max[i, j] = max(var_max[i, j], var_neighbor) + end # TODO: lower level neighbor + if i < nnodes(dg) + var_min[i, j] = min(var_min[i, j], indicator[i+1, j]) + var_max[i, j] = max(var_max[i, j], indicator[i+1, j]) + elseif has_neighbor(mesh.tree, cell_id, 2) + neighbor_cell_id = mesh.tree.neighbor_ids[2, cell_id] + if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor + u_local = get_node_vars(u_old, equations, dg, 1, j, c2e[neighbor_cell_id]) + var_neighbor = indicator_IDP.variable(u_local, equations) + else # Higher level neighbor TODO: interpolate values + u_local = get_node_vars(u_old, equations, dg, 1, j, c2e[neighbor_cell_id + 1]) + var_neighbor = indicator_IDP.variable(u_local, equations) + end + var_min[i, j] = min(var_min[i, j], var_neighbor) + var_max[i, j] = max(var_max[i, j], var_neighbor) + end # TODO: lower level neighbor + if j > 1 + var_min[i, j] = min(var_min[i, j], indicator[i, j-1]) + var_max[i, j] = max(var_max[i, j], indicator[i, j-1]) + elseif has_neighbor(mesh.tree, cell_id, 3) + neighbor_cell_id = mesh.tree.neighbor_ids[3, cell_id] + if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor + u_local = get_node_vars(u_old, equations, dg, i, nnodes(dg), c2e[neighbor_cell_id]) + var_neighbor = indicator_IDP.variable(u_local, equations) + else # Higher level neighbor TODO: interpolate values + u_local = get_node_vars(u_old, equations, dg, i, nnodes(dg), c2e[neighbor_cell_id + 3]) + var_neighbor = indicator_IDP.variable(u_local, equations) + end + var_min[i, j] = min(var_min[i, j], var_neighbor) + var_max[i, j] = max(var_max[i, j], var_neighbor) + end # TODO: lower level neighbor + if j < nnodes(dg) + var_min[i, j] = min(var_min[i, j], indicator[i, j+1]) + var_max[i, j] = max(var_max[i, j], indicator[i, j+1]) + elseif has_neighbor(mesh.tree, cell_id, 4) + neighbor_cell_id = mesh.tree.neighbor_ids[4, cell_id] + if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor + u_local = get_node_vars(u_old, equations, dg, i, 1, c2e[neighbor_cell_id]) + var_neighbor = indicator_IDP.variable(u_local, equations) + else # Higher level neighbor TODO: interpolate values + u_local = get_node_vars(u_old, equations, dg, i, 1, c2e[neighbor_cell_id + 1]) + var_neighbor = indicator_IDP.variable(u_local, equations) + end + var_min[i, j] = min(var_min[i, j], var_neighbor) + var_max[i, j] = max(var_max[i, j], var_neighbor) + end # TODO: lower level neighbor end - # Calculate maximum and mean alpha per element - alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) - alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] - end + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + var = indicator_IDP.variable(u_local, equations) + if abs(var_max[i, j] - var) < sqrt(eps()) || abs(var_min[i, j] - var) < sqrt(eps()) + alpha[i, j, element] = 0.0 + else + # Calculate P_plus and P_minus + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) + val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) + + P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + + # Calculate alpha_plus and alpha_minus + frac_plus = (var_max[i, j] - var) / P_plus + frac_minus = (var_min[i, j] - var) / P_minus + + alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) + alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha_plus, alpha_minus) + + # Clip the maximum amount of FV allowed + alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + end - # Calculate alpha1 and alpha2 - alpha1 = alpha1_threaded[Threads.threadid()] - alpha2 = alpha2_threaded[Threads.threadid()] - for j in eachnode(dg), i in 2:nnodes(dg) - alpha1[i, j] = max(alpha[i-1, j, element], alpha[i, j, element]) - end - for j in 2:nnodes(dg), i in eachnode(dg) - alpha2[i, j] = max(alpha[i, j-1, element], alpha[i, j, element]) + # Calculate maximum and mean alpha per element + alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) + alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] + end + + # Calculate alpha1 and alpha2 + for j in eachnode(dg), i in 2:nnodes(dg) + alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) + end + for j in 2:nnodes(dg), i in eachnode(dg) + alpha2[i, j, element] = max(alpha[i, j-1, element], alpha[i, j, element]) + end + alpha1[1, :, element] .= zero(eltype(alpha1)) + alpha1[nnodes(dg)+1, :, element] .= zero(eltype(alpha1)) + alpha2[:, 1, element] .= zero(eltype(alpha2)) + alpha2[:, nnodes(dg)+1, element] .= zero(eltype(alpha2)) end - alpha1[1, :] .= zero(eltype(alpha1)) - alpha1[nnodes(dg)+1, :] .= zero(eltype(alpha1)) - alpha2[:, 1] .= zero(eltype(alpha2)) - alpha2[:, nnodes(dg)+1] .= zero(eltype(alpha2)) - return alpha1, alpha2 + return nothing end From c6ec3a76b4f6bf9769f089776559fb4ea42e9900 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 8 Mar 2022 12:25:28 +0100 Subject: [PATCH 024/423] Include neighbor values into `var_max/min` calculation --- ...kelvin_helmholtz_instability_sc_subcell.jl | 10 +- src/solvers/dgsem_tree/containers_2d.jl | 20 +- src/solvers/dgsem_tree/indicators_2d.jl | 267 +++++++++++++----- 3 files changed, 212 insertions(+), 85 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 9b5513b546..09bccf4349 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -40,7 +40,7 @@ indicator_sc = IndicatorIDP(equations, basis; alpha_maxIDP=1.0, variable=Trixi.density) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=volume_flux) + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) @@ -53,7 +53,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 2.0) +tspan = (0.0, 3.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -76,13 +76,13 @@ amr_indicator = IndicatorHennemannGassner(semi, amr_controller = ControllerThreeLevel(semi, amr_indicator, base_level=4, med_level=0, med_threshold=0.0003, # med_level = current level - max_level=7, max_threshold=0.03) + max_level=7, max_threshold=0.003) amr_callback = AMRCallback(semi, amr_controller, interval=1, adapt_initial_condition=true, adapt_initial_condition_only_refine=true) -stepsize_callback = StepsizeCallback(cfl=0.1) +stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -96,5 +96,5 @@ callbacks = CallbackSet(summary_callback, sol = Trixi.solve_IDP(ode, semi, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + callback=callbacks); summary_callback() # print the timer summary diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index f020be59ee..da5621f21f 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1310,10 +1310,14 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, elements] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} + var_max::Array{uEltype, 3} + var_min::Array{uEltype, 3} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} + _var_max::Vector{uEltype} + _var_min::Vector{uEltype} alpha_max_per_element::Vector{uEltype} # [elements] @@ -1331,10 +1335,17 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) w _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) alpha2 = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes+1, capacity)) + _var_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) + var_max = unsafe_wrap(Array, pointer(_var_max), (n_nodes, n_nodes, capacity)) + _var_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) + var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) + alpha_max_per_element = fill(nan_uEltype, capacity) alpha_mean_per_element = fill(nan_uEltype, capacity) - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, _alpha, _alpha1, _alpha2, alpha_max_per_element, alpha_mean_per_element) + return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_max, var_min, + _alpha, _alpha1, _alpha2, _var_max, _var_min, + alpha_max_per_element, alpha_mean_per_element) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1347,7 +1358,7 @@ nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) n_nodes = nnodes(indicator) - @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, alpha_max_per_element, alpha_mean_per_element = indicator + @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, _var_max, var_max, _var_min, var_min, alpha_max_per_element, alpha_mean_per_element = indicator resize!(_alpha, n_nodes * n_nodes * capacity) indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) @@ -1356,6 +1367,11 @@ function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) + resize!(_var_max, n_nodes * n_nodes * capacity) + indicator.var_max = unsafe_wrap(Array, pointer(_var_max), (n_nodes, n_nodes, capacity)) + resize!(_var_min, n_nodes * n_nodes * capacity) + indicator.var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) + resize!(alpha_max_per_element, capacity) resize!(alpha_mean_per_element, capacity) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index f405bea479..7d9a9f391e 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -196,16 +196,13 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas A = Array{real(basis), ndims(equations)} indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - var_max_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - var_min_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) # TODO: Nicer way to set a length? alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) - return (; indicator_threaded, var_max_threaded, var_min_threaded, + return (; indicator_threaded, ContainerShockCapturingIndicator, alpha_max_per_timestep, alpha_mean_per_timestep) end @@ -214,25 +211,16 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac mesh, equations, dg::DGSEM, dt, cache; kwargs...) - @unpack indicator_threaded, var_max_threaded, var_min_threaded = indicator_IDP.cache + @unpack indicator_threaded = indicator_IDP.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - @unpack alpha, alpha1, alpha2, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha1, alpha2, var_max, var_min, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator @unpack inverse_weights = dg.basis @unpack alpha_maxIDP = indicator_IDP - # Construct cell -> element mapping for easier algorithm implementation - c2e = zeros(Int, length(mesh.tree)) - for element in eachelement(dg, cache) - c2e[cache.elements.cell_ids[element]] = element - end - @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] - - cell_id = cache.elements.cell_ids[element] # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] @@ -241,79 +229,202 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac indicator[i, j] = indicator_IDP.variable(u_local, equations) end - var_max = var_max_threaded[Threads.threadid()] - var_min = var_min_threaded[Threads.threadid()] - for j in eachnode(dg), i in eachnode(dg) # Calculate max and min of variable at Gauss-Lobatto nodes - var_min[i, j] = indicator[i, j] - var_max[i, j] = indicator[i, j] + var_min[i, j, element] = indicator[i, j] + var_max[i, j, element] = indicator[i, j] if i > 1 - var_min[i, j] = min(var_min[i, j], indicator[i-1, j]) - var_max[i, j] = max(var_max[i, j], indicator[i-1, j]) - elseif has_neighbor(mesh.tree, cell_id, 1) - neighbor_cell_id = mesh.tree.neighbor_ids[1, cell_id] - if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor - u_local = get_node_vars(u_old, equations, dg, nnodes(dg), j, c2e[neighbor_cell_id]) - var_neighbor = indicator_IDP.variable(u_local, equations) - else # Higher level neighbor TODO: interpolate values - u_local = get_node_vars(u_old, equations, dg, nnodes(dg), j, c2e[neighbor_cell_id + 2]) - var_neighbor = indicator_IDP.variable(u_local, equations) - end - var_min[i, j] = min(var_min[i, j], var_neighbor) - var_max[i, j] = max(var_max[i, j], var_neighbor) - end # TODO: lower level neighbor + var_min[i, j, element] = min(var_min[i, j, element], indicator[i-1, j]) + var_max[i, j, element] = max(var_max[i, j, element], indicator[i-1, j]) + end if i < nnodes(dg) - var_min[i, j] = min(var_min[i, j], indicator[i+1, j]) - var_max[i, j] = max(var_max[i, j], indicator[i+1, j]) - elseif has_neighbor(mesh.tree, cell_id, 2) - neighbor_cell_id = mesh.tree.neighbor_ids[2, cell_id] - if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor - u_local = get_node_vars(u_old, equations, dg, 1, j, c2e[neighbor_cell_id]) - var_neighbor = indicator_IDP.variable(u_local, equations) - else # Higher level neighbor TODO: interpolate values - u_local = get_node_vars(u_old, equations, dg, 1, j, c2e[neighbor_cell_id + 1]) - var_neighbor = indicator_IDP.variable(u_local, equations) - end - var_min[i, j] = min(var_min[i, j], var_neighbor) - var_max[i, j] = max(var_max[i, j], var_neighbor) - end # TODO: lower level neighbor + var_min[i, j, element] = min(var_min[i, j, element], indicator[i+1, j]) + var_max[i, j, element] = max(var_max[i, j, element], indicator[i+1, j]) + end if j > 1 - var_min[i, j] = min(var_min[i, j], indicator[i, j-1]) - var_max[i, j] = max(var_max[i, j], indicator[i, j-1]) - elseif has_neighbor(mesh.tree, cell_id, 3) - neighbor_cell_id = mesh.tree.neighbor_ids[3, cell_id] - if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor - u_local = get_node_vars(u_old, equations, dg, i, nnodes(dg), c2e[neighbor_cell_id]) - var_neighbor = indicator_IDP.variable(u_local, equations) - else # Higher level neighbor TODO: interpolate values - u_local = get_node_vars(u_old, equations, dg, i, nnodes(dg), c2e[neighbor_cell_id + 3]) - var_neighbor = indicator_IDP.variable(u_local, equations) - end - var_min[i, j] = min(var_min[i, j], var_neighbor) - var_max[i, j] = max(var_max[i, j], var_neighbor) - end # TODO: lower level neighbor + var_min[i, j, element] = min(var_min[i, j, element], indicator[i, j-1]) + var_max[i, j, element] = max(var_max[i, j, element], indicator[i, j-1]) + end if j < nnodes(dg) - var_min[i, j] = min(var_min[i, j], indicator[i, j+1]) - var_max[i, j] = max(var_max[i, j], indicator[i, j+1]) - elseif has_neighbor(mesh.tree, cell_id, 4) - neighbor_cell_id = mesh.tree.neighbor_ids[4, cell_id] - if !has_children(mesh.tree, neighbor_cell_id) # Same level neighbor - u_local = get_node_vars(u_old, equations, dg, i, 1, c2e[neighbor_cell_id]) - var_neighbor = indicator_IDP.variable(u_local, equations) - else # Higher level neighbor TODO: interpolate values - u_local = get_node_vars(u_old, equations, dg, i, 1, c2e[neighbor_cell_id + 1]) - var_neighbor = indicator_IDP.variable(u_local, equations) + var_min[i, j, element] = min(var_min[i, j, element], indicator[i, j+1]) + var_max[i, j, element] = max(var_max[i, j, element], indicator[i, j+1]) + end + end + end + + # Loop over interfaces + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + u_local_left = get_node_vars(u_old, equations, dg, index_left...) + u_local_right = get_node_vars(u_old, equations, dg, index_right...) + var_neighbor_left = indicator_IDP.variable(u_local_left, equations) + var_neighbor_right = indicator_IDP.variable(u_local_right, equations) + + var_min[index_right...] = min(var_min[index_right...], var_neighbor_left) + var_max[index_right...] = max(var_max[index_right...], var_neighbor_left) + + var_min[index_left...] = min(var_min[index_left...], var_neighbor_right) + var_max[index_left...] = max(var_max[index_left...], var_neighbor_right) + end + end + + # Loop over L2 mortars + for mortar in eachmortar(dg, cache) + # Get neighboring element ids + lower = cache.mortars.neighbor_ids[1, mortar] + upper = cache.mortars.neighbor_ids[2, mortar] + large = cache.mortars.neighbor_ids[3, mortar] + + # buffer variables. TODO: Spare these unnecessary allocations + u_tmp_upper = similar(view(u_old, :, 1, :, large)) + u_tmp_lower = similar(u_tmp_upper) + u_tmp_large1 = similar(u_tmp_upper) + u_tmp_large2 = similar(u_tmp_upper) + + # Interpolate element face data to adjacent interface locations and use for var_max/min + if cache.mortars.large_sides[mortar] == 1 # -> large element on left side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(u_old, :, nnodes(dg), :, large) + u_upper = view(u_old, :, 1, :, upper) + u_lower = view(u_old, :, 1, :, lower) + + multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) + multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + + multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) + multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + + for i in eachnode(dg) + # large to small + var_min[1, i, upper] = min(var_min[1, i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + var_max[1, i, upper] = max(var_max[1, i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + + var_min[1, i, lower] = min(var_min[1, i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + var_max[1, i, lower] = max(var_max[1, i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + + # small to large + if i <= nnodes(dg)/2 + var_min[nnodes(dg), i, large] = min(var_min[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + var_max[nnodes(dg), i, large] = max(var_max[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + else + var_min[nnodes(dg), i, large] = min(var_min[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + var_max[nnodes(dg), i, large] = max(var_max[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + end end - var_min[i, j] = min(var_min[i, j], var_neighbor) - var_max[i, j] = max(var_max[i, j], var_neighbor) - end # TODO: lower level neighbor + else + # L2 mortars in y-direction + u_large = view(u_old, :, :, nnodes(dg), large) + u_upper = view(u_old, :, :, 1, upper) + u_lower = view(u_old, :, :, 1, lower) + + multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) + multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + + multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) + multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + + for i in eachnode(dg) + # large to small + var_min[i, 1, upper] = min(var_min[i, 1, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + var_max[i, 1, upper] = max(var_max[i, 1, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + + var_min[i, 1, lower] = min(var_min[i, 1, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + var_max[i, 1, lower] = max(var_max[i, 1, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + + # small to large + if i <= nnodes(dg)/2 + var_min[i, nnodes(dg), large] = min(var_min[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + var_max[i, nnodes(dg), large] = max(var_max[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + else + var_min[i, nnodes(dg), large] = min(var_min[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + var_max[i, nnodes(dg), large] = max(var_max[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + end + end + end + else # large_sides[mortar] == 2 -> large element on right side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(u_old, :, 1, :, large) + u_upper = view(u_old, :, nnodes(dg), :, upper) + u_lower = view(u_old, :, nnodes(dg), :, lower) + + multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) + multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + + multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) + multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + + for i in eachnode(dg) + # large to small + var_min[nnodes(dg), i, upper] = min(var_min[nnodes(dg), i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + var_max[nnodes(dg), i, upper] = max(var_max[nnodes(dg), i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + + var_min[nnodes(dg), i, lower] = min(var_min[nnodes(dg), i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + var_max[nnodes(dg), i, lower] = max(var_max[nnodes(dg), i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + + # small to large + if i <= nnodes(dg)/2 + var_min[1, i, large] = min(var_min[1, i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + var_max[1, i, large] = max(var_max[1, i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + else + var_min[1, i, large] = min(var_min[1, i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + var_max[1, i, large] = max(var_max[1, i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + end + end + else + # L2 mortars in y-direction + u_large = view(u_old, :, :, 1, large) + u_upper = view(u_old, :, :, nnodes(dg), upper) + u_lower = view(u_old, :, :, nnodes(dg), lower) + + multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) + multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + + multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) + multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + + for i in eachnode(dg) + # large to small + var_min[i, nnodes(dg), upper] = min(var_min[i, nnodes(dg), upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + var_max[i, nnodes(dg), upper] = max(var_max[i, nnodes(dg), upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + + var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + + # small to large + if i <= nnodes(dg)/2 + var_min[i, 1, large] = min(var_min[i, 1, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + var_max[i, 1, large] = max(var_max[i, 1, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + else + var_min[i, 1, large] = min(var_min[i, 1, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + var_max[i, 1, large] = max(var_max[i, 1, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + end + end + end end + end + + @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) var = indicator_IDP.variable(u_local, equations) - if abs(var_max[i, j] - var) < sqrt(eps()) || abs(var_min[i, j] - var) < sqrt(eps()) + if abs(var_max[i, j, element] - var) < sqrt(eps()) || abs(var_min[i, j, element] - var) < sqrt(eps()) alpha[i, j, element] = 0.0 else # Calculate P_plus and P_minus @@ -329,8 +440,8 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) # Calculate alpha_plus and alpha_minus - frac_plus = (var_max[i, j] - var) / P_plus - frac_minus = (var_min[i, j] - var) / P_minus + frac_plus = (var_max[i, j, element] - var) / P_plus + frac_minus = (var_min[i, j, element] - var) / P_minus alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) From 5c8a0b46fbbb0fcb36ab2377d435a6727a65f283 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Mar 2022 17:09:15 +0100 Subject: [PATCH 025/423] Optimize indicator calculation for mortars --- src/callbacks_step/amr.jl | 4 + src/solvers/dgsem_tree/indicators_2d.jl | 173 ++++++++---------------- 2 files changed, 63 insertions(+), 114 deletions(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index a00a1b8965..939f09d175 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -124,6 +124,10 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u, t, integrator) amr_callback = cb.affect! semi = integrator.p + if integrator isa SimpleIntegratorSSP + println("WARNING: The TVD-property can not be guaranteed when using a non-conforming mesh (i.e. with AMR).\n") + end + @trixi_timeit timer() "initial condition AMR" if amr_callback.adapt_initial_condition # iterate until mesh does not change anymore has_changed = amr_callback(integrator, diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 7d9a9f391e..ad0fcde021 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -288,132 +288,34 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac upper = cache.mortars.neighbor_ids[2, mortar] large = cache.mortars.neighbor_ids[3, mortar] - # buffer variables. TODO: Spare these unnecessary allocations - u_tmp_upper = similar(view(u_old, :, 1, :, large)) - u_tmp_lower = similar(u_tmp_upper) - u_tmp_large1 = similar(u_tmp_upper) - u_tmp_large2 = similar(u_tmp_upper) - # Interpolate element face data to adjacent interface locations and use for var_max/min if cache.mortars.large_sides[mortar] == 1 # -> large element on left side if cache.mortars.orientations[mortar] == 1 # L2 mortars in x-direction - u_large = view(u_old, :, nnodes(dg), :, large) - u_upper = view(u_old, :, 1, :, upper) - u_lower = view(u_old, :, 1, :, lower) - - multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) - multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) - - multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) - multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) - - for i in eachnode(dg) - # large to small - var_min[1, i, upper] = min(var_min[1, i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - var_max[1, i, upper] = max(var_max[1, i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - - var_min[1, i, lower] = min(var_min[1, i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - var_max[1, i, lower] = max(var_max[1, i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - - # small to large - if i <= nnodes(dg)/2 - var_min[nnodes(dg), i, large] = min(var_min[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - var_max[nnodes(dg), i, large] = max(var_max[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - else - var_min[nnodes(dg), i, large] = min(var_min[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - var_max[nnodes(dg), i, large] = max(var_max[nnodes(dg), i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - end - end + index_large = i -> (nnodes(dg), i) + index_small = i -> (1, i) + element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, + large, upper, lower, index_large, index_small) else # L2 mortars in y-direction - u_large = view(u_old, :, :, nnodes(dg), large) - u_upper = view(u_old, :, :, 1, upper) - u_lower = view(u_old, :, :, 1, lower) - - multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) - multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) - - multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) - multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) - - for i in eachnode(dg) - # large to small - var_min[i, 1, upper] = min(var_min[i, 1, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - var_max[i, 1, upper] = max(var_max[i, 1, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - - var_min[i, 1, lower] = min(var_min[i, 1, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - var_max[i, 1, lower] = max(var_max[i, 1, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - - # small to large - if i <= nnodes(dg)/2 - var_min[i, nnodes(dg), large] = min(var_min[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - var_max[i, nnodes(dg), large] = max(var_max[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - else - var_min[i, nnodes(dg), large] = min(var_min[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - var_max[i, nnodes(dg), large] = max(var_max[i, nnodes(dg), large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - end - end + index_large = i -> (i, nnodes(dg)) + index_small = i -> (i, 1) + element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, + large, upper, lower, index_large, index_small) end else # large_sides[mortar] == 2 -> large element on right side if cache.mortars.orientations[mortar] == 1 # L2 mortars in x-direction - u_large = view(u_old, :, 1, :, large) - u_upper = view(u_old, :, nnodes(dg), :, upper) - u_lower = view(u_old, :, nnodes(dg), :, lower) - - multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) - multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) - - multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) - multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) - - for i in eachnode(dg) - # large to small - var_min[nnodes(dg), i, upper] = min(var_min[nnodes(dg), i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - var_max[nnodes(dg), i, upper] = max(var_max[nnodes(dg), i, upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - - var_min[nnodes(dg), i, lower] = min(var_min[nnodes(dg), i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - var_max[nnodes(dg), i, lower] = max(var_max[nnodes(dg), i, lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - - # small to large - if i <= nnodes(dg)/2 - var_min[1, i, large] = min(var_min[1, i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - var_max[1, i, large] = max(var_max[1, i, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - else - var_min[1, i, large] = min(var_min[1, i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - var_max[1, i, large] = max(var_max[1, i, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - end - end + index_large = i -> (1, i) + index_small = i -> (nnodes(dg), i) + element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, + large, upper, lower, index_large, index_small) else # L2 mortars in y-direction - u_large = view(u_old, :, :, 1, large) - u_upper = view(u_old, :, :, nnodes(dg), upper) - u_lower = view(u_old, :, :, nnodes(dg), lower) - - multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) - multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) - - multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) - multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) - - for i in eachnode(dg) - # large to small - var_min[i, nnodes(dg), upper] = min(var_min[i, nnodes(dg), upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - var_max[i, nnodes(dg), upper] = max(var_max[i, nnodes(dg), upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - - var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - - # small to large - if i <= nnodes(dg)/2 - var_min[i, 1, large] = min(var_min[i, 1, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - var_max[i, 1, large] = max(var_max[i, 1, large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - else - var_min[i, 1, large] = min(var_min[i, 1, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - var_max[i, 1, large] = max(var_max[i, 1, large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - end - end + index_large = i -> (i, 1) + index_small = i -> (i, nnodes(dg)) + element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, + large, upper, lower, index_large, index_small) end end end @@ -475,6 +377,49 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end +@inline function element_solutions_to_mortars!(u_old::AbstractArray{<:Any,4}, indicator_IDP, dg, equations, + large, upper, lower, + index_large, index_small) + + @unpack var_max, var_min = indicator_IDP.cache.ContainerShockCapturingIndicator + + u_tmp_upper = similar(view(u_old, :, 1, :, large)) + u_tmp_lower = similar(u_tmp_upper) + u_tmp_large1 = similar(u_tmp_upper) + u_tmp_large2 = similar(u_tmp_upper) + + u_large = view(u_old, :, index_large(:)..., large) + u_upper = view(u_old, :, index_small(:)..., upper) + u_lower = view(u_old, :, index_small(:)..., lower) + + multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) + multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + + multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) + multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + + for i in eachnode(dg) + # large to small + var_min[index_small(i)..., upper] = min(var_min[index_small(i)..., upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + var_max[index_small(i)..., upper] = max(var_max[index_small(i)..., upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + + var_min[index_small(i)..., lower] = min(var_min[index_small(i)..., lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + var_max[index_small(i)..., lower] = max(var_max[index_small(i)..., lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + + # small to large + if i <= nnodes(dg)/2 + var_min[index_large(i)..., large] = min(var_min[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + var_max[index_large(i)..., large] = max(var_max[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + else + var_min[index_large(i)..., large] = min(var_min[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + var_max[index_large(i)..., large] = max(var_max[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + end + end + + return nothing +end + + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) From f164fad03f711975ecade7a51ba239235e885e7f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Mar 2022 17:20:31 +0100 Subject: [PATCH 026/423] Rename and clean up elixir and add some tests --- ...=> elixir_euler_shockcapturing_subcell.jl} | 43 ++++++++----------- src/callbacks_step/amr.jl | 2 +- test/test_tree_2d_euler.jl | 14 ++++++ 3 files changed, 33 insertions(+), 26 deletions(-) rename examples/tree_2d_dgsem/{elixir_euler_ec_sc_subcell.jl => elixir_euler_shockcapturing_subcell.jl} (53%) diff --git a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl similarity index 53% rename from examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl rename to examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index f3a939ab4a..6c114adffa 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -4,34 +4,33 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations + equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave -polydeg = 3 -basis = LobattoLegendreBasis(polydeg) -volume_flux = flux_ranocha +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; variable=Trixi.density) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=volume_flux) -solver = DGSEM(basis, flux_ranocha, volume_integral) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=volume_flux) +solver = DGSEM(basis, volume_flux, volume_integral) 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, - periodicity=true) + n_cells_max=10_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_periodic) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.4) +tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -39,30 +38,24 @@ summary_callback = SummaryCallback() analysis_interval = 100 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=5, +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -alive_callback = AliveCallback(analysis_interval=analysis_interval) - stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, +callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, - stepsize_callback) + analysis_callback, alive_callback) ############################################################################### # run the simulation -# Trixi.solve(ode, Trixi.CarpenterKennedy2N43(); -# dt=0.01, callback=callbacks) -# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks + sol = Trixi.solve_IDP(ode, semi; - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary - -using Plots -plot(indicator_sc.cache.alpha_mean_per_timestep, legend=false, ylabel="mean(alpha)", xlabel="timestep", ylims=(0, 1)) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 939f09d175..2006b8e629 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -125,7 +125,7 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u, t, integrator) semi = integrator.p if integrator isa SimpleIntegratorSSP - println("WARNING: The TVD-property can not be guaranteed when using a non-conforming mesh (i.e. with AMR).\n") + println("WARNING: The TVD property of IDP-FV-DG subcell blending shock-capturing methods is not guaranteed when using a non-conforming mesh (i.e. with AMR).\n") end @trixi_timeit timer() "initial condition AMR" if amr_callback.adapt_initial_condition diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index d82322a523..281ba4775c 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -64,6 +64,12 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) end + @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), + l2 = [0.0553929262398195, 0.04893322397478265, 0.048963817832536935, 0.20274672386802076], + linf = [0.24421260611907802, 0.3304859275088113, 0.3305295968021732, 0.8829660515342019]) + end + @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), l2 = [0.14170569763947993, 0.11647068900798814, 0.11647072556898294, 0.3391989213659599], @@ -179,6 +185,14 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=2,)) end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), + l2 = [0.05815738785949766, 0.03556776269333907, 0.050648761230924, 0.07841750042670147], + linf = [0.3593491373564508, 0.22403042619291816, 0.15284799979856273, 0.2892795213007946], + tspan = (0.0, 0.2), + coverage_override = (maxiters=2,)) + end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), # This stuff is experimental and annoying to test. In the future, we plan From b8be85bf6e4080d8cb693af796b7d66d3387d3bd Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 23 Mar 2022 17:34:20 +0100 Subject: [PATCH 027/423] Delete alpha per element --- src/solvers/dgsem_tree/containers_2d.jl | 15 +------ src/solvers/dgsem_tree/indicators.jl | 6 --- src/solvers/dgsem_tree/indicators_2d.jl | 56 ++++++++++++------------- src/time_integration/methods_SSP.jl | 18 +++----- 4 files changed, 33 insertions(+), 62 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index da5621f21f..ced5333307 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1318,10 +1318,6 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} _alpha2::Vector{uEltype} _var_max::Vector{uEltype} _var_min::Vector{uEltype} - - - alpha_max_per_element::Vector{uEltype} # [elements] - alpha_mean_per_element::Vector{uEltype} # [elements] end function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) where uEltype<:Real @@ -1340,12 +1336,8 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) w _var_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) - alpha_max_per_element = fill(nan_uEltype, capacity) - alpha_mean_per_element = fill(nan_uEltype, capacity) - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_max, var_min, - _alpha, _alpha1, _alpha2, _var_max, _var_min, - alpha_max_per_element, alpha_mean_per_element) + _alpha, _alpha1, _alpha2, _var_max, _var_min) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1358,7 +1350,7 @@ nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) n_nodes = nnodes(indicator) - @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, _var_max, var_max, _var_min, var_min, alpha_max_per_element, alpha_mean_per_element = indicator + @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, _var_max, var_max, _var_min, var_min = indicator resize!(_alpha, n_nodes * n_nodes * capacity) indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) @@ -1372,9 +1364,6 @@ function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) resize!(_var_min, n_nodes * n_nodes * capacity) indicator.var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) - resize!(alpha_max_per_element, capacity) - resize!(alpha_mean_per_element, capacity) - return nothing end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 4ae6788798..455f04df6a 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -16,12 +16,6 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end -function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) - element_variables[:indicator_shock_capturing_max] = indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element - element_variables[:indicator_shock_capturing_mean] = indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element - return nothing -end - """ IndicatorHennemannGassner diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ad0fcde021..ff32bb2d55 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -214,7 +214,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac @unpack indicator_threaded = indicator_IDP.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - @unpack alpha, alpha1, alpha2, var_max, var_min, alpha_max_per_element, alpha_mean_per_element = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha1, alpha2, var_max, var_min = indicator_IDP.cache.ContainerShockCapturingIndicator @unpack inverse_weights = dg.basis @@ -328,36 +328,32 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac var = indicator_IDP.variable(u_local, equations) if abs(var_max[i, j, element] - var) < sqrt(eps()) || abs(var_min[i, j, element] - var) < sqrt(eps()) alpha[i, j, element] = 0.0 - else - # Calculate P_plus and P_minus - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) - val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) - - P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) - P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - - # Calculate alpha_plus and alpha_minus - frac_plus = (var_max[i, j, element] - var) / P_plus - frac_minus = (var_min[i, j, element] - var) / P_minus - - alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) - alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha_plus, alpha_minus) - - # Clip the maximum amount of FV allowed - alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + continue end - - # Calculate maximum and mean alpha per element - alpha_max_per_element[element] = max(alpha_max_per_element[element], alpha[i, j, element]) - alpha_mean_per_element[element] += 1/3 * 1/(nnodes(dg)^2) * alpha[i, j, element] + # Calculate P_plus and P_minus + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) + val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) + + P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + + # Calculate alpha_plus and alpha_minus + frac_plus = (var_max[i, j, element] - var) / P_plus + frac_minus = (var_min[i, j, element] - var) / P_minus + + alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) + alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha_plus, alpha_minus) + + # Clip the maximum amount of FV allowed + alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) end # Calculate alpha1 and alpha2 diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index ef58327dee..6260fc8480 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -89,14 +89,10 @@ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) # Resize antidiffusive fluxes resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha, alpha_max_per_element, alpha_mean_per_element + # Resize alpha resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) - # Reset alpha_max_per_element, alpha_mean_per_element - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element .= 0.0 - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element .= 0.0 - if callback isa CallbackSet for cb in callback.continuous_callbacks error("unsupported") @@ -129,10 +125,6 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - # Reset alpha_max_per_element and alpha_mean_per_element - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element .= 0.0 - integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element .= 0.0 - @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) @. integrator.u_old = integrator.u @@ -161,10 +153,10 @@ function solve!(integrator::SimpleIntegratorSSP) end integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_max_per_element) + maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = - 1/length(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element) * - sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha_mean_per_element) + (1/(nnodes(integrator.p.solver)^ndims(integrator.p.equations) * nelements(integrator.p.solver, integrator.p.cache))) * + sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) integrator.iter += 1 integrator.t += integrator.dt @@ -220,7 +212,7 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) # Resize antidiffusive fluxes resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha, alpha_max_per_element, alpha_mean_per_element + # Resize alpha resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) From dc6c83064c80e02e4776c37dc94d1b253ea1ed02 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 4 Apr 2022 12:00:44 +0200 Subject: [PATCH 028/423] Fix indicator calculation --- .../elixir_euler_blast_wave_sc_subcell.jl | 3 --- .../elixir_euler_shockcapturing_subcell.jl | 7 +++--- src/solvers/dgsem_tree/indicators_2d.jl | 15 +++++++++--- test/test_tree_2d_euler.jl | 24 +++++++++---------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index eb3626370a..be38e7079d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -88,6 +88,3 @@ sol = Trixi.solve_IDP(ode, semi; 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 - -using Plots -plot(indicator_sc.cache.alpha_mean_per_timestep, legend=false, ylabel="mean(alpha)", xlabel="timestep") diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 6c114adffa..4dbed9202e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -9,13 +9,14 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave +surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; variable=Trixi.density) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=volume_flux) -solver = DGSEM(basis, volume_flux, volume_integral) + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) coordinates_max = ( 2.0, 2.0) @@ -45,7 +46,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ff32bb2d55..1f617ba0af 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -326,10 +326,12 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) var = indicator_IDP.variable(u_local, equations) - if abs(var_max[i, j, element] - var) < sqrt(eps()) || abs(var_min[i, j, element] - var) < sqrt(eps()) + + if maximum(abs.((var_max[i, j, element] - var, var_min[i, j, element] - var))) < eps() alpha[i, j, element] = 0.0 continue end + # Calculate P_plus and P_minus # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) @@ -342,9 +344,16 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + if maximum(abs.((P_plus, P_minus))) < eps() + alpha[i, j, element] = 0.0 + continue + end + # Calculate alpha_plus and alpha_minus - frac_plus = (var_max[i, j, element] - var) / P_plus - frac_minus = (var_min[i, j, element] - var) / P_minus + # Note: If P_plus or P_minus is 0.0, eventually frac_plus/minus = -Inf and then alpha = 1. + # So, add maschine precision to values. + frac_plus = (var_max[i, j, element] - var) / (P_plus + eps()) + frac_minus = (var_min[i, j, element] - var) / (P_minus - eps()) alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 281ba4775c..014ad4ab30 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -64,11 +64,11 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) end - @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - l2 = [0.0553929262398195, 0.04893322397478265, 0.048963817832536935, 0.20274672386802076], - linf = [0.24421260611907802, 0.3304859275088113, 0.3305295968021732, 0.8829660515342019]) - end + # @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin + # @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), + # l2 = [0.0553929262398195, 0.04893322397478265, 0.048963817832536935, 0.20274672386802076], + # linf = [0.24421260611907802, 0.3304859275088113, 0.3305295968021732, 0.8829660515342019]) + # end @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), @@ -185,13 +185,13 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=2,)) end - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.05815738785949766, 0.03556776269333907, 0.050648761230924, 0.07841750042670147], - linf = [0.3593491373564508, 0.22403042619291816, 0.15284799979856273, 0.2892795213007946], - tspan = (0.0, 0.2), - coverage_override = (maxiters=2,)) - end + # @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin + # @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), + # l2 = [0.05815738785949766, 0.03556776269333907, 0.050648761230924, 0.07841750042670147], + # linf = [0.3593491373564508, 0.22403042619291816, 0.15284799979856273, 0.2892795213007946], + # tspan = (0.0, 0.2), + # coverage_override = (maxiters=2,)) + # end @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), From 20301ac35b89babe2eb775a230376662e465cd17 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 25 Apr 2022 11:30:53 +0200 Subject: [PATCH 029/423] Update structure, add correction for nonlinear contraints --- .../elixir_euler_astro_jet_subcell.jl | 95 +++ ...kelvin_helmholtz_instability_sc_subcell.jl | 7 +- .../elixir_euler_source_terms_sc_subcell.jl | 69 +++ src/equations/compressible_euler_2d.jl | 51 ++ src/solvers/dgsem_tree/containers_2d.jl | 66 ++- src/solvers/dgsem_tree/dg_2d.jl | 24 +- src/solvers/dgsem_tree/indicators.jl | 40 +- src/solvers/dgsem_tree/indicators_2d.jl | 548 ++++++++++++++---- src/time_integration/methods_SSP.jl | 27 +- 9 files changed, 762 insertions(+), 165 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl new file mode 100644 index 0000000000..1aec2a49af --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -0,0 +1,95 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 5/3 +equations = CompressibleEulerEquations2D(gamma) + +# Initial condition adopted from +# - Yong Liu, Jianfang Lu, and Chi-Wang Shu +# An oscillation free discontinuous Galerkin method for hyperbolic systems +# https://tinyurl.com/c76fjtx4 +# Mach = 2000 jet +function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) + @unpack gamma = equations + rho = 0.5 + v1 = 0 + v2 = 0 + p = 0.4127 + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_astro_jet + +boundary_conditions = ( + x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), + x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), + y_neg=boundary_condition_periodic, + y_pos=boundary_condition_periodic, + ) + +surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) +volume_flux = flux_ranocha # works with Chandrashekar flux as well +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +# shock capturing necessary for this tough example +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=true, + IDPSpecEntropy=false, + IDPMathEntropy=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-0.5, -0.5) +coordinates_max = ( 0.5, 0.5) + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + periodicity=(false,true), + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.001) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 5000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.004) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation +sol = Trixi.solve_IDP(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 09bccf4349..c5a5392222 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,8 +37,11 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - alpha_maxIDP=1.0, - variable=Trixi.density) + IDPDensityTVD=true, + IDPPressureTVD=false, + IDPPositivity=false, + IDPSpecEntropy=false, + IDPMathEntropy=false) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl new file mode 100644 index 0000000000..184ab37080 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -0,0 +1,69 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_convergence_test + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +indicator_sc = IndicatorIDP(equations, basis; + alpha_maxIDP=1.0, + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=true, + IDPSpecEntropy=false, + IDPMathEntropy=false) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (0.0, 0.0) +coordinates_max = (2.0, 2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + n_cells_max=10_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms=source_terms_convergence_test) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.4) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = Trixi.solve_IDP(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index fea83db3d4..e046429a28 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1003,6 +1003,42 @@ end return SVector(w1, w2, w3, w4) end +# Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) +@inline function cons2specentropy(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + srho_gammap1 = (1/rho)^(equations.gamma + 1.0) + + # The derivative vector for the modified specific entropy of Guermond et al. + w1 = srho_gammap1 * (0.5 * rho * v_square - equations.gamma * rho_e) + w2 = -rho_v1 * srho_gammap1 + w3 = -rho_v2 * srho_gammap1 + w4 = (1/rho)^equations.gamma + + # The derivative vector for other specific entropy + # sp = 1.0/(gammam1 * (rho_e - 0.5 * rho * v_square) + # w1 = gammam1 * 0.5 * v_square * sp - gamma / rho + # w2 = -gammam1 * v1 * sp + # w3 = -gammam1 * v2 * sp + # w4 = gammam1 * sp + + return SVector(w1, w2, w3, w4) +end + +# Transformation from conservative variables u to d(p)/d(u) +@inline function dpdu(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + + return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) +end + @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD # [DOI: 10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) @@ -1103,6 +1139,21 @@ end return S end +@inline function specEntropy(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + + # Modified specific entropy from Guermond et al. (2019) + return (rho_e - 0.5 * rho * v_square) * (1/rho)^equations.gamma + + # Other specific entropy + # rho_sp = rho/((equations.gamma - 1.0) * (rho_e - 0.5 * rho * v_square)) + # return - log(rho_sp * rho^equations.gamma) +end + # Default entropy is the mathematical entropy @inline entropy(cons, equations::CompressibleEulerEquations2D) = entropy_math(cons, equations) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index ced5333307..7c4ddbb192 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1310,14 +1310,22 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, elements] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} - var_max::Array{uEltype, 3} - var_min::Array{uEltype, 3} + rho_max::Array{uEltype, 3} + rho_min::Array{uEltype, 3} + p_max::Array{uEltype, 3} + p_min::Array{uEltype, 3} + s_max::Array{uEltype, 3} + s_min::Array{uEltype, 3} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} - _var_max::Vector{uEltype} - _var_min::Vector{uEltype} + _rho_max::Vector{uEltype} + _rho_min::Vector{uEltype} + _p_max::Vector{uEltype} + _p_min::Vector{uEltype} + _s_max::Vector{uEltype} + _s_min::Vector{uEltype} end function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) where uEltype<:Real @@ -1331,13 +1339,27 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) w _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) alpha2 = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes+1, capacity)) - _var_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) - var_max = unsafe_wrap(Array, pointer(_var_max), (n_nodes, n_nodes, capacity)) - _var_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) - var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) + _rho_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) + rho_max = unsafe_wrap(Array, pointer(_rho_max), (n_nodes, n_nodes, capacity)) + _rho_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) + rho_min = unsafe_wrap(Array, pointer(_rho_min), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_max, var_min, - _alpha, _alpha1, _alpha2, _var_max, _var_min) + _p_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) + p_max = unsafe_wrap(Array, pointer(_p_max), (n_nodes, n_nodes, capacity)) + _p_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) + p_min = unsafe_wrap(Array, pointer(_p_min), (n_nodes, n_nodes, capacity)) + + _s_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) + s_max = unsafe_wrap(Array, pointer(_s_max), (n_nodes, n_nodes, capacity)) + _s_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) + s_min = unsafe_wrap(Array, pointer(_s_min), (n_nodes, n_nodes, capacity)) + + # idp_bounds_delta = zeros(uEltype, ) + + return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, + rho_max, rho_min, p_max, p_min, s_max, s_min, + _alpha, _alpha1, _alpha2, + _rho_max, _rho_min, _p_max, _p_min, _s_max, _s_min) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1350,8 +1372,7 @@ nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) n_nodes = nnodes(indicator) - @unpack _alpha, alpha, _alpha1, alpha1, _alpha2, alpha2, _var_max, var_max, _var_min, var_min = indicator - + @unpack _alpha, _alpha1, _alpha2 = indicator resize!(_alpha, n_nodes * n_nodes * capacity) indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) resize!(_alpha1, (n_nodes + 1) * n_nodes * capacity) @@ -1359,10 +1380,23 @@ function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - resize!(_var_max, n_nodes * n_nodes * capacity) - indicator.var_max = unsafe_wrap(Array, pointer(_var_max), (n_nodes, n_nodes, capacity)) - resize!(_var_min, n_nodes * n_nodes * capacity) - indicator.var_min = unsafe_wrap(Array, pointer(_var_min), (n_nodes, n_nodes, capacity)) + @unpack _rho_max, _rho_min = indicator + resize!(_rho_max, n_nodes * n_nodes * capacity) + indicator.rho_max = unsafe_wrap(Array, pointer(_rho_max), (n_nodes, n_nodes, capacity)) + resize!(_rho_min, n_nodes * n_nodes * capacity) + indicator.rho_min = unsafe_wrap(Array, pointer(_rho_min), (n_nodes, n_nodes, capacity)) + + @unpack _p_max, _p_min = indicator + resize!(_p_max, n_nodes * n_nodes * capacity) + indicator.p_max = unsafe_wrap(Array, pointer(_p_max), (n_nodes, n_nodes, capacity)) + resize!(_p_min, n_nodes * n_nodes * capacity) + indicator.p_min = unsafe_wrap(Array, pointer(_p_min), (n_nodes, n_nodes, capacity)) + + @unpack _s_max, _s_min = indicator + resize!(_s_max, n_nodes * n_nodes * capacity) + indicator.s_max = unsafe_wrap(Array, pointer(_s_max), (n_nodes, n_nodes, capacity)) + resize!(_s_min, n_nodes * n_nodes * capacity) + indicator.s_min = unsafe_wrap(Array, pointer(_s_min), (n_nodes, n_nodes, capacity)) return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index a857dd6214..c5cb0e8fb8 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -671,9 +671,6 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - @unpack inverse_weights = solver.basis - - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -681,16 +678,25 @@ end @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) @unpack alpha1, alpha2 = semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(solver, semi.cache) + IDP_correction!(u, alpha1, alpha2, dt, equations, solver, cache) + + return nothing +end + +@inline function IDP_correction!(u::AbstractArray{<:Any,4}, alpha1, alpha2, dt, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + + @threaded for element in eachelement(dg, cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] # Calculate volume integral contribution # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - for j in eachnode(solver), i in eachnode(solver) - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) + for j in eachnode(dg), i in eachnode(dg) + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 455f04df6a..7a4aabc649 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -163,26 +163,52 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT<:Real, Variable, Cache} <: AbstractIndicator +struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator alpha_maxIDP::RealT - variable::Variable + IDPPositivity::Bool + IDPDensityTVD::Bool + IDPPressureTVD::Bool + IDPSpecEntropy::Bool + IDPMathEntropy::Bool cache::Cache end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; alpha_maxIDP=1.0, - variable) - cache = create_cache(IndicatorIDP, equations, basis) - IndicatorIDP{typeof(alpha_maxIDP), typeof(variable), typeof(cache)}(alpha_maxIDP, variable, cache) + IDPPositivity=false, + IDPDensityTVD=false, + IDPPressureTVD=false, + IDPSpecEntropy=false, + IDPMathEntropy=false) + + if IDPMathEntropy && IDPSpecEntropy + error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") + end + + if !(IDPPositivity || IDPDensityTVD || IDPPressureTVD || IDPSpecEntropy || IDPMathEntropy) + println("No limiter selected. Default: use IDPSpecEntropy") + IDPSpecEntropy = true + end + + cache = create_cache(IndicatorIDP, equations, basis) # , 2 * (IDPDensityTVD + IDPPressureTVD + IDPPositivity) + IDPMathEntropy + IDPSpecEntropy) + IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, + IDPPositivity, IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, + cache) end function Base.show(io::IO, indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time print(io, "IndicatorIDP(") - print(io, indicator.variable) - print(io, ", alpha_maxIDP=", indicator.alpha_maxIDP) + print(io, "limiter=(") + indicator.IDPPositivity && print(io, "IDPPositivity, ") + indicator.IDPDensityTVD && print(io, "IDPDensityTVD, ") + indicator.IDPPressureTVD && print(io, "IDPPressureTVD, ") + indicator.IDPSpecEntropy && print(io, "IDPSpecEntropy, ") + indicator.IDPMathEntropy && print(io, "IDPMathEntropy, ") + print(io, "), ") + print(io, "alpha_maxIDP=", indicator.alpha_maxIDP) print(io, ")") end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 1f617ba0af..b11d5555bc 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -211,43 +211,185 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac mesh, equations, dg::DGSEM, dt, cache; kwargs...) + @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator + alpha .= 0.0 + + indicator_IDP.IDPDensityTVD && + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + indicator_IDP.IDPPressureTVD && + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + indicator_IDP.IDPPositivity && + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, equations, dg, dt, cache) + indicator_IDP.IDPSpecEntropy && + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + indicator_IDP.IDPMathEntropy && + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + + # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) + @unpack alpha_maxIDP = indicator_IDP + if alpha_maxIDP != 1.0 + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) + end + end + end + + # Calculate alpha1 and alpha2 + @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) + end + for j in 2:nnodes(dg), i in eachnode(dg) + alpha2[i, j, element] = max(alpha[i, j-1, element], alpha[i, j, element]) + end + alpha1[1, :, element] .= zero(eltype(alpha1)) + alpha1[nnodes(dg)+1, :, element] .= zero(eltype(alpha1)) + alpha2[:, 1, element] .= zero(eltype(alpha2)) + alpha2[:, nnodes(dg)+1, element] .= zero(eltype(alpha2)) + end + + return nothing +end + +@inline function IDP_densityTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + @unpack rho_max, rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator + + # calculate_max_min_values!(rho_max, rho_min, u_safe, indicator_IDP, density, equations, dg, cache) @unpack indicator_threaded = indicator_IDP.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @threaded for element in eachelement(dg, cache) + # Calculate indicator variables at Gauss-Lobatto nodes + indicator = indicator_threaded[Threads.threadid()] + for j in eachnode(dg), i in eachnode(dg) + indicator[i, j] = u_old[1, i, j, element] + end - @unpack alpha, alpha1, alpha2, var_max, var_min = indicator_IDP.cache.ContainerShockCapturingIndicator + for j in eachnode(dg), i in eachnode(dg) + # Calculate max and min of variable at Gauss-Lobatto nodes + rho_min[i, j, element] = indicator[i, j] + rho_max[i, j, element] = indicator[i, j] + if i > 1 + rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i-1, j]) + rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i-1, j]) + end + if i < nnodes(dg) + rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i+1, j]) + rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i+1, j]) + end + if j > 1 + rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i, j-1]) + rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i, j-1]) + end + if j < nnodes(dg) + rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i, j+1]) + rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i, j+1]) + end + end + end - @unpack inverse_weights = dg.basis + # Loop over interfaces + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] - @unpack alpha_maxIDP = indicator_IDP + orientation = cache.interfaces.orientations[interface] + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + rho_neighbor_left = u_old[1, index_left...] + rho_neighbor_right = u_old[1, index_right...] + + rho_min[index_right...] = min(rho_min[index_right...], rho_neighbor_left) + rho_max[index_right...] = max(rho_max[index_right...], rho_neighbor_left) + + rho_min[index_left...] = min(rho_min[index_left...], rho_neighbor_right) + rho_max[index_left...] = max(rho_max[index_left...], rho_neighbor_right) + end + end + + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + var = u[1, i, j, element] + + # Calculate P_plus and P_minus + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] + val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] + + P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + P_plus = dt * inverse_jacobian * P_plus + P_minus = dt * inverse_jacobian * P_minus + + # Calculate alpha_plus and alpha_minus + if P_plus == 0.0 + frac_plus = 1.0 + else + frac_plus = max(0.0, rho_max[i, j, element] - var) / P_plus + end + if P_minus == 0.0 + frac_minus = 1.0 + else + frac_minus = min(0.0, rho_min[i, j, element] - var) / P_minus + end + + # Calculate alpha at nodes + alpha[i, j, element] = 1 - min(1.0, frac_plus, frac_minus) + end + end + + return nothing +end + +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + @unpack p_max, p_min = indicator_IDP.cache.ContainerShockCapturingIndicator + + # calculate_max_min_values!(p_max, p_min, u_safe, indicator_IDP, pressure, equations, dg, cache) + @unpack indicator_threaded = indicator_IDP.cache + + @threaded for element in eachelement(dg, cache) # Calculate indicator variables at Gauss-Lobatto nodes indicator = indicator_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u_old, equations, dg, i, j, element) - indicator[i, j] = indicator_IDP.variable(u_local, equations) + indicator[i, j] = pressure(u_local, equations) end for j in eachnode(dg), i in eachnode(dg) # Calculate max and min of variable at Gauss-Lobatto nodes - var_min[i, j, element] = indicator[i, j] - var_max[i, j, element] = indicator[i, j] + p_min[i, j, element] = indicator[i, j] + p_max[i, j, element] = indicator[i, j] if i > 1 - var_min[i, j, element] = min(var_min[i, j, element], indicator[i-1, j]) - var_max[i, j, element] = max(var_max[i, j, element], indicator[i-1, j]) + p_min[i, j, element] = min(p_min[i, j, element], indicator[i-1, j]) + p_max[i, j, element] = max(p_max[i, j, element], indicator[i-1, j]) end if i < nnodes(dg) - var_min[i, j, element] = min(var_min[i, j, element], indicator[i+1, j]) - var_max[i, j, element] = max(var_max[i, j, element], indicator[i+1, j]) + p_min[i, j, element] = min(p_min[i, j, element], indicator[i+1, j]) + p_max[i, j, element] = max(p_max[i, j, element], indicator[i+1, j]) end if j > 1 - var_min[i, j, element] = min(var_min[i, j, element], indicator[i, j-1]) - var_max[i, j, element] = max(var_max[i, j, element], indicator[i, j-1]) + p_min[i, j, element] = min(p_min[i, j, element], indicator[i, j-1]) + p_max[i, j, element] = max(p_max[i, j, element], indicator[i, j-1]) end if j < nnodes(dg) - var_min[i, j, element] = min(var_min[i, j, element], indicator[i, j+1]) - var_max[i, j, element] = max(var_max[i, j, element], indicator[i, j+1]) + p_min[i, j, element] = min(p_min[i, j, element], indicator[i, j+1]) + p_max[i, j, element] = max(p_max[i, j, element], indicator[i, j+1]) end end end @@ -270,160 +412,332 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end u_local_left = get_node_vars(u_old, equations, dg, index_left...) u_local_right = get_node_vars(u_old, equations, dg, index_right...) - var_neighbor_left = indicator_IDP.variable(u_local_left, equations) - var_neighbor_right = indicator_IDP.variable(u_local_right, equations) + p_neighbor_left = pressure(u_local_left, equations) + p_neighbor_right = pressure(u_local_right, equations) - var_min[index_right...] = min(var_min[index_right...], var_neighbor_left) - var_max[index_right...] = max(var_max[index_right...], var_neighbor_left) + p_min[index_right...] = min(p_min[index_right...], p_neighbor_left) + p_max[index_right...] = max(p_max[index_right...], p_neighbor_left) - var_min[index_left...] = min(var_min[index_left...], var_neighbor_right) - var_max[index_left...] = max(var_max[index_left...], var_neighbor_right) + p_min[index_left...] = min(p_min[index_left...], p_neighbor_right) + p_max[index_left...] = max(p_max[index_left...], p_neighbor_right) end end - # Loop over L2 mortars - for mortar in eachmortar(dg, cache) - # Get neighboring element ids - lower = cache.mortars.neighbor_ids[1, mortar] - upper = cache.mortars.neighbor_ids[2, mortar] - large = cache.mortars.neighbor_ids[3, mortar] + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack inverse_weights = dg.basis + @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + var = pressure(u_local, equations) + + # Calculate P_plus and P_minus + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + v1 = u[2, i, j, element] / u[1, i, j, element] + v2 = u[3, i, j, element] / u[1, i, j, element] + # vel = get_node_vars(u, equations, dg, i, j, element)[2:3] / u[1, i, j, element] + v2s2 = 0.5 * sum(v1^2 + v2^2) + gamma_m1 = equations.gamma - 1.0 + val_flux1_local = gamma_m1 * (antidiffusive_flux1[4, i, j, element] + v2s2 * antidiffusive_flux1[1, i, j, element] - + v1 * antidiffusive_flux1[2, i, j, element] - v2 * antidiffusive_flux1[3, i, j, element]) + val_flux1_local_ip1 = gamma_m1 * (antidiffusive_flux1[4, i+1, j, element] + v2s2 * antidiffusive_flux1[1, i+1, j, element] - + v1 * antidiffusive_flux1[2, i+1, j, element] - v2 * antidiffusive_flux1[3, i+1, j, element]) + val_flux2_local = gamma_m1 * (antidiffusive_flux2[4, i, j, element] + v2s2 * antidiffusive_flux2[1, i, j, element] - + v1 * antidiffusive_flux2[2, i, j, element] - v2 * antidiffusive_flux2[3, i, j, element]) + val_flux2_local_jp1 = gamma_m1 * (antidiffusive_flux2[4, i, j+1, element] + v2s2 * antidiffusive_flux2[1, i, j+1, element] - + v1 * antidiffusive_flux2[2, i, j+1, element] - v2 * antidiffusive_flux2[3, i, j+1, element]) + + P_plus = max(0.0, inverse_weights[i] * val_flux1_local) + max(0.0, -inverse_weights[i] * val_flux1_local_ip1) + + max(0.0, inverse_weights[j] * val_flux2_local) + max(0.0, -inverse_weights[j] * val_flux2_local_jp1) + P_minus = min(0.0, inverse_weights[i] * val_flux1_local) + min(0.0, -inverse_weights[i] * val_flux1_local_ip1) + + min(0.0, inverse_weights[j] * val_flux2_local) + min(0.0, -inverse_weights[j] * val_flux2_local_jp1) + P_plus = dt * inverse_jacobian * P_plus + P_minus = dt * inverse_jacobian * P_minus - # Interpolate element face data to adjacent interface locations and use for var_max/min - if cache.mortars.large_sides[mortar] == 1 # -> large element on left side - if cache.mortars.orientations[mortar] == 1 - # L2 mortars in x-direction - index_large = i -> (nnodes(dg), i) - index_small = i -> (1, i) - element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, - large, upper, lower, index_large, index_small) + # Calculate alpha_plus and alpha_minus + if P_plus == 0.0 + frac_plus = 1.0 else - # L2 mortars in y-direction - index_large = i -> (i, nnodes(dg)) - index_small = i -> (i, 1) - element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, - large, upper, lower, index_large, index_small) - end - else # large_sides[mortar] == 2 -> large element on right side - if cache.mortars.orientations[mortar] == 1 - # L2 mortars in x-direction - index_large = i -> (1, i) - index_small = i -> (nnodes(dg), i) - element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, - large, upper, lower, index_large, index_small) + frac_plus = max(0.0, p_max[i, j, element] - var) / P_plus + end + if P_minus == 0.0 + frac_minus = 1.0 else - # L2 mortars in y-direction - index_large = i -> (i, 1) - index_small = i -> (i, nnodes(dg)) - element_solutions_to_mortars!(u_old, indicator_IDP, dg, equations, - large, upper, lower, index_large, index_small) + frac_minus = min(0.0, p_min[i, j, element] - var) / P_minus end + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1.0, frac_plus, frac_minus)) end end + return nothing +end + +@inline function IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + @unpack s_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + # Get limit states; no neighbors. + s_min[i, j, element] = specEntropy(get_node_vars(u, equations, dg, i, j, element), equations) + if i > 1 + s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i-1, j, element), equations)) + end + if i < nnodes(dg) + s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i+1, j, element), equations)) + end + if j > 1 + s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i, j-1, element), equations)) + end + if j < nnodes(dg) + s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i, j+1, element), equations)) + end + + # Get current alpha # TODO: delta alpha? + # new_alpha = alpha[i, j, element] + + # Perform Newton's bisection method to find new alpha + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, + specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, + equations, dg, dt, cache) + + # Update alpha + # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) + end + end + + return nothing +end + +specEntropy_goal(bound, u, equations) = bound - specEntropy(u, equations) +specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2specentropy(u, equations), dt * antidiffusive_flux) +specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) + +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + @unpack s_max = indicator_IDP.cache.ContainerShockCapturingIndicator + + @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) + + # Get limit states; no neighbors. + s_max[i, j, element] = mathEntropy(get_node_vars(u, equations, dg, i, j, element), equations) + if i > 1 + s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i-1, j, element), equations)) + end + if i < nnodes(dg) + s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i+1, j, element), equations)) + end + if j > 1 + s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i, j-1, element), equations)) + end + if j < nnodes(dg) + s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i, j+1, element), equations)) + end + + # Get current alpha # TODO: delta alpha? + # new_alpha = alpha[i, j, element] + + # Perform Newton's bisection method to find new alpha u_local = get_node_vars(u, equations, dg, i, j, element) - var = indicator_IDP.variable(u_local, equations) + newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, + mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, + equations, dg, dt, cache) - if maximum(abs.((var_max[i, j, element] - var, var_min[i, j, element] - var))) < eps() - alpha[i, j, element] = 0.0 - continue + # Update alpha + # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) + end + end + + return nothing +end + +mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) +mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) +mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) + +@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack inverse_weights = dg.basis + + positCorrFactor = 0.1 # The correction factor for IDPPositivity # TODO + + # Correct density + @unpack rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator + for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + + # Compute bound + if indicator_IDP.IDPDensityTVD + rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * u_safe[1, i, j, element]) + else + rho_min[i, j, element] = positCorrFactor * u_safe[1, i, j, element] end - # Calculate P_plus and P_minus + # Real one-sided Zalesak-type limiter + frac_minus = min(0.0, (rho_min[i, j, element] - u_safe[1, i, j, element]) / dt) + + # Calculate P_minus # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) - val_flux2_local = indicator_IDP.variable( dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = indicator_IDP.variable(-dt * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) + val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] + val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] - P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + P_minus = inverse_jacobian * P_minus - if maximum(abs.((P_plus, P_minus))) < eps() - alpha[i, j, element] = 0.0 - continue + if P_minus < 0.0 + frac_minus = min(1.0, frac_minus / P_minus) + else + frac_minus = 1.0 end - # Calculate alpha_plus and alpha_minus - # Note: If P_plus or P_minus is 0.0, eventually frac_plus/minus = -Inf and then alpha = 1. - # So, add maschine precision to values. - frac_plus = (var_max[i, j, element] - var) / (P_plus + eps()) - frac_minus = (var_min[i, j, element] - var) / (P_minus - eps()) + # Calculate alpha + # TODO: Respect current alpha. Is it enough to just use: alpha = max(alpha, 1-frac_minus)? + alpha[i, j, element] = max(alpha[i, j, element], 1 - frac_minus) + end + end - alpha_plus = 1 - min(1.0, max(0.0, frac_plus)) - alpha_minus = 1 - min(1.0, max(0.0, frac_minus)) + # Correct pressure + @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator + for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha_plus, alpha_minus) + # Compute bound + u_local = get_node_vars(u_safe, equations, dg, i, j, element) + p_safe = pressure(u_local, equations) + if p_safe < 0.0 + println("Error: safe pressure is not safe. element=$element, node: $i $j, pressure=$p_safe") + end + if indicator_IDP.IDPPressureTVD + p_min[i, j, element] = max(p_min[i, j, element], positCorrFactor * p_safe) + else + p_min[i, j, element] = positCorrFactor * p_safe + end - # Clip the maximum amount of FV allowed - alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) - end + # Get current alpha # TODO: delta alpha? + # new_alpha = alpha[i, j, element] - # Calculate alpha1 and alpha2 - for j in eachnode(dg), i in 2:nnodes(dg) - alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) - end - for j in 2:nnodes(dg), i in eachnode(dg) - alpha2[i, j, element] = max(alpha[i, j-1, element], alpha[i, j, element]) + # Perform Newton's bisection method to find new alpha + newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, equations, dg, dt, cache) + + # Update alpha + # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) end - alpha1[1, :, element] .= zero(eltype(alpha1)) - alpha1[nnodes(dg)+1, :, element] .= zero(eltype(alpha1)) - alpha2[:, 1, element] .= zero(eltype(alpha2)) - alpha2[:, nnodes(dg)+1, element] .= zero(eltype(alpha2)) end return nothing end +pressure_goal(bound, u, equations) = bound - pressure(u, equations) +pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(dpdu(u, equations), dt * antidiffusive_flux) +pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0.0 +pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) + +@inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dg, dt, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + inverse_jacobian = cache.elements.inverse_jacobian[element] + + IDPgamma = 4.0 # Constant for the subcell limiting of convex (nonlinear) constraints (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) + + # negative xi direction + antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + + # positive xi direction + antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + + # negative eta direction + antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + + # positive eta direction + antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) -@inline function element_solutions_to_mortars!(u_old::AbstractArray{<:Any,4}, indicator_IDP, dg, equations, - large, upper, lower, - index_large, index_small) + return nothing +end - @unpack var_max, var_min = indicator_IDP.cache.ContainerShockCapturingIndicator +@inline function newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + beta = 1.0 - alpha[i, j, element] - u_tmp_upper = similar(view(u_old, :, 1, :, large)) - u_tmp_lower = similar(u_tmp_upper) - u_tmp_large1 = similar(u_tmp_upper) - u_tmp_large2 = similar(u_tmp_upper) + beta_L = 0.0 # alpha = 1 + beta_R = beta # No higher beta (lower alpha) than the current one - u_large = view(u_old, :, index_large(:)..., large) - u_upper = view(u_old, :, index_small(:)..., upper) - u_lower = view(u_old, :, index_small(:)..., lower) + u_curr = u_safe + beta * dt * antidiffusive_flux - multiply_dimensionwise!(u_tmp_upper, dg.mortar.forward_upper, u_large) - multiply_dimensionwise!(u_tmp_lower, dg.mortar.forward_lower, u_large) + # Perform initial Check + as = goal_fct(bound, u_curr, equations) - multiply_dimensionwise!(u_tmp_large1, dg.mortar.reverse_upper, u_upper) - multiply_dimensionwise!(u_tmp_large2, dg.mortar.reverse_lower, u_lower) + # TODO: save tolerances somewhere + newton_reltol = 1.0e-12 # Relative tolerance to exit Newton loop + newton_abstol = 1.0e-14 # Absolute tolerance (with respect to the value of the entropy goal, tol = NEWTON_ABSTOL*s_goal) + initialCheck(bound, as, newton_abstol) && return nothing - for i in eachnode(dg) - # large to small - var_min[index_small(i)..., upper] = min(var_min[index_small(i)..., upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) - var_max[index_small(i)..., upper] = max(var_max[index_small(i)..., upper], indicator_IDP.variable(view(u_tmp_upper, :, i), equations)) + # Newton iterations + IDPMaxIter = 10 # TODO: save somewhere + for iter in 1:IDPMaxIter + beta_old = beta - var_min[index_small(i)..., lower] = min(var_min[index_small(i)..., lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) - var_max[index_small(i)..., lower] = max(var_max[index_small(i)..., lower], indicator_IDP.variable(view(u_tmp_lower, :, i), equations)) + # Evaluate d(goal)/d(beta) + dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + + if dSdbeta != 0.0 + # Update beta with Newton's method + beta = beta - as / dSdbeta + end - # small to large - if i <= nnodes(dg)/2 - var_min[index_large(i)..., large] = min(var_min[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) - var_max[index_large(i)..., large] = max(var_max[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large2, :, i), equations)) + # Check bounds + if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0.0) || isnan(beta) + # Out of bounds, do a bisection step + beta = 0.5 * (beta_L + beta_R) + # Get new u + u_curr = u_safe + beta * dt * antidiffusive_flux + # Check new beta for condition and update bounds + as = goal_fct(bound, u_curr, equations) + if initialCheck(bound, as, newton_abstol) + beta_L = beta + else + beta_R = beta + end else - var_min[index_large(i)..., large] = min(var_min[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) - var_max[index_large(i)..., large] = max(var_max[index_large(i)..., large], indicator_IDP.variable(view(u_tmp_large1, :, i), equations)) + # Get new u + u_curr = u_safe + beta * dt * antidiffusive_flux + # Evaluate goal function + as = goal_fct(bound, u_curr, equations) + end + + # Check relative tolerance + if abs(beta_old - beta) <= newton_reltol + break + end + + # Check absolute tolerance + if finalCheck(bound, as, newton_abstol) + break end end + new_alpha = 1.0 - beta + if alpha[i, j, element] > new_alpha + newton_abstol + error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") + else + alpha[i, j, element] = new_alpha + end + return nothing end +standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 6260fc8480..2853f178f0 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -40,9 +40,9 @@ end # https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 # which are used in Trixi. mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, Alg, SimpleIntegratorSSPOptions} - u::uType # + u::uType du::uType - u_tmp::uType + u_safe::uType u_old::uType t::RealT dt::RealT # current time step @@ -79,11 +79,11 @@ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) u = copy(ode.u0) du = similar(u) - u_tmp = similar(u) + u_safe = similar(u) u_old = similar(u) t = first(ode.tspan) iter = 0 - integrator = SimpleIntegratorSSP(u, du, u_tmp, u_old, t, dt, zero(dt), iter, ode.p, + integrator = SimpleIntegratorSSP(u, du, u_safe, u_old, t, dt, zero(dt), iter, ode.p, (prob=ode,), alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) @@ -127,21 +127,20 @@ function solve!(integrator::SimpleIntegratorSSP) @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u, integrator.p, integrator.t) - @. integrator.u_old = integrator.u - @. integrator.u_tmp = integrator.u_old + integrator.dt * integrator.du + @. integrator.u_safe = integrator.u + integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u_old, integrator.dt, integrator.p) + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u, integrator.dt, integrator.p) @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + integrator.dt) - @. integrator.u_old = 3/4 * integrator.u + 1/4 * integrator.u_tmp - @. integrator.u_tmp = integrator.u_old + 1/4 * integrator.dt * integrator.du + prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + integrator.dt) + @. integrator.u_old = 3/4 * integrator.u + 1/4 * integrator.u_safe + @. integrator.u_safe = integrator.u_old + 1/4 * integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_tmp, integrator.u_old, 1/4 * integrator.dt, integrator.p) + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, 1/4 * integrator.dt, integrator.p) @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_tmp, integrator.p, integrator.t + 1/2 * integrator.dt) - @. integrator.u_old = 1/3 * integrator.u + 2/3 * integrator.u_tmp + prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + 1/2 * integrator.dt) + @. integrator.u_old = 1/3 * integrator.u + 2/3 * integrator.u_safe @. integrator.u = integrator.u_old + 2/3 * integrator.dt * integrator.du end @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, integrator.u_old, 2/3 * integrator.dt, integrator.p) @@ -184,7 +183,7 @@ end # get a cache where the RHS can be stored get_du(integrator::SimpleIntegratorSSP) = integrator.du -get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_tmp, integrator.u_old) +get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_safe, integrator.u_old) # some algorithms from DiffEq like FSAL-ones need to be informed when a callback has modified u u_modified!(integrator::SimpleIntegratorSSP, ::Bool) = false From 9db45cc4c7f5276e40332035ccaeacc4f4589b96 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 25 Apr 2022 12:18:03 +0200 Subject: [PATCH 030/423] Change name of spec entropy --- src/equations/compressible_euler_2d.jl | 5 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 37 +++++++------------------ 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index e046429a28..b33082a754 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1004,7 +1004,7 @@ end end # Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) -@inline function cons2specentropy(u, equations::CompressibleEulerEquations2D) +@inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1139,7 +1139,8 @@ end return S end -@inline function specEntropy(u, equations::CompressibleEulerEquations2D) +# Calculate specific entropy for conservative variable u +@inline function entropy_spec(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index b11d5555bc..74ffbf9f58 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -482,39 +482,33 @@ end for j in eachnode(dg), i in eachnode(dg) # Get limit states; no neighbors. - s_min[i, j, element] = specEntropy(get_node_vars(u, equations, dg, i, j, element), equations) + s_min[i, j, element] = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) if i > 1 - s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i-1, j, element), equations)) + s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i-1, j, element), equations)) end if i < nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i+1, j, element), equations)) + s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i+1, j, element), equations)) end if j > 1 - s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i, j-1, element), equations)) + s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i, j-1, element), equations)) end if j < nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], specEntropy(get_node_vars(u, equations, dg, i, j+1, element), equations)) + s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i, j+1, element), equations)) end - # Get current alpha # TODO: delta alpha? - # new_alpha = alpha[i, j, element] - # Perform Newton's bisection method to find new alpha u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, equations, dg, dt, cache) - - # Update alpha - # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) end end return nothing end -specEntropy_goal(bound, u, equations) = bound - specEntropy(u, equations) -specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2specentropy(u, equations), dt * antidiffusive_flux) +specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) +specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) @inline function IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) @@ -538,17 +532,11 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i, j+1, element), equations)) end - # Get current alpha # TODO: delta alpha? - # new_alpha = alpha[i, j, element] - # Perform Newton's bisection method to find new alpha u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, equations, dg, dt, cache) - - # Update alpha - # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) end end @@ -599,7 +587,6 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto end # Calculate alpha - # TODO: Respect current alpha. Is it enough to just use: alpha = max(alpha, 1-frac_minus)? alpha[i, j, element] = max(alpha[i, j, element], 1 - frac_minus) end end @@ -621,14 +608,10 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto p_min[i, j, element] = positCorrFactor * p_safe end - # Get current alpha # TODO: delta alpha? - # new_alpha = alpha[i, j, element] - # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, equations, dg, dt, cache) - - # Update alpha - # alpha[i, j, element] = max(alpha[i, j, element], new_alpha) + newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, + pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, + equations, dg, dt, cache) end end From 61f5707832521d835cf694bcd4689dbc99922072 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 25 Apr 2022 13:48:52 +0200 Subject: [PATCH 031/423] Speed up calculation of s_min and s_max --- src/equations/compressible_euler_2d.jl | 17 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 108 ++++++++++++------------ 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index b33082a754..7309cd532e 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1010,12 +1010,12 @@ end v1 = rho_v1 / rho v2 = rho_v2 / rho v_square = v1^2 + v2^2 - srho_gammap1 = (1/rho)^(equations.gamma + 1.0) + inv_rho_gammap1 = (1/rho)^(equations.gamma + 1.0) # The derivative vector for the modified specific entropy of Guermond et al. - w1 = srho_gammap1 * (0.5 * rho * v_square - equations.gamma * rho_e) - w2 = -rho_v1 * srho_gammap1 - w3 = -rho_v2 * srho_gammap1 + w1 = inv_rho_gammap1 * (0.5 * rho * v_square - equations.gamma * rho_e) + w2 = -rho_v1 * inv_rho_gammap1 + w3 = -rho_v2 * inv_rho_gammap1 w4 = (1/rho)^equations.gamma # The derivative vector for other specific entropy @@ -1143,16 +1143,13 @@ end @inline function entropy_spec(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v_square = v1^2 + v2^2 - # Modified specific entropy from Guermond et al. (2019) - return (rho_e - 0.5 * rho * v_square) * (1/rho)^equations.gamma + s = (rho_e - 0.5 * (rho_v1^2 + rho_v2^2) / rho) * (1/rho)^equations.gamma # Other specific entropy # rho_sp = rho/((equations.gamma - 1.0) * (rho_e - 0.5 * rho * v_square)) - # return - log(rho_sp * rho^equations.gamma) + # s = log(p) - (equaions.gamma + 1) * log(rho) + return s end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 74ffbf9f58..005402e868 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -193,17 +193,13 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) - A = Array{real(basis), ndims(equations)} - indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) for _ in 1:Threads.nthreads()] - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) # TODO: Nicer way to set a length? alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) - return (; indicator_threaded, - ContainerShockCapturingIndicator, + return (; ContainerShockCapturingIndicator, alpha_max_per_timestep, alpha_mean_per_timestep) end @@ -256,34 +252,31 @@ end @inline function IDP_densityTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) @unpack rho_max, rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator - # calculate_max_min_values!(rho_max, rho_min, u_safe, indicator_IDP, density, equations, dg, cache) - @unpack indicator_threaded = indicator_IDP.cache + # Calculate bound: rho_min, rho_max @threaded for element in eachelement(dg, cache) + rho_min[:, :, element] .= typemax(eltype(rho_min)) + rho_max[:, :, element] .= typemin(eltype(rho_max)) # Calculate indicator variables at Gauss-Lobatto nodes - indicator = indicator_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) - indicator[i, j] = u_old[1, i, j, element] - end + rho = u_old[1, i, j, element] + rho_min[i, j, element] = min(rho_min[i, j, element], rho) + rho_max[i, j, element] = max(rho_max[i, j, element], rho) - for j in eachnode(dg), i in eachnode(dg) - # Calculate max and min of variable at Gauss-Lobatto nodes - rho_min[i, j, element] = indicator[i, j] - rho_max[i, j, element] = indicator[i, j] if i > 1 - rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i-1, j]) - rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i-1, j]) + rho_min[i-1, j, element] = min(rho_min[i-1, j, element], rho) + rho_max[i-1, j, element] = max(rho_max[i-1, j, element], rho) end if i < nnodes(dg) - rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i+1, j]) - rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i+1, j]) + rho_min[i+1, j, element] = min(rho_min[i+1, j, element], rho) + rho_max[i+1, j, element] = max(rho_max[i+1, j, element], rho) end if j > 1 - rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i, j-1]) - rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i, j-1]) + rho_min[i, j-1, element] = min(rho_min[i, j-1, element], rho) + rho_max[i, j-1, element] = max(rho_max[i, j-1, element], rho) end if j < nnodes(dg) - rho_min[i, j, element] = min(rho_min[i, j, element], indicator[i, j+1]) - rho_max[i, j, element] = max(rho_max[i, j, element], indicator[i, j+1]) + rho_min[i, j+1, element] = min(rho_min[i, j+1, element], rho) + rho_max[i, j+1, element] = max(rho_max[i, j+1, element], rho) end end end @@ -360,36 +353,32 @@ end @inline function IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) @unpack p_max, p_min = indicator_IDP.cache.ContainerShockCapturingIndicator - # calculate_max_min_values!(p_max, p_min, u_safe, indicator_IDP, pressure, equations, dg, cache) - @unpack indicator_threaded = indicator_IDP.cache - + # Calculate bound: p_min, p_max @threaded for element in eachelement(dg, cache) + p_min[:, :, element] .= typemax(eltype(p_min)) + p_max[:, :, element] .= typemin(eltype(p_max)) # Calculate indicator variables at Gauss-Lobatto nodes - indicator = indicator_threaded[Threads.threadid()] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u_old, equations, dg, i, j, element) - indicator[i, j] = pressure(u_local, equations) - end + p = pressure(u_local, equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) - for j in eachnode(dg), i in eachnode(dg) - # Calculate max and min of variable at Gauss-Lobatto nodes - p_min[i, j, element] = indicator[i, j] - p_max[i, j, element] = indicator[i, j] if i > 1 - p_min[i, j, element] = min(p_min[i, j, element], indicator[i-1, j]) - p_max[i, j, element] = max(p_max[i, j, element], indicator[i-1, j]) + p_min[i-1, j, element] = min(p_min[i-1, j, element], p) + p_max[i-1, j, element] = max(p_max[i-1, j, element], p) end if i < nnodes(dg) - p_min[i, j, element] = min(p_min[i, j, element], indicator[i+1, j]) - p_max[i, j, element] = max(p_max[i, j, element], indicator[i+1, j]) + p_min[i+1, j, element] = min(p_min[i+1, j, element], p) + p_max[i+1, j, element] = max(p_max[i+1, j, element], p) end if j > 1 - p_min[i, j, element] = min(p_min[i, j, element], indicator[i, j-1]) - p_max[i, j, element] = max(p_max[i, j, element], indicator[i, j-1]) + p_min[i, j-1, element] = min(p_min[i, j-1, element], p) + p_max[i, j-1, element] = max(p_max[i, j-1, element], p) end if j < nnodes(dg) - p_min[i, j, element] = min(p_min[i, j, element], indicator[i, j+1]) - p_max[i, j, element] = max(p_max[i, j, element], indicator[i, j+1]) + p_min[i, j+1, element] = min(p_min[i, j+1, element], p) + p_max[i, j+1, element] = max(p_max[i, j+1, element], p) end end end @@ -478,25 +467,33 @@ end @inline function IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) @unpack s_min = indicator_IDP.cache.ContainerShockCapturingIndicator + # Calculate bound: s_min @threaded for element in eachelement(dg, cache) + s_min[:, :, element] .= typemax(eltype(s_min)) for j in eachnode(dg), i in eachnode(dg) # Get limit states; no neighbors. - s_min[i, j, element] = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) + s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) if i > 1 - s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i-1, j, element), equations)) + s_min[i-1, j, element] = min(s_min[i-1, j, element], s) end if i < nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i+1, j, element), equations)) + s_min[i+1, j, element] = min(s_min[i+1, j, element], s) end if j > 1 - s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i, j-1, element), equations)) + s_min[i, j-1, element] = min(s_min[i, j-1, element], s) end if j < nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], entropy_spec(get_node_vars(u, equations, dg, i, j+1, element), equations)) + s_min[i, j+1, element] = min(s_min[i, j+1, element], s) end + end + end + + # Perform Newton's bisection method to find new alpha + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) - # Perform Newton's bisection method to find new alpha u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, @@ -514,25 +511,32 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol @inline function IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) @unpack s_max = indicator_IDP.cache.ContainerShockCapturingIndicator + # Calculate bound: s_max @threaded for element in eachelement(dg, cache) + s_max[:, :, element] .= typemin(eltype(s_max)) for j in eachnode(dg), i in eachnode(dg) # Get limit states; no neighbors. - s_max[i, j, element] = mathEntropy(get_node_vars(u, equations, dg, i, j, element), equations) + s = entropy_math(get_node_vars(u, equations, dg, i, j, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) if i > 1 - s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i-1, j, element), equations)) + s_max[i-1, j, element] = max(s_max[i-1, j, element], s) end if i < nnodes(dg) - s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i+1, j, element), equations)) + s_max[i+1, j, element] = max(s_max[i+1, j, element], s) end if j > 1 - s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i, j-1, element), equations)) + s_max[i, j-1, element] = max(s_max[i, j-1, element], s) end if j < nnodes(dg) - s_max[i, j, element] = max(s_max[i, j, element], mathEntropy(get_node_vars(u, equations, dg, i, j+1, element), equations)) + s_max[i, j+1, element] = max(s_max[i, j+1, element], s) end + end + end - # Perform Newton's bisection method to find new alpha + # Perform Newton's bisection method to find new alpha + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, From 101a43eb0108a1c7f8c061f9b9b0f9a1ff4ccc40 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 25 Apr 2022 14:31:33 +0200 Subject: [PATCH 032/423] Fix specific entropy vector --- src/equations/compressible_euler_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 7309cd532e..e4b283fdac 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1013,7 +1013,7 @@ end inv_rho_gammap1 = (1/rho)^(equations.gamma + 1.0) # The derivative vector for the modified specific entropy of Guermond et al. - w1 = inv_rho_gammap1 * (0.5 * rho * v_square - equations.gamma * rho_e) + w1 = inv_rho_gammap1 * (0.5 * rho * (equations.gamma + 1.0) * v_square - equations.gamma * rho_e) w2 = -rho_v1 * inv_rho_gammap1 w3 = -rho_v2 * inv_rho_gammap1 w4 = (1/rho)^equations.gamma From dbcbe9b1ee4f88ea21d4350bc421d685fe37d448 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 27 Apr 2022 12:10:00 +0200 Subject: [PATCH 033/423] Fix thread parallelization --- src/solvers/dgsem_tree/dg_2d.jl | 11 +++++------ src/solvers/dgsem_tree/indicators.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 14 ++++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c5cb0e8fb8..aa4c674eed 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -536,7 +536,7 @@ end fhat1 = fhat1_threaded[Threads.threadid()] fhat2 = fhat2_threaded[Threads.threadid()] - @trixi_timeit timer() "high-order flux" calcflux_fhat!(fhat1, fhat2, u, mesh, + calcflux_fhat!(fhat1, fhat2, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # low-order FV fluxes @@ -546,16 +546,16 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "low-order flux" calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - # Calculate blending factor alpha_blending + # Calculate antidiffusive flux @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - @trixi_timeit timer() "antidiffusive flux" calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) - # Calculate volume integral contribution + # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + @@ -647,7 +647,6 @@ end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) - @unpack inverse_weights = dg.basis for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 7a4aabc649..1da8bd4ac7 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -191,7 +191,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPSpecEntropy = true end - cache = create_cache(IndicatorIDP, equations, basis) # , 2 * (IDPDensityTVD + IDPPressureTVD + IDPPositivity) + IDPMathEntropy + IDPSpecEntropy) + cache = create_cache(IndicatorIDP, equations, basis) IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, IDPPositivity, IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, cache) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 005402e868..00ec7b23fa 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -282,7 +282,7 @@ end end # Loop over interfaces - for interface in eachinterface(dg, cache) + @threaded for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -384,7 +384,7 @@ end end # Loop over interfaces - for interface in eachinterface(dg, cache) + @threaded for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -559,7 +559,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Correct density @unpack rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator - for element in eachelement(dg, cache) + @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) @@ -571,7 +571,9 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto end # Real one-sided Zalesak-type limiter - frac_minus = min(0.0, (rho_min[i, j, element] - u_safe[1, i, j, element]) / dt) + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + frac_minus = min(0.0, rho_min[i, j, element] - u_safe[1, i, j, element]) # Calculate P_minus # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -582,7 +584,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - P_minus = inverse_jacobian * P_minus + P_minus = dt * inverse_jacobian * P_minus if P_minus < 0.0 frac_minus = min(1.0, frac_minus / P_minus) @@ -597,7 +599,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Correct pressure @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator - for element in eachelement(dg, cache) + @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) # Compute bound From 49459724314b3ac703bc94153d52bbf1a43e97d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 29 Apr 2022 17:17:56 +0200 Subject: [PATCH 034/423] Fix astro jet example --- .../elixir_euler_astro_jet_subcell.jl | 18 ++++---- .../elixir_euler_astro_jet_subcell_restart.jl | 44 +++++++++++++++++++ src/solvers/dgsem_tree/indicators_2d.jl | 29 ++++++------ src/time_integration/methods_SSP.jl | 1 - 4 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 1aec2a49af..c7818052fb 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -44,11 +44,9 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, + IDPDensityTVD=false, IDPPressureTVD=true, - IDPPositivity=true, - IDPSpecEntropy=false, - IDPMathEntropy=false) + IDPPositivity=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -65,26 +63,30 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.001) +tspan = (0.0, 2.5e-6) # simulation with end time T=0.001 in the restart file ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 5000 +analysis_interval = 1000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) +# The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted +save_restart = SaveRestartCallback(interval=5000, + save_final_restart=true) + save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, - save_final_solution=true, + save_final_solution=false, solution_variables=cons2prim) stepsize_callback = StepsizeCallback(cfl=0.004) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, + save_restart, save_solution, stepsize_callback) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl new file mode 100644 index 0000000000..19e4febf54 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl @@ -0,0 +1,44 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# create a restart file + +trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_subcell.jl")) + +############################################################################### +# adapt the parameters that have changed compared to "elixir_euler_astro_jet_subcell.jl" + +restart_filename = joinpath("out", "restart_000001.h5") +# setups: +# - refinement level = 6: +# * Limiter: IDPPressureTVD, IDPPositivity: T_1=2.5e-6 (CFL=0.004, 1 timestep) +# - refinement level = 7: +# * Limiter: IDPPressureTVD, IDPPositivity: T_1=5.0e-6 (CFL=0.004, 260 timesteps) +# - refinement level = 8: +# * Limiter: IDPPressureTVD, IDPPositivity: T_1=2.5e-6 (CFL=0.004, 269 timesteps) +mesh = load_mesh(restart_filename) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + +tspan = (load_time(restart_filename), 0.001) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=false, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) +############################################################################### +# run the simulation +sol = Trixi.solve_IDP(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 00ec7b23fa..c551a37fa0 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -195,7 +195,6 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) - # TODO: Nicer way to set a length? alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) @@ -425,9 +424,9 @@ end # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. v1 = u[2, i, j, element] / u[1, i, j, element] v2 = u[3, i, j, element] / u[1, i, j, element] - # vel = get_node_vars(u, equations, dg, i, j, element)[2:3] / u[1, i, j, element] - v2s2 = 0.5 * sum(v1^2 + v2^2) + v2s2 = 0.5 * (v1^2 + v2^2) gamma_m1 = equations.gamma - 1.0 + val_flux1_local = gamma_m1 * (antidiffusive_flux1[4, i, j, element] + v2s2 * antidiffusive_flux1[1, i, j, element] - v1 * antidiffusive_flux1[2, i, j, element] - v2 * antidiffusive_flux1[3, i, j, element]) val_flux1_local_ip1 = gamma_m1 * (antidiffusive_flux1[4, i+1, j, element] + v2s2 * antidiffusive_flux1[1, i+1, j, element] - @@ -555,14 +554,22 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @unpack inverse_weights = dg.basis - positCorrFactor = 0.1 # The correction factor for IDPPositivity # TODO + positCorrFactor = 0.1 # The correction factor for IDPPositivity - # Correct density @unpack rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) + ####################### + # Correct density + ####################### + if u_safe[1, i, j, element] < 0.0 + println("Error: safe density is not safe. element=$element, node: $i $j, density=$(u_safe[1, i, j, element])") + end + # Compute bound if indicator_IDP.IDPDensityTVD rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * u_safe[1, i, j, element]) @@ -594,13 +601,10 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Calculate alpha alpha[i, j, element] = max(alpha[i, j, element], 1 - frac_minus) - end - end - # Correct pressure - @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) + ####################### + # Correct pressure + ####################### # Compute bound u_local = get_node_vars(u_safe, equations, dg, i, j, element) @@ -666,13 +670,12 @@ end # Perform initial Check as = goal_fct(bound, u_curr, equations) - # TODO: save tolerances somewhere newton_reltol = 1.0e-12 # Relative tolerance to exit Newton loop newton_abstol = 1.0e-14 # Absolute tolerance (with respect to the value of the entropy goal, tol = NEWTON_ABSTOL*s_goal) initialCheck(bound, as, newton_abstol) && return nothing # Newton iterations - IDPMaxIter = 10 # TODO: save somewhere + IDPMaxIter = 10 for iter in 1:IDPMaxIter beta_old = beta diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 2853f178f0..bc3387fbd9 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -74,7 +74,6 @@ method [`SimpleSSPRK33`](@ref). This is an experimental feature and may change in future releases. """ function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) - # TODO: Maybe add alg to dependency alg = SimpleSSPRK33() u = copy(ode.u0) From 602eb5894fafab9fbaaea41946d1b4df9f9a99fb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 2 May 2022 20:41:01 +0200 Subject: [PATCH 035/423] Update examples and add tests --- .../elixir_euler_blast_wave_sc_subcell.jl | 4 +- .../elixir_euler_blob_sc_subcell.jl | 110 ++++++++++++++++++ .../elixir_euler_colliding_flow_sc_subcell.jl | 109 +++++++++++++++++ ...kelvin_helmholtz_instability_sc_subcell.jl | 15 --- ... => elixir_euler_positivity_sc_subcell.jl} | 65 +++++++---- .../elixir_euler_shockcapturing_subcell.jl | 5 +- src/solvers/dg.jl | 6 - test/test_tree_2d_euler.jl | 67 +++++++++-- 8 files changed, 326 insertions(+), 55 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl rename examples/tree_2d_dgsem/{elixir_euler_source_terms_sc_subcell.jl => elixir_euler_positivity_sc_subcell.jl} (51%) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index be38e7079d..a448eeb9e6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,7 +39,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - variable=Trixi.density) + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl new file mode 100644 index 0000000000..a48c38f6aa --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl @@ -0,0 +1,110 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 5/3 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) + +The blob test case taken from +- Agertz et al. (2006) + Fundamental differences between SPH and grid methods + [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) +""" +function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^2, 256^2 + # domain size is [-20.0,20.0]^2 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + dens0 = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh/1.6 # crushing time + # determine background velocity + velx0 = 2*R*sqrt(Chi)/tau_cr + vely0 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = velx0/Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p0 = c*c*dens0/equations.gamma + # initial center of the blob + inicenter = [-15,0] + x_rel = x-inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) + # velocity blob is zero + velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) + return prim2cons(SVector(dens, velx, vely0, p0), equations) +end +initial_condition = initial_condition_blob + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=false, + IDPPressureTVD=false, + IDPPositivity=true, + IDPSpecEntropy=false, + IDPMathEntropy=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-32.0, -32.0) +coordinates_max = ( 32.0, 32.0) + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000,) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 16.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=0.7) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve_IDP(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl new file mode 100644 index 0000000000..cc96284335 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -0,0 +1,109 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.001 # almost isothermal when gamma reaches 1 +equations = CompressibleEulerEquations2D(gamma) + +# This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both +# sides, with relative low temperature, such that pressure keeps relatively small +# Computed with gamma close to 1, to simulate isothermal gas +function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) + # domain size is [-64,+64]^2 + @unpack gamma = equations + # the quantities are chosen such, that they are as close as possible to the astro examples + # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) + rho = 0.0247 + c = 0.2 + p = c^2 / gamma * rho + vel = 13.907432274789372 + slope = 1.0 + v1 = -vel*tanh(slope * x[1]) + # add small initial disturbance to the field, but only close to the interface + if abs(x[1]) < 10 + v1 = v1 * (1 + 0.01 * sin(pi * x[2])) + end + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_colliding_flow_astro + + +boundary_conditions = ( + x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + y_neg=boundary_condition_periodic, + y_pos=boundary_condition_periodic, + ) + + + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +# shock capturing necessary for this tough example +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=true, + IDPSpecEntropy=false, + IDPMathEntropy=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-64.0, -64.0) +coordinates_max = ( 64.0, 64.0) + +# only refinment in a patch. Needs x=-17/+17 to trigger refinment due to coarse base mesh +refinement_patches = ( + (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), + (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), + (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), + (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), + #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores +) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + refinement_patches=refinement_patches, + periodicity=(false,true), + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 25.0) +ode = semidiscretize(semi, tspan) + +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, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.4) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation +sol = Trixi.solve_IDP(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index c5a5392222..e0f00b20aa 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -71,26 +71,11 @@ save_solution = SaveSolutionCallback(interval=50, save_final_solution=true, solution_variables=cons2prim) -amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level=0, med_threshold=0.0003, # med_level = current level - max_level=7, max_threshold=0.003) -amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, - amr_callback, stepsize_callback) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl similarity index 51% rename from examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl rename to examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl index 184ab37080..5ce18658cd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl @@ -4,46 +4,71 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -initial_condition = initial_condition_convergence_test +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) - indicator_sc = IndicatorIDP(equations, basis; - alpha_maxIDP=1.0, IDPDensityTVD=true, IDPPressureTVD=true, - IDPPositivity=true, - IDPSpecEntropy=false, - IDPMathEntropy=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + IDPPositivity=true,) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (0.0, 0.0) -coordinates_max = (2.0, 2.0) +coordinates_min = (-2.0, -2.0) +coordinates_max = ( 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) + initial_refinement_level=6, + n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 2.0) +tspan = (0.0, 4.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 100 +analysis_interval = 500 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) @@ -53,7 +78,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.4) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 4dbed9202e..b17d155c50 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -12,7 +12,10 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; variable=Trixi.density) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index fe05368086..d7280416c5 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -191,12 +191,6 @@ function get_element_variables!(element_variables, u, mesh, equations, get_element_variables!(element_variables, volume_integral.indicator, volume_integral) end -function get_element_variables!(element_variables, u, mesh, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) - # call the indicator to get up-to-date values for IO - volume_integral.indicator(u, u, mesh, equations, dg, 0.0, cache) - get_element_variables!(element_variables, volume_integral.indicator, volume_integral) -end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 014ad4ab30..6e2c9aa4e8 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -64,11 +64,11 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) end - # @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin - # @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - # l2 = [0.0553929262398195, 0.04893322397478265, 0.048963817832536935, 0.20274672386802076], - # linf = [0.24421260611907802, 0.3304859275088113, 0.3305295968021732, 0.8829660515342019]) - # end + @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), + l2 = [0.0528852022914957, 0.04605220278777441, 0.046051285430361966, 0.19333536195011322], + linf = [0.18676597825683394, 0.23170518015350347, 0.2316394218254613, 0.6910854547329741]) + end @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), @@ -130,6 +130,15 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), + l2 = [0.33497677827522393, 0.18846649571882834, 0.18846957823831056, 0.6202202597584124], + linf = [1.570337061620338, 1.2688091762034825, 1.2691766589473688, 2.4069374156041263], + tspan = (0.0, 0.5), + initial_refinement_level = 4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), l2 = [0.4866953770742574, 0.1673477470091984, 0.16734774700934, 0.6184367248923149], @@ -154,6 +163,15 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=3,)) end + @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), + l2 = [0.4737997603865771, 0.16275172537763907, 0.16275172598146603, 0.6346965849521918], + linf = [2.361159555716611, 1.1430595884028167, 1.1430595769596035, 6.465210487181045], + tspan = (0.0, 1.0), + initial_refinement_level=5, + coverage_override = (maxiters=3,)) + end + @trixi_testset "elixir_euler_blob_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_mortar.jl"), l2 = [0.22271619518391986, 0.6284824759323494, 0.24864213447943648, 2.9591811489995474], @@ -170,6 +188,14 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=10^5,)) end + @trixi_testset "elixir_euler_blob_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_sc_subcell.jl"), + l2 = [0.23649189278780317, 0.6993516078054665, 0.24313747935314953, 3.071644108599621], + linf = [7.850214101046176, 21.245196819766562, 10.004355873576252, 76.18578781492629], + tspan = (0.0, 0.5), + initial_refinement_level=5) + end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability.jl"), l2 = [0.055691508271624536, 0.032986009333751655, 0.05224390923711999, 0.08009536362771563], @@ -185,13 +211,14 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=2,)) end - # @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin - # @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - # l2 = [0.05815738785949766, 0.03556776269333907, 0.050648761230924, 0.07841750042670147], - # linf = [0.3593491373564508, 0.22403042619291816, 0.15284799979856273, 0.2892795213007946], - # tspan = (0.0, 0.2), - # coverage_override = (maxiters=2,)) - # end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), + l2 = [0.05564063128068906, 0.032967180169445796, 0.051599370799795104, 0.07981143071307957], + linf = [0.23439245841020262, 0.17117470779640565, 0.1325280369889718, 0.27221948654913763], + tspan = (0.0, 0.2), + initial_refinement_level=5, + coverage_override = (maxiters=2,)) + end @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), @@ -219,6 +246,14 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=2,)) end + @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), + l2 = [0.00602947379660612, 0.04306243986204804, 1.0176612188422975e-6, 0.6026033201629001], + linf = [0.13328714860404622, 0.46245151773119775, 4.8413260718655235e-5, 11.460518493633284], + tspan = (0.0, 0.1), + coverage_override = (maxiters=2,)) + end + @trixi_testset "elixir_euler_astro_jet_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_amr.jl"), l2 = [0.011338365293662804, 10.09743543555765, 0.00392429463200361, 4031.7811487690506], @@ -227,6 +262,14 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), + l2 = [0.4360530254790599, 351.83324431719006, 13.841995590128272, 138429.10256913095], + linf = [9.349440577987206, 6938.823487053745, 503.9002738813788, 2.6096438436575336e6], + tspan = (2.5e-6, 1.0e-4), + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), l2 = [3.53375983916925e-6, 0.0032123259330577325, 0.00321232443824996, 0.004547280616310348], From ca817d7d45ff4393a7a102bb48d5edb545694ae4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 3 May 2022 16:40:01 +0200 Subject: [PATCH 036/423] Save parameters --- src/solvers/dgsem_tree/indicators.jl | 11 ++++++-- src/solvers/dgsem_tree/indicators_2d.jl | 34 ++++++++++++------------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 1da8bd4ac7..f1b29928ca 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -171,6 +171,11 @@ struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator IDPSpecEntropy::Bool IDPMathEntropy::Bool cache::Cache + positCorrFactor::RealT # Correction factor for IDPPositivity + IDPMaxIter::Int # Maximal number of iterations for Newton's method + newton_tol::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method + IDPgamma::RealT # Constant for the subcell limiting of convex (nonlinear) constraints + # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) end # this method is used when the indicator is constructed as for shock-capturing volume integrals @@ -180,7 +185,9 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPDensityTVD=false, IDPPressureTVD=false, IDPSpecEntropy=false, - IDPMathEntropy=false) + IDPMathEntropy=false, + positCorrFactor=0.1, IDPMaxIter=10, + newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations)) if IDPMathEntropy && IDPSpecEntropy error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") @@ -194,7 +201,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; cache = create_cache(IndicatorIDP, equations, basis) IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, IDPPositivity, IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, - cache) + cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma) end function Base.show(io::IO, indicator::IndicatorIDP) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index c551a37fa0..7336d04fc1 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -492,11 +492,10 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache) + equations, dg, dt, cache, indicator_IDP) end end @@ -539,7 +538,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache) + equations, dg, dt, cache, indicator_IDP) end end @@ -553,8 +552,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto @inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D @unpack inverse_weights = dg.basis - - positCorrFactor = 0.1 # The correction factor for IDPPositivity + @unpack positCorrFactor = indicator_IDP @unpack rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -621,7 +619,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, - equations, dg, dt, cache) + equations, dg, dt, cache, indicator_IDP) end end @@ -633,33 +631,37 @@ pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(dpdu(u, equati pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0.0 pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) -@inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dg, dt, cache) +@inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, + goal_fct, dgoal_fct, initialCheck, finalCheck, + equations, dg, dt, cache, indicator_IDP) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D inverse_jacobian = cache.elements.inverse_jacobian[element] - IDPgamma = 4.0 # Constant for the subcell limiting of convex (nonlinear) constraints (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) + @unpack IDPgamma = indicator_IDP # negative xi direction antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # positive xi direction antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # negative eta direction antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # positive eta direction antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) + newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, antidiffusive_flux) +@inline function newton_loop!(alpha, bound, u_safe, i, j, element, + goal_fct, dgoal_fct, initialCheck, finalCheck, + equations, dt, indicator_IDP, antidiffusive_flux) beta = 1.0 - alpha[i, j, element] beta_L = 0.0 # alpha = 1 @@ -670,13 +672,11 @@ end # Perform initial Check as = goal_fct(bound, u_curr, equations) - newton_reltol = 1.0e-12 # Relative tolerance to exit Newton loop - newton_abstol = 1.0e-14 # Absolute tolerance (with respect to the value of the entropy goal, tol = NEWTON_ABSTOL*s_goal) + newton_reltol, newton_abstol = indicator_IDP.newton_tol initialCheck(bound, as, newton_abstol) && return nothing # Newton iterations - IDPMaxIter = 10 - for iter in 1:IDPMaxIter + for iter in 1:indicator_IDP.IDPMaxIter beta_old = beta # Evaluate d(goal)/d(beta) From e691e85807531d2396a54d2a18908a3064ed4299 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 4 May 2022 13:49:11 +0200 Subject: [PATCH 037/423] Stack bound saving location as Vector --- src/solvers/dgsem_tree/containers_2d.jl | 70 +++++++------------------ src/solvers/dgsem_tree/indicators.jl | 19 ++++--- src/solvers/dgsem_tree/indicators_2d.jl | 43 ++++++++++++--- 3 files changed, 64 insertions(+), 68 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index d9929a197c..8cd29d0676 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1310,56 +1310,34 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, elements] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} - rho_max::Array{uEltype, 3} - rho_min::Array{uEltype, 3} - p_max::Array{uEltype, 3} - p_min::Array{uEltype, 3} - s_max::Array{uEltype, 3} - s_min::Array{uEltype, 3} + var_bounds::Vector{Array{uEltype, 3}} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} - _rho_max::Vector{uEltype} - _rho_min::Vector{uEltype} - _p_max::Vector{uEltype} - _p_min::Vector{uEltype} - _s_max::Vector{uEltype} - _s_min::Vector{uEltype} + _var_bounds::Vector{Vector{uEltype}} end -function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes) where uEltype<:Real +function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults _alpha = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) _alpha1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) - alpha1 = unsafe_wrap(Array, pointer(_alpha), (n_nodes+1, n_nodes, capacity)) + alpha1 = unsafe_wrap(Array, pointer(_alpha1), (n_nodes+1, n_nodes, capacity)) _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) - alpha2 = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes+1, capacity)) + alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes+1, capacity)) - _rho_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) - rho_max = unsafe_wrap(Array, pointer(_rho_max), (n_nodes, n_nodes, capacity)) - _rho_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) - rho_min = unsafe_wrap(Array, pointer(_rho_min), (n_nodes, n_nodes, capacity)) - - _p_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) - p_max = unsafe_wrap(Array, pointer(_p_max), (n_nodes, n_nodes, capacity)) - _p_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) - p_min = unsafe_wrap(Array, pointer(_p_min), (n_nodes, n_nodes, capacity)) - - _s_max = fill(nan_uEltype, n_nodes * n_nodes * capacity) - s_max = unsafe_wrap(Array, pointer(_s_max), (n_nodes, n_nodes, capacity)) - _s_min = fill(nan_uEltype, n_nodes * n_nodes * capacity) - s_min = unsafe_wrap(Array, pointer(_s_min), (n_nodes, n_nodes, capacity)) - - # idp_bounds_delta = zeros(uEltype, ) + _var_bounds = Vector{Vector{uEltype}}(undef, length) + var_bounds = Vector{Array{uEltype, 3}}(undef, length) + for i in 1:length + _var_bounds[i] = fill(nan_uEltype, n_nodes * n_nodes * capacity) + var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) + end - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, - rho_max, rho_min, p_max, p_min, s_max, s_min, - _alpha, _alpha1, _alpha2, - _rho_max, _rho_min, _p_max, _p_min, _s_max, _s_min) + return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_bounds, + _alpha, _alpha1, _alpha2, _var_bounds) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) @@ -1380,23 +1358,11 @@ function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - @unpack _rho_max, _rho_min = indicator - resize!(_rho_max, n_nodes * n_nodes * capacity) - indicator.rho_max = unsafe_wrap(Array, pointer(_rho_max), (n_nodes, n_nodes, capacity)) - resize!(_rho_min, n_nodes * n_nodes * capacity) - indicator.rho_min = unsafe_wrap(Array, pointer(_rho_min), (n_nodes, n_nodes, capacity)) - - @unpack _p_max, _p_min = indicator - resize!(_p_max, n_nodes * n_nodes * capacity) - indicator.p_max = unsafe_wrap(Array, pointer(_p_max), (n_nodes, n_nodes, capacity)) - resize!(_p_min, n_nodes * n_nodes * capacity) - indicator.p_min = unsafe_wrap(Array, pointer(_p_min), (n_nodes, n_nodes, capacity)) - - @unpack _s_max, _s_min = indicator - resize!(_s_max, n_nodes * n_nodes * capacity) - indicator.s_max = unsafe_wrap(Array, pointer(_s_max), (n_nodes, n_nodes, capacity)) - resize!(_s_min, n_nodes * n_nodes * capacity) - indicator.s_min = unsafe_wrap(Array, pointer(_s_min), (n_nodes, n_nodes, capacity)) + @unpack _var_bounds = indicator + for i in 1:length(_var_bounds) + resize!(_var_bounds[i], n_nodes * n_nodes * capacity) + indicator.var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) + end return nothing end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index f1b29928ca..1300d452b4 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -165,9 +165,9 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi """ struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator alpha_maxIDP::RealT - IDPPositivity::Bool IDPDensityTVD::Bool IDPPressureTVD::Bool + IDPPositivity::Bool IDPSpecEntropy::Bool IDPMathEntropy::Bool cache::Cache @@ -181,9 +181,9 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; alpha_maxIDP=1.0, - IDPPositivity=false, IDPDensityTVD=false, IDPPressureTVD=false, + IDPPositivity=false, IDPSpecEntropy=false, IDPMathEntropy=false, positCorrFactor=0.1, IDPMaxIter=10, @@ -193,14 +193,17 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") end - if !(IDPPositivity || IDPDensityTVD || IDPPressureTVD || IDPSpecEntropy || IDPMathEntropy) - println("No limiter selected. Default: use IDPSpecEntropy") - IDPSpecEntropy = true + if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + println("No limiter selected. Default: use IDPDensityTVD") + IDPDensityTVD = true end - cache = create_cache(IndicatorIDP, equations, basis) + length = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) + + cache = create_cache(IndicatorIDP, equations, basis, length) IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, - IDPPositivity, IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, + IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma) end @@ -209,9 +212,9 @@ function Base.show(io::IO, indicator::IndicatorIDP) print(io, "IndicatorIDP(") print(io, "limiter=(") - indicator.IDPPositivity && print(io, "IDPPositivity, ") indicator.IDPDensityTVD && print(io, "IDPDensityTVD, ") indicator.IDPPressureTVD && print(io, "IDPPressureTVD, ") + indicator.IDPPositivity && print(io, "IDPPositivity, ") indicator.IDPSpecEntropy && print(io, "IDPSpecEntropy, ") indicator.IDPMathEntropy && print(io, "IDPMathEntropy, ") print(io, "), ") diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 7336d04fc1..79161ab98a 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -191,9 +191,9 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) +function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis)) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis), length) alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) @@ -249,7 +249,10 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac end @inline function IDP_densityTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) - @unpack rho_max, rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + rho_min = var_bounds[1] + rho_max = var_bounds[2] # Calculate bound: rho_min, rho_max @threaded for element in eachelement(dg, cache) @@ -350,7 +353,11 @@ end end @inline function IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) - @unpack p_max, p_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + offset = 2 * indicator_IDP.IDPDensityTVD + p_min = var_bounds[1 + offset] + p_max = var_bounds[2 + offset] # Calculate bound: p_min, p_max @threaded for element in eachelement(dg, cache) @@ -464,7 +471,11 @@ end end @inline function IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) - @unpack s_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + offset = 2 * (indicator_IDP.IDPDensityTVD + indicator_IDP.IDPPressureTVD) + + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPDensityTVD) + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPPressureTVD) + s_min = var_bounds[1 + offset] # Calculate bound: s_min @threaded for element in eachelement(dg, cache) @@ -507,7 +518,11 @@ specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entrop specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) @inline function IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) - @unpack s_max = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + offset = 2 * (indicator_IDP.IDPDensityTVD + indicator_IDP.IDPPressureTVD) + indicator_IDP.IDPSpecEntropy + + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPDensityTVD) + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPPressureTVD) + s_max = var_bounds[1 + offset] # Calculate bound: s_max @threaded for element in eachelement(dg, cache) @@ -554,8 +569,20 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP - @unpack rho_min = indicator_IDP.cache.ContainerShockCapturingIndicator - @unpack p_min = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + if indicator_IDP.IDPDensityTVD + rho_min = var_bounds[1] + p_min = var_bounds[3] + else + if indicator_IDP.IDPPressureTVD + rho_min = var_bounds[3] + p_min = var_bounds[1] + else + rho_min = var_bounds[1] + p_min = var_bounds[2] + end + end @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] From 96a1f82d6b91e7ce1a33fd3286126f296a6aa76a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 10 May 2022 12:32:50 +0200 Subject: [PATCH 038/423] Clean up RK and antidiffusive stages in for loop --- .../elixir_euler_positivity_sc_subcell.jl | 1 - src/solvers/dgsem_tree/indicators.jl | 3 +- src/time_integration/methods_SSP.jl | 65 ++++++++++++------- test/test_tree_2d_euler.jl | 12 ++-- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl index 5ce18658cd..a4c1481e0a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl @@ -43,7 +43,6 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, IDPPositivity=true,) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 1300d452b4..4217cdc93c 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -194,8 +194,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; end if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) - println("No limiter selected. Default: use IDPDensityTVD") - IDPDensityTVD = true + println("No limiter selected => pure DG method") end length = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index bc3387fbd9..9ec4c909f6 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -18,8 +18,29 @@ The third-order SSP Runge-Kutta method of !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct SimpleSSPRK33 <: SimpleAlgorithmSSP end - +struct SimpleSSPRK33 <: SimpleAlgorithmSSP + a1::SVector{3, Float64} + a2::SVector{3, Float64} + b::SVector{3, Float64} + c::SVector{3, Float64} + + function SimpleSSPRK33() + a1 = SVector(1.0, 1/4, 2/3) + a2 = SVector(0.0, 3/4, 1/3) # Note: a2 != 1.0 .- a1 + b = SVector(1.0, 1/4, 2/3) + c = SVector(0.0, 1.0, 1/2) + + # Butcher tableau + # c | a + # 0 | + # 1 | 1 + # 1/2 | 1/4 1/4 + # -------------------- + # b | 1/6 1/6 2/3 + + new(a1, a2, b, c) + end +end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L1 mutable struct SimpleIntegratorSSPOptions{Callback} @@ -73,9 +94,7 @@ method [`SimpleSSPRK33`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -function solve_IDP(ode::ODEProblem, semi; dt, callback=nothing, kwargs...) - alg = SimpleSSPRK33() - +function solve_IDP(ode::ODEProblem, semi; alg=SimpleSSPRK33(), dt, callback=nothing, kwargs...) u = copy(ode.u0) du = similar(u) u_safe = similar(u) @@ -124,25 +143,25 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u, integrator.p, integrator.t) - @. integrator.u_safe = integrator.u + integrator.dt * integrator.du - end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u, integrator.dt, integrator.p) - - @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + integrator.dt) - @. integrator.u_old = 3/4 * integrator.u + 1/4 * integrator.u_safe - @. integrator.u_safe = integrator.u_old + 1/4 * integrator.dt * integrator.du - end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, 1/4 * integrator.dt, integrator.p) - - @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + 1/2 * integrator.dt) - @. integrator.u_old = 1/3 * integrator.u + 2/3 * integrator.u_safe - @. integrator.u = integrator.u_old + 2/3 * integrator.dt * integrator.du + @. integrator.u_safe = integrator.u + for i in 1:length(alg.a1) + @trixi_timeit timer() "RK stage" begin + prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + alg.c[i] * integrator.dt) + @. integrator.u_old = (1.0 - alg.a1[i]) * integrator.u + alg.a1[i] * integrator.u_safe + @. integrator.u_safe = integrator.u_old + alg.b[i] * integrator.dt * integrator.du + end + @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[i] * integrator.dt, integrator.p) end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u, integrator.u_old, 2/3 * integrator.dt, integrator.p) + @. integrator.u = integrator.u_safe + + # Note: + # @. integrator.u_old = alg.a2[i] * integrator.u + alg.a1[i] * integrator.u_safe + # The combination of the macro muladd with the operator @. changes the order of operations knowingly, which + # results in changed solutions. + # Moreover, unrolling the for-loop changes the order unexpectedly. Using a cache variable like + # @. u_tmp = alg.a2[i] * integrator.u + # @. integrator.u_old = u_tmp + alg.a1[i] * integrator.u_safe + # solves the differences between the (not-)unrolled for-loop versions. if integrator.iter == length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) new_length = length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) + 200 diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 6e2c9aa4e8..77b1405f11 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -165,8 +165,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.4737997603865771, 0.16275172537763907, 0.16275172598146603, 0.6346965849521918], - linf = [2.361159555716611, 1.1430595884028167, 1.1430595769596035, 6.465210487181045], + l2 = [0.49388182696965016, 0.1664478265682381, 0.16644705322200087, 0.6351261288582164], + linf = [2.510295676164479, 1.2096774802395878, 1.2095916433265121, 6.471103817989863], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -213,8 +213,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.05564063128068906, 0.032967180169445796, 0.051599370799795104, 0.07981143071307957], - linf = [0.23439245841020262, 0.17117470779640565, 0.1325280369889718, 0.27221948654913763], + l2 = [0.05564090964202828, 0.03296787545497902, 0.05160670623577235, 0.07981492521336583], + linf = [0.23439134058145372, 0.17117426653305845, 0.13912663188297486, 0.2720460320318123], tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=2,)) @@ -248,8 +248,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.00602947379660612, 0.04306243986204804, 1.0176612188422975e-6, 0.6026033201629001], - linf = [0.13328714860404622, 0.46245151773119775, 4.8413260718655235e-5, 11.460518493633284], + l2 = [0.006029492126577196, 0.043062741345985846, 1.0176748408651053e-6, 0.6026035110310333], + linf = [0.1332870788544167, 0.46245136511653623, 4.841326309109683e-5, 11.460514399212578], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end From ced6668ed812a94fd077ce0aa0c2aa5cb34b2c1f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 10 May 2022 12:35:54 +0200 Subject: [PATCH 039/423] Replace a1 and a2 with one a for RK method --- src/time_integration/methods_SSP.jl | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 9ec4c909f6..a885ffc772 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -19,14 +19,12 @@ The third-order SSP Runge-Kutta method of This is an experimental feature and may change in future releases. """ struct SimpleSSPRK33 <: SimpleAlgorithmSSP - a1::SVector{3, Float64} - a2::SVector{3, Float64} + a::SVector{3, Float64} b::SVector{3, Float64} c::SVector{3, Float64} function SimpleSSPRK33() - a1 = SVector(1.0, 1/4, 2/3) - a2 = SVector(0.0, 3/4, 1/3) # Note: a2 != 1.0 .- a1 + a = SVector(1.0, 1/4, 2/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -38,7 +36,7 @@ struct SimpleSSPRK33 <: SimpleAlgorithmSSP # -------------------- # b | 1/6 1/6 2/3 - new(a1, a2, b, c) + new(a, b, c) end end @@ -144,10 +142,10 @@ function solve!(integrator::SimpleIntegratorSSP) end @. integrator.u_safe = integrator.u - for i in 1:length(alg.a1) + for i in 1:length(alg.a) @trixi_timeit timer() "RK stage" begin prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + alg.c[i] * integrator.dt) - @. integrator.u_old = (1.0 - alg.a1[i]) * integrator.u + alg.a1[i] * integrator.u_safe + @. integrator.u_old = (1.0 - alg.a[i]) * integrator.u + alg.a[i] * integrator.u_safe @. integrator.u_safe = integrator.u_old + alg.b[i] * integrator.dt * integrator.du end @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[i] * integrator.dt, integrator.p) @@ -155,12 +153,12 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = integrator.u_safe # Note: - # @. integrator.u_old = alg.a2[i] * integrator.u + alg.a1[i] * integrator.u_safe + # @. integrator.u_old = (1.0 - alg.a[i]) * integrator.u + alg.a[i] * integrator.u_safe # The combination of the macro muladd with the operator @. changes the order of operations knowingly, which # results in changed solutions. # Moreover, unrolling the for-loop changes the order unexpectedly. Using a cache variable like - # @. u_tmp = alg.a2[i] * integrator.u - # @. integrator.u_old = u_tmp + alg.a1[i] * integrator.u_safe + # @. u_tmp = (1.0 - alg.a[i]) * integrator.u + # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. if integrator.iter == length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) From 1d76765d93763167022f80076038f14a5d21b520 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 10 May 2022 13:14:15 +0200 Subject: [PATCH 040/423] Fix tests --- src/solvers/dgsem_tree/indicators.jl | 1 + test/test_tree_2d_euler.jl | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 4217cdc93c..0e30ee833d 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -17,6 +17,7 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, end + """ IndicatorHennemannGassner diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 77b1405f11..9cdddb7b13 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -166,7 +166,7 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), l2 = [0.49388182696965016, 0.1664478265682381, 0.16644705322200087, 0.6351261288582164], - linf = [2.510295676164479, 1.2096774802395878, 1.2095916433265121, 6.471103817989863], + linf = [2.510295676164479, 1.2096774802395878, 1.2095916433265121, 6.471098677030467], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -213,8 +213,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.05564090964202828, 0.03296787545497902, 0.05160670623577235, 0.07981492521336583], - linf = [0.23439134058145372, 0.17117426653305845, 0.13912663188297486, 0.2720460320318123], + l2 = [0.05564045019484471, 0.03296714778723376, 0.05160031886304709, 0.0798132537431978], + linf = [0.2343924443588683, 0.1711747394866538, 0.1340845767284859, 0.27221997312881907], tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=2,)) @@ -248,8 +248,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.006029492126577196, 0.043062741345985846, 1.0176748408651053e-6, 0.6026035110310333], - linf = [0.1332870788544167, 0.46245136511653623, 4.841326309109683e-5, 11.460514399212578], + l2 = [0.006029487817162152, 0.04306352664570119, 1.0196317105626685e-6, 0.602600980127913], + linf = [0.133287118940215, 0.46245152812030377, 4.841326071863473e-5, 11.460517088011834], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end From eea41f45ec7030cbdfe1aeb53a427b69eec7d58b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 16 May 2022 13:45:55 +0200 Subject: [PATCH 041/423] Use correct solution for limiter --- src/solvers/dgsem_tree/indicators_2d.jl | 155 ++++++++++++++++-------- 1 file changed, 107 insertions(+), 48 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 79161ab98a..2fc7d74d1f 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -202,7 +202,7 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha_max_per_timestep, alpha_mean_per_timestep) end -function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, +function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, mesh, equations, dg::DGSEM, dt, cache; kwargs...) @@ -210,15 +210,15 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac alpha .= 0.0 indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP @@ -248,7 +248,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, u_old::Abstrac return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) +@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator rho_min = var_bounds[1] @@ -260,7 +260,7 @@ end rho_max[:, :, element] .= typemin(eltype(rho_max)) # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - rho = u_old[1, i, j, element] + rho = u_safe[1, i, j, element] rho_min[i, j, element] = min(rho_min[i, j, element], rho) rho_max[i, j, element] = max(rho_max[i, j, element], rho) @@ -299,14 +299,14 @@ end index_left = (i, nnodes(dg), left) index_right = (i, 1, right) end - rho_neighbor_left = u_old[1, index_left...] - rho_neighbor_right = u_old[1, index_right...] + rho_left = u_safe[1, index_left...] + rho_right = u_safe[1, index_right...] - rho_min[index_right...] = min(rho_min[index_right...], rho_neighbor_left) - rho_max[index_right...] = max(rho_max[index_right...], rho_neighbor_left) + rho_min[index_right...] = min(rho_min[index_right...], rho_left) + rho_max[index_right...] = max(rho_max[index_right...], rho_left) - rho_min[index_left...] = min(rho_min[index_left...], rho_neighbor_right) - rho_max[index_left...] = max(rho_max[index_left...], rho_neighbor_right) + rho_min[index_left...] = min(rho_min[index_left...], rho_right) + rho_max[index_left...] = max(rho_max[index_left...], rho_right) end end @@ -316,7 +316,12 @@ end inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - var = u[1, i, j, element] + rho = u_safe[1, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node # Calculate P_plus and P_minus # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -336,12 +341,12 @@ end if P_plus == 0.0 frac_plus = 1.0 else - frac_plus = max(0.0, rho_max[i, j, element] - var) / P_plus + frac_plus = max(0.0, rho_max[i, j, element] - rho) / P_plus end if P_minus == 0.0 frac_minus = 1.0 else - frac_minus = min(0.0, rho_min[i, j, element] - var) / P_minus + frac_minus = min(0.0, rho_min[i, j, element] - rho) / P_minus end # Calculate alpha at nodes @@ -352,7 +357,9 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u, u_old, equations, dg, dt, cache) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + # IDP limiter for pressure based on + # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * indicator_IDP.IDPDensityTVD @@ -365,8 +372,7 @@ end p_max[:, :, element] .= typemin(eltype(p_max)) # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u_old, equations, dg, i, j, element) - p = pressure(u_local, equations) + p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) p_min[i, j, element] = min(p_min[i, j, element], p) p_max[i, j, element] = max(p_max[i, j, element], p) @@ -405,16 +411,14 @@ end index_left = (i, nnodes(dg), left) index_right = (i, 1, right) end - u_local_left = get_node_vars(u_old, equations, dg, index_left...) - u_local_right = get_node_vars(u_old, equations, dg, index_right...) - p_neighbor_left = pressure(u_local_left, equations) - p_neighbor_right = pressure(u_local_right, equations) + p_left = pressure(get_node_vars(u_safe, equations, dg, index_left...), equations) + p_right = pressure(get_node_vars(u_safe, equations, dg, index_right...), equations) - p_min[index_right...] = min(p_min[index_right...], p_neighbor_left) - p_max[index_right...] = max(p_max[index_right...], p_neighbor_left) + p_min[index_right...] = min(p_min[index_right...], p_left) + p_max[index_right...] = max(p_max[index_right...], p_left) - p_min[index_left...] = min(p_min[index_left...], p_neighbor_right) - p_max[index_left...] = max(p_max[index_left...], p_neighbor_right) + p_min[index_left...] = min(p_min[index_left...], p_right) + p_max[index_left...] = max(p_max[index_left...], p_right) end end @@ -424,13 +428,17 @@ end inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - var = pressure(u_local, equations) + p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node # Calculate P_plus and P_minus # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - v1 = u[2, i, j, element] / u[1, i, j, element] - v2 = u[3, i, j, element] / u[1, i, j, element] + v1 = u_safe[2, i, j, element] / u_safe[1, i, j, element] + v2 = u_safe[3, i, j, element] / u_safe[1, i, j, element] v2s2 = 0.5 * (v1^2 + v2^2) gamma_m1 = equations.gamma - 1.0 @@ -454,12 +462,12 @@ end if P_plus == 0.0 frac_plus = 1.0 else - frac_plus = max(0.0, p_max[i, j, element] - var) / P_plus + frac_plus = max(0.0, p_max[i, j, element] - p) / P_plus end if P_minus == 0.0 frac_minus = 1.0 else - frac_minus = min(0.0, p_min[i, j, element] - var) / P_minus + frac_minus = min(0.0, p_min[i, j, element] - p) / P_minus end # Calculate alpha at nodes @@ -470,20 +478,20 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - offset = 2 * (indicator_IDP.IDPDensityTVD + indicator_IDP.IDPPressureTVD) + - min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPDensityTVD) + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPPressureTVD) - s_min = var_bounds[1 + offset] + offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) + s_min = var_bounds[offset + 1] # Calculate bound: s_min @threaded for element in eachelement(dg, cache) s_min[:, :, element] .= typemax(eltype(s_min)) for j in eachnode(dg), i in eachnode(dg) - # Get limit states; no neighbors. - s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) + # Get limit states + s = entropy_spec(get_node_vars(u_old, equations, dg, i, j, element), equations) s_min[i, j, element] = min(s_min[i, j, element], s) if i > 1 s_min[i-1, j, element] = min(s_min[i-1, j, element], s) @@ -500,10 +508,34 @@ end end end + # Loop over interfaces + @threaded for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + s_left = entropy_spec(get_node_vars(u_old, equations, dg, index_left...), equations) + s_right = entropy_spec(get_node_vars(u_old, equations, dg, index_right...), equations) + + s_min[index_right...] = min(s_min[index_right...], s_left) + s_min[index_left...] = min(s_min[index_left...], s_right) + end + end + # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) + u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, equations, dg, dt, cache, indicator_IDP) @@ -517,20 +549,21 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u, equations, dg, dt, cache) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - offset = 2 * (indicator_IDP.IDPDensityTVD + indicator_IDP.IDPPressureTVD) + indicator_IDP.IDPSpecEntropy + - min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPDensityTVD) + min(indicator_IDP.IDPPositivity, !indicator_IDP.IDPPressureTVD) - s_max = var_bounds[1 + offset] + offset = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + + min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) + s_max = var_bounds[offset + 1] # Calculate bound: s_max @threaded for element in eachelement(dg, cache) s_max[:, :, element] .= typemin(eltype(s_max)) for j in eachnode(dg), i in eachnode(dg) - # Get limit states; no neighbors. - s = entropy_math(get_node_vars(u, equations, dg, i, j, element), equations) + # Get limit states + s = entropy_math(get_node_vars(u_old, equations, dg, i, j, element), equations) s_max[i, j, element] = max(s_max[i, j, element], s) if i > 1 s_max[i-1, j, element] = max(s_max[i-1, j, element], s) @@ -547,10 +580,34 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol end end + # Loop over interfaces + @threaded for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + s_left = entropy_math(get_node_vars(u_old, equations, dg, index_left...), equations) + s_right = entropy_math(get_node_vars(u_old, equations, dg, index_right...), equations) + + s_max[index_right...] = max(s_max[index_right...], s_left) + s_max[index_left...] = max(s_max[index_left...], s_right) + end + end + # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) + u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, equations, dg, dt, cache, indicator_IDP) @@ -603,6 +660,8 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto end # Real one-sided Zalesak-type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node frac_minus = min(0.0, rho_min[i, j, element] - u_safe[1, i, j, element]) From 9c63c64bd9333cb17aecdb783f1f398bd88dd064 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 16 May 2022 13:47:06 +0200 Subject: [PATCH 042/423] Add bounds check routine --- src/solvers/dgsem_tree/containers_2d.jl | 6 ++- src/solvers/dgsem_tree/dg_2d.jl | 52 +++++++++++++++++++++++++ src/solvers/dgsem_tree/indicators.jl | 10 +++-- src/time_integration/methods_SSP.jl | 46 ++++++++++++++++++++++ 4 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 8cd29d0676..6b0a0cf595 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1316,6 +1316,7 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} _var_bounds::Vector{Vector{uEltype}} + idp_bounds_delta::Vector{uEltype} end function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real @@ -1336,8 +1337,11 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, l var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) end + idp_bounds_delta = zeros(uEltype, length) + return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_bounds, - _alpha, _alpha1, _alpha2, _var_bounds) + _alpha, _alpha1, _alpha2, _var_bounds, + idp_bounds_delta) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index aa4c674eed..ab94b14844 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -679,6 +679,11 @@ end IDP_correction!(u, alpha1, alpha2, dt, equations, solver, cache) + # Check that we are within bounds + if solver.volume_integral.indicator.IDPCheckBounds + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(u, semi) + end + return nothing end @@ -707,6 +712,53 @@ end return nothing end +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, semi) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator + @unpack idp_bounds_delta, var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + + @threaded for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + counter = 0 + if IDPDensityTVD + counter += 1 # rho_min + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[1][i, j, element] - u[1, i, j, element]) + counter += 1 # rho_max + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], u[1, i, j, element] - var_bounds[2][i, j, element]) + end + if IDPPressureTVD + p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) + counter += 1 # p_min + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) + counter += 1 # p_max + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], p - var_bounds[counter][i, j, element]) + end + if IDPPositivity && !IDPDensityTVD + counter += 1 # rho_min + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - u[1, i, j, element]) + end + if IDPPositivity && !IDPPressureTVD + p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) + counter += 1 # p_min + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) + end + if IDPSpecEntropy + s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) + counter += 1 # s_min + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - s) + end + if IDPMathEntropy + s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) + counter += 1 # s_max + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], s - var_bounds[counter][i, j, element]) + end + end + end + + return nothing +end + function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 0e30ee833d..a3fd5b46d8 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -177,6 +177,7 @@ struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator newton_tol::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method IDPgamma::RealT # Constant for the subcell limiting of convex (nonlinear) constraints # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) + IDPCheckBounds::Bool end # this method is used when the indicator is constructed as for shock-capturing volume integrals @@ -188,7 +189,8 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPSpecEntropy=false, IDPMathEntropy=false, positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations)) + newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), + IDPCheckBounds=false) if IDPMathEntropy && IDPSpecEntropy error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") @@ -204,7 +206,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; cache = create_cache(IndicatorIDP, equations, basis, length) IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy, - cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma) + cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -287,9 +289,9 @@ Depending on the indicator_type, different input values and corresponding traine - Based on convolutional neural network. - 2d Input: Interpolation of the nodal values of the `indicator.variable` to the 4x4 LGL nodes. -If `alpha_continuous == true` the continuous network output for troubled cells (`alpha > 0.5`) is considered. +If `alpha_continuous == true` the continuous network output for troubled cells (`alpha > 0.5`) is considered. If the cells are good (`alpha < 0.5`), `alpha` is set to `0`. -If `alpha_continuous == false`, the blending factor is set to `alpha = 0` for good cells and +If `alpha_continuous == false`, the blending factor is set to `alpha = 0` for good cells and `alpha = 1` for troubled cells. !!! warning "Experimental implementation" diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index a885ffc772..1a29ac93dd 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -192,6 +192,11 @@ function solve!(integrator::SimpleIntegratorSSP) end end + # Check that we are within bounds + if integrator.p.solver.volume_integral.indicator.IDPCheckBounds + summary_check_bounds(integrator) + end + return TimeIntegratorSolution((first(prob.tspan), integrator.t), (prob.u0, integrator.u), integrator.sol.prob) @@ -233,5 +238,46 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end +# check deviation from boundaries of IDP indicator +@inline function summary_check_bounds(integrator) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = integrator.p.solver.volume_integral.indicator + @unpack idp_bounds_delta = integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + + println("─"^100) + println("Maximum deviation from bounds:") + println("─"^100) + counter = 0 + if IDPDensityTVD + counter += 1 + println("rho_min: ", idp_bounds_delta[counter]) + counter += 1 + println("rho_max: ", idp_bounds_delta[counter]) + end + if IDPPressureTVD + counter += 1 + println("p_min: ", idp_bounds_delta[counter]) + counter += 1 + println("p_max: ", idp_bounds_delta[counter]) + end + if IDPPositivity && !IDPDensityTVD + counter += 1 + println("rho_min: ", idp_bounds_delta[counter]) + end + if IDPPositivity && !IDPPressureTVD + counter += 1 + println("p_min: ", idp_bounds_delta[counter]) + end + if IDPSpecEntropy + counter += 1 + println("ent_min: ", idp_bounds_delta[counter]) + end + if IDPMathEntropy + counter += 1 + println("ent_max: ", idp_bounds_delta[counter]) + end + println("─"^100 * "\n") + + return nothing +end end # @muladd From 64bec705f98c447ab29405fcd2060899a1e9049f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 May 2022 19:45:18 +0200 Subject: [PATCH 043/423] Fix thread parallelization for BoundsCheck and update examples --- .../elixir_euler_astro_jet_subcell.jl | 4 ++-- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_blob_sc_subcell.jl | 6 +---- .../elixir_euler_colliding_flow_sc_subcell.jl | 6 ++--- ...kelvin_helmholtz_instability_sc_subcell.jl | 6 +---- .../elixir_euler_positivity_sc_subcell.jl | 2 +- src/solvers/dgsem_tree/containers_2d.jl | 6 +---- src/solvers/dgsem_tree/dg_2d.jl | 4 +++- src/solvers/dgsem_tree/indicators_2d.jl | 17 +++++++------ src/time_integration/methods_SSP.jl | 10 +++++++- test/test_tree_2d_euler.jl | 24 +++++++++---------- 11 files changed, 43 insertions(+), 44 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index c7818052fb..639f137185 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -44,8 +44,8 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=false, - IDPPressureTVD=true, + IDPDensityTVD=true, + IDPPressureTVD=false, IDPPositivity=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index a448eeb9e6..e5a2bda7d3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -40,7 +40,7 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, + IDPPressureTVD=false, IDPPositivity=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl index a48c38f6aa..a806ebe8fd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl @@ -56,11 +56,7 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=false, - IDPPressureTVD=false, - IDPPositivity=true, - IDPSpecEntropy=false, - IDPMathEntropy=false) + IDPPositivity=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl index cc96284335..c8e07fc2a2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -50,10 +50,8 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, - IDPPositivity=true, - IDPSpecEntropy=false, - IDPMathEntropy=false) + IDPPressureTVD=false, + IDPPositivity=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index e0f00b20aa..8acf738dd1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,11 +37,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPressureTVD=false, - IDPPositivity=false, - IDPSpecEntropy=false, - IDPMathEntropy=false) + IDPPositivity=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl index a4c1481e0a..b889d23f42 100644 --- a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl @@ -43,7 +43,7 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPositivity=true,) + IDPPositivity=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 6b0a0cf595..8cd29d0676 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1316,7 +1316,6 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} _var_bounds::Vector{Vector{uEltype}} - idp_bounds_delta::Vector{uEltype} end function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real @@ -1337,11 +1336,8 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, l var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) end - idp_bounds_delta = zeros(uEltype, length) - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_bounds, - _alpha, _alpha1, _alpha2, _var_bounds, - idp_bounds_delta) + _alpha, _alpha1, _alpha2, _var_bounds) end nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ab94b14844..92848411f8 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -716,9 +716,11 @@ end mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator - @unpack idp_bounds_delta, var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache @threaded for element in eachelement(solver, cache) + idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] for j in eachnode(solver), i in eachnode(solver) counter = 0 if IDPDensityTVD diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 2fc7d74d1f..fc508c5d5a 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -198,8 +198,11 @@ function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, bas alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) + idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] + return (; ContainerShockCapturingIndicator, - alpha_max_per_timestep, alpha_mean_per_timestep) + alpha_max_per_timestep, alpha_mean_per_timestep, + idp_bounds_delta_threaded) end function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -216,9 +219,9 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab indicator_IDP.IDPPositivity && @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP @@ -284,7 +287,7 @@ end end # Loop over interfaces - @threaded for interface in eachinterface(dg, cache) + for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -396,7 +399,7 @@ end end # Loop over interfaces - @threaded for interface in eachinterface(dg, cache) + for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -509,7 +512,7 @@ end end # Loop over interfaces - @threaded for interface in eachinterface(dg, cache) + for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -581,7 +584,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol end # Loop over interfaces - @threaded for interface in eachinterface(dg, cache) + for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 1a29ac93dd..fe3fe75141 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -241,7 +241,15 @@ end # check deviation from boundaries of IDP indicator @inline function summary_check_bounds(integrator) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = integrator.p.solver.volume_integral.indicator - @unpack idp_bounds_delta = integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack idp_bounds_delta_threaded = integrator.p.solver.volume_integral.indicator.cache + + idp_bounds_delta = zeros(eltype(idp_bounds_delta_threaded[1]), length(idp_bounds_delta_threaded[1])) + + for index in 1:length(idp_bounds_delta) + for i in 1:Threads.nthreads() + idp_bounds_delta[index] = max(idp_bounds_delta[index], idp_bounds_delta_threaded[i][index]) + end + end println("─"^100) println("Maximum deviation from bounds:") diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 9cdddb7b13..5169b10ffa 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -66,8 +66,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - l2 = [0.0528852022914957, 0.04605220278777441, 0.046051285430361966, 0.19333536195011322], - linf = [0.18676597825683394, 0.23170518015350347, 0.2316394218254613, 0.6910854547329741]) + l2 = [0.05279461354314492, 0.045989178414492675, 0.04598740128933962, 0.19301796760176929], + linf = [0.18653503138166105, 0.23196626025079317, 0.23205043616292115, 0.6911505364900443]) end @trixi_testset "elixir_euler_blast_wave.jl" begin @@ -132,8 +132,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.33497677827522393, 0.18846649571882834, 0.18846957823831056, 0.6202202597584124], - linf = [1.570337061620338, 1.2688091762034825, 1.2691766589473688, 2.4069374156041263], + l2 = [0.35190218236276916, 0.1932735857321866, 0.1932566034003023, 0.6193245526148682], + linf = [1.6865111411650586, 1.3647962470261445, 1.363807717209087, 2.443080751122044], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) @@ -165,8 +165,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.49388182696965016, 0.1664478265682381, 0.16644705322200087, 0.6351261288582164], - linf = [2.510295676164479, 1.2096774802395878, 1.2095916433265121, 6.471098677030467], + l2 = [0.49171272129274185, 0.1654059921666582, 0.16540322728288526, 0.6346745392214297], + linf = [2.5231800623551552, 1.1676860712180208, 1.1676908666193262, 6.469773077354864], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -213,8 +213,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.05564045019484471, 0.03296714778723376, 0.05160031886304709, 0.0798132537431978], - linf = [0.2343924443588683, 0.1711747394866538, 0.1340845767284859, 0.27221997312881907], + l2 = [0.05570314908537475, 0.03298722583361271, 0.052244709734327016, 0.08011559032847568], + linf = [0.24091015067867505, 0.166018978319328, 0.12356154832726032, 0.26951669929779953], tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=2,)) @@ -248,8 +248,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.006029487817162152, 0.04306352664570119, 1.0196317105626685e-6, 0.602600980127913], - linf = [0.133287118940215, 0.46245152812030377, 4.841326071863473e-5, 11.460517088011834], + l2 = [0.0065670105355693535, 0.04549413637429556, 1.5617641521208659e-6, 0.6247664278274535], + linf = [0.1448901649616433, 0.5279507148840341, 8.892604457705052e-5, 12.030176754489556], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end @@ -264,8 +264,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), - l2 = [0.4360530254790599, 351.83324431719006, 13.841995590128272, 138429.10256913095], - linf = [9.349440577987206, 6938.823487053745, 503.9002738813788, 2.6096438436575336e6], + l2 = [0.4424122644556847, 353.5424835076033, 14.195424344914256, 138995.99716665552], + linf = [7.729363826700428, 5819.847107066928, 659.5924852103605, 2.186983178009216e6], tspan = (2.5e-6, 1.0e-4), coverage_override = (maxiters=6,)) end From b902de1a4c4aac4274841049bdd88202da3fe549 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 May 2022 20:48:37 +0200 Subject: [PATCH 044/423] Fix tests --- test/test_tree_2d_euler.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 5169b10ffa..b9241024e5 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -165,8 +165,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.49171272129274185, 0.1654059921666582, 0.16540322728288526, 0.6346745392214297], - linf = [2.5231800623551552, 1.1676860712180208, 1.1676908666193262, 6.469773077354864], + l2 = [0.49171288879147707, 0.16540604409411028, 0.165403281995138, 0.6346743704341865], + linf = [2.523187390223829, 1.1676864180461144, 1.1676912091995713, 6.469768610580735], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -248,8 +248,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.0065670105355693535, 0.04549413637429556, 1.5617641521208659e-6, 0.6247664278274535], - linf = [0.1448901649616433, 0.5279507148840341, 8.892604457705052e-5, 12.030176754489556], + l2 = [0.006567503201406924, 0.045494701197468755, 1.5604684539276876e-6, 0.624781570252251], + linf = [0.1448916669656563, 0.5279925643783724, 8.77139846451784e-5, 12.03029820002121], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end @@ -264,8 +264,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), - l2 = [0.4424122644556847, 353.5424835076033, 14.195424344914256, 138995.99716665552], - linf = [7.729363826700428, 5819.847107066928, 659.5924852103605, 2.186983178009216e6], + l2 = [0.442412359159042, 353.54254537346463, 14.195423442065804, 138996.0083518854], + linf = [7.729364707886681, 5819.848679298194, 659.5925327100372, 2.1869838429080946e6], tspan = (2.5e-6, 1.0e-4), coverage_override = (maxiters=6,)) end From d1360a73283b7db5fde9df98a3cb8e51bec996fe Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 19 May 2022 11:11:03 +0200 Subject: [PATCH 045/423] Rename solve function --- .../elixir_euler_astro_jet_subcell.jl | 6 ++--- .../elixir_euler_astro_jet_subcell_restart.jl | 6 ++--- .../elixir_euler_blast_wave_sc_subcell.jl | 6 ++--- .../elixir_euler_blob_sc_subcell.jl | 6 ++--- .../elixir_euler_colliding_flow_sc_subcell.jl | 6 ++--- ...kelvin_helmholtz_instability_sc_subcell.jl | 6 ++--- .../elixir_euler_positivity_sc_subcell.jl | 6 ++--- .../elixir_euler_shockcapturing_subcell.jl | 6 ++--- src/time_integration/methods_SSP.jl | 24 +++++++++++-------- 9 files changed, 38 insertions(+), 34 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 639f137185..f20d3c1cf5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -91,7 +91,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl index 19e4febf54..01c276c332 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl @@ -38,7 +38,7 @@ callbacks = CallbackSet(summary_callback, stepsize_callback) ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index e5a2bda7d3..cca18b3dfd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -86,7 +86,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi; - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode; + 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_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl index a806ebe8fd..2ff08a2fb1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl @@ -100,7 +100,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl index c8e07fc2a2..2e90555918 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -101,7 +101,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, semi, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 8acf738dd1..70505edde9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -78,7 +78,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl index b889d23f42..f7b638a447 100644 --- a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl @@ -87,7 +87,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index b17d155c50..9aea2be01b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -59,7 +59,7 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, ############################################################################### # run the simulation -sol = Trixi.solve_IDP(ode, semi; - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); summary_callback() # print the timer summary diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index fe3fe75141..8d6504d8a5 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -84,7 +84,7 @@ function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) end """ - solve_IDP(ode, semi; dt, callbacks, kwargs...) + solve(ode; dt, callbacks, kwargs...) The following structures and methods provide a implementation of the third-order SSP Runge-Kutta method [`SimpleSSPRK33`](@ref). @@ -92,7 +92,8 @@ method [`SimpleSSPRK33`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -function solve_IDP(ode::ODEProblem, semi; alg=SimpleSSPRK33(), dt, callback=nothing, kwargs...) +function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, + dt, callback=nothing, kwargs...) u = copy(ode.u0) du = similar(u) u_safe = similar(u) @@ -109,6 +110,7 @@ function solve_IDP(ode::ODEProblem, semi; alg=SimpleSSPRK33(), dt, callback=noth resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, nelements(integrator.p.solver, integrator.p.cache)) + # initialize callbacks if callback isa CallbackSet for cb in callback.continuous_callbacks error("unsupported") @@ -142,13 +144,15 @@ function solve!(integrator::SimpleIntegratorSSP) end @. integrator.u_safe = integrator.u - for i in 1:length(alg.a) - @trixi_timeit timer() "RK stage" begin - prob.f(integrator.du, integrator.u_safe, integrator.p, integrator.t + alg.c[i] * integrator.dt) - @. integrator.u_old = (1.0 - alg.a[i]) * integrator.u + alg.a[i] * integrator.u_safe - @. integrator.u_safe = integrator.u_old + alg.b[i] * integrator.dt * integrator.du + for stage in eachindex(alg.c) + t_stage = integrator.t + integrator.dt * alg.c[stage] + prob.f(integrator.du, integrator.u_safe, integrator.p, t_stage) + + @trixi_timeit timer() "Runge-Kutta stage" begin + @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe + @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du end - @trixi_timeit timer() "antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[i] * integrator.dt, integrator.p) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p) end @. integrator.u = integrator.u_safe @@ -198,8 +202,8 @@ function solve!(integrator::SimpleIntegratorSSP) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), - (prob.u0, integrator.u), - integrator.sol.prob) + (prob.u0, integrator.u), + integrator.sol.prob) end # get a cache where the RHS can be stored From c2442a70a3d60fab000eb95c3cea35a9e03f80df Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 19 May 2022 13:57:11 +0200 Subject: [PATCH 046/423] Fix example --- .../tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl index 2e90555918..d259808a42 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -101,7 +101,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, semi, +sol = Trixi.solve(ode, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary From b65703689233e748dcb165e7af70811c9e6e316e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 14 Jun 2022 15:45:08 +0200 Subject: [PATCH 047/423] Update structure --- src/solvers/dgsem_tree/dg.jl | 10 +++++ src/solvers/dgsem_tree/dg_2d.jl | 64 +++++++++++++--------------- src/solvers/dgsem_tree/indicators.jl | 25 +++++------ src/time_integration/methods_SSP.jl | 39 ++++++++++------- 4 files changed, 77 insertions(+), 61 deletions(-) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 2b947e1594..9d3b1aa593 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -39,6 +39,16 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end +@inline function IDP_checkBounds(u_ode, semi) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + u = wrap_array(u_ode, mesh, equations, solver, cache) + + IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator) + + return nothing +end + + function volume_jacobian(element, mesh::TreeMesh, cache) return inv(cache.elements.inverse_jacobian[element])^ndims(mesh) end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 92848411f8..d0e4bb847e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -94,9 +94,15 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] + cache = add2cache(cache, mesh, equations, volume_integral.indicator, dg, uEltype) + + return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) +end + +function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded, ContainerFCT2D) + return (; cache..., ContainerFCT2D) end @@ -518,18 +524,20 @@ function calc_volume_integral!(du, u, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) @threaded for element in eachelement(dg, cache) - subcell_DG_FV_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral, dg, cache) + subcell_limiting_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, volume_integral.indicator, + dg, cache) end end -@inline function subcell_DG_FV_kernel!(du, u, - element, mesh::TreeMesh{2}, - nonconservative_terms::Val{false}, equations, - volume_integral, dg::DGSEM, cache) +@inline function subcell_limiting_kernel!(du, u, + element, mesh::TreeMesh{2}, + nonconservative_terms::Val{false}, equations, + volume_integral, indicator::IndicatorIDP, + dg::DGSEM, cache) @unpack inverse_weights = dg.basis - @unpack volume_flux_dg, volume_flux_fv, indicator = volume_integral + @unpack volume_flux_dg, volume_flux_fv = volume_integral # high-order DG fluxes @unpack fhat1_threaded, fhat2_threaded = cache @@ -553,7 +561,7 @@ end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, dg, element, cache) + nonconservative_terms, equations, indicator, dg, element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -646,7 +654,7 @@ end end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, dg, element, cache) + nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) @@ -668,8 +676,10 @@ end return nothing end -@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi) +@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + @unpack inverse_weights = solver.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -677,30 +687,16 @@ end @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) @unpack alpha1, alpha2 = semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - IDP_correction!(u, alpha1, alpha2, dt, equations, solver, cache) - - # Check that we are within bounds - if solver.volume_integral.indicator.IDPCheckBounds - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(u, semi) - end - - return nothing -end - -@inline function IDP_correction!(u::AbstractArray{<:Any,4}, alpha1, alpha2, dt, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - - @threaded for element in eachelement(dg, cache) + @threaded for element in eachelement(solver, cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] # Calculate volume integral contribution # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - for j in eachnode(dg), i in eachnode(dg) - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + for j in eachnode(solver), i in eachnode(solver) + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + @@ -712,8 +708,8 @@ end return nothing end -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, semi) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) +# 2d, IndicatorIDP +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index a3fd5b46d8..cdec4a9bdf 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -196,10 +196,6 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") end - if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) - println("No limiter selected => pure DG method") - end - length = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) @@ -211,16 +207,21 @@ end function Base.show(io::IO, indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator print(io, "IndicatorIDP(") - print(io, "limiter=(") - indicator.IDPDensityTVD && print(io, "IDPDensityTVD, ") - indicator.IDPPressureTVD && print(io, "IDPPressureTVD, ") - indicator.IDPPositivity && print(io, "IDPPositivity, ") - indicator.IDPSpecEntropy && print(io, "IDPSpecEntropy, ") - indicator.IDPMathEntropy && print(io, "IDPMathEntropy, ") - print(io, "), ") - print(io, "alpha_maxIDP=", indicator.alpha_maxIDP) + if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + print(io, "No limiter selected => pure DG method") + else + print(io, "limiter=(") + IDPDensityTVD && print(io, "IDPDensityTVD, ") + IDPPressureTVD && print(io, "IDPPressureTVD, ") + IDPPositivity && print(io, "IDPPositivity, ") + IDPSpecEntropy && print(io, "IDPSpecEntropy, ") + IDPMathEntropy && print(io, "IDPMathEntropy, ") + print(io, "), ") + end + indicator.alpha_maxIDP != 1.0 && print(io, "alpha_maxIDP=", indicator.alpha_maxIDP) print(io, ")") end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 8d6504d8a5..7e53370360 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -104,11 +104,8 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, (prob=ode,), alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) - # Resize antidiffusive fluxes - resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha - resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, - nelements(integrator.p.solver, integrator.p.cache)) + # Resize container + resize!(integrator.p, nelements(integrator.p.solver, integrator.p.cache)) # initialize callbacks if callback isa CallbackSet @@ -152,7 +149,11 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, integrator.p.solver.volume_integral.indicator) + + # Check that we are within bounds + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) + end @. integrator.u = integrator.u_safe @@ -198,7 +199,7 @@ function solve!(integrator::SimpleIntegratorSSP) # Check that we are within bounds if integrator.p.solver.volume_integral.indicator.IDPCheckBounds - summary_check_bounds(integrator) + summary_check_bounds(integrator.p.solver.volume_integral.indicator) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), @@ -234,18 +235,26 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) resize!(integrator.u_tmp, new_size) resize!(integrator.u_old, new_size) - # Resize antidiffusive fluxes - resize!(integrator.p.cache.ContainerFCT2D, nelements(integrator.p.solver, integrator.p.cache)) - # Resize alpha - resize!(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, - nelements(integrator.p.solver, integrator.p.cache)) + # Resize container + resize!(integrator.p, new_size) +end + +function Base.resize!(semi::AbstractSemidiscretization, new_size) + # Resize ContainerFCT2D or ContainerMCL2D + if semi.solver.volume_integral.indicator isa IndicatorIDP + resize!(semi.cache.ContainerFCT2D, new_size) + else # semi.solver.volume_integral.indicator isa IndicatorKuzminetal + resize!(semi.cache.ContainerMCL2D, new_size) + end + # Resize ContainerShockCapturingIndicator + resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) end # check deviation from boundaries of IDP indicator -@inline function summary_check_bounds(integrator) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = integrator.p.solver.volume_integral.indicator - @unpack idp_bounds_delta_threaded = integrator.p.solver.volume_integral.indicator.cache +@inline function summary_check_bounds(indicator::IndicatorIDP) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack idp_bounds_delta_threaded = indicator.cache idp_bounds_delta = zeros(eltype(idp_bounds_delta_threaded[1]), length(idp_bounds_delta_threaded[1])) From 4c81ab24a209fb632982cdfc22fdadd6e6ded3ab Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 21 Jun 2022 15:00:20 +0200 Subject: [PATCH 048/423] Add WIP version of MCL indicator --- ...ir_euler_blast_wave_monolithic_limiting.jl | 90 +++ ...lmholtz_instability_monolithic_limiting.jl | 87 +++ ...uler_shockcapturing_monolithic_limiting.jl | 63 ++ src/Trixi.jl | 2 +- src/callbacks_step/stepsize.jl | 27 + src/solvers/dgsem_tree/containers_2d.jl | 88 +++ src/solvers/dgsem_tree/dg.jl | 10 + src/solvers/dgsem_tree/dg_2d.jl | 560 ++++++++++++++++++ src/solvers/dgsem_tree/indicators.jl | 32 + src/solvers/dgsem_tree/indicators_2d.jl | 2 +- src/time_integration/methods_SSP.jl | 46 +- 11 files changed, 999 insertions(+), 8 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl new file mode 100644 index 0000000000..af82ef8331 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl @@ -0,0 +1,90 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +A medium blast wave taken from +- Sebastian Hennemann, Gregor J. 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) +""" +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorKuzminetal(equations, basis; + IDPCheckBounds=true) +volume_integral = VolumeIntegralShockCapturingSubcell(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=10_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=20, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.2) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode; + 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_euler_kelvin_helmholtz_instability_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl new file mode 100644 index 0000000000..b10d064cf4 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl @@ -0,0 +1,87 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorKuzminetal(equations, basis; + IDPCheckBounds=true, + IDPPressureTVD=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +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=50, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.8) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_solution, + ) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, #alg=SSPRK43(); + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl new file mode 100644 index 0000000000..916ed9ae73 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl @@ -0,0 +1,63 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_weak_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorKuzminetal(equations, basis; + IDPCheckBounds=true) +volume_integral = VolumeIntegralShockCapturingSubcell(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=5, + n_cells_max=10_000) + + +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 = 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=0.8) + +callbacks = CallbackSet(summary_callback, stepsize_callback, + save_solution, + analysis_callback, alive_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index 6fa76e332f..2cb9f89cf8 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -177,7 +177,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralShockCapturingSubcell, IndicatorIDP, + VolumeIntegralShockCapturingSubcell, IndicatorIDP, IndicatorKuzminetal, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, MortarL2 diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 13e4f9dfa5..953e1e59bf 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -72,9 +72,36 @@ end @unpack cfl_number = stepsize_callback u = wrap_array(u_ode, mesh, equations, solver, cache) + # TODO BB: Fix the implementation of the second CFL condition. + a=2 + if a==1 dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, have_constant_speed(equations), equations, solver, cache) + elseif a==2 + @unpack inverse_weights = solver.basis + # if t == 0.0 + calc_lambda!(u_ode, semi)#, mesh, equations, solver.volume_integral.indicator, solver, cache) + # end + @unpack lambda1, lambda2 = cache.ContainerMCL2D + + maxdt = typemax(eltype(u_ode)) + for element in eachelement(solver, cache) + J = 1 / cache.elements.inverse_jacobian[element] + + for j in eachnode(solver), i in eachnode(solver) + denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + + inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) + maxdt = min(maxdt, J / denom) + end + end + + dt = @trixi_timeit timer() "calculate dt" cfl_number * maxdt + # dt = 1e-4 + else + dt = 1e-4 + end + set_proposed_dt!(integrator, dt) integrator.opts.dtmax = dt integrator.dtcache = dt diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 8cd29d0676..1a994ae413 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1306,6 +1306,94 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) return nothing end +mutable struct ContainerMCL2D{uEltype<:Real} + lambda1::Array{uEltype, 3} # [i, j, element] + lambda2::Array{uEltype, 3} # [i, j, element] + # Bar states at subcell interfaces for cons variable + bar_states1::Array{uEltype, 4} # [variable, i, j, element] + bar_states2::Array{uEltype, 4} # [variable, i, j, element] + # TODO: Do I really need to save the fluxes? For now, yes, because I need them to check the bounds at the end. + # Idea: Just save the limited bar states. Problem: In there, the sign of the antidiffusive flux is not unique. + antidiffusive_flux1_limited::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2_limited::Array{uEltype, 4} # [variables, i, j, elements] + # internal `resize!`able storage + _lambda1::Vector{uEltype} + _lambda2::Vector{uEltype} + _bar_states1::Vector{uEltype} + _bar_states2::Vector{uEltype} + _antidiffusive_flux1_limited::Vector{uEltype} + _antidiffusive_flux2_limited::Vector{uEltype} +end + +function ContainerMCL2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real + nan_uEltype = convert(uEltype, NaN) + + # Initialize fields with defaults + _lambda1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) + lambda1 = unsafe_wrap(Array, pointer(_lambda1), + (n_nodes+1, n_nodes, capacity)) + _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) + lambda2 = unsafe_wrap(Array, pointer(_lambda2), + (n_nodes, n_nodes+1, capacity)) + _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), + (n_variables, n_nodes+1, n_nodes, capacity)) + _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), + (n_variables, n_nodes, n_nodes+1, capacity)) + + _antidiffusive_flux1_limited = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + antidiffusive_flux1_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux1_limited), + (n_variables, n_nodes+1, n_nodes, capacity)) + + _antidiffusive_flux2_limited = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + antidiffusive_flux2_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux2_limited), + (n_variables, n_nodes, n_nodes+1, capacity)) + + return ContainerMCL2D{uEltype}(lambda1, lambda2, bar_states1, bar_states2, antidiffusive_flux1_limited, antidiffusive_flux2_limited, + _lambda1, _lambda2, _bar_states1, _bar_states2, _antidiffusive_flux1_limited, _antidiffusive_flux2_limited) +end + +nvariables(container::ContainerMCL2D) = size(container.bar_states1, 1) +nnodes(container::ContainerMCL2D) = size(container.lambda1, 2) + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(container::ContainerMCL2D, capacity) + n_nodes = nnodes(container) + n_variables = nvariables(container) + + @unpack _lambda1, _lambda2, _bar_states1, _bar_states2 = container + + resize!(_lambda1, (n_nodes+1) * n_nodes * capacity) + container.lambda1 = unsafe_wrap(Array, pointer(_lambda1), + (n_nodes+1, n_nodes, capacity)) + resize!(_lambda2, n_nodes * (n_nodes+1) * capacity) + container.lambda2 = unsafe_wrap(Array, pointer(_lambda2), + (n_nodes, n_nodes+1, capacity)) + resize!(_bar_states1, n_variables * (n_nodes+1) * n_nodes * capacity) + container.bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), + (n_variables, n_nodes+1, n_nodes, capacity)) + resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) + container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), + (n_variables, n_nodes, n_nodes+1, capacity)) + + @unpack _antidiffusive_flux1_limited, _antidiffusive_flux2_limited = container + + resize!(_antidiffusive_flux1_limited, n_variables * (n_nodes+1) * n_nodes * capacity) + container.antidiffusive_flux1_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux1_limited), + (n_variables, n_nodes+1, n_nodes, capacity)) + resize!(_antidiffusive_flux2_limited, n_variables * n_nodes * (n_nodes+1) * capacity) + container.antidiffusive_flux2_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux2_limited), + (n_variables, n_nodes, n_nodes+1, capacity)) + + return nothing +end + + mutable struct ContainerShockCapturingIndicator{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, elements] alpha1::Array{uEltype, 3} diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 9d3b1aa593..388a3f3f5e 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -39,6 +39,16 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end +@inline function calc_lambda!(u_ode, semi) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + u = wrap_array(u_ode, mesh, equations, solver, cache) + + calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) + + return nothing +end + + @inline function IDP_checkBounds(u_ode, semi) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index d0e4bb847e..4145fa7d35 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -105,6 +105,24 @@ function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, return (; cache..., ContainerFCT2D) end +function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorKuzminetal, dg::DG, uEltype) + ContainerMCL2D = Trixi.ContainerMCL2D{uEltype}(0, nvariables(equations), nnodes(dg)) + # n_limiters = length(indicator.variables) + + A3dp1_x = Array{uEltype, 3} + A3dp1_y = Array{uEltype, 3} + + antidiffusive_flux1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + antidiffusive_flux2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + + # antidiffusive_flux1_limited_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] + # antidiffusive_flux2_limited_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] + + return (; cache..., ContainerMCL2D, + antidiffusive_flux1_threaded, antidiffusive_flux2_threaded,) + # antidiffusive_flux1_limited_threaded, antidiffusive_flux2_limited_threaded) +end + # The methods below are specialized on the mortar type # and called from the basic `create_cache` method at the top. @@ -523,6 +541,23 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) + # Calculate maximum wave speeds lambda + # TODO: + # Option one: Calculate the lambdas 4 times each time step (before each RK stage and in callback) plus one time to init the callback + # 1 In the stepsize callback to get the right time step + # Remove 1, the first time step cannot be calculated and the others are not accurate (with old lambdas) + # 2 In the volume integral (here). + # Remove 2, the first entropy analysis of the analysis_callback doesn't work. + # And we get different result because otherwise the lambdas are only updated once in a RK step. + # -> 4 times per timestep is actually not that bad. (3 times would be optimal) + # Option two: (Right now) Calculate lambdas after each RK stage plus in the init_stepsize_callback. + # Problem: Entropy change at t=0 only works if the stepsize callback is listed before analysis callback (to calculate the lambdas before) + # calc_lambda!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + # Calculate bar states + @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + # Calculate boundaries + @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + @threaded for element in eachelement(dg, cache) subcell_limiting_kernel!(du, u, element, mesh, nonconservative_terms, equations, @@ -575,6 +610,60 @@ end return nothing end +@inline function subcell_limiting_kernel!(du, u, + element, mesh::TreeMesh{2}, + nonconservative_terms::Val{false}, equations, + volume_integral, indicator::IndicatorKuzminetal, + dg::DGSEM, cache) + @unpack inverse_weights = dg.basis + @unpack volume_flux_dg, volume_flux_fv = volume_integral + + # high-order DG fluxes + @unpack fhat1_threaded, fhat2_threaded = cache + fhat1 = fhat1_threaded[Threads.threadid()] + fhat2 = fhat2_threaded[Threads.threadid()] + calcflux_fhat!(fhat1, fhat2, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + + # low-order FV fluxes + @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache + fstar1_L = fstar1_L_threaded[Threads.threadid()] + fstar2_L = fstar2_L_threaded[Threads.threadid()] + fstar1_R = fstar1_R_threaded[Threads.threadid()] + fstar2_R = fstar2_R_threaded[Threads.threadid()] + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + + # antidiffusive flux + @unpack antidiffusive_flux1_threaded, antidiffusive_flux2_threaded = cache + antidiffusive_flux1 = antidiffusive_flux1_threaded[Threads.threadid()] + antidiffusive_flux2 = antidiffusive_flux2_threaded[Threads.threadid()] + calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, + u, mesh, nonconservative_terms, equations, volume_integral, indicator, dg, element, cache) + + # limited antidiffusive flux + calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, + u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D + + if indicator.Plotting + calc_limiting_factor!(antidiffusive_flux1_limited, antidiffusive_flux2_limited, + antidiffusive_flux1, antidiffusive_flux2, equations, indicator, dg, element, cache) + end + + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j]) + + du[v, i, j, element] += inverse_weights[i] * (antidiffusive_flux1_limited[v, i+1, j, element] - antidiffusive_flux1_limited[v, i, j, element]) + + inverse_weights[j] * (antidiffusive_flux2_limited[v, i, j+1, element] - antidiffusive_flux2_limited[v, i, j, element]) + end + end + + return nothing +end + # calcflux_fhat!(fhat1, fhat2, u, mesh, # nonconservative_terms, equations, volume_flux_dg, dg, element, cache) @@ -653,6 +742,8 @@ end return nothing end +# TODO: For IndicatorIDP the antidiffusive flux is saved bacause it's needed in the antidifussive stage. For IndicatorKuzminetal not. +# Possible to use the same function? @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) @@ -676,6 +767,367 @@ end return nothing end +@inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, volume_integral, indicator::IndicatorKuzminetal, + dg, element, cache) + + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j] = fhat1[v, i, j] - fstar1[v, i, j] + antidiffusive_flux2[v, i, j] = fhat2[v, i, j] - fstar2[v, i, j] + end + end + + antidiffusive_flux1[:, 1, :] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, ] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1] .= zero(eltype(antidiffusive_flux2)) + + return nothing +end + +@inline function calc_bar_states!(u, mesh, + nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) + + return nothing +end + +@inline function calc_bar_states!(u, mesh, + nonconservative_terms, equations, indicator::IndicatorKuzminetal, dg, cache) + @unpack lambda1, lambda2, bar_states1, bar_states2 = cache.ContainerMCL2D + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + + flux1 = flux(u_node, 1, equations) + flux1_im1 = flux(u_node_im1, 1, equations) + + for v in eachvariable(equations) + bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] + end + end + bar_states1[:, 1, :, element] .= zero(eltype(bar_states1)) + bar_states1[:, nnodes(dg)+1, :, element] .= zero(eltype(bar_states1)) + + for j in 2:nnodes(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j , element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + + flux2 = flux(u_node, 2, equations) + flux2_jm1 = flux(u_node_jm1, 2, equations) + + for v in eachvariable(equations) + bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] + end + end + bar_states2[:, :, 1, element] .= zero(eltype(bar_states2)) + bar_states2[:, :, nnodes(dg)+1, element] .= zero(eltype(bar_states2)) + end + + return nothing +end + +@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) + + return nothing +end + +@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorKuzminetal, dg, cache) + @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2 = cache.ContainerMCL2D + + # Note: Bar states and lambdas at the interfaces are not needed anywhere else. Calculate here without saving. + + # Density + var_min = var_bounds[1] + var_max = var_bounds[2] + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state = bar_states1[1, i, j, element] + var_min[i-1, j, element] = min(var_min[i-1, j, element], bar_state) + var_max[i-1, j, element] = max(var_max[i-1, j, element], bar_state) + var_min[i , j, element] = min(var_min[i , j, element], bar_state) + var_max[i , j, element] = max(var_max[i , j, element], bar_state) + end + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state = bar_states2[1, i, j, element] + var_min[i, j-1, element] = min(var_min[i, j-1, element], bar_state) + var_max[i, j-1, element] = max(var_max[i, j-1, element], bar_state) + var_min[i, j , element] = min(var_min[i, j, element], bar_state) + var_max[i, j , element] = max(var_max[i, j, element], bar_state) + end + end + + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + + u_left = get_node_vars(u, equations, dg, index_left...) + u_right = get_node_vars(u, equations, dg, index_right...) + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + bar_state = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_left[1] - flux_right[1]) / lambda + + var_min[index_left...] = min(var_min[index_left...], bar_state) + var_max[index_left...] = max(var_max[index_left...], bar_state) + var_min[index_right...] = min(var_min[index_right...], bar_state) + var_max[index_right...] = max(var_max[index_right...], bar_state) + end + end + + # Other primitive variables phi with conservative variable rho * phi + @threaded for element in eachelement(dg, cache) + for v in 2:nvariables(equations) + var_min = var_bounds[2*(v-1)+1] + var_max = var_bounds[2*v] + + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state = bar_states1[v, i, j, element] / bar_states1[1, i, j, element] + var_min[i-1, j, element] = min(var_min[i-1, j, element], bar_state) + var_max[i-1, j, element] = max(var_max[i-1, j, element], bar_state) + var_min[i , j, element] = min(var_min[i , j, element], bar_state) + var_max[i , j, element] = max(var_max[i , j, element], bar_state) + end + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state = bar_states2[v, i, j, element] / bar_states2[1, i, j, element] + var_min[i, j-1, element] = min(var_min[i, j-1, element], bar_state) + var_max[i, j-1, element] = max(var_max[i, j-1, element], bar_state) + var_min[i, j , element] = min(var_min[i, j, element], bar_state) + var_max[i, j , element] = max(var_max[i, j, element], bar_state) + end + end + end + + # Loop over interfaces + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + + u_left = get_node_vars(u, equations, dg, index_left...) + u_right = get_node_vars(u, equations, dg, index_right...) + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + bar_state_rho = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_left[1] - flux_right[1]) / lambda + + for v in 2:nvariables(equations) + var_min = var_bounds[2*(v-1)+1] + var_max = var_bounds[2*v] + bar_state = 0.5 * (u_left[v] + u_right[v]) - 0.5 * (flux_left[v] - flux_right[v]) / lambda + bar_state = bar_state / bar_state_rho + + var_min[index_left...] = min(var_min[index_left...], bar_state) + var_max[index_left...] = max(var_max[index_left...], bar_state) + var_min[index_right...] = min(var_min[index_right...], bar_state) + var_max[index_right...] = max(var_max[index_right...], bar_state) + end + end + end + + return nothing +end + +@inline function calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, + u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D + @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack lambda1, lambda2, bar_states1, bar_states2 = cache.ContainerMCL2D + + # Limit density + rho_min = var_bounds[1] + rho_max = var_bounds[2] + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state = bar_states1[1, i, j, element] + if antidiffusive_flux1[1, i, j] > 0 + antidiffusive_flux1_limited[1, i, j, element] = min(antidiffusive_flux1[1, i, j], + lambda1[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i-1, j, element])) + else + antidiffusive_flux1_limited[1, i, j, element] = max(antidiffusive_flux1[1, i, j], + lambda1[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i-1, j, element])) + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state = bar_states2[1, i, j, element] + if antidiffusive_flux2[1, i, j] > 0 + antidiffusive_flux2_limited[1, i, j, element] = min(antidiffusive_flux2[1, i, j], + lambda2[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i, j-1, element])) + else + antidiffusive_flux2_limited[1, i, j, element] = max(antidiffusive_flux2[1, i, j], + lambda2[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i, j-1, element])) + end + end + + # Limit velocity and total energy + for v in 2:nvariables(equations) + var_min = var_bounds[2*(v-1)+1] + var_max = var_bounds[2*v] + + for j in eachnode(dg), i in 2:nnodes(dg) + # Note: To make sure that the local bounds of both adjacent nodes (i-1, j), (i, j) are fulfilled, + # use different limited density and maximum/minimum values. + lambda = lambda1[i, j, element] + rho_limited_i = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda# TODO BB: use limited bar state + rho_limited_im1 = bar_states1[1, i, j, element] - antidiffusive_flux1_limited[1, i, j, element] / lambda + + phi = bar_states1[v, i, j, element] / bar_states1[1, i, j, element] + + antidiffusive_flux1_limited[v, i, j, element] = lambda * (rho_limited_i * phi - bar_states1[v, i, j, element]) + + g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] + + g_max = lambda * min(rho_limited_i * (var_max[i, j, element] - phi), + rho_limited_im1 * (phi - var_min[i-1, j, element])) + g_min = lambda * max(rho_limited_i * (var_min[i, j, element] - phi), + rho_limited_im1 * (phi - var_max[i-1, j, element])) + + if g > 0 + g_limited = min(g_max, max(g, g_min)) + else + g_limited = max(g_min, min(g, g_max)) + end + antidiffusive_flux1_limited[v, i, j, element] += g_limited + end + + + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + rho_limited_j = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda + rho_limited_jm1 = bar_states2[1, i, j, element] - antidiffusive_flux2_limited[1, i, j, element] / lambda + + phi = bar_states2[v, i, j, element] / bar_states2[1, i, j, element] + + antidiffusive_flux2_limited[v, i, j, element] = lambda * (rho_limited_j * phi - bar_states2[v, i, j, element]) + + g = antidiffusive_flux2[v, i, j] - antidiffusive_flux2_limited[v, i, j, element] + + g_max = lambda * min(rho_limited_j * (var_max[i, j, element] - phi), + rho_limited_jm1 * (phi - var_min[i, j-1, element])) + g_min = lambda * max(rho_limited_j * (var_min[i, j, element] - phi), + rho_limited_jm1 * (phi - var_max[i, j-1, element])) + + if g > 0 + g_limited = min(g_max, max(g, g_min)) + else + g_limited = max(g_min, min(g, g_max)) + end + antidiffusive_flux2_limited[v, i, j, element] += g_limited + end + end + + # Limit pressure + if indicator.IDPPressureTVD + for j in eachnode(dg), i in 2:nnodes(dg) + Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - + 0.5 * (bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2)) + R_max = lambda1[i, j, element] * sqrt(bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2) * + sqrt(antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) + + abs(lambda1[i, j, element] * bar_states1[1, i, j, element] * antidiffusive_flux1_limited[4, i, j, element]) + + abs(lambda1[i, j, element] * bar_states1[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + + max(0, 0.5 * (antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) - + antidiffusive_flux1_limited[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + + if R_max > Q + for v in eachvariable(equations) + antidiffusive_flux1_limited[v, i, j, element] *= Q / R_max + end + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - + 0.5 * (bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2)) + R_max = lambda2[i, j, element] * sqrt(bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2) * + sqrt(antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) + + abs(lambda2[i, j, element] * bar_states2[1, i, j, element] * antidiffusive_flux2_limited[4, i, j, element]) + + abs(lambda2[i, j, element] * bar_states2[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + + max(0, 0.5 * (antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) - + antidiffusive_flux2_limited[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + + if R_max > Q + for v in eachvariable(equations) + antidiffusive_flux2_limited[v, i, j, element] *= Q / R_max + end + end + end + end + + antidiffusive_flux1_limited[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_limited)) + antidiffusive_flux1_limited[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1_limited)) + + antidiffusive_flux2_limited[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_limited)) + antidiffusive_flux2_limited[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2_limited)) + + return nothing +end + +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorIDP) + + return nothing +end + +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorKuzminetal, ) + @unpack lambda1, lambda2 = cache.ContainerMCL2D + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) + end + lambda1[1, :, element] .= zero(eltype(lambda1)) + lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) + + for j in 2:nnodes(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) + end + lambda2[:, 1, element] .= zero(eltype(lambda2)) + lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + end + + return nothing +end + @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack inverse_weights = solver.basis @@ -708,6 +1160,11 @@ end return nothing end +@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorKuzminetal) + + return nothing +end + # 2d, IndicatorIDP @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) @@ -757,6 +1214,109 @@ end return nothing end +# 2d, IndicatorKuzminetal +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorKuzminetal) + + # @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator + @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache + @unpack bar_states1, bar_states2, antidiffusive_flux1_limited, antidiffusive_flux2_limited, lambda1, lambda2 = cache.ContainerMCL2D + + # Density + bound_min = var_bounds[1] + bound_max = var_bounds[2] + @threaded for element in eachelement(solver, cache) + left_error = zero(eltype(u)) + right_error = zero(eltype(u)) + idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] + for j in eachnode(solver), i in eachnode(solver) + var_min = bound_min[i, j, element] + var_max = bound_max[i, j, element] + + # TODO BB: use limited bar states instead of formula + # -x + if i>1 + var_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] + left_error = max(left_error, var_min - var_limited) + right_error = max(right_error, var_limited - var_max) + end + # +x + if i1 + var_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] + left_error = max(left_error, var_min - var_limited) + right_error = max(right_error, var_limited - var_max) + end + # +y + if j1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1_limited[v, i, j, element] / lambda1[i, j, element] + err_lower_bound = max(err_lower_bound, rho_limited * var_min - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max) + end + # +x + if i1 + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] / lambda2[i, j, element] + err_lower_bound = max(err_lower_bound, rho_limited * var_min - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max) + end + # +y + if j Date: Tue, 21 Jun 2022 15:02:36 +0200 Subject: [PATCH 049/423] Remove plotting variable --- src/solvers/dgsem_tree/indicators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 314039b0fb..df9ebfee74 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -246,7 +246,7 @@ function IndicatorKuzminetal(equations::AbstractEquations, basis; Plotting=false) cache = create_cache(IndicatorKuzminetal, equations, basis, 2*nvariables(equations)) - IndicatorKuzminetal{typeof(cache)}(cache, IDPPressureTVD, IDPCheckBounds, Plotting) + IndicatorKuzminetal{typeof(cache)}(cache, IDPPressureTVD, IDPCheckBounds) end function Base.show(io::IO, indicator::IndicatorKuzminetal) From 92e789587086b117dcf802202461799d44eb23eb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 21 Jun 2022 15:03:23 +0200 Subject: [PATCH 050/423] Remove plotting variable again --- src/solvers/dgsem_tree/indicators.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index df9ebfee74..7be42255f5 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -242,8 +242,7 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorKuzminetal(equations::AbstractEquations, basis; IDPPressureTVD=true, - IDPCheckBounds=false, - Plotting=false) + IDPCheckBounds=false) cache = create_cache(IndicatorKuzminetal, equations, basis, 2*nvariables(equations)) IndicatorKuzminetal{typeof(cache)}(cache, IDPPressureTVD, IDPCheckBounds) From ac32befdda6a8a4b06233689e70599bd94d4f22a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 22 Jun 2022 14:17:07 +0200 Subject: [PATCH 051/423] Update calculation of lambda, unpack indicator --- ...ir_euler_blast_wave_monolithic_limiting.jl | 6 ++-- src/callbacks_step/stepsize.jl | 6 ++-- src/solvers/dgsem_tree/dg.jl | 10 ------ src/solvers/dgsem_tree/dg_2d.jl | 20 +++-------- src/solvers/dgsem_tree/indicators_2d.jl | 2 +- src/time_integration/methods_SSP.jl | 33 +++++++++---------- 6 files changed, 28 insertions(+), 49 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl index af82ef8331..98de6abf2f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl @@ -58,7 +58,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 2.0) +tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -68,12 +68,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=20, +save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.2) +stepsize_callback = StepsizeCallback(cfl=0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 953e1e59bf..8637089722 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -79,10 +79,10 @@ end have_constant_speed(equations), equations, solver, cache) elseif a==2 + # TODO Maybe it's possible to remove one calculation of the lambda (see volume integral) @unpack inverse_weights = solver.basis - # if t == 0.0 - calc_lambda!(u_ode, semi)#, mesh, equations, solver.volume_integral.indicator, solver, cache) - # end + u = wrap_array(u_ode, mesh, equations, solver, cache) + calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) @unpack lambda1, lambda2 = cache.ContainerMCL2D maxdt = typemax(eltype(u_ode)) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 388a3f3f5e..9d3b1aa593 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -39,16 +39,6 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end -@inline function calc_lambda!(u_ode, semi) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - u = wrap_array(u_ode, mesh, equations, solver, cache) - - calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) - - return nothing -end - - @inline function IDP_checkBounds(u_ode, semi) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4145fa7d35..52d92e00de 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -543,16 +543,16 @@ function calc_volume_integral!(du, u, dg::DGSEM, cache) # Calculate maximum wave speeds lambda # TODO: - # Option one: Calculate the lambdas 4 times each time step (before each RK stage and in callback) plus one time to init the callback + # Option one: (Right now) Calculate the lambdas 4 times each time step (before each RK stage and in callback) plus one time to init the callback # 1 In the stepsize callback to get the right time step # Remove 1, the first time step cannot be calculated and the others are not accurate (with old lambdas) # 2 In the volume integral (here). # Remove 2, the first entropy analysis of the analysis_callback doesn't work. # And we get different result because otherwise the lambdas are only updated once in a RK step. # -> 4 times per timestep is actually not that bad. (3 times would be optimal) - # Option two: (Right now) Calculate lambdas after each RK stage plus in the init_stepsize_callback. + # Option two: Calculate lambdas after each RK stage plus in the init_stepsize_callback. # Problem: Entropy change at t=0 only works if the stepsize callback is listed before analysis callback (to calculate the lambdas before) - # calc_lambda!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, volume_integral.indicator) # Calculate bar states @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) # Calculate boundaries @@ -644,13 +644,8 @@ end # limited antidiffusive flux calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) - @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D - - if indicator.Plotting - calc_limiting_factor!(antidiffusive_flux1_limited, antidiffusive_flux2_limited, - antidiffusive_flux1, antidiffusive_flux2, equations, indicator, dg, element, cache) - end + @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + @@ -1099,12 +1094,7 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorIDP) - - return nothing -end - -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorKuzminetal, ) +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorKuzminetal) @unpack lambda1, lambda2 = cache.ContainerMCL2D @threaded for element in eachelement(dg, cache) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 22aed985cd..aa0b82afeb 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -210,7 +210,7 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab dt, cache; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator - alpha .= 0.0 + alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. indicator_IDP.IDPDensityTVD && @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index d2b5f5c10d..d979bc17d1 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -123,6 +123,7 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, end function solve!(integrator::SimpleIntegratorSSP) + @unpack indicator = integrator.p.solver.volume_integral @unpack prob = integrator.sol @unpack alg = integrator t_end = last(prob.tspan) @@ -149,14 +150,12 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, integrator.p.solver.volume_integral.indicator) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) # Check that we are within bounds - if integrator.p.solver.volume_integral.indicator.IDPCheckBounds + if indicator.IDPCheckBounds @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) end - - @trixi_timeit timer() "calc_lambda!" calc_lambda!(integrator.u_safe, integrator.p) end @. integrator.u = integrator.u_safe @@ -169,18 +168,19 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. - if integrator.iter == length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) - new_length = length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) + 200 - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, new_length) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, new_length) + if integrator.iter == length(indicator.cache.alpha_max_per_timestep) + new_length = length(indicator.cache.alpha_max_per_timestep) + 200 + resize!(indicator.cache.alpha_max_per_timestep, new_length) + resize!(indicator.cache.alpha_mean_per_timestep, new_length) end - if integrator.p.solver.volume_integral.indicator isa IndicatorIDP - integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) - integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = + # TODO BB: Move this calculation to the for loop to get the mean and maximum of all alpha in that timestep (not only of the last RK stage)? + if indicator isa IndicatorIDP || (indicator isa IndicatorKuzminetal && indicator.Plotting) + indicator.cache.alpha_max_per_timestep[integrator.iter+1] = + maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) + indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = (1/(nnodes(integrator.p.solver)^ndims(integrator.p.equations) * nelements(integrator.p.solver, integrator.p.cache))) * - sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) + sum(indicator.cache.ContainerShockCapturingIndicator.alpha) end integrator.iter += 1 @@ -203,13 +203,12 @@ function solve!(integrator::SimpleIntegratorSSP) end # Check that we are within bounds - if integrator.p.solver.volume_integral.indicator.IDPCheckBounds - summary_check_bounds(integrator.p.solver.volume_integral.indicator) + if indicator.IDPCheckBounds + summary_check_bounds(indicator) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), - (prob.u0, integrator.u), - integrator.sol.prob) + (prob.u0, integrator.u), prob) end # get a cache where the RHS can be stored From 2bfd8b0876869de0d1dc0c6e06a550eb2e535fb6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 22 Jun 2022 14:19:13 +0200 Subject: [PATCH 052/423] Remove Plotting variable --- ...r_euler_kelvin_helmholtz_instability_monolithic_limiting.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl index b10d064cf4..8299ade24a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl @@ -38,8 +38,7 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorKuzminetal(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true, - Plotting=true) + IDPPressureTVD=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) From f4caaa3fd1aa59ae29e8bb45559cdd47f194fc42 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Jun 2022 11:00:18 +0200 Subject: [PATCH 053/423] Add notes and unpack indicator --- src/solvers/dgsem_tree/indicators_2d.jl | 2 +- src/time_integration/methods_SSP.jl | 32 +++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index fc508c5d5a..6574d1d63e 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -210,7 +210,7 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab dt, cache; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator - alpha .= 0.0 + alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. indicator_IDP.IDPDensityTVD && @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 7e53370360..fd98197e10 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -123,6 +123,7 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, end function solve!(integrator::SimpleIntegratorSSP) + @unpack indicator = integrator.p.solver.volume_integral @unpack prob = integrator.sol @unpack alg = integrator t_end = last(prob.tspan) @@ -149,11 +150,12 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, integrator.p.solver.volume_integral.indicator) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) # Check that we are within bounds - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) - + if indicator.IDPCheckBounds + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) + end end @. integrator.u = integrator.u_safe @@ -166,17 +168,18 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. - if integrator.iter == length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) - new_length = length(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep) + 200 - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, new_length) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, new_length) + if integrator.iter == length(indicator.cache.alpha_max_per_timestep) + new_length = length(indicator.cache.alpha_max_per_timestep) + 200 + resize!(indicator.cache.alpha_max_per_timestep, new_length) + resize!(indicator.cache.alpha_mean_per_timestep, new_length) end - integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) - integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = + # TODO BB: Move this calculation to the for loop to get the mean and maximum of all alpha in that timestep (not only of the last RK stage)? + indicator.cache.alpha_max_per_timestep[integrator.iter+1] = + maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) + indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = (1/(nnodes(integrator.p.solver)^ndims(integrator.p.equations) * nelements(integrator.p.solver, integrator.p.cache))) * - sum(integrator.p.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator.alpha) + sum(indicator.cache.ContainerShockCapturingIndicator.alpha) integrator.iter += 1 integrator.t += integrator.dt @@ -198,13 +201,12 @@ function solve!(integrator::SimpleIntegratorSSP) end # Check that we are within bounds - if integrator.p.solver.volume_integral.indicator.IDPCheckBounds - summary_check_bounds(integrator.p.solver.volume_integral.indicator) + if indicator.IDPCheckBounds + summary_check_bounds(indicator) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), - (prob.u0, integrator.u), - integrator.sol.prob) + (prob.u0, integrator.u), prob) end # get a cache where the RHS can be stored From c9c102d44106402ace27956857c959053dca29d6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Jun 2022 12:01:15 +0200 Subject: [PATCH 054/423] Update stepsize calculation --- src/callbacks_step/stepsize.jl | 44 +++++++++++++++------------------ src/solvers/dgsem_tree/dg_2d.jl | 10 +++++--- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 8637089722..5eb5fac57d 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -73,33 +73,29 @@ end u = wrap_array(u_ode, mesh, equations, solver, cache) # TODO BB: Fix the implementation of the second CFL condition. - a=2 - if a==1 - dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, - have_constant_speed(equations), equations, - solver, cache) - elseif a==2 - # TODO Maybe it's possible to remove one calculation of the lambda (see volume integral) - @unpack inverse_weights = solver.basis - u = wrap_array(u_ode, mesh, equations, solver, cache) - calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) - @unpack lambda1, lambda2 = cache.ContainerMCL2D - - maxdt = typemax(eltype(u_ode)) - for element in eachelement(solver, cache) - J = 1 / cache.elements.inverse_jacobian[element] - - for j in eachnode(solver), i in eachnode(solver) - denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + - inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) - maxdt = min(maxdt, J / denom) + if solver.volume_integral isa VolumeIntegralShockCapturingSubcell && solver.volume_integral.indicator isa IndicatorKuzminetal + # TODO Maybe it's possible to remove one calculation of the lambda (see volume integral) + @unpack inverse_weights = solver.basis + u = wrap_array(u_ode, mesh, equations, solver, cache) + calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) + @unpack lambda1, lambda2 = cache.ContainerMCL2D + + maxdt = typemax(eltype(u_ode)) + for element in eachelement(solver, cache) + J = 1 / cache.elements.inverse_jacobian[element] + + for j in eachnode(solver), i in eachnode(solver) + denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + + inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) + maxdt = min(maxdt, J / denom) + end end - end - dt = @trixi_timeit timer() "calculate dt" cfl_number * maxdt - # dt = 1e-4 + dt = @trixi_timeit timer() "calculate dt" cfl_number * maxdt else - dt = 1e-4 + dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, + have_constant_speed(equations), equations, + solver, cache) end set_proposed_dt!(integrator, dt) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 52d92e00de..46456272b3 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -782,8 +782,7 @@ end return nothing end -@inline function calc_bar_states!(u, mesh, - nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) +@inline function calc_bar_states!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) return nothing end @@ -825,7 +824,7 @@ end return nothing end -@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) +@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) return nothing end @@ -1094,6 +1093,11 @@ end return nothing end +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator) + + return nothing +end + @inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorKuzminetal) @unpack lambda1, lambda2 = cache.ContainerMCL2D From b0239dd419534afd5120b80b9346dca0d492e236 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Jun 2022 14:20:18 +0200 Subject: [PATCH 055/423] Rename files and add astro jet --- .../elixir_euler_astro_jet_MCL.jl | 97 +++++++++++++++++++ .../elixir_euler_astro_jet_MCL_restart.jl | 37 +++++++ ...ting.jl => elixir_euler_blast_wave_MCL.jl} | 3 +- ...euler_kelvin_helmholtz_instability_MCL.jl} | 5 +- ....jl => elixir_euler_shockcapturing_MCL.jl} | 3 +- 5 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl rename examples/tree_2d_dgsem/{elixir_euler_blast_wave_monolithic_limiting.jl => elixir_euler_blast_wave_MCL.jl} (96%) rename examples/tree_2d_dgsem/{elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl => elixir_euler_kelvin_helmholtz_instability_MCL.jl} (96%) rename examples/tree_2d_dgsem/{elixir_euler_shockcapturing_monolithic_limiting.jl => elixir_euler_shockcapturing_MCL.jl} (95%) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl new file mode 100644 index 0000000000..3781744748 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -0,0 +1,97 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 5/3 +equations = CompressibleEulerEquations2D(gamma) + +# Initial condition adopted from +# - Yong Liu, Jianfang Lu, and Chi-Wang Shu +# An oscillation free discontinuous Galerkin method for hyperbolic systems +# https://tinyurl.com/c76fjtx4 +# Mach = 2000 jet +function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) + @unpack gamma = equations + rho = 0.5 + v1 = 0 + v2 = 0 + p = 0.4127 + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_astro_jet + +boundary_conditions = ( + x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), + x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), + y_neg=boundary_condition_periodic, + y_pos=boundary_condition_periodic, + ) + +surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) +volume_flux = flux_ranocha # works with Chandrashekar flux as well +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +# shock capturing necessary for this tough example +indicator_sc = IndicatorKuzminetal(equations, basis; + IDPCheckBounds=true, + IDPPressureTVD=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-0.5, -0.5) +coordinates_max = ( 0.5, 0.5) + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + periodicity=(false,true), + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.5e-6) # simulation with end time T=0.001 in the restart file +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +# The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted +save_restart = SaveRestartCallback(interval=5000, + save_final_restart=true) + +save_solution = SaveSolutionCallback(interval=5000, + save_initial_solution=true, + save_final_solution=false, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.1) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_restart, save_solution, + stepsize_callback) + +############################################################################### +# run the simulation +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl new file mode 100644 index 0000000000..c9a9f89fe4 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl @@ -0,0 +1,37 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# create a restart file + +trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_MCL.jl")) + +############################################################################### +# adapt the parameters that have changed compared to "elixir_euler_astro_jet_subcell.jl" + +restart_filename = joinpath("out", "restart_000001.h5") +mesh = load_mesh(restart_filename) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + +tspan = (load_time(restart_filename), 0.001) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=false, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.8) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) +############################################################################### +# run the simulation +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl similarity index 96% rename from examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl rename to examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 98de6abf2f..32c5264dd2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_monolithic_limiting.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,7 +39,8 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true) + IDPCheckBounds=true, + Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl similarity index 96% rename from examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl rename to examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 8299ade24a..756fbfb3df 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_monolithic_limiting.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -38,7 +38,8 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorKuzminetal(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true) + IDPPressureTVD=true, + Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -53,7 +54,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.1) +tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl similarity index 95% rename from examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl rename to examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl index 916ed9ae73..0d1feeb191 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_monolithic_limiting.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl @@ -13,7 +13,8 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true) + IDPCheckBounds=true, + Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) From aa4111488b46c36fde7cee664428e9e11ba7f7b9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 24 Jun 2022 11:20:12 +0200 Subject: [PATCH 056/423] Remove remaining plotting features --- examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl | 3 +-- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 3 +-- .../elixir_euler_kelvin_helmholtz_instability_MCL.jl | 3 +-- examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl | 3 +-- src/time_integration/methods_SSP.jl | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 3781744748..be227ecdd0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -45,8 +45,7 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorKuzminetal(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true, - Plotting=true) + IDPPressureTVD=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 32c5264dd2..98de6abf2f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,8 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true, - Plotting=true) + IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 756fbfb3df..aef1c48245 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -38,8 +38,7 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorKuzminetal(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true, - Plotting=true) + IDPPressureTVD=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl index 0d1feeb191..916ed9ae73 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl @@ -13,8 +13,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true, - Plotting=true) + IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index d979bc17d1..bca6f88922 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -175,7 +175,7 @@ function solve!(integrator::SimpleIntegratorSSP) end # TODO BB: Move this calculation to the for loop to get the mean and maximum of all alpha in that timestep (not only of the last RK stage)? - if indicator isa IndicatorIDP || (indicator isa IndicatorKuzminetal && indicator.Plotting) + if indicator isa IndicatorIDP indicator.cache.alpha_max_per_timestep[integrator.iter+1] = maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = From f9d2fb6ce7d79cc202173014789acb7be23e7e58 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 24 Jun 2022 19:23:23 +0200 Subject: [PATCH 057/423] Accelerate volume integral --- .../elixir_euler_astro_jet_MCL_restart.jl | 2 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 92 ++++++++++--------- 3 files changed, 49 insertions(+), 47 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl index c9a9f89fe4..2ece4cbd98 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl @@ -8,7 +8,7 @@ using Trixi trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_MCL.jl")) ############################################################################### -# adapt the parameters that have changed compared to "elixir_euler_astro_jet_subcell.jl" +# adapt the parameters that have changed compared to "elixir_euler_astro_jet_MCL.jl" restart_filename = joinpath("out", "restart_000001.h5") mesh = load_mesh(restart_filename) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index aef1c48245..8af7c7c5d1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -68,7 +68,7 @@ save_solution = SaveSolutionCallback(interval=50, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, stepsize_callback, diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 46456272b3..ddf38fd4ed 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -742,23 +742,23 @@ end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) - for j in eachnode(dg), i in eachnode(dg) + for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] end end - - for i in eachnode(dg) + for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, 1, i, element] = zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[v, nnodes(dg)+1, i, element] = zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[v, i, 1, element] = zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[v, i, nnodes(dg)+1, element] = zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] end end + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) + return nothing end @@ -766,9 +766,13 @@ end nonconservative_terms, equations, volume_integral, indicator::IndicatorKuzminetal, dg, element, cache) - for j in eachnode(dg), i in eachnode(dg) + for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) antidiffusive_flux1[v, i, j] = fhat1[v, i, j] - fstar1[v, i, j] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) antidiffusive_flux2[v, i, j] = fhat2[v, i, j] - fstar2[v, i, j] end end @@ -803,8 +807,8 @@ end bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] end end - bar_states1[:, 1, :, element] .= zero(eltype(bar_states1)) - bar_states1[:, nnodes(dg)+1, :, element] .= zero(eltype(bar_states1)) + # bar_states1[:, 1, :, element] .= zero(eltype(bar_states1)) + # bar_states1[:, nnodes(dg)+1, :, element] .= zero(eltype(bar_states1)) for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j , element) @@ -817,8 +821,8 @@ end bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] end end - bar_states2[:, :, 1, element] .= zero(eltype(bar_states2)) - bar_states2[:, :, nnodes(dg)+1, element] .= zero(eltype(bar_states2)) + # bar_states2[:, :, 1, element] .= zero(eltype(bar_states2)) + # bar_states2[:, :, nnodes(dg)+1, element] .= zero(eltype(bar_states2)) end return nothing @@ -890,7 +894,7 @@ end end end - # Other primitive variables phi with conservative variable rho * phi + # Other variables phi @threaded for element in eachelement(dg, cache) for v in 2:nvariables(equations) var_min = var_bounds[2*(v-1)+1] @@ -916,7 +920,6 @@ end end end - # Loop over interfaces for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] @@ -940,12 +943,12 @@ end flux_right = flux(u_right, orientation, equations) lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - bar_state_rho = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_left[1] - flux_right[1]) / lambda + bar_state_rho = (u_left[1] + u_right[1]) - (flux_right[1] - flux_left[1]) / lambda # 2 * bar_state_rho for v in 2:nvariables(equations) var_min = var_bounds[2*(v-1)+1] var_max = var_bounds[2*v] - bar_state = 0.5 * (u_left[v] + u_right[v]) - 0.5 * (flux_left[v] - flux_right[v]) / lambda + bar_state = (u_left[v] + u_right[v]) - (flux_right[v] - flux_left[v]) / lambda # 2 * bar_state bar_state = bar_state / bar_state_rho var_min[index_left...] = min(var_min[index_left...], bar_state) @@ -999,19 +1002,19 @@ end # Note: To make sure that the local bounds of both adjacent nodes (i-1, j), (i, j) are fulfilled, # use different limited density and maximum/minimum values. lambda = lambda1[i, j, element] - rho_limited_i = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda# TODO BB: use limited bar state - rho_limited_im1 = bar_states1[1, i, j, element] - antidiffusive_flux1_limited[1, i, j, element] / lambda + rho_limited_i = lambda * bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] + rho_limited_im1 = lambda * bar_states1[1, i, j, element] - antidiffusive_flux1_limited[1, i, j, element] phi = bar_states1[v, i, j, element] / bar_states1[1, i, j, element] - antidiffusive_flux1_limited[v, i, j, element] = lambda * (rho_limited_i * phi - bar_states1[v, i, j, element]) + antidiffusive_flux1_limited[v, i, j, element] = (rho_limited_i * phi - lambda * bar_states1[v, i, j, element]) g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] - g_max = lambda * min(rho_limited_i * (var_max[i, j, element] - phi), - rho_limited_im1 * (phi - var_min[i-1, j, element])) - g_min = lambda * max(rho_limited_i * (var_min[i, j, element] - phi), - rho_limited_im1 * (phi - var_max[i-1, j, element])) + g_max = min(rho_limited_i * (var_max[i, j, element] - phi), + rho_limited_im1 * (phi - var_min[i-1, j, element])) + g_min = max(rho_limited_i * (var_min[i, j, element] - phi), + rho_limited_im1 * (phi - var_max[i-1, j, element])) if g > 0 g_limited = min(g_max, max(g, g_min)) @@ -1024,19 +1027,19 @@ end for j in 2:nnodes(dg), i in eachnode(dg) lambda = lambda2[i, j, element] - rho_limited_j = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda - rho_limited_jm1 = bar_states2[1, i, j, element] - antidiffusive_flux2_limited[1, i, j, element] / lambda + rho_limited_j = lambda * bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] + rho_limited_jm1 = lambda * bar_states2[1, i, j, element] - antidiffusive_flux2_limited[1, i, j, element] phi = bar_states2[v, i, j, element] / bar_states2[1, i, j, element] - antidiffusive_flux2_limited[v, i, j, element] = lambda * (rho_limited_j * phi - bar_states2[v, i, j, element]) + antidiffusive_flux2_limited[v, i, j, element] = rho_limited_j * phi - lambda * bar_states2[v, i, j, element] g = antidiffusive_flux2[v, i, j] - antidiffusive_flux2_limited[v, i, j, element] - g_max = lambda * min(rho_limited_j * (var_max[i, j, element] - phi), - rho_limited_jm1 * (phi - var_min[i, j-1, element])) - g_min = lambda * max(rho_limited_j * (var_min[i, j, element] - phi), - rho_limited_jm1 * (phi - var_max[i, j-1, element])) + g_max = min(rho_limited_j * (var_max[i, j, element] - phi), + rho_limited_jm1 * (phi - var_min[i, j-1, element])) + g_min = max(rho_limited_j * (var_min[i, j, element] - phi), + rho_limited_jm1 * (phi - var_max[i, j-1, element])) if g > 0 g_limited = min(g_max, max(g, g_min)) @@ -1051,11 +1054,12 @@ end if indicator.IDPPressureTVD for j in eachnode(dg), i in 2:nnodes(dg) Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - - 0.5 * (bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2)) - R_max = lambda1[i, j, element] * sqrt(bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2) * - sqrt(antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) + - abs(lambda1[i, j, element] * bar_states1[1, i, j, element] * antidiffusive_flux1_limited[4, i, j, element]) + - abs(lambda1[i, j, element] * bar_states1[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + + 0.5 * (bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2)) + R_max = sqrt(bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 + + antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) + + abs(bar_states1[1, i, j, element] * antidiffusive_flux1_limited[4, i, j, element]) + + abs(bar_states1[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + R_max = lambda1[i, j, element] * R_max + max(0, 0.5 * (antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) - antidiffusive_flux1_limited[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) @@ -1068,11 +1072,12 @@ end for j in 2:nnodes(dg), i in eachnode(dg) Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - - 0.5 * (bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2)) - R_max = lambda2[i, j, element] * sqrt(bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2) * - sqrt(antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) + - abs(lambda2[i, j, element] * bar_states2[1, i, j, element] * antidiffusive_flux2_limited[4, i, j, element]) + - abs(lambda2[i, j, element] * bar_states2[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + + 0.5 * (bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2)) + R_max = sqrt(bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 + + antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) + + abs(bar_states2[1, i, j, element] * antidiffusive_flux2_limited[4, i, j, element]) + + abs(bar_states2[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + R_max = lambda2[i, j, element] * R_max + max(0, 0.5 * (antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) - antidiffusive_flux2_limited[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) @@ -1227,7 +1232,6 @@ end var_min = bound_min[i, j, element] var_max = bound_max[i, j, element] - # TODO BB: use limited bar states instead of formula # -x if i>1 var_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] @@ -1306,8 +1310,6 @@ end end end - # println([maximum.(idp_bounds_delta_threaded[thread]) for thread in 1:Threads.nthreads()]) - return nothing end From 7d82b42252fc53ad04915a9258191e34c2fca327 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 26 Jun 2022 15:36:08 +0200 Subject: [PATCH 058/423] Delete unnessecary resetting variables --- src/callbacks_step/stepsize.jl | 6 ++- src/solvers/dgsem_tree/dg_2d.jl | 89 +++++++++++++++++---------------- 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 5eb5fac57d..ee6bc98f1c 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -85,8 +85,10 @@ end J = 1 / cache.elements.inverse_jacobian[element] for j in eachnode(solver), i in eachnode(solver) - denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + - inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) + denom = inverse_weights[i] * ((i > 1 ? lambda1[i, j, element] : 0) + + (i < nnodes(solver) ? lambda1[i+1, j, element] : 0)) + + inverse_weights[j] * ((j > 1 ? lambda2[i, j, element] : 0) + + (j < nnodes(solver) ? lambda2[i, j+1, element] : 0)) maxdt = min(maxdt, J / denom) end end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ddf38fd4ed..5a4b785b39 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -107,7 +107,6 @@ end function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorKuzminetal, dg::DG, uEltype) ContainerMCL2D = Trixi.ContainerMCL2D{uEltype}(0, nvariables(equations), nnodes(dg)) - # n_limiters = length(indicator.variables) A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -115,12 +114,8 @@ function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorKuzm antidiffusive_flux1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] antidiffusive_flux2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - # antidiffusive_flux1_limited_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] - # antidiffusive_flux2_limited_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - return (; cache..., ContainerMCL2D, - antidiffusive_flux1_threaded, antidiffusive_flux2_threaded,) - # antidiffusive_flux1_limited_threaded, antidiffusive_flux2_limited_threaded) + antidiffusive_flux1_threaded, antidiffusive_flux2_threaded) end @@ -777,11 +772,11 @@ end end end - antidiffusive_flux1[:, 1, :] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg)+1, :] .= zero(eltype(antidiffusive_flux1)) + # antidiffusive_flux1[:, 1, :] .= zero(eltype(antidiffusive_flux1)) + # antidiffusive_flux1[:, nnodes(dg)+1, :] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux2[:, :, 1, ] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg)+1] .= zero(eltype(antidiffusive_flux2)) + # antidiffusive_flux2[:, :, 1, ] .= zero(eltype(antidiffusive_flux2)) + # antidiffusive_flux2[:, :, nnodes(dg)+1] .= zero(eltype(antidiffusive_flux2)) return nothing end @@ -972,25 +967,43 @@ end rho_min = var_bounds[1] rho_max = var_bounds[2] for j in eachnode(dg), i in 2:nnodes(dg) - bar_state = bar_states1[1, i, j, element] - if antidiffusive_flux1[1, i, j] > 0 - antidiffusive_flux1_limited[1, i, j, element] = min(antidiffusive_flux1[1, i, j], - lambda1[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i-1, j, element])) - else - antidiffusive_flux1_limited[1, i, j, element] = max(antidiffusive_flux1[1, i, j], - lambda1[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i-1, j, element])) - end + # bar_state = bar_states1[1, i, j, element] + # if antidiffusive_flux1[1, i, j] > 0 + # antidiffusive_flux1_limited[1, i, j, element] = min(antidiffusive_flux1[1, i, j], + # lambda1[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i-1, j, element])) + # else + # antidiffusive_flux1_limited[1, i, j, element] = max(antidiffusive_flux1[1, i, j], + # lambda1[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i-1, j, element])) + # end + + # alternative density limiting + lambda = lambda1[i, j, element] + bar_state = lambda * bar_states1[1, i, j, element] + f_min = max(lambda * rho_min[i, j, element] - bar_state, + bar_state - lambda * rho_max[i-1, j, element]) + f_max = min(lambda * rho_max[i, j, element] - bar_state, + bar_state - lambda * rho_min[i-1, j, element]) + antidiffusive_flux1_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux1[1, i, j], f_max)) end for j in 2:nnodes(dg), i in eachnode(dg) - bar_state = bar_states2[1, i, j, element] - if antidiffusive_flux2[1, i, j] > 0 - antidiffusive_flux2_limited[1, i, j, element] = min(antidiffusive_flux2[1, i, j], - lambda2[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i, j-1, element])) - else - antidiffusive_flux2_limited[1, i, j, element] = max(antidiffusive_flux2[1, i, j], - lambda2[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i, j-1, element])) - end + # bar_state = bar_states2[1, i, j, element] + # if antidiffusive_flux2[1, i, j] > 0 + # antidiffusive_flux2_limited[1, i, j, element] = min(antidiffusive_flux2[1, i, j], + # lambda2[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i, j-1, element])) + # else + # antidiffusive_flux2_limited[1, i, j, element] = max(antidiffusive_flux2[1, i, j], + # lambda2[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i, j-1, element])) + # end + + # alternative density limiting + lambda = lambda2[i, j, element] + bar_state = lambda * bar_states2[1, i, j, element] + f_min = max(lambda * rho_min[i, j, element] - bar_state, + bar_state - lambda * rho_max[i, j-1, element]) + f_max = min(lambda * rho_max[i, j, element] - bar_state, + bar_state - lambda * rho_min[i, j-1, element]) + antidiffusive_flux2_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux2[1, i, j], f_max)) end # Limit velocity and total energy @@ -999,8 +1012,6 @@ end var_max = var_bounds[2*v] for j in eachnode(dg), i in 2:nnodes(dg) - # Note: To make sure that the local bounds of both adjacent nodes (i-1, j), (i, j) are fulfilled, - # use different limited density and maximum/minimum values. lambda = lambda1[i, j, element] rho_limited_i = lambda * bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] rho_limited_im1 = lambda * bar_states1[1, i, j, element] - antidiffusive_flux1_limited[1, i, j, element] @@ -1016,12 +1027,7 @@ end g_min = max(rho_limited_i * (var_min[i, j, element] - phi), rho_limited_im1 * (phi - var_max[i-1, j, element])) - if g > 0 - g_limited = min(g_max, max(g, g_min)) - else - g_limited = max(g_min, min(g, g_max)) - end - antidiffusive_flux1_limited[v, i, j, element] += g_limited + antidiffusive_flux1_limited[v, i, j, element] += max(g_min, min(g, g_max)) end @@ -1041,12 +1047,7 @@ end g_min = max(rho_limited_j * (var_min[i, j, element] - phi), rho_limited_jm1 * (phi - var_max[i, j-1, element])) - if g > 0 - g_limited = min(g_max, max(g, g_min)) - else - g_limited = max(g_min, min(g, g_max)) - end - antidiffusive_flux2_limited[v, i, j, element] += g_limited + antidiffusive_flux2_limited[v, i, j, element] += max(g_min, min(g, g_max)) end end @@ -1112,16 +1113,16 @@ end u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) end - lambda1[1, :, element] .= zero(eltype(lambda1)) - lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) + # lambda1[1, :, element] .= zero(eltype(lambda1)) + # lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) end - lambda2[:, 1, element] .= zero(eltype(lambda2)) - lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + # lambda2[:, 1, element] .= zero(eltype(lambda2)) + # lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) end return nothing From 78e002f4558e34f6e85cb2d62b4e068406fd37e2 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 26 Jun 2022 16:45:36 +0200 Subject: [PATCH 059/423] Revise limiting formulation --- src/solvers/dgsem_tree/dg_2d.jl | 51 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5a4b785b39..d591fa66e7 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1012,13 +1012,14 @@ end var_max = var_bounds[2*v] for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - rho_limited_i = lambda * bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] - rho_limited_im1 = lambda * bar_states1[1, i, j, element] - antidiffusive_flux1_limited[1, i, j, element] + bar_state_rho = lambda1[i, j, element] * bar_states1[1, i, j, element] + bar_state_phi = lambda1[i, j, element] * bar_states1[v, i, j, element] + rho_limited_i = bar_state_rho + antidiffusive_flux1_limited[1, i, j, element] + rho_limited_im1 = bar_state_rho - antidiffusive_flux1_limited[1, i, j, element] - phi = bar_states1[v, i, j, element] / bar_states1[1, i, j, element] + phi = bar_state_phi / bar_state_rho - antidiffusive_flux1_limited[v, i, j, element] = (rho_limited_i * phi - lambda * bar_states1[v, i, j, element]) + antidiffusive_flux1_limited[v, i, j, element] = (rho_limited_i * phi - bar_state_phi) g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] @@ -1032,13 +1033,14 @@ end for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - rho_limited_j = lambda * bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] - rho_limited_jm1 = lambda * bar_states2[1, i, j, element] - antidiffusive_flux2_limited[1, i, j, element] + bar_state_rho = lambda2[i, j, element] * bar_states2[1, i, j, element] + bar_state_phi = lambda2[i, j, element] * bar_states2[v, i, j, element] + rho_limited_j = bar_state_rho + antidiffusive_flux2_limited[1, i, j, element] + rho_limited_jm1 = bar_state_rho - antidiffusive_flux2_limited[1, i, j, element] - phi = bar_states2[v, i, j, element] / bar_states2[1, i, j, element] + phi = bar_state_phi / bar_state_rho - antidiffusive_flux2_limited[v, i, j, element] = rho_limited_j * phi - lambda * bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] = rho_limited_j * phi - bar_state_phi g = antidiffusive_flux2[v, i, j] - antidiffusive_flux2_limited[v, i, j, element] @@ -1054,15 +1056,17 @@ end # Limit pressure if indicator.IDPPressureTVD for j in eachnode(dg), i in 2:nnodes(dg) + bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 + flux_velocity = antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2 + Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - - 0.5 * (bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2)) - R_max = sqrt(bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 + - antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) + + 0.5 * bar_state_velocity) + R_max = sqrt(bar_state_velocity * flux_velocity) + abs(bar_states1[1, i, j, element] * antidiffusive_flux1_limited[4, i, j, element]) + abs(bar_states1[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) - R_max = lambda1[i, j, element] * R_max + - max(0, 0.5 * (antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2) - - antidiffusive_flux1_limited[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + R_max *= lambda1[i, j, element] + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux1_limited[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) if R_max > Q for v in eachvariable(equations) @@ -1072,15 +1076,17 @@ end end for j in 2:nnodes(dg), i in eachnode(dg) + bar_state_velocity = bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 + flux_velocity = antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2 + Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - - 0.5 * (bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2)) - R_max = sqrt(bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 + - antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) + + 0.5 * bar_state_velocity) + R_max = sqrt(bar_state_velocity * flux_velocity) + abs(bar_states2[1, i, j, element] * antidiffusive_flux2_limited[4, i, j, element]) + abs(bar_states2[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) - R_max = lambda2[i, j, element] * R_max + - max(0, 0.5 * (antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2) - - antidiffusive_flux2_limited[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + R_max *= lambda2[i, j, element] + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux2_limited[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) if R_max > Q for v in eachvariable(equations) @@ -1275,7 +1281,6 @@ end var_min = bound_min[i, j, element] var_max = bound_max[i, j, element] - # TODO BB: use limited bar states instead of formula # -x if i>1 rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] From 75289a68813cf76c9a08d4e953844d2f3bf0a4b0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 30 Jun 2022 16:21:28 +0200 Subject: [PATCH 060/423] Update caches and container --- .../elixir_euler_astro_jet_MCL.jl | 6 +- .../elixir_euler_blast_wave_MCL.jl | 4 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 8 +- .../elixir_euler_shockcapturing_MCL.jl | 4 +- src/Trixi.jl | 2 +- src/callbacks_step/stepsize.jl | 12 +- src/solvers/dgsem_tree/containers_2d.jl | 142 ++++--- src/solvers/dgsem_tree/dg_2d.jl | 357 +++++++----------- src/solvers/dgsem_tree/indicators.jl | 18 +- src/solvers/dgsem_tree/indicators_2d.jl | 9 +- src/time_integration/methods_SSP.jl | 32 +- 11 files changed, 284 insertions(+), 310 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index be227ecdd0..13c6477ede 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -43,9 +43,9 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example -indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true, - IDPPressureTVD=true) +indicator_sc = IndicatorMCL(equations, basis; + IDPCheckBounds=true, + IDPPressureTVD=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 98de6abf2f..08a8479c8f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -38,8 +38,8 @@ initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true) +indicator_sc = IndicatorMCL(equations, basis; + IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 8af7c7c5d1..4895f3c337 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -36,9 +36,9 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true, - IDPPressureTVD=true) +indicator_sc = IndicatorMCL(equations, basis; + IDPCheckBounds=true, + IDPPressureTVD=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -80,7 +80,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, #alg=SSPRK43(); +sol = Trixi.solve(ode, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl index 916ed9ae73..a546d1ce94 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl @@ -12,8 +12,8 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorKuzminetal(equations, basis; - IDPCheckBounds=true) +indicator_sc = IndicatorMCL(equations, basis; + IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/Trixi.jl b/src/Trixi.jl index 2cb9f89cf8..ff3e8c78d3 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -177,7 +177,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralShockCapturingSubcell, IndicatorIDP, IndicatorKuzminetal, + VolumeIntegralShockCapturingSubcell, IndicatorIDP, IndicatorMCL, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, MortarL2 diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index ee6bc98f1c..9bfdc554f7 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -72,23 +72,19 @@ end @unpack cfl_number = stepsize_callback u = wrap_array(u_ode, mesh, equations, solver, cache) - # TODO BB: Fix the implementation of the second CFL condition. - if solver.volume_integral isa VolumeIntegralShockCapturingSubcell && solver.volume_integral.indicator isa IndicatorKuzminetal - # TODO Maybe it's possible to remove one calculation of the lambda (see volume integral) + if solver.volume_integral isa VolumeIntegralShockCapturingSubcell && solver.volume_integral.indicator isa IndicatorMCL @unpack inverse_weights = solver.basis u = wrap_array(u_ode, mesh, equations, solver, cache) calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) - @unpack lambda1, lambda2 = cache.ContainerMCL2D + @unpack lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator maxdt = typemax(eltype(u_ode)) for element in eachelement(solver, cache) J = 1 / cache.elements.inverse_jacobian[element] for j in eachnode(solver), i in eachnode(solver) - denom = inverse_weights[i] * ((i > 1 ? lambda1[i, j, element] : 0) + - (i < nnodes(solver) ? lambda1[i+1, j, element] : 0)) + - inverse_weights[j] * ((j > 1 ? lambda2[i, j, element] : 0) + - (j < nnodes(solver) ? lambda2[i, j+1, element] : 0)) + denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + + inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) maxdt = min(maxdt, J / denom) end end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 1a994ae413..f31bc11934 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1307,20 +1307,10 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) end mutable struct ContainerMCL2D{uEltype<:Real} - lambda1::Array{uEltype, 3} # [i, j, element] - lambda2::Array{uEltype, 3} # [i, j, element] - # Bar states at subcell interfaces for cons variable - bar_states1::Array{uEltype, 4} # [variable, i, j, element] - bar_states2::Array{uEltype, 4} # [variable, i, j, element] - # TODO: Do I really need to save the fluxes? For now, yes, because I need them to check the bounds at the end. # Idea: Just save the limited bar states. Problem: In there, the sign of the antidiffusive flux is not unique. antidiffusive_flux1_limited::Array{uEltype, 4} # [variables, i, j, elements] antidiffusive_flux2_limited::Array{uEltype, 4} # [variables, i, j, elements] # internal `resize!`able storage - _lambda1::Vector{uEltype} - _lambda2::Vector{uEltype} - _bar_states1::Vector{uEltype} - _bar_states2::Vector{uEltype} _antidiffusive_flux1_limited::Vector{uEltype} _antidiffusive_flux2_limited::Vector{uEltype} end @@ -1329,19 +1319,6 @@ function ContainerMCL2D{uEltype}(capacity::Integer, n_variables, n_nodes) where nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults - _lambda1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) - lambda1 = unsafe_wrap(Array, pointer(_lambda1), - (n_nodes+1, n_nodes, capacity)) - _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) - lambda2 = unsafe_wrap(Array, pointer(_lambda2), - (n_nodes, n_nodes+1, capacity)) - _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) - bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), - (n_variables, n_nodes+1, n_nodes, capacity)) - _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) - bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), - (n_variables, n_nodes, n_nodes+1, capacity)) - _antidiffusive_flux1_limited = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) antidiffusive_flux1_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux1_limited), (n_variables, n_nodes+1, n_nodes, capacity)) @@ -1350,12 +1327,12 @@ function ContainerMCL2D{uEltype}(capacity::Integer, n_variables, n_nodes) where antidiffusive_flux2_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux2_limited), (n_variables, n_nodes, n_nodes+1, capacity)) - return ContainerMCL2D{uEltype}(lambda1, lambda2, bar_states1, bar_states2, antidiffusive_flux1_limited, antidiffusive_flux2_limited, - _lambda1, _lambda2, _bar_states1, _bar_states2, _antidiffusive_flux1_limited, _antidiffusive_flux2_limited) + return ContainerMCL2D{uEltype}(antidiffusive_flux1_limited, antidiffusive_flux2_limited, + _antidiffusive_flux1_limited, _antidiffusive_flux2_limited) end -nvariables(container::ContainerMCL2D) = size(container.bar_states1, 1) -nnodes(container::ContainerMCL2D) = size(container.lambda1, 2) +nvariables(container::ContainerMCL2D) = size(container.antidiffusive_flux1_limited, 1) +nnodes(container::ContainerMCL2D) = size(container.antidiffusive_flux1_limited, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` @@ -1366,21 +1343,6 @@ function Base.resize!(container::ContainerMCL2D, capacity) n_nodes = nnodes(container) n_variables = nvariables(container) - @unpack _lambda1, _lambda2, _bar_states1, _bar_states2 = container - - resize!(_lambda1, (n_nodes+1) * n_nodes * capacity) - container.lambda1 = unsafe_wrap(Array, pointer(_lambda1), - (n_nodes+1, n_nodes, capacity)) - resize!(_lambda2, n_nodes * (n_nodes+1) * capacity) - container.lambda2 = unsafe_wrap(Array, pointer(_lambda2), - (n_nodes, n_nodes+1, capacity)) - resize!(_bar_states1, n_variables * (n_nodes+1) * n_nodes * capacity) - container.bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), - (n_variables, n_nodes+1, n_nodes, capacity)) - resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) - container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), - (n_variables, n_nodes, n_nodes+1, capacity)) - @unpack _antidiffusive_flux1_limited, _antidiffusive_flux2_limited = container resize!(_antidiffusive_flux1_limited, n_variables * (n_nodes+1) * n_nodes * capacity) @@ -1394,8 +1356,8 @@ function Base.resize!(container::ContainerMCL2D, capacity) end -mutable struct ContainerShockCapturingIndicator{uEltype<:Real} - alpha::Array{uEltype, 3} # [i, j, elements] +mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} + alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} var_bounds::Vector{Array{uEltype, 3}} @@ -1406,7 +1368,7 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} _var_bounds::Vector{Vector{uEltype}} end -function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real +function ContainerShockCapturingIndicatorIDP{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1424,18 +1386,18 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, l var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) end - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_bounds, - _alpha, _alpha1, _alpha2, _var_bounds) + return ContainerShockCapturingIndicatorIDP{uEltype}(alpha, alpha1, alpha2, var_bounds, + _alpha, _alpha1, _alpha2, _var_bounds) end -nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) +nnodes(indicator::ContainerShockCapturingIndicatorIDP) = size(indicator.alpha, 1) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) +function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) n_nodes = nnodes(indicator) @unpack _alpha, _alpha1, _alpha2 = indicator @@ -1455,5 +1417,87 @@ function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) return nothing end +mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} + alpha::Array{uEltype, 4} # [variable, i, j, element] + var_min::Array{uEltype, 4} # [variable, i, j, element] + var_max::Array{uEltype, 4} # [variable, i, j, element] + lambda1::Array{uEltype, 3} # [i, j, element] + lambda2::Array{uEltype, 3} # [i, j, element] + bar_states1::Array{uEltype, 4} # [variable, i, j, element] + bar_states2::Array{uEltype, 4} # [variable, i, j, element] + # internal `resize!`able storage + _alpha::Vector{uEltype} + _var_min::Vector{uEltype} + _var_max::Vector{uEltype} + _lambda1::Vector{uEltype} + _lambda2::Vector{uEltype} + _bar_states1::Vector{uEltype} + _bar_states2::Vector{uEltype} +end + +function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real + nan_uEltype = convert(uEltype, NaN) + + # Initialize fields with defaults + _alpha = fill(nan_uEltype, (n_variables+1) * n_nodes * n_nodes * capacity) + alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables+1, n_nodes, n_nodes, capacity)) + + _var_min = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) + var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) + + _var_max = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) + var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) + + _lambda1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) + lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) + _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) + lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) + + _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) + _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) + + return ContainerShockCapturingIndicatorMCL{uEltype}(alpha, var_min, var_max, lambda1, lambda2, bar_states1, bar_states2, + _alpha, _var_min, _var_max, _lambda1, _lambda2, _bar_states1, _bar_states2) +end + +nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.alpha, 1) +nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.alpha, 2) + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) + n_variables = nvariables(container) + n_nodes = nnodes(container) + + @unpack _alpha = container + resize!(_alpha, (n_variables+1) * n_nodes * n_nodes * capacity) + container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables+1, n_nodes, n_nodes, capacity)) + + @unpack _var_min, _var_max = container + resize!(_var_min, n_variables * n_nodes * n_nodes * capacity) + container.var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) + @unpack _var_max, _var_max = container + resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) + container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) + + @unpack _lambda1, _lambda2 = container + resize!(_lambda1, (n_nodes+1) * n_nodes * capacity) + container.lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) + resize!(_lambda2, n_nodes * (n_nodes+1) * capacity) + container.lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) + + @unpack _bar_states1, _bar_states2 = container + resize!(_bar_states1, n_variables * (n_nodes+1) * n_nodes * capacity) + container.bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) + resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) + container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) + + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index d591fa66e7..62a618fcb0 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -82,7 +82,7 @@ end function create_cache(mesh::TreeMesh{2}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) - cache = create_cache(mesh, equations, + cache1 = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) @@ -94,18 +94,18 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - cache = add2cache(cache, mesh, equations, volume_integral.indicator, dg, uEltype) + cache2 = create_cache(mesh, equations, volume_integral.indicator, dg, uEltype) - return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) + return (; cache1..., cache2..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) end -function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) +function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., ContainerFCT2D) + return (; ContainerFCT2D) end -function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorKuzminetal, dg::DG, uEltype) +function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorMCL, dg::DG, uEltype) ContainerMCL2D = Trixi.ContainerMCL2D{uEltype}(0, nvariables(equations), nnodes(dg)) A3dp1_x = Array{uEltype, 3} @@ -114,7 +114,7 @@ function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorKuzm antidiffusive_flux1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] antidiffusive_flux2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - return (; cache..., ContainerMCL2D, + return (; ContainerMCL2D, antidiffusive_flux1_threaded, antidiffusive_flux2_threaded) end @@ -553,7 +553,7 @@ function calc_volume_integral!(du, u, # Calculate boundaries @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) - @threaded for element in eachelement(dg, cache) + @trixi_timeit timer() "subcell_limiting_kernel!" @threaded for element in eachelement(dg, cache) subcell_limiting_kernel!(du, u, element, mesh, nonconservative_terms, equations, volume_integral, volume_integral.indicator, @@ -608,7 +608,7 @@ end @inline function subcell_limiting_kernel!(du, u, element, mesh::TreeMesh{2}, nonconservative_terms::Val{false}, equations, - volume_integral, indicator::IndicatorKuzminetal, + volume_integral, indicator::IndicatorMCL, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv = volume_integral @@ -634,7 +634,7 @@ end antidiffusive_flux1 = antidiffusive_flux1_threaded[Threads.threadid()] antidiffusive_flux2 = antidiffusive_flux2_threaded[Threads.threadid()] calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, volume_integral, indicator, dg, element, cache) + u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) # limited antidiffusive flux calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, @@ -732,8 +732,6 @@ end return nothing end -# TODO: For IndicatorIDP the antidiffusive flux is saved bacause it's needed in the antidifussive stage. For IndicatorKuzminetal not. -# Possible to use the same function? @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) @@ -758,8 +756,7 @@ end end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, volume_integral, indicator::IndicatorKuzminetal, - dg, element, cache) + nonconservative_terms, equations, indicator::IndicatorMCL, dg, element, cache) for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -787,8 +784,8 @@ end end @inline function calc_bar_states!(u, mesh, - nonconservative_terms, equations, indicator::IndicatorKuzminetal, dg, cache) - @unpack lambda1, lambda2, bar_states1, bar_states2 = cache.ContainerMCL2D + nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in 2:nnodes(dg) @@ -828,89 +825,43 @@ end return nothing end -@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorKuzminetal, dg, cache) - @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2 = cache.ContainerMCL2D +@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) + @unpack var_min, var_max, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator - # Note: Bar states and lambdas at the interfaces are not needed anywhere else. Calculate here without saving. + # Note: Bar states and lambdas at the interfaces are not needed anywhere else. Calculating here without saving. - # Density - var_min = var_bounds[1] - var_max = var_bounds[2] @threaded for element in eachelement(dg, cache) - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) - - for j in eachnode(dg), i in 2:nnodes(dg) - bar_state = bar_states1[1, i, j, element] - var_min[i-1, j, element] = min(var_min[i-1, j, element], bar_state) - var_max[i-1, j, element] = max(var_max[i-1, j, element], bar_state) - var_min[i , j, element] = min(var_min[i , j, element], bar_state) - var_max[i , j, element] = max(var_max[i , j, element], bar_state) - end - for j in 2:nnodes(dg), i in eachnode(dg) - bar_state = bar_states2[1, i, j, element] - var_min[i, j-1, element] = min(var_min[i, j-1, element], bar_state) - var_max[i, j-1, element] = max(var_max[i, j-1, element], bar_state) - var_min[i, j , element] = min(var_min[i, j, element], bar_state) - var_max[i, j , element] = max(var_max[i, j, element], bar_state) + for v in eachvariable(equations) + var_min[v, :, :, element] .= typemax(eltype(var_min)) + var_max[v, :, :, element] .= typemin(eltype(var_max)) end - end - - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state_rho = bar_states1[1, i, j, element] + var_min[1, i-1, j, element] = min(var_min[1, i-1, j, element], bar_state_rho) + var_max[1, i-1, j, element] = max(var_max[1, i-1, j, element], bar_state_rho) + var_min[1, i , j, element] = min(var_min[1, i , j, element], bar_state_rho) + var_max[1, i , j, element] = max(var_max[1, i , j, element], bar_state_rho) + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho + var_min[v, i-1, j, element] = min(var_min[v, i-1, j, element], bar_state_phi) + var_max[v, i-1, j, element] = max(var_max[v, i-1, j, element], bar_state_phi) + var_min[v, i , j, element] = min(var_min[v, i , j, element], bar_state_phi) + var_max[v, i , j, element] = max(var_max[v, i , j, element], bar_state_phi) end - - u_left = get_node_vars(u, equations, dg, index_left...) - u_right = get_node_vars(u, equations, dg, index_right...) - - flux_left = flux(u_left, orientation, equations) - flux_right = flux(u_right, orientation, equations) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - - bar_state = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_left[1] - flux_right[1]) / lambda - - var_min[index_left...] = min(var_min[index_left...], bar_state) - var_max[index_left...] = max(var_max[index_left...], bar_state) - var_min[index_right...] = min(var_min[index_right...], bar_state) - var_max[index_right...] = max(var_max[index_right...], bar_state) end - end - - # Other variables phi - @threaded for element in eachelement(dg, cache) - for v in 2:nvariables(equations) - var_min = var_bounds[2*(v-1)+1] - var_max = var_bounds[2*v] - - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) - - for j in eachnode(dg), i in 2:nnodes(dg) - bar_state = bar_states1[v, i, j, element] / bar_states1[1, i, j, element] - var_min[i-1, j, element] = min(var_min[i-1, j, element], bar_state) - var_max[i-1, j, element] = max(var_max[i-1, j, element], bar_state) - var_min[i , j, element] = min(var_min[i , j, element], bar_state) - var_max[i , j, element] = max(var_max[i , j, element], bar_state) - end - for j in 2:nnodes(dg), i in eachnode(dg) - bar_state = bar_states2[v, i, j, element] / bar_states2[1, i, j, element] - var_min[i, j-1, element] = min(var_min[i, j-1, element], bar_state) - var_max[i, j-1, element] = max(var_max[i, j-1, element], bar_state) - var_min[i, j , element] = min(var_min[i, j, element], bar_state) - var_max[i, j , element] = max(var_max[i, j, element], bar_state) + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state_rho = bar_states2[1, i, j, element] + var_min[1, i, j-1, element] = min(var_min[1, i, j-1, element], bar_state_rho) + var_max[1, i, j-1, element] = max(var_max[1, i, j-1, element], bar_state_rho) + var_min[1, i, j , element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j , element] = max(var_max[1, i, j, element], bar_state_rho) + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho + var_min[v, i, j-1, element] = min(var_min[v, i, j-1, element], bar_state_phi) + var_max[v, i, j-1, element] = max(var_max[v, i, j-1, element], bar_state_phi) + var_min[v, i, j , element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j , element] = max(var_max[v, i, j, element], bar_state_phi) end end end @@ -938,18 +889,18 @@ end flux_right = flux(u_right, orientation, equations) lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - bar_state_rho = (u_left[1] + u_right[1]) - (flux_right[1] - flux_left[1]) / lambda # 2 * bar_state_rho - + bar_state_rho = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_right[1] - flux_left[1]) / lambda + var_min[1, index_left...] = min(var_min[1, index_left...], bar_state_rho) + var_max[1, index_left...] = max(var_max[1, index_left...], bar_state_rho) + var_min[1, index_right...] = min(var_min[1, index_right...], bar_state_rho) + var_max[1, index_right...] = max(var_max[1, index_right...], bar_state_rho) for v in 2:nvariables(equations) - var_min = var_bounds[2*(v-1)+1] - var_max = var_bounds[2*v] - bar_state = (u_left[v] + u_right[v]) - (flux_right[v] - flux_left[v]) / lambda # 2 * bar_state - bar_state = bar_state / bar_state_rho - - var_min[index_left...] = min(var_min[index_left...], bar_state) - var_max[index_left...] = max(var_max[index_left...], bar_state) - var_min[index_right...] = min(var_min[index_right...], bar_state) - var_max[index_right...] = max(var_max[index_right...], bar_state) + bar_state_phi = 0.5 * (u_left[v] + u_right[v]) - 0.5 * (flux_right[v] - flux_left[v]) / lambda + bar_state_phi = bar_state_phi / bar_state_rho + var_min[v, index_left...] = min(var_min[v, index_left...], bar_state_phi) + var_max[v, index_left...] = max(var_max[v, index_left...], bar_state_phi) + var_min[v, index_right...] = min(var_min[v, index_right...], bar_state_phi) + var_max[v, index_right...] = max(var_max[v, index_right...], bar_state_phi) end end end @@ -960,13 +911,10 @@ end @inline function calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D - @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator - @unpack lambda1, lambda2, bar_states1, bar_states2 = cache.ContainerMCL2D + @unpack var_min, var_max, lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator - # Limit density - rho_min = var_bounds[1] - rho_max = var_bounds[2] for j in eachnode(dg), i in 2:nnodes(dg) + # Limit density # bar_state = bar_states1[1, i, j, element] # if antidiffusive_flux1[1, i, j] > 0 # antidiffusive_flux1_limited[1, i, j, element] = min(antidiffusive_flux1[1, i, j], @@ -978,15 +926,37 @@ end # alternative density limiting lambda = lambda1[i, j, element] - bar_state = lambda * bar_states1[1, i, j, element] - f_min = max(lambda * rho_min[i, j, element] - bar_state, - bar_state - lambda * rho_max[i-1, j, element]) - f_max = min(lambda * rho_max[i, j, element] - bar_state, - bar_state - lambda * rho_min[i-1, j, element]) + bar_state_rho = lambda * bar_states1[1, i, j, element] + f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i-1, j, element]) + f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i-1, j, element]) antidiffusive_flux1_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux1[1, i, j], f_max)) + + # Limit velocity and total energy + for v in 2:nvariables(equations) + bar_states_phi = lambda * bar_states1[v, i, j, element] + + rho_limited_i = bar_state_rho + antidiffusive_flux1_limited[1, i, j, element] + rho_limited_im1 = bar_state_rho - antidiffusive_flux1_limited[1, i, j, element] + + phi = bar_states_phi / bar_state_rho + + antidiffusive_flux1_limited[v, i, j, element] = rho_limited_i * phi - bar_states_phi + + g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] + + g_min = max(rho_limited_i * (var_min[v, i, j, element] - phi), + rho_limited_im1 * (phi - var_max[v, i-1, j, element])) + g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), + rho_limited_im1 * (phi - var_min[v, i-1, j, element])) + + antidiffusive_flux1_limited[v, i, j, element] += max(g_min, min(g, g_max)) + end end for j in 2:nnodes(dg), i in eachnode(dg) + # Limit density # bar_state = bar_states2[1, i, j, element] # if antidiffusive_flux2[1, i, j] > 0 # antidiffusive_flux2_limited[1, i, j, element] = min(antidiffusive_flux2[1, i, j], @@ -998,43 +968,17 @@ end # alternative density limiting lambda = lambda2[i, j, element] - bar_state = lambda * bar_states2[1, i, j, element] - f_min = max(lambda * rho_min[i, j, element] - bar_state, - bar_state - lambda * rho_max[i, j-1, element]) - f_max = min(lambda * rho_max[i, j, element] - bar_state, - bar_state - lambda * rho_min[i, j-1, element]) + bar_state_rho = lambda * bar_states2[1, i, j, element] + f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i, j-1, element]) + f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i, j-1, element]) antidiffusive_flux2_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux2[1, i, j], f_max)) - end - - # Limit velocity and total energy - for v in 2:nvariables(equations) - var_min = var_bounds[2*(v-1)+1] - var_max = var_bounds[2*v] - - for j in eachnode(dg), i in 2:nnodes(dg) - bar_state_rho = lambda1[i, j, element] * bar_states1[1, i, j, element] - bar_state_phi = lambda1[i, j, element] * bar_states1[v, i, j, element] - rho_limited_i = bar_state_rho + antidiffusive_flux1_limited[1, i, j, element] - rho_limited_im1 = bar_state_rho - antidiffusive_flux1_limited[1, i, j, element] - - phi = bar_state_phi / bar_state_rho - - antidiffusive_flux1_limited[v, i, j, element] = (rho_limited_i * phi - bar_state_phi) - - g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] - - g_max = min(rho_limited_i * (var_max[i, j, element] - phi), - rho_limited_im1 * (phi - var_min[i-1, j, element])) - g_min = max(rho_limited_i * (var_min[i, j, element] - phi), - rho_limited_im1 * (phi - var_max[i-1, j, element])) - - antidiffusive_flux1_limited[v, i, j, element] += max(g_min, min(g, g_max)) - end + # Limit velocity and total energy + for v in 2:nvariables(equations) + bar_state_phi = lambda * bar_states2[v, i, j, element] - for j in 2:nnodes(dg), i in eachnode(dg) - bar_state_rho = lambda2[i, j, element] * bar_states2[1, i, j, element] - bar_state_phi = lambda2[i, j, element] * bar_states2[v, i, j, element] rho_limited_j = bar_state_rho + antidiffusive_flux2_limited[1, i, j, element] rho_limited_jm1 = bar_state_rho - antidiffusive_flux2_limited[1, i, j, element] @@ -1044,10 +988,10 @@ end g = antidiffusive_flux2[v, i, j] - antidiffusive_flux2_limited[v, i, j, element] - g_max = min(rho_limited_j * (var_max[i, j, element] - phi), - rho_limited_jm1 * (phi - var_min[i, j-1, element])) - g_min = max(rho_limited_j * (var_min[i, j, element] - phi), - rho_limited_jm1 * (phi - var_max[i, j-1, element])) + g_min = max(rho_limited_j * (var_min[v, i, j, element] - phi), + rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) + g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), + rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) antidiffusive_flux2_limited[v, i, j, element] += max(g_min, min(g, g_max)) end @@ -1110,8 +1054,8 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorKuzminetal) - @unpack lambda1, lambda2 = cache.ContainerMCL2D +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorMCL) + @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in 2:nnodes(dg) @@ -1119,16 +1063,16 @@ end u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) end - # lambda1[1, :, element] .= zero(eltype(lambda1)) - # lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) + lambda1[1, :, element] .= zero(eltype(lambda1)) + lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) end - # lambda2[:, 1, element] .= zero(eltype(lambda2)) - # lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + lambda2[:, 1, element] .= zero(eltype(lambda2)) + lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) end return nothing @@ -1166,14 +1110,13 @@ end return nothing end -@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorKuzminetal) +@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorMCL) return nothing end # 2d, IndicatorIDP @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache @@ -1220,99 +1163,89 @@ end return nothing end -# 2d, IndicatorKuzminetal -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorKuzminetal) - - # @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator - @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator +# 2d, IndicatorMCL +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL) + @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache - @unpack bar_states1, bar_states2, antidiffusive_flux1_limited, antidiffusive_flux2_limited, lambda1, lambda2 = cache.ContainerMCL2D + @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D - # Density - bound_min = var_bounds[1] - bound_max = var_bounds[2] @threaded for element in eachelement(solver, cache) - left_error = zero(eltype(u)) - right_error = zero(eltype(u)) idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] + + # Density + err_lower_bound = zero(eltype(u)) + err_upper_bound = zero(eltype(u)) for j in eachnode(solver), i in eachnode(solver) - var_min = bound_min[i, j, element] - var_max = bound_max[i, j, element] + var_min_local = var_min[1, i, j, element] + var_max_local = var_max[1, i, j, element] # -x - if i>1 + if i > 1 var_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] - left_error = max(left_error, var_min - var_limited) - right_error = max(right_error, var_limited - var_max) + err_lower_bound = max(err_lower_bound, var_min_local - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - var_max_local) end # +x - if i1 + if j > 1 var_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] - left_error = max(left_error, var_min - var_limited) - right_error = max(right_error, var_limited - var_max) + err_lower_bound = max(err_lower_bound, var_min_local - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - var_max_local) end # +y - if j1 + if i > 1 rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1_limited[v, i, j, element] / lambda1[i, j, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max) + err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) end # +x - if i1 + if j > 1 rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] / lambda2[i, j, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max) + err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) + err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) end # +y - if j Date: Mon, 4 Jul 2022 11:29:02 +0200 Subject: [PATCH 061/423] Update examples --- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 8 ++++---- .../tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 08a8479c8f..e732597b06 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorMCL(equations, basis; - IDPCheckBounds=true) + IDPPressureTVD=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -58,7 +58,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 1.0) +tspan = (0.0, 2.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -68,12 +68,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=100, +save_solution = SaveSolutionCallback(interval=500, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index cca18b3dfd..47c418ca7a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -70,12 +70,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=20, +save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.2) +stepsize_callback = StepsizeCallback(cfl=0.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, From 29add6835b5f2bc0439aad19c9f88defa45726de Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 4 Jul 2022 11:40:50 +0200 Subject: [PATCH 062/423] Merge updates from branch 'MCL' --- .../elixir_euler_blast_wave_sc_subcell.jl | 4 +-- src/solvers/dgsem_tree/containers_2d.jl | 14 ++++---- src/solvers/dgsem_tree/dg_2d.jl | 35 +++++++++---------- src/solvers/dgsem_tree/indicators_2d.jl | 3 +- src/time_integration/methods_SSP.jl | 9 ++--- 5 files changed, 29 insertions(+), 36 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index cca18b3dfd..47c418ca7a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -70,12 +70,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=20, +save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.2) +stepsize_callback = StepsizeCallback(cfl=0.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 8cd29d0676..75194f06c0 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1306,8 +1306,8 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) return nothing end -mutable struct ContainerShockCapturingIndicator{uEltype<:Real} - alpha::Array{uEltype, 3} # [i, j, elements] +mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} + alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} var_bounds::Vector{Array{uEltype, 3}} @@ -1318,7 +1318,7 @@ mutable struct ContainerShockCapturingIndicator{uEltype<:Real} _var_bounds::Vector{Vector{uEltype}} end -function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real +function ContainerShockCapturingIndicatorIDP{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1336,18 +1336,18 @@ function ContainerShockCapturingIndicator{uEltype}(capacity::Integer, n_nodes, l var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) end - return ContainerShockCapturingIndicator{uEltype}(alpha, alpha1, alpha2, var_bounds, - _alpha, _alpha1, _alpha2, _var_bounds) + return ContainerShockCapturingIndicatorIDP{uEltype}(alpha, alpha1, alpha2, var_bounds, + _alpha, _alpha1, _alpha2, _var_bounds) end -nnodes(indicator::ContainerShockCapturingIndicator) = size(indicator.alpha, 1) +nnodes(indicator::ContainerShockCapturingIndicatorIDP) = size(indicator.alpha, 1) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(indicator::ContainerShockCapturingIndicator, capacity) +function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) n_nodes = nnodes(indicator) @unpack _alpha, _alpha1, _alpha2 = indicator diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index d0e4bb847e..e9ccb357df 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -82,9 +82,9 @@ end function create_cache(mesh::TreeMesh{2}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) - cache = create_cache(mesh, equations, - VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), - dg, uEltype) + cache_FV = create_cache(mesh, equations, + VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), + dg, uEltype) A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -94,15 +94,15 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - cache = add2cache(cache, mesh, equations, volume_integral.indicator, dg, uEltype) + cache_indicator = create_cache(mesh, equations, volume_integral.indicator, dg, uEltype) - return (; cache..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) + return (; cache_FV..., cache_indicator..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) end -function add2cache(cache, mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) +function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., ContainerFCT2D) + return (; ContainerFCT2D) end @@ -523,7 +523,7 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) - @threaded for element in eachelement(dg, cache) + @trixi_timeit timer() "subcell_limiting_kernel!" @threaded for element in eachelement(dg, cache) subcell_limiting_kernel!(du, u, element, mesh, nonconservative_terms, equations, volume_integral, volume_integral.indicator, @@ -656,23 +656,23 @@ end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) - for j in eachnode(dg), i in eachnode(dg) + for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] end end - - for i in eachnode(dg) + for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, 1, i, element] = zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[v, nnodes(dg)+1, i, element] = zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[v, i, 1, element] = zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[v, i, nnodes(dg)+1, element] = zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] end end + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) + return nothing end @@ -710,7 +710,6 @@ end # 2d, IndicatorIDP @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 6574d1d63e..425a3a8c87 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -192,8 +192,7 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) - - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicator{real(basis)}(0, nnodes(basis), length) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), length) alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index fd98197e10..402b9f2943 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -174,7 +174,6 @@ function solve!(integrator::SimpleIntegratorSSP) resize!(indicator.cache.alpha_mean_per_timestep, new_length) end - # TODO BB: Move this calculation to the for loop to get the mean and maximum of all alpha in that timestep (not only of the last RK stage)? indicator.cache.alpha_max_per_timestep[integrator.iter+1] = maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = @@ -242,12 +241,8 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end function Base.resize!(semi::AbstractSemidiscretization, new_size) - # Resize ContainerFCT2D or ContainerMCL2D - if semi.solver.volume_integral.indicator isa IndicatorIDP - resize!(semi.cache.ContainerFCT2D, new_size) - else # semi.solver.volume_integral.indicator isa IndicatorKuzminetal - resize!(semi.cache.ContainerMCL2D, new_size) - end + # Resize ContainerFCT2D + resize!(semi.cache.ContainerFCT2D, new_size) # Resize ContainerShockCapturingIndicator resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) From 82064dcd0b8b48d496eb02a642b965fb37220998 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 4 Jul 2022 12:11:52 +0200 Subject: [PATCH 063/423] Reuse function `calcflux_antidiffusive!` for both indicators --- src/solvers/dgsem_tree/dg_2d.jl | 35 ++++----------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 6e841a7564..e456749746 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -633,8 +633,10 @@ end @unpack antidiffusive_flux1_threaded, antidiffusive_flux2_threaded = cache antidiffusive_flux1 = antidiffusive_flux1_threaded[Threads.threadid()] antidiffusive_flux2 = antidiffusive_flux2_threaded[Threads.threadid()] + # Note: For MCL, antidiffusive_flux is 3-dimensional. To use the same function as for IndicatorIDP, + # use Julia hack with 1 as last index using element=1. calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + u, mesh, nonconservative_terms, equations, dg, 1, cache) # limited antidiffusive flux calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, @@ -733,7 +735,7 @@ end end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) + nonconservative_terms, equations, dg, element, cache) for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -746,35 +748,6 @@ end end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) - - return nothing -end - -@inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, indicator::IndicatorMCL, dg, element, cache) - - for j in eachnode(dg), i in 2:nnodes(dg) - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j] = fhat1[v, i, j] - fstar1[v, i, j] - end - end - for j in 2:nnodes(dg), i in eachnode(dg) - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j] = fhat2[v, i, j] - fstar2[v, i, j] - end - end - - # antidiffusive_flux1[:, 1, :] .= zero(eltype(antidiffusive_flux1)) - # antidiffusive_flux1[:, nnodes(dg)+1, :] .= zero(eltype(antidiffusive_flux1)) - - # antidiffusive_flux2[:, :, 1, ] .= zero(eltype(antidiffusive_flux2)) - # antidiffusive_flux2[:, :, nnodes(dg)+1] .= zero(eltype(antidiffusive_flux2)) - return nothing end From a069ff5b394cfb15fce878ba4ae3b598bd5a5e56 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 4 Jul 2022 12:14:53 +0200 Subject: [PATCH 064/423] Merge update from branch MCL --- src/solvers/dgsem_tree/dg_2d.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e9ccb357df..a5952858b6 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -561,7 +561,7 @@ end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, indicator, dg, element, cache) + nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -654,7 +654,7 @@ end end @inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) + nonconservative_terms, equations, dg, element, cache) for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -667,12 +667,6 @@ end end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) - return nothing end From 9d41707f81eceab8c03d51dd45b81e804b1dd2cd Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 4 Jul 2022 13:27:01 +0200 Subject: [PATCH 065/423] Speed up CheckBounds routine --- src/solvers/dgsem_tree/dg_2d.jl | 111 ++++++++++++-------------------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 3f34d21b54..62391395e7 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1145,80 +1145,53 @@ end @threaded for element in eachelement(solver, cache) idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] - # Density - err_lower_bound = zero(eltype(u)) - err_upper_bound = zero(eltype(u)) - for j in eachnode(solver), i in eachnode(solver) - var_min_local = var_min[1, i, j, element] - var_max_local = var_max[1, i, j, element] - - # -x - if i > 1 - var_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] - err_lower_bound = max(err_lower_bound, var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - var_max_local) - end - # +x - if i < nnodes(solver) - var_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1_limited[1, i+1, j, element] / lambda1[i+1, j, element] - err_lower_bound = max(err_lower_bound, var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - var_max_local) + # -x + for j in eachnode(solver), i in 2:nnodes(solver) + lambda = lambda1[i, j, element] + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda + idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) + idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) + for v in 2:nvariables(equations) + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1_limited[v, i, j, element] / lambda + idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) + idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end - # -y - if j > 1 - var_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] - err_lower_bound = max(err_lower_bound, var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - var_max_local) + end + # +x + for j in eachnode(solver), i in 1:nnodes(solver)-1 + lambda = lambda1[i+1, j, element] + rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1_limited[1, i+1, j, element] / lambda + idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) + idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) + for v in 2:nvariables(equations) + var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1_limited[v, i+1, j, element] / lambda + idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) + idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end - # +y - if j < nnodes(solver) - var_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2_limited[1, i, j+1, element] / lambda2[i, j+1, element] - err_lower_bound = max(err_lower_bound, var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - var_max_local) + end + # -y + for j in 2:nnodes(solver), i in eachnode(solver) + lambda = lambda2[i, j, element] + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda + idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) + idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) + for v in 2:nvariables(equations) + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] / lambda + idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) + idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end end - idp_bounds_delta[1] = max(idp_bounds_delta[1], err_lower_bound) - idp_bounds_delta[2] = max(idp_bounds_delta[2], err_upper_bound) - - # Velocity and total energy - for v in 2:nvariables(equations) - err_lower_bound = zero(eltype(u)) - err_upper_bound = zero(eltype(u)) - for j in eachnode(solver), i in eachnode(solver) - var_min_local = var_min[v, i, j, element] - var_max_local = var_max[v, i, j, element] - - # -x - if i > 1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda1[i, j, element] - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1_limited[v, i, j, element] / lambda1[i, j, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) - end - # +x - if i < nnodes(solver) - rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1_limited[1, i+1, j, element] / lambda1[i+1, j, element] - var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1_limited[v, i+1, j, element] / lambda1[i+1, j, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) - end - # -y - if j > 1 - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda2[i, j, element] - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] / lambda2[i, j, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) - end - # +y - if j < nnodes(solver) - rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2_limited[1, i, j+1, element] / lambda2[i, j+1, element] - var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2_limited[v, i, j+1, element] / lambda2[i, j+1, element] - err_lower_bound = max(err_lower_bound, rho_limited * var_min_local - var_limited) - err_upper_bound = max(err_upper_bound, var_limited - rho_limited * var_max_local) - end + # +y + for j in 1:nnodes(solver)-1, i in eachnode(solver) + lambda = lambda2[i, j+1, element] + rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2_limited[1, i, j+1, element] / lambda + idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) + idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) + for v in 2:nvariables(equations) + var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2_limited[v, i, j+1, element] / lambda + idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) + idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end - idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], err_lower_bound) - idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], err_upper_bound) end end From d8eca113b2b3324d77e6de2ad92f024ae9011f26 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 10 Jul 2022 16:18:28 +0200 Subject: [PATCH 066/423] Merge antidiffusive fluxes --- .../elixir_euler_astro_jet_MCL.jl | 2 +- .../elixir_euler_astro_jet_MCL_restart.jl | 9 +- src/solvers/dgsem_tree/containers_2d.jl | 134 +++++-------- src/solvers/dgsem_tree/dg_2d.jl | 185 +++++++----------- src/solvers/dgsem_tree/indicators_2d.jl | 8 +- 5 files changed, 137 insertions(+), 201 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 13c6477ede..e8fcbb0af9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -81,7 +81,7 @@ save_solution = SaveSolutionCallback(interval=5000, save_final_solution=false, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.1) +stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl index 2ece4cbd98..f554f09914 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl @@ -11,6 +11,13 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_MCL.jl")) # adapt the parameters that have changed compared to "elixir_euler_astro_jet_MCL.jl" restart_filename = joinpath("out", "restart_000001.h5") +# setups: +# - refinement level = 6: +# * Limiter: IDPPressureTVD: T_1=2.5e-6 (CFL=1.0, 1 timestep) +# - refinement level = 7: +# * Limiter: IDPPressureTVD: T_1=2.0e-6 (CFL=0.005, 219 timesteps) +# - refinement level = 8: +# * Limiter: IDPPressureTVD: T_1=1.0e-6 (CFL=0.005, 220 timesteps) mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) @@ -23,7 +30,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index f31bc11934..b85ea3d852 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1258,7 +1258,7 @@ end # flux2(i, j) # | # (i, j-1) -mutable struct ContainerFCT2D{uEltype<:Real} +mutable struct ContainerAntidiffusiveFlux2D{uEltype<:Real} antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] # internal `resize!`able storage @@ -1266,7 +1266,7 @@ mutable struct ContainerFCT2D{uEltype<:Real} _antidiffusive_flux2::Vector{uEltype} end -function ContainerFCT2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real +function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1278,19 +1278,19 @@ function ContainerFCT2D{uEltype}(capacity::Integer, n_variables, n_nodes) where antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), (n_variables, n_nodes, n_nodes+1, capacity)) - return ContainerFCT2D{uEltype}(antidiffusive_flux1, antidiffusive_flux2, - _antidiffusive_flux1, _antidiffusive_flux2) + return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1, antidiffusive_flux2, + _antidiffusive_flux1, _antidiffusive_flux2) end -nvariables(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 1) -nnodes(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 3) +nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 1) +nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(fluxes::ContainerFCT2D, capacity) +function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) n_nodes = nnodes(fluxes) n_variables = nvariables(fluxes) @@ -1306,55 +1306,6 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) return nothing end -mutable struct ContainerMCL2D{uEltype<:Real} - # Idea: Just save the limited bar states. Problem: In there, the sign of the antidiffusive flux is not unique. - antidiffusive_flux1_limited::Array{uEltype, 4} # [variables, i, j, elements] - antidiffusive_flux2_limited::Array{uEltype, 4} # [variables, i, j, elements] - # internal `resize!`able storage - _antidiffusive_flux1_limited::Vector{uEltype} - _antidiffusive_flux2_limited::Vector{uEltype} -end - -function ContainerMCL2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real - nan_uEltype = convert(uEltype, NaN) - - # Initialize fields with defaults - _antidiffusive_flux1_limited = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) - antidiffusive_flux1_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux1_limited), - (n_variables, n_nodes+1, n_nodes, capacity)) - - _antidiffusive_flux2_limited = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) - antidiffusive_flux2_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux2_limited), - (n_variables, n_nodes, n_nodes+1, capacity)) - - return ContainerMCL2D{uEltype}(antidiffusive_flux1_limited, antidiffusive_flux2_limited, - _antidiffusive_flux1_limited, _antidiffusive_flux2_limited) -end - -nvariables(container::ContainerMCL2D) = size(container.antidiffusive_flux1_limited, 1) -nnodes(container::ContainerMCL2D) = size(container.antidiffusive_flux1_limited, 3) - -# Only one-dimensional `Array`s are `resize!`able in Julia. -# Hence, we use `Vector`s as internal storage and `resize!` -# them whenever needed. Then, we reuse the same memory by -# `unsafe_wrap`ping multi-dimensional `Array`s around the -# internal storage. -function Base.resize!(container::ContainerMCL2D, capacity) - n_nodes = nnodes(container) - n_variables = nvariables(container) - - @unpack _antidiffusive_flux1_limited, _antidiffusive_flux2_limited = container - - resize!(_antidiffusive_flux1_limited, n_variables * (n_nodes+1) * n_nodes * capacity) - container.antidiffusive_flux1_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux1_limited), - (n_variables, n_nodes+1, n_nodes, capacity)) - resize!(_antidiffusive_flux2_limited, n_variables * n_nodes * (n_nodes+1) * capacity) - container.antidiffusive_flux2_limited = unsafe_wrap(Array, pointer(_antidiffusive_flux2_limited), - (n_variables, n_nodes, n_nodes+1, capacity)) - - return nothing -end - mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, element] @@ -1418,29 +1369,33 @@ function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) end mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} - alpha::Array{uEltype, 4} # [variable, i, j, element] - var_min::Array{uEltype, 4} # [variable, i, j, element] - var_max::Array{uEltype, 4} # [variable, i, j, element] - lambda1::Array{uEltype, 3} # [i, j, element] - lambda2::Array{uEltype, 3} # [i, j, element] - bar_states1::Array{uEltype, 4} # [variable, i, j, element] - bar_states2::Array{uEltype, 4} # [variable, i, j, element] + bar_states1::Array{uEltype, 4} # [variable, i, j, element] + bar_states2::Array{uEltype, 4} # [variable, i, j, element] + var_min::Array{uEltype, 4} # [variable, i, j, element] + var_max::Array{uEltype, 4} # [variable, i, j, element] + volume_flux_difference::Array{uEltype, 4} # [variable, i, j, element] + alpha_pressure::Array{uEltype, 3} # [i, j, element] + lambda1::Array{uEltype, 3} # [i, j, element] + lambda2::Array{uEltype, 3} # [i, j, element] # internal `resize!`able storage - _alpha::Vector{uEltype} + _bar_states1::Vector{uEltype} + _bar_states2::Vector{uEltype} _var_min::Vector{uEltype} _var_max::Vector{uEltype} + _volume_flux_difference::Vector{uEltype} + _alpha_pressure::Vector{uEltype} _lambda1::Vector{uEltype} _lambda2::Vector{uEltype} - _bar_states1::Vector{uEltype} - _bar_states2::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults - _alpha = fill(nan_uEltype, (n_variables+1) * n_nodes * n_nodes * capacity) - alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables+1, n_nodes, n_nodes, capacity)) + _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) + _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) _var_min = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) @@ -1448,22 +1403,25 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _var_max = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) + _volume_flux_difference = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) + volume_flux_difference = unsafe_wrap(Array, pointer(_volume_flux_difference), (n_variables, n_nodes, n_nodes, capacity)) + + _alpha_pressure = fill(nan_uEltype, n_nodes * n_nodes * capacity) + alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) + _lambda1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) - _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) - bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) - _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) - bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) - - return ContainerShockCapturingIndicatorMCL{uEltype}(alpha, var_min, var_max, lambda1, lambda2, bar_states1, bar_states2, - _alpha, _var_min, _var_max, _lambda1, _lambda2, _bar_states1, _bar_states2) + return ContainerShockCapturingIndicatorMCL{uEltype}(bar_states1, bar_states2, var_min, var_max, + volume_flux_difference, alpha_pressure, lambda1, lambda2, + _bar_states1, _bar_states2, _var_min, _var_max, + _volume_flux_difference, _alpha_pressure, _lambda1, _lambda2) end -nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.alpha, 1) -nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.alpha, 2) +nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) +nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 2) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` @@ -1474,9 +1432,11 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) n_variables = nvariables(container) n_nodes = nnodes(container) - @unpack _alpha = container - resize!(_alpha, (n_variables+1) * n_nodes * n_nodes * capacity) - container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables+1, n_nodes, n_nodes, capacity)) + @unpack _bar_states1, _bar_states2 = container + resize!(_bar_states1, n_variables * (n_nodes+1) * n_nodes * capacity) + container.bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) + resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) + container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) @unpack _var_min, _var_max = container resize!(_var_min, n_variables * n_nodes * n_nodes * capacity) @@ -1485,18 +1445,20 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) + @unpack _volume_flux_difference = container + resize!(_volume_flux_difference, n_variables * n_nodes * n_nodes * capacity) + container.volume_flux_difference = unsafe_wrap(Array, pointer(_volume_flux_difference), (n_variables, n_nodes, n_nodes, capacity)) + + @unpack _alpha_pressure = container + resize!(_alpha_pressure, n_nodes * n_nodes * capacity) + container.alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) + @unpack _lambda1, _lambda2 = container resize!(_lambda1, (n_nodes+1) * n_nodes * capacity) container.lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) resize!(_lambda2, n_nodes * (n_nodes+1) * capacity) container.lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) - @unpack _bar_states1, _bar_states2 = container - resize!(_bar_states1, n_variables * (n_nodes+1) * n_nodes * capacity) - container.bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) - resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) - container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) - return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 62391395e7..6277425b42 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -82,9 +82,9 @@ end function create_cache(mesh::TreeMesh{2}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) - cache_FV = create_cache(mesh, equations, - VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), - dg, uEltype) + cache = create_cache(mesh, equations, + VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), + dg, uEltype) A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -94,28 +94,9 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - cache_indicator = create_cache(mesh, equations, volume_integral.indicator, dg, uEltype) - - return (; cache_FV..., cache_indicator..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) -end - -function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) - ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) - - return (; ContainerFCT2D) -end - -function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorMCL, dg::DG, uEltype) - ContainerMCL2D = Trixi.ContainerMCL2D{uEltype}(0, nvariables(equations), nnodes(dg)) - - A3dp1_x = Array{uEltype, 3} - A3dp1_y = Array{uEltype, 3} + ContainerAntidiffusiveFlux2D = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - antidiffusive_flux1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg)+1, nnodes(dg)) for _ in 1:Threads.nthreads()] - antidiffusive_flux2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] - - return (; ContainerMCL2D, - antidiffusive_flux1_threaded, antidiffusive_flux2_threaded) + return (; cache..., ContainerAntidiffusiveFlux2D, fhat1_threaded, fhat2_threaded, flux_temp_threaded) end @@ -587,10 +568,8 @@ end calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - # Calculate antidiffusive flux - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - - calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + # antidiffusive flux + calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution of low-order FV flux @@ -630,26 +609,20 @@ end nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # antidiffusive flux - @unpack antidiffusive_flux1_threaded, antidiffusive_flux2_threaded = cache - antidiffusive_flux1 = antidiffusive_flux1_threaded[Threads.threadid()] - antidiffusive_flux2 = antidiffusive_flux2_threaded[Threads.threadid()] - # Note: For MCL, antidiffusive_flux is 3-dimensional. To use the same function as for IndicatorIDP, - # use Julia hack with 1 as last index using element=1. - calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, dg, 1, cache) - - # limited antidiffusive flux - calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, - u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) - - @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D + calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, + u, mesh, nonconservative_terms, equations, dg, element, cache) + + # limit antidiffusive flux + calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j]) - du[v, i, j, element] += inverse_weights[i] * (antidiffusive_flux1_limited[v, i+1, j, element] - antidiffusive_flux1_limited[v, i, j, element]) + - inverse_weights[j] * (antidiffusive_flux2_limited[v, i, j+1, element] - antidiffusive_flux2_limited[v, i, j, element]) + du[v, i, j, element] += inverse_weights[i] * (antidiffusive_flux1[v, i+1, j, element] - antidiffusive_flux1[v, i, j, element]) + + inverse_weights[j] * (antidiffusive_flux2[v, i, j+1, element] - antidiffusive_flux2[v, i, j, element]) end end @@ -734,8 +707,9 @@ end return nothing end -@inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, +@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -772,8 +746,6 @@ end bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] end end - # bar_states1[:, 1, :, element] .= zero(eltype(bar_states1)) - # bar_states1[:, nnodes(dg)+1, :, element] .= zero(eltype(bar_states1)) for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j , element) @@ -786,8 +758,6 @@ end bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] end end - # bar_states2[:, :, 1, element] .= zero(eltype(bar_states2)) - # bar_states2[:, :, nnodes(dg)+1, element] .= zero(eltype(bar_states2)) end return nothing @@ -881,92 +851,85 @@ end return nothing end -@inline function calcflux_antidiffusive_limited!(antidiffusive_flux1, antidiffusive_flux2, - u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) - @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D +@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack var_min, var_max, lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = lambda * bar_states1[1, i, j, element] # Limit density - # bar_state = bar_states1[1, i, j, element] - # if antidiffusive_flux1[1, i, j] > 0 - # antidiffusive_flux1_limited[1, i, j, element] = min(antidiffusive_flux1[1, i, j], - # lambda1[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i-1, j, element])) + # if antidiffusive_flux1[1, i, j, element] > 0 + # antidiffusive_flux1[1, i, j, element] = min(antidiffusive_flux1[1, i, j, element], + # min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element])) # else - # antidiffusive_flux1_limited[1, i, j, element] = max(antidiffusive_flux1[1, i, j], - # lambda1[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i-1, j, element])) + # antidiffusive_flux1[1, i, j, element] = max(antidiffusive_flux1[1, i, j, element], + # max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i-1, j, element])) # end # alternative density limiting - lambda = lambda1[i, j, element] - bar_state_rho = lambda * bar_states1[1, i, j, element] f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i-1, j, element]) f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element]) - antidiffusive_flux1_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux1[1, i, j], f_max)) + antidiffusive_flux1[1, i, j, element] = max(f_min, min(antidiffusive_flux1[1, i, j, element], f_max)) # Limit velocity and total energy for v in 2:nvariables(equations) bar_states_phi = lambda * bar_states1[v, i, j, element] - rho_limited_i = bar_state_rho + antidiffusive_flux1_limited[1, i, j, element] - rho_limited_im1 = bar_state_rho - antidiffusive_flux1_limited[1, i, j, element] + rho_limited_i = bar_state_rho + antidiffusive_flux1[1, i, j, element] + rho_limited_im1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] phi = bar_states_phi / bar_state_rho - antidiffusive_flux1_limited[v, i, j, element] = rho_limited_i * phi - bar_states_phi - - g = antidiffusive_flux1[v, i, j] - antidiffusive_flux1_limited[v, i, j, element] + g = antidiffusive_flux1[v, i, j, element] - rho_limited_i * phi + bar_states_phi g_min = max(rho_limited_i * (var_min[v, i, j, element] - phi), rho_limited_im1 * (phi - var_max[v, i-1, j, element])) g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), rho_limited_im1 * (phi - var_min[v, i-1, j, element])) - antidiffusive_flux1_limited[v, i, j, element] += max(g_min, min(g, g_max)) + antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + max(g_min, min(g, g_max)) end end for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = lambda * bar_states2[1, i, j, element] # Limit density - # bar_state = bar_states2[1, i, j, element] - # if antidiffusive_flux2[1, i, j] > 0 - # antidiffusive_flux2_limited[1, i, j, element] = min(antidiffusive_flux2[1, i, j], - # lambda2[i, j, element] * min(rho_max[i, j, element] - bar_state, bar_state - rho_min[i, j-1, element])) + # if antidiffusive_flux2[1, i, j, element] > 0 + # antidiffusive_flux2[1, i, j, element] = min(antidiffusive_flux2[1, i, j, element], + # min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element])) # else - # antidiffusive_flux2_limited[1, i, j, element] = max(antidiffusive_flux2[1, i, j], - # lambda2[i, j, element] * max(rho_min[i, j, element] - bar_state, bar_state - rho_max[i, j-1, element])) + # antidiffusive_flux2[1, i, j, element] = max(antidiffusive_flux2[1, i, j, element], + # max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i, j-1, element])) # end # alternative density limiting - lambda = lambda2[i, j, element] - bar_state_rho = lambda * bar_states2[1, i, j, element] f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i, j-1, element]) f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i, j-1, element]) - antidiffusive_flux2_limited[1, i, j, element] = max(f_min, min(antidiffusive_flux2[1, i, j], f_max)) + antidiffusive_flux2[1, i, j, element] = max(f_min, min(antidiffusive_flux2[1, i, j, element], f_max)) # Limit velocity and total energy for v in 2:nvariables(equations) bar_state_phi = lambda * bar_states2[v, i, j, element] - rho_limited_j = bar_state_rho + antidiffusive_flux2_limited[1, i, j, element] - rho_limited_jm1 = bar_state_rho - antidiffusive_flux2_limited[1, i, j, element] + rho_limited_j = bar_state_rho + antidiffusive_flux2[1, i, j, element] + rho_limited_jm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] phi = bar_state_phi / bar_state_rho - antidiffusive_flux2_limited[v, i, j, element] = rho_limited_j * phi - bar_state_phi - - g = antidiffusive_flux2[v, i, j] - antidiffusive_flux2_limited[v, i, j, element] + g = antidiffusive_flux2[v, i, j, element] - rho_limited_j * phi + bar_state_phi g_min = max(rho_limited_j * (var_min[v, i, j, element] - phi), rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) - antidiffusive_flux2_limited[v, i, j, element] += max(g_min, min(g, g_max)) + antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + max(g_min, min(g, g_max)) end end @@ -974,50 +937,54 @@ end if indicator.IDPPressureTVD for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 - flux_velocity = antidiffusive_flux1_limited[2, i, j, element]^2 + antidiffusive_flux1_limited[3, i, j, element]^2 + flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) - R_max = sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states1[1, i, j, element] * antidiffusive_flux1_limited[4, i, j, element]) + - abs(bar_states1[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) - R_max *= lambda1[i, j, element] + + R_max = lambda1[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + + abs(bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element])) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux1_limited[4, i, j, element] * antidiffusive_flux1_limited[1, i, j, element]) + antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) if R_max > Q + alpha = Q / R_max for v in eachvariable(equations) - antidiffusive_flux1_limited[v, i, j, element] *= Q / R_max + antidiffusive_flux1[v, i, j, element] *= alpha end end end for j in 2:nnodes(dg), i in eachnode(dg) bar_state_velocity = bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 - flux_velocity = antidiffusive_flux2_limited[2, i, j, element]^2 + antidiffusive_flux2_limited[3, i, j, element]^2 + flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + antidiffusive_flux2[3, i, j, element]^2 Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) - R_max = sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states2[1, i, j, element] * antidiffusive_flux2_limited[4, i, j, element]) + - abs(bar_states2[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) - R_max *= lambda2[i, j, element] + + R_max = lambda2[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + + abs(bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element])) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux2_limited[4, i, j, element] * antidiffusive_flux2_limited[1, i, j, element]) + antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) if R_max > Q + alpha = Q / R_max for v in eachvariable(equations) - antidiffusive_flux2_limited[v, i, j, element] *= Q / R_max + antidiffusive_flux2[v, i, j, element] *= alpha end end end end - antidiffusive_flux1_limited[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_limited)) - antidiffusive_flux1_limited[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1_limited)) + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux2_limited[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_limited)) - antidiffusive_flux2_limited[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2_limited)) + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) return nothing end @@ -1054,7 +1021,7 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack inverse_weights = solver.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -1140,7 +1107,7 @@ end @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL) @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache - @unpack antidiffusive_flux1_limited, antidiffusive_flux2_limited = cache.ContainerMCL2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @threaded for element in eachelement(solver, cache) idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] @@ -1148,11 +1115,11 @@ end # -x for j in eachnode(solver), i in 2:nnodes(solver) lambda = lambda1[i, j, element] - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1_limited[1, i, j, element] / lambda + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) for v in 2:nvariables(equations) - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1_limited[v, i, j, element] / lambda + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end @@ -1160,11 +1127,11 @@ end # +x for j in eachnode(solver), i in 1:nnodes(solver)-1 lambda = lambda1[i+1, j, element] - rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1_limited[1, i+1, j, element] / lambda + rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1[1, i+1, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) for v in 2:nvariables(equations) - var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1_limited[v, i+1, j, element] / lambda + var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1[v, i+1, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end @@ -1172,11 +1139,11 @@ end # -y for j in 2:nnodes(solver), i in eachnode(solver) lambda = lambda2[i, j, element] - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2_limited[1, i, j, element] / lambda + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) for v in 2:nvariables(equations) - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2_limited[v, i, j, element] / lambda + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end @@ -1184,11 +1151,11 @@ end # +y for j in 1:nnodes(solver)-1, i in eachnode(solver) lambda = lambda2[i, j+1, element] - rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2_limited[1, i, j+1, element] / lambda + rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2[1, i, j+1, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) for v in 2:nvariables(equations) - var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2_limited[v, i, j+1, element] / lambda + var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2[v, i, j+1, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index b25531fb25..c5bb333cfa 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -316,7 +316,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -428,7 +428,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -628,7 +628,7 @@ mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entrop mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) @inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -727,7 +727,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dg, dt, cache, indicator_IDP) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D inverse_jacobian = cache.elements.inverse_jacobian[element] @unpack IDPgamma = indicator_IDP From 202869c1210a029cf47c05c27229acf21da8bc9b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 10 Jul 2022 16:22:51 +0200 Subject: [PATCH 067/423] Fix resize function --- src/time_integration/methods_SSP.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index db31386e7c..73880687a9 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -243,12 +243,8 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end function Base.resize!(semi::AbstractSemidiscretization, new_size) - # Resize ContainerFCT2D or ContainerMCL2D - if semi.solver.volume_integral.indicator isa IndicatorIDP - resize!(semi.cache.ContainerFCT2D, new_size) - else # semi.solver.volume_integral.indicator isa IndicatorMCL - resize!(semi.cache.ContainerMCL2D, new_size) - end + # Resize ContainerAntidiffusiveFlux2D + resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) # Resize ContainerShockCapturingIndicator resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) From 2ea7434dc60ff7865a04f862e5756babb365c59c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 10 Jul 2022 16:25:50 +0200 Subject: [PATCH 068/423] Fix resize function --- src/solvers/dgsem_tree/dg_2d.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 8 ++++---- src/time_integration/methods_SSP.jl | 8 ++------ 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 6277425b42..69481bf9b6 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1021,7 +1021,7 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack inverse_weights = solver.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index c5bb333cfa..630fc8921d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -316,7 +316,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -428,7 +428,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -628,7 +628,7 @@ mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entrop mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) @inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -727,7 +727,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dg, dt, cache, indicator_IDP) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D inverse_jacobian = cache.elements.inverse_jacobian[element] @unpack IDPgamma = indicator_IDP diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index db31386e7c..73880687a9 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -243,12 +243,8 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end function Base.resize!(semi::AbstractSemidiscretization, new_size) - # Resize ContainerFCT2D or ContainerMCL2D - if semi.solver.volume_integral.indicator isa IndicatorIDP - resize!(semi.cache.ContainerFCT2D, new_size) - else # semi.solver.volume_integral.indicator isa IndicatorMCL - resize!(semi.cache.ContainerMCL2D, new_size) - end + # Resize ContainerAntidiffusiveFlux2D + resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) # Resize ContainerShockCapturingIndicator resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) From d19e509272ca7efeb5f9f140c624e360dfddd0a5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 12 Jul 2022 13:26:24 +0200 Subject: [PATCH 069/423] Fix time step calculation --- src/callbacks_step/stepsize.jl | 35 ++++++--------- src/callbacks_step/stepsize_dg2d.jl | 20 +++++++++ src/solvers/dgsem_tree/dg_2d.jl | 70 +++++++++++++++++++++++------ 3 files changed, 89 insertions(+), 36 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 9bfdc554f7..113841d5e4 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -72,29 +72,9 @@ end @unpack cfl_number = stepsize_callback u = wrap_array(u_ode, mesh, equations, solver, cache) - if solver.volume_integral isa VolumeIntegralShockCapturingSubcell && solver.volume_integral.indicator isa IndicatorMCL - @unpack inverse_weights = solver.basis - u = wrap_array(u_ode, mesh, equations, solver, cache) - calc_lambda!(u, mesh, equations, solver, cache, solver.volume_integral.indicator) - @unpack lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - - maxdt = typemax(eltype(u_ode)) - for element in eachelement(solver, cache) - J = 1 / cache.elements.inverse_jacobian[element] - - for j in eachnode(solver), i in eachnode(solver) - denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + - inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) - maxdt = min(maxdt, J / denom) - end - end - - dt = @trixi_timeit timer() "calculate dt" cfl_number * maxdt - else - dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, + dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, have_constant_speed(equations), equations, - solver, cache) - end + solver, cache, solver.volume_integral) set_proposed_dt!(integrator, dt) integrator.opts.dtmax = dt @@ -106,6 +86,17 @@ end return nothing end +max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) + +@inline function max_dt(u, t, mesh, + constant_speed, equations, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) + + return max_dt(u, t, mesh, + constant_speed, equations, dg::DG, cache, volume_integral.indicator) +end + +max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator::AbstractIndicator) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) + # Time integration methods from the DiffEq ecosystem without adaptive time stepping on their own # such as `CarpenterKennedy2N54` require passing `dt=...` in `solve(ode, ...)`. Since we don't have diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 821e4e744f..424df4cb1c 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -42,6 +42,26 @@ function max_dt(u, t, mesh::TreeMesh{2}, return 2 / (nnodes(dg) * max_scaled_speed) end +@inline function max_dt(u, t, mesh::TreeMesh{2}, + constant_speed::Val{false}, equations, dg::DG, cache, indicator::IndicatorMCL) + @unpack inverse_weights = dg.basis + @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) + @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + + maxdt = typemax(eltype(u)) + for element in eachelement(dg, cache) + J = 1 / cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + + inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) + maxdt = min(maxdt, J / denom) + end + end + + return maxdt +end + function max_dt(u, t, mesh::ParallelTreeMesh{2}, constant_speed::Val{false}, equations, dg::DG, cache) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 69481bf9b6..58a5f2675d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -769,9 +769,7 @@ end end @inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) - @unpack var_min, var_max, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator - - # Note: Bar states and lambdas at the interfaces are not needed anywhere else. Calculating here without saving. + @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(dg, cache) for v in eachvariable(equations) @@ -811,18 +809,20 @@ end for interface in eachinterface(dg, cache) # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] + left_id = cache.interfaces.neighbor_ids[1, interface] + right_id = cache.interfaces.neighbor_ids[2, interface] orientation = cache.interfaces.orientations[interface] for i in eachnode(dg) if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) + index_left = (nnodes(dg), i, left_id) + index_right = (1, i, right_id) + lambda = lambda1[1, i, right_id] else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) + index_left = (i, nnodes(dg), left_id) + index_right = (i, 1, right_id) + lambda = lambda2[i, 1, right_id] end u_left = get_node_vars(u, equations, dg, index_left...) @@ -830,7 +830,6 @@ end flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) bar_state_rho = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_right[1] - flux_left[1]) / lambda var_min[1, index_left...] = min(var_min[1, index_left...], bar_state_rho) @@ -1003,16 +1002,59 @@ end u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) end - lambda1[1, :, element] .= zero(eltype(lambda1)) - lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) end - lambda2[:, 1, element] .= zero(eltype(lambda2)) - lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + end + + @threaded for interface in eachinterface(dg, cache) + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + if orientation == 1 + for j in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left) + u_right = get_node_vars(u, equations, dg, 1, j, right) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda1[nnodes(dg)+1, j, left] = lambda + lambda1[1, j, right] = lambda + end + else + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left) + u_right = get_node_vars(u, equations, dg, i, 1, right) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda2[i, nnodes(dg)+1, left] = lambda + lambda2[i, 1, right] = lambda + end + end + end + + @threaded for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # boundary_side == 1 + lambda1[1, :, element] .= zero(eltype(lambda1)) + else # boundary_side == 2 + lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) + end + else # orientation == 2 + if neighbor_side == 2 # boundary_side == 1 + lambda2[:, 1, element] .= zero(eltype(lambda2)) + else # boundary_side == 2 + lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + end + end end return nothing From e4b92ade14b5ebd56d869a09a54dc99c129bec74 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 12 Jul 2022 16:20:36 +0200 Subject: [PATCH 070/423] Merge updates from branch 'MCL' --- src/solvers/dgsem_tree/containers_2d.jl | 15 +++++++------- src/solvers/dgsem_tree/dg_2d.jl | 27 +++++++++---------------- src/solvers/dgsem_tree/indicators_2d.jl | 8 ++++---- src/time_integration/methods_SSP.jl | 4 ++-- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 75194f06c0..c308174c20 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1258,7 +1258,7 @@ end # flux2(i, j) # | # (i, j-1) -mutable struct ContainerFCT2D{uEltype<:Real} +mutable struct ContainerAntidiffusiveFlux2D{uEltype<:Real} antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] # internal `resize!`able storage @@ -1266,7 +1266,7 @@ mutable struct ContainerFCT2D{uEltype<:Real} _antidiffusive_flux2::Vector{uEltype} end -function ContainerFCT2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real +function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1278,19 +1278,19 @@ function ContainerFCT2D{uEltype}(capacity::Integer, n_variables, n_nodes) where antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), (n_variables, n_nodes, n_nodes+1, capacity)) - return ContainerFCT2D{uEltype}(antidiffusive_flux1, antidiffusive_flux2, - _antidiffusive_flux1, _antidiffusive_flux2) + return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1, antidiffusive_flux2, + _antidiffusive_flux1, _antidiffusive_flux2) end -nvariables(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 1) -nnodes(fluxes::ContainerFCT2D) = size(fluxes.antidiffusive_flux1, 3) +nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 1) +nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(fluxes::ContainerFCT2D, capacity) +function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) n_nodes = nnodes(fluxes) n_variables = nvariables(fluxes) @@ -1306,6 +1306,7 @@ function Base.resize!(fluxes::ContainerFCT2D, capacity) return nothing end + mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index a5952858b6..bc47b52608 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -82,9 +82,9 @@ end function create_cache(mesh::TreeMesh{2}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) - cache_FV = create_cache(mesh, equations, - VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), - dg, uEltype) + cache = create_cache(mesh, equations, + VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), + dg, uEltype) A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -94,15 +94,9 @@ function create_cache(mesh::TreeMesh{2}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - cache_indicator = create_cache(mesh, equations, volume_integral.indicator, dg, uEltype) - - return (; cache_FV..., cache_indicator..., fhat1_threaded, fhat2_threaded, flux_temp_threaded) -end - -function create_cache(mesh::TreeMesh{2}, equations, indicator::IndicatorIDP, dg::DG, uEltype) - ContainerFCT2D = Trixi.ContainerFCT2D{uEltype}(0, nvariables(equations), nnodes(dg)) + ContainerAntidiffusiveFlux2D = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; ContainerFCT2D) + return (; cache..., ContainerAntidiffusiveFlux2D, fhat1_threaded, fhat2_threaded, flux_temp_threaded) end @@ -557,10 +551,8 @@ end calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - # Calculate antidiffusive flux - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D - - calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + # antidiffusive flux + calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, nonconservative_terms, equations, dg, element, cache) # Calculate volume integral contribution of low-order FV flux @@ -653,8 +645,9 @@ end return nothing end -@inline function calcflux_antidiffusive!(antidiffusive_flux1, antidiffusive_flux2, fhat1, fhat2, fstar1, fstar2, u, mesh, +@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -673,7 +666,7 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @unpack inverse_weights = solver.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 425a3a8c87..502e537d1d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -312,7 +312,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -424,7 +424,7 @@ end end end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -624,7 +624,7 @@ mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entrop mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) @inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -723,7 +723,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dg, dt, cache, indicator_IDP) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerFCT2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D inverse_jacobian = cache.elements.inverse_jacobian[element] @unpack IDPgamma = indicator_IDP diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 402b9f2943..1881cf15b0 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -241,8 +241,8 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end function Base.resize!(semi::AbstractSemidiscretization, new_size) - # Resize ContainerFCT2D - resize!(semi.cache.ContainerFCT2D, new_size) + # Resize ContainerAntidiffusiveFlux2D + resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) # Resize ContainerShockCapturingIndicator resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) From 2cf10d55c236e444eed91964bf4f48279861c287 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 13 Jul 2022 13:38:05 +0200 Subject: [PATCH 071/423] Fix tests --- .../tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 6 ++++++ test/test_tree_2d_euler.jl | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 9aea2be01b..3c16339f6f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -49,7 +49,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index bc47b52608..0bb8fce882 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -660,6 +660,12 @@ end end end + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) + return nothing end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 1bab3bda76..d4f246b380 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -66,8 +66,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - l2 = [0.05279461354314492, 0.045989178414492675, 0.04598740128933962, 0.19301796760176929], - linf = [0.18653503138166105, 0.23196626025079317, 0.23205043616292115, 0.6911505364900443]) + l2 = [0.05279387793678434, 0.04598968102076476, 0.04598873940396531, 0.19301779222816706], + linf = [0.1866584355939257, 0.2319290947473017, 0.23237647269183395, 0.6911745732545076]) end @trixi_testset "elixir_euler_blast_wave.jl" begin From 29fa5c4986af16e0d14cf66fcd7e531776f6934b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 13 Jul 2022 14:11:06 +0200 Subject: [PATCH 072/423] Fix tests with linux numbers --- test/test_tree_2d_euler.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index d4f246b380..a5ac74bb6e 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -132,8 +132,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.35190218236276916, 0.1932735857321866, 0.1932566034003023, 0.6193245526148682], - linf = [1.6865111411650586, 1.3647962470261445, 1.363807717209087, 2.443080751122044], + l2 = [0.3518553249794659, 0.19310220470973063, 0.1930955995353822, 0.619265328729751], + linf = [1.6781299814634756, 1.3624305216971244, 1.3621049685174218, 2.4493280170024123], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From 6edc636d5ef00ac2954bc39cb5eeb8cb34c6f2b5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 13 Jul 2022 14:14:31 +0200 Subject: [PATCH 073/423] Remove unnecessary operation --- src/solvers/dgsem_tree/dg_2d.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 7ae5499f39..0f20e7c420 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -985,12 +985,6 @@ end end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) - return nothing end From d7d5a0d9f3391c520e96babde828f7c326c16860 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 14 Jul 2022 12:41:03 +0200 Subject: [PATCH 074/423] Fix AMR --- src/time_integration/methods_SSP.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 1881cf15b0..0e250d967f 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -233,7 +233,7 @@ end function Base.resize!(integrator::SimpleIntegratorSSP, new_size) resize!(integrator.u, new_size) resize!(integrator.du, new_size) - resize!(integrator.u_tmp, new_size) + resize!(integrator.u_safe, new_size) resize!(integrator.u_old, new_size) # Resize container From 793033a9f03cace60a584715d68f8a778672c188 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 14 Jul 2022 12:49:07 +0200 Subject: [PATCH 075/423] Add AMR warning --- src/callbacks_step/amr.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index ac29abe92f..b0dc278cc0 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -125,7 +125,9 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u, t, integrator) semi = integrator.p if integrator isa SimpleIntegratorSSP - println("WARNING: The TVD property of IDP-FV-DG subcell blending shock-capturing methods is not guaranteed when using a non-conforming mesh (i.e. with AMR).\n") + println("WARNING: The TVD property of IDP-FV-DG subcell blending shock-capturing methods is not + guaranteed when using a non-conforming mesh (i.e. with AMR). Many operations are not implemented + for AMR yet.\n") end @trixi_timeit timer() "initial condition AMR" if amr_callback.adapt_initial_condition From 7e31ff09b011fa2329b7c6ba51ef2b5025175eca Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 15 Jul 2022 14:49:03 +0200 Subject: [PATCH 076/423] Add bounds check for pressure --- src/solvers/dgsem_tree/dg_2d.jl | 56 ++++++++++++++++++++++++++-- src/solvers/dgsem_tree/indicators.jl | 2 +- src/time_integration/methods_SSP.jl | 17 ++++----- 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 0f20e7c420..e0b1d3e5ea 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -947,6 +947,7 @@ end Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) + # approximation R_max R_max = lambda1[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + abs(bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + @@ -969,6 +970,7 @@ end Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) + # approximation R_max R_max = lambda2[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + abs(bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + @@ -1151,6 +1153,8 @@ end @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + n_vars = nvariables(equations) + @threaded for element in eachelement(solver, cache) idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] @@ -1160,10 +1164,21 @@ end rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - for v in 2:nvariables(equations) + if indicator.IDPPressureTVD + error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(idp_bounds_delta)) + end + for v in 2:n_vars var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) + if indicator.IDPPressureTVD + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressureTVD + error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited + idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) end end # +x @@ -1172,10 +1187,21 @@ end rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1[1, i+1, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - for v in 2:nvariables(equations) + if indicator.IDPPressureTVD + error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(idp_bounds_delta)) + end + for v in 2:n_vars var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1[v, i+1, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) + if indicator.IDPPressureTVD + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressureTVD + error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited + idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) end end # -y @@ -1184,10 +1210,21 @@ end rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - for v in 2:nvariables(equations) + if indicator.IDPPressureTVD + error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(idp_bounds_delta)) + end + for v in 2:n_vars var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) + if indicator.IDPPressureTVD + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressureTVD + error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited + idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) end end # +y @@ -1196,10 +1233,21 @@ end rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2[1, i, j+1, element] / lambda idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - for v in 2:nvariables(equations) + if indicator.IDPPressureTVD + error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(idp_bounds_delta)) + end + for v in 2:n_vars var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2[v, i, j+1, element] / lambda idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) + if indicator.IDPPressureTVD + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressureTVD + error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited + idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) end end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 3c37b59c8d..670983722d 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -244,7 +244,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; IDPPressureTVD=true, IDPCheckBounds=false) - cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)) + cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)+IDPPressureTVD) IndicatorMCL{typeof(cache)}(cache, IDPPressureTVD, IDPCheckBounds) end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index d58a6881d4..c81394bdf5 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -301,7 +301,7 @@ end end # check deviation from boundaries of IndicatorMCL -@inline function summary_check_bounds(indicator::IndicatorMCL) +@inline function summary_check_bounds(indicator::IndicatorMCL, equations::CompressibleEulerEquations2D) @unpack idp_bounds_delta_threaded = indicator.cache err_bounds = idp_bounds_delta_threaded[1] @@ -315,14 +315,13 @@ end println("─"^100) println("Maximum deviation from bounds:") println("─"^100) - println("rho_min: ", err_bounds[1]) - println("rho_max: ", err_bounds[2]) - println("rho_v1_min: ", err_bounds[3]) - println("rho_v1_max: ", err_bounds[4]) - println("rho_v2_min: ", err_bounds[5]) - println("rho_v2_max: ", err_bounds[6]) - println("rho_E_min: ", err_bounds[7]) - println("rho_E_max: ", err_bounds[8]) + variables = varnames(cons2cons, equations) + for v in eachvariable(equations) + println(variables[v], ":\n- lower bound: ", err_bounds[2*v-1], "\n- upper bound: ", err_bounds[2*v]) + end + if indicator.IDPPressureTVD + println("pressure:\n- lower bound: ", err_bounds[2*nvariables(equations)+1]) + end println("─"^100 * "\n") return nothing From 382b161eece64a6ad66e3b4b53be596ae6e4c7ec Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 15 Jul 2022 15:12:08 +0200 Subject: [PATCH 077/423] Update BoundsCheck routine --- src/time_integration/methods_SSP.jl | 32 +++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 0e250d967f..5ae1cc5aa5 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -201,7 +201,7 @@ function solve!(integrator::SimpleIntegratorSSP) # Check that we are within bounds if indicator.IDPCheckBounds - summary_check_bounds(indicator) + summary_check_bounds(indicator, integrator.p.equations) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), @@ -249,15 +249,15 @@ function Base.resize!(semi::AbstractSemidiscretization, new_size) end # check deviation from boundaries of IDP indicator -@inline function summary_check_bounds(indicator::IndicatorIDP) +@inline function summary_check_bounds(indicator::IndicatorIDP, equations::CompressibleEulerEquations2D) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator @unpack idp_bounds_delta_threaded = indicator.cache - idp_bounds_delta = zeros(eltype(idp_bounds_delta_threaded[1]), length(idp_bounds_delta_threaded[1])) + err_bounds = idp_bounds_delta_threaded[1] - for index in 1:length(idp_bounds_delta) - for i in 1:Threads.nthreads() - idp_bounds_delta[index] = max(idp_bounds_delta[index], idp_bounds_delta_threaded[i][index]) + for i in 2:Threads.nthreads() + for index in 1:length(err_bounds) + err_bounds[index] = max(err_bounds[index], idp_bounds_delta_threaded[i][index]) end end @@ -266,32 +266,28 @@ end println("─"^100) counter = 0 if IDPDensityTVD - counter += 1 - println("rho_min: ", idp_bounds_delta[counter]) - counter += 1 - println("rho_max: ", idp_bounds_delta[counter]) + counter += 2 + println("rho:\n- lower bound: ", err_bounds[counter-1], "\n- upper bound: ", err_bounds[counter]) end if IDPPressureTVD - counter += 1 - println("p_min: ", idp_bounds_delta[counter]) - counter += 1 - println("p_max: ", idp_bounds_delta[counter]) + counter += 2 + println("pressure:\n- lower bound: ", err_bounds[counter-1], "\n- upper bound: ", err_bounds[counter]) end if IDPPositivity && !IDPDensityTVD counter += 1 - println("rho_min: ", idp_bounds_delta[counter]) + println("rho:\n- positivity: ", err_bounds[counter]) end if IDPPositivity && !IDPPressureTVD counter += 1 - println("p_min: ", idp_bounds_delta[counter]) + println("pressure:\n- positivity: ", err_bounds[counter]) end if IDPSpecEntropy counter += 1 - println("ent_min: ", idp_bounds_delta[counter]) + println("spec. entropy:\n- lower bound: ", err_bounds[counter]) end if IDPMathEntropy counter += 1 - println("ent_max: ", idp_bounds_delta[counter]) + println("math. entropy:\n- upper bound: ", err_bounds[counter]) end println("─"^100 * "\n") From e1bace0ce9e8ecf8cbac0ca15781ce84b174126f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 5 Aug 2022 16:03:53 +0200 Subject: [PATCH 078/423] Fix newton method bug if state is not valid --- .../elixir_euler_colliding_flow_sc_subcell.jl | 2 +- src/equations/compressible_euler_2d.jl | 7 ++++ src/solvers/dgsem_tree/indicators_2d.jl | 33 +++++++++++++++---- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl index d259808a42..40e80bda06 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -92,7 +92,7 @@ save_solution = SaveSolutionCallback(interval=1000, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.4) +stepsize_callback = StepsizeCallback(cfl=0.35) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index e4b283fdac..f889f1a571 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1062,6 +1062,13 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end +@inline function isValidState(cons, equations::CompressibleEulerEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 502e537d1d..55f4176991 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -750,6 +750,8 @@ end @inline function newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_reltol, newton_abstol = indicator_IDP.newton_tol + beta = 1.0 - alpha[i, j, element] beta_L = 0.0 # alpha = 1 @@ -757,18 +759,23 @@ end u_curr = u_safe + beta * dt * antidiffusive_flux - # Perform initial Check - as = goal_fct(bound, u_curr, equations) + # If state is valid, perform initial check and return if correction is not needed + if isValidState(u_curr, equations) + as = goal_fct(bound, u_curr, equations) - newton_reltol, newton_abstol = indicator_IDP.newton_tol - initialCheck(bound, as, newton_abstol) && return nothing + initialCheck(bound, as, newton_abstol) && return nothing + end # Newton iterations for iter in 1:indicator_IDP.IDPMaxIter beta_old = beta - # Evaluate d(goal)/d(beta) - dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + # If the state is valid, evaluate d(goal)/d(beta) + if isValidState(u_curr, equations) + dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + else # Otherwise, perform a bisection step + dSdbeta = 0.0 + end if dSdbeta != 0.0 # Update beta with Newton's method @@ -781,6 +788,13 @@ end beta = 0.5 * (beta_L + beta_R) # Get new u u_curr = u_safe + beta * dt * antidiffusive_flux + + # If the state is invalid, finish bisection step without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + # Check new beta for condition and update bounds as = goal_fct(bound, u_curr, equations) if initialCheck(bound, as, newton_abstol) @@ -791,6 +805,13 @@ end else # Get new u u_curr = u_safe + beta * dt * antidiffusive_flux + + # If the state is invalid, redefine right bound without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + # Evaluate goal function as = goal_fct(bound, u_curr, equations) end From 698679de979ad85370326294588d11d4e11947d9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sat, 6 Aug 2022 11:30:52 +0200 Subject: [PATCH 079/423] Fix tests --- test/test_tree_2d_euler.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index a5ac74bb6e..bee54b1320 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -165,8 +165,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.49171288879147707, 0.16540604409411028, 0.165403281995138, 0.6346743704341865], - linf = [2.523187390223829, 1.1676864180461144, 1.1676912091995713, 6.469768610580735], + l2 = [0.49170711532017397, 0.16545207388505218, 0.16545210945870265, 0.6347169459573236], + linf = [2.525440391740859, 1.167550417094284, 1.1675492773007656, 6.468729876521227], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -190,8 +190,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_blob_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_sc_subcell.jl"), - l2 = [0.23649189278780317, 0.6993516078054665, 0.24313747935314953, 3.071644108599621], - linf = [7.850214101046176, 21.245196819766562, 10.004355873576252, 76.18578781492629], + l2 = [0.22952600868491232, 0.6598694971331289, 0.2375222572511259, 3.0485750678229198], + linf = [7.661392002055745, 19.336398494293007, 9.378519483511768, 79.18768909325449], tspan = (0.0, 0.5), initial_refinement_level=5) end @@ -255,8 +255,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.006567503201406924, 0.045494701197468755, 1.5604684539276876e-6, 0.624781570252251], - linf = [0.1448916669656563, 0.5279925643783724, 8.77139846451784e-5, 12.03029820002121], + l2 = [0.006577159539817667, 0.04554740746415583, 1.4554079130334693e-6, 0.6258024941421835], + linf = [0.14555535078246196, 0.5306125024728012, 8.590620121863414e-5, 12.092753540073211], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end @@ -271,8 +271,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), - l2 = [0.442412359159042, 353.54254537346463, 14.195423442065804, 138996.0083518854], - linf = [7.729364707886681, 5819.848679298194, 659.5925327100372, 2.1869838429080946e6], + l2 = [0.4399267169815457, 352.321452114897, 14.089381141646252, 138648.81629357373], + linf = [7.532813790308049, 5594.80343019963, 626.966037014211, 2.154789660969525e6], tspan = (2.5e-6, 1.0e-4), coverage_override = (maxiters=6,)) end From ab3c2fff1e5d314124cd24028f355c02d344dbff Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 25 Aug 2022 13:14:05 +0200 Subject: [PATCH 080/423] Restructure bounds calculation --- src/solvers/dgsem_tree/indicators_2d.jl | 284 +++++++++--------------- 1 file changed, 99 insertions(+), 185 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 55f4176991..ba3c6c6d52 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -212,15 +212,15 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, mesh, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, mesh, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP @@ -250,42 +250,98 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator +@inline function calc_bounds_2sided!(var_min, var_max, variable, u, mesh, equations, dg, cache) + # Values inside each element + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + # Calculate indicator variables at Gauss-Lobatto nodes + for j in eachnode(dg), i in eachnode(dg) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_min[i, j, element] = min(var_min[i, j, element], var) + var_max[i, j, element] = max(var_max[i, j, element], var) - rho_min = var_bounds[1] - rho_max = var_bounds[2] + if i > 1 + var_min[i-1, j, element] = min(var_min[i-1, j, element], var) + var_max[i-1, j, element] = max(var_max[i-1, j, element], var) + end + if i < nnodes(dg) + var_min[i+1, j, element] = min(var_min[i+1, j, element], var) + var_max[i+1, j, element] = max(var_max[i+1, j, element], var) + end + if j > 1 + var_min[i, j-1, element] = min(var_min[i, j-1, element], var) + var_max[i, j-1, element] = max(var_max[i, j-1, element], var) + end + if j < nnodes(dg) + var_min[i, j+1, element] = min(var_min[i, j+1, element], var) + var_max[i, j+1, element] = max(var_max[i, j+1, element], var) + end + end + end + + # Values at element boundary + calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh, equations, dg, cache) +end + +@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::TreeMesh2D, equations, dg, cache) + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) + var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) + + var_min[index_right...] = min(var_min[index_right...], var_left) + var_max[index_right...] = max(var_max[index_right...], var_left) + + var_min[index_left...] = min(var_min[index_left...], var_right) + var_max[index_left...] = max(var_max[index_left...], var_right) + end + end +end - # Calculate bound: rho_min, rho_max +@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, mesh, equations, dg, cache) + # Values inside each element @threaded for element in eachelement(dg, cache) - rho_min[:, :, element] .= typemax(eltype(rho_min)) - rho_max[:, :, element] .= typemin(eltype(rho_max)) + var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) + # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - rho = u_safe[1, i, j, element] - rho_min[i, j, element] = min(rho_min[i, j, element], rho) - rho_max[i, j, element] = max(rho_max[i, j, element], rho) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) if i > 1 - rho_min[i-1, j, element] = min(rho_min[i-1, j, element], rho) - rho_max[i-1, j, element] = max(rho_max[i-1, j, element], rho) + var_minmax[i-1, j, element] = minmax(var_minmax[i-1, j, element], var) end if i < nnodes(dg) - rho_min[i+1, j, element] = min(rho_min[i+1, j, element], rho) - rho_max[i+1, j, element] = max(rho_max[i+1, j, element], rho) + var_minmax[i+1, j, element] = minmax(var_minmax[i+1, j, element], var) end if j > 1 - rho_min[i, j-1, element] = min(rho_min[i, j-1, element], rho) - rho_max[i, j-1, element] = max(rho_max[i, j-1, element], rho) + var_minmax[i, j-1, element] = minmax(var_minmax[i, j-1, element], var) end if j < nnodes(dg) - rho_min[i, j+1, element] = min(rho_min[i, j+1, element], rho) - rho_max[i, j+1, element] = max(rho_max[i, j+1, element], rho) + var_minmax[i, j+1, element] = minmax(var_minmax[i, j+1, element], var) end end end - # Loop over interfaces + # Values at element boundary + calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh, equations, dg, cache) +end + +@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::TreeMesh2D, equations, dg, cache) for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] @@ -301,16 +357,21 @@ end index_left = (i, nnodes(dg), left) index_right = (i, 1, right) end - rho_left = u_safe[1, index_left...] - rho_right = u_safe[1, index_right...] + var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) + var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) - rho_min[index_right...] = min(rho_min[index_right...], rho_left) - rho_max[index_right...] = max(rho_max[index_right...], rho_left) - - rho_min[index_left...] = min(rho_min[index_left...], rho_right) - rho_max[index_left...] = max(rho_max[index_left...], rho_right) + var_minmax[index_right...] = minmax(var_minmax[index_right...], var_left) + var_minmax[index_left...] = minmax(var_minmax[index_left...], var_right) end end +end + +@inline function IDP_densityTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + rho_min = var_bounds[1] + rho_max = var_bounds[2] + calc_bounds_2sided!(rho_min, rho_max, density, u_safe, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -359,7 +420,7 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_pressureTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -367,62 +428,7 @@ end offset = 2 * indicator_IDP.IDPDensityTVD p_min = var_bounds[1 + offset] p_max = var_bounds[2 + offset] - - # Calculate bound: p_min, p_max - @threaded for element in eachelement(dg, cache) - p_min[:, :, element] .= typemax(eltype(p_min)) - p_max[:, :, element] .= typemin(eltype(p_max)) - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - - if i > 1 - p_min[i-1, j, element] = min(p_min[i-1, j, element], p) - p_max[i-1, j, element] = max(p_max[i-1, j, element], p) - end - if i < nnodes(dg) - p_min[i+1, j, element] = min(p_min[i+1, j, element], p) - p_max[i+1, j, element] = max(p_max[i+1, j, element], p) - end - if j > 1 - p_min[i, j-1, element] = min(p_min[i, j-1, element], p) - p_max[i, j-1, element] = max(p_max[i, j-1, element], p) - end - if j < nnodes(dg) - p_min[i, j+1, element] = min(p_min[i, j+1, element], p) - p_max[i, j+1, element] = max(p_max[i, j+1, element], p) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - p_left = pressure(get_node_vars(u_safe, equations, dg, index_left...), equations) - p_right = pressure(get_node_vars(u_safe, equations, dg, index_right...), equations) - - p_min[index_right...] = min(p_min[index_right...], p_left) - p_max[index_right...] = max(p_max[index_right...], p_left) - - p_min[index_left...] = min(p_min[index_left...], p_right) - p_max[index_left...] = max(p_max[index_left...], p_right) - end - end + calc_bounds_2sided!(p_min, p_max, pressure, u_safe, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -480,59 +486,13 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_specEntropy!(alpha, mesh, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) s_min = var_bounds[offset + 1] - - # Calculate bound: s_min - @threaded for element in eachelement(dg, cache) - s_min[:, :, element] .= typemax(eltype(s_min)) - for j in eachnode(dg), i in eachnode(dg) - - # Get limit states - s = entropy_spec(get_node_vars(u_old, equations, dg, i, j, element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - if i > 1 - s_min[i-1, j, element] = min(s_min[i-1, j, element], s) - end - if i < nnodes(dg) - s_min[i+1, j, element] = min(s_min[i+1, j, element], s) - end - if j > 1 - s_min[i, j-1, element] = min(s_min[i, j-1, element], s) - end - if j < nnodes(dg) - s_min[i, j+1, element] = min(s_min[i, j+1, element], s) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - s_left = entropy_spec(get_node_vars(u_old, equations, dg, index_left...), equations) - s_right = entropy_spec(get_node_vars(u_old, equations, dg, index_right...), equations) - - s_min[index_right...] = min(s_min[index_right...], s_left) - s_min[index_left...] = min(s_min[index_left...], s_right) - end - end + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -551,60 +511,14 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_mathEntropy!(alpha, mesh, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) s_max = var_bounds[offset + 1] - - # Calculate bound: s_max - @threaded for element in eachelement(dg, cache) - s_max[:, :, element] .= typemin(eltype(s_max)) - for j in eachnode(dg), i in eachnode(dg) - - # Get limit states - s = entropy_math(get_node_vars(u_old, equations, dg, i, j, element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - if i > 1 - s_max[i-1, j, element] = max(s_max[i-1, j, element], s) - end - if i < nnodes(dg) - s_max[i+1, j, element] = max(s_max[i+1, j, element], s) - end - if j > 1 - s_max[i, j-1, element] = max(s_max[i, j-1, element], s) - end - if j < nnodes(dg) - s_max[i, j+1, element] = max(s_max[i, j+1, element], s) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - s_left = entropy_math(get_node_vars(u_old, equations, dg, index_left...), equations) - s_right = entropy_math(get_node_vars(u_old, equations, dg, index_right...), equations) - - s_max[index_right...] = max(s_max[index_right...], s_left) - s_max[index_left...] = max(s_max[index_left...], s_right) - end - end + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -623,7 +537,7 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_positivity!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP From 4cbf4b06e491d62cdb93147130a4b8ca881f6933 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 26 Aug 2022 16:13:58 +0200 Subject: [PATCH 081/423] Add perform correction function --- src/solvers/dgsem_tree/dg_2d.jl | 27 ++++++++++++++++--------- src/solvers/dgsem_tree/indicators_2d.jl | 4 ++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 0bb8fce882..24f9d4ded2 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -671,25 +671,32 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - @unpack inverse_weights = solver.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) - @unpack alpha1, alpha2 = semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(solver, cache) + perform_IDP_correction(u, dt, mesh, equations, solver, cache) + + return nothing +end + +@inline function perform_IDP_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + + @threaded for element in eachelement(dg, cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] # Calculate volume integral contribution - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - for j in eachnode(solver), i in eachnode(solver) - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) + for j in eachnode(dg), i in eachnode(dg) + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ba3c6c6d52..17ebc9d271 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -241,9 +241,9 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab for j in 2:nnodes(dg), i in eachnode(dg) alpha2[i, j, element] = max(alpha[i, j-1, element], alpha[i, j, element]) end - alpha1[1, :, element] .= zero(eltype(alpha1)) + alpha1[1, :, element] .= zero(eltype(alpha1)) alpha1[nnodes(dg)+1, :, element] .= zero(eltype(alpha1)) - alpha2[:, 1, element] .= zero(eltype(alpha2)) + alpha2[:, 1, element] .= zero(eltype(alpha2)) alpha2[:, nnodes(dg)+1, element] .= zero(eltype(alpha2)) end From 1028cda2405015f76d03b4020be17237be333699 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 30 Aug 2022 15:09:31 +0200 Subject: [PATCH 082/423] Add mesh to parameters --- src/solvers/dgsem_structured/indicators_2d.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 1 - src/solvers/dgsem_tree/indicators_2d.jl | 28 +++++++++---------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index abc054b572..4e0296a0f0 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -16,7 +16,7 @@ function apply_smoothing!(mesh::StructuredMesh{2}, alpha, alpha_tmp, dg, cache) for element in eachelement(dg,cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] + lower = cache.elements.left_neighbors[2, element] # Apply smoothing alpha[left] = max(alpha_tmp[left], 0.5 * alpha_tmp[element], alpha[left]) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 24f9d4ded2..f5775712cb 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -690,7 +690,6 @@ end @threaded for element in eachelement(dg, cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] - # Calculate volume integral contribution for j in eachnode(dg), i in eachnode(dg) # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 17ebc9d271..32e51a0e28 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -212,15 +212,15 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, mesh, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, mesh, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP @@ -366,7 +366,7 @@ end end end -@inline function IDP_densityTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator rho_min = var_bounds[1] @@ -420,7 +420,7 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -486,7 +486,7 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, mesh, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -500,7 +500,7 @@ end u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -511,7 +511,7 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, mesh, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -526,7 +526,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -537,7 +537,7 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, mesh, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -621,7 +621,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -635,7 +635,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma @inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D inverse_jacobian = cache.elements.inverse_jacobian[element] From d97141ca482054a9b0fa36f2855a6683acfa8fc6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 21 Oct 2022 20:27:26 +0200 Subject: [PATCH 083/423] Fix alpha_per_timestep computation --- src/solvers/dgsem_tree/indicators_2d.jl | 12 +++++++++++- src/time_integration/methods_SSP.jl | 15 ++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 32e51a0e28..1bfe8a7c1c 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -209,7 +209,7 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab dt, cache; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator - alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. + alpha .= 0.0 indicator_IDP.IDPDensityTVD && @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) @@ -753,6 +753,16 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) +@inline function update_alpha_per_timestep!(alpha_max_per_timestep, alpha_mean_per_timestep, alpha, + timestep, n_stages, semi) + _, equations, solver, cache = mesh_equations_solver_cache(semi) + n_elements = nelements(solver, cache) + n_nodes = nnodes(solver)^ndims(equations) + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_mean_per_timestep[timestep] += 1/(n_stages * n_nodes * n_elements) * sum(alpha) + + return nothing +end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 5ae1cc5aa5..1f44c75a7a 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -152,6 +152,11 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) + update_alpha_per_timestep!(indicator.cache.alpha_max_per_timestep, + indicator.cache.alpha_mean_per_timestep, + indicator.cache.ContainerShockCapturingIndicator.alpha, + integrator.iter+1, length(alg.c), integrator.p) + # Check that we are within bounds if indicator.IDPCheckBounds @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) @@ -168,18 +173,14 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. - if integrator.iter == length(indicator.cache.alpha_max_per_timestep) + if integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep new_length = length(indicator.cache.alpha_max_per_timestep) + 200 resize!(indicator.cache.alpha_max_per_timestep, new_length) resize!(indicator.cache.alpha_mean_per_timestep, new_length) + indicator.cache.alpha_max_per_timestep[new_length - 199:new_length] .= 0.0 + indicator.cache.alpha_mean_per_timestep[new_length - 199:new_length] .= 0.0 end - indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) - indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = - (1/(nnodes(integrator.p.solver)^ndims(integrator.p.equations) * nelements(integrator.p.solver, integrator.p.cache))) * - sum(indicator.cache.ContainerShockCapturingIndicator.alpha) - integrator.iter += 1 integrator.t += integrator.dt From f0f66b23881e04b4efc5e3923cef14772e2d5487 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 25 Oct 2022 18:02:42 +0200 Subject: [PATCH 084/423] Merge staggered-grid-volume-integral into IndicatorMCL --- .github/workflows/Invalidations.yml | 40 ++ .github/workflows/ci.yml | 1 + NEWS.md | 16 + Project.toml | 8 +- README.md | 19 + docs/Project.toml | 2 +- docs/literate/src/files/DGSEM_FluxDiff.jl | 8 +- .../src/files/adding_new_parabolic_terms.jl | 160 +++++ docs/literate/src/files/parabolic_terms.jl | 88 +++ docs/literate/src/files/time_stepping.jl | 2 + docs/make.jl | 2 + docs/src/index.md | 7 + docs/src/visualization.md | 4 +- .../dgmulti_1d/elixir_advection_gauss_sbp.jl | 69 ++ .../dgmulti_2d/elixir_advection_diffusion.jl | 56 ++ .../elixir_advection_diffusion_nonperiodic.jl | 72 +++ .../elixir_advection_diffusion_periodic.jl | 35 + .../elixir_navierstokes_convergence.jl | 205 ++++++ .../elixir_navierstokes_lid_driven_cavity.jl | 73 +++ .../elixir_advection_diffusion.jl | 83 +++ .../elixir_advection_diffusion_nonperiodic.jl | 89 +++ .../elixir_euler_colliding_flow_sc_subcell.jl | 2 +- .../elixir_navierstokes_convergence.jl | 213 ++++++ .../elixir_navierstokes_lid_driven_cavity.jl | 79 +++ src/Trixi.jl | 29 +- src/auxiliary/auxiliary.jl | 32 +- src/basic_types.jl | 14 + src/callbacks_step/amr_dg.jl | 2 +- src/callbacks_step/amr_dg2d.jl | 2 +- src/callbacks_step/analysis.jl | 6 +- src/equations/compressible_euler_1d.jl | 4 +- src/equations/compressible_euler_2d.jl | 21 +- src/equations/compressible_euler_3d.jl | 8 +- .../compressible_euler_multicomponent_1d.jl | 10 +- .../compressible_euler_multicomponent_2d.jl | 12 +- .../compressible_navier_stokes_2d.jl | 407 ++++++++++++ src/equations/equations.jl | 20 + src/equations/equations_parabolic.jl | 11 + src/equations/laplace_diffusion_2d.jl | 58 ++ src/equations/linear_scalar_advection_1d.jl | 2 +- src/semidiscretization/semidiscretization.jl | 6 +- ...semidiscretization_hyperbolic_parabolic.jl | 264 ++++++++ src/solvers/dgmulti.jl | 3 + src/solvers/dgmulti/dg.jl | 67 +- src/solvers/dgmulti/dg_parabolic.jl | 322 ++++++++++ src/solvers/dgmulti/flux_differencing.jl | 67 +- .../dgmulti/flux_differencing_gauss_sbp.jl | 37 +- src/solvers/dgmulti/sbp.jl | 13 +- src/solvers/dgsem_p4est/dg_2d.jl | 1 + src/solvers/dgsem_p4est/dg_3d.jl | 1 + src/solvers/dgsem_p4est/dg_parallel.jl | 16 +- src/solvers/dgsem_structured/indicators_2d.jl | 2 +- src/solvers/dgsem_tree/dg.jl | 1 + src/solvers/dgsem_tree/dg_1d.jl | 9 +- src/solvers/dgsem_tree/dg_2d.jl | 36 +- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 605 ++++++++++++++++++ src/solvers/dgsem_tree/dg_2d_parallel.jl | 8 +- src/solvers/dgsem_tree/dg_3d.jl | 1 + src/solvers/dgsem_tree/indicators.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 341 +++++----- src/solvers/dgsem_unstructured/dg_2d.jl | 1 + src/solvers/solvers.jl | 3 +- src/solvers/solvers_parabolic.jl | 31 + src/time_integration/methods_2N.jl | 7 +- src/time_integration/methods_3Sstar.jl | 5 +- src/time_integration/methods_SSP.jl | 26 +- test/Project.toml | 4 +- test/runtests.jl | 4 + test/test_dgmulti_1d.jl | 9 + test/test_dgmulti_2d.jl | 5 +- test/test_dgmulti_3d.jl | 4 +- test/test_parabolic_2d.jl | 185 ++++++ test/test_tree_2d_euler.jl | 16 +- 73 files changed, 3714 insertions(+), 359 deletions(-) create mode 100644 .github/workflows/Invalidations.yml create mode 100644 docs/literate/src/files/adding_new_parabolic_terms.jl create mode 100644 docs/literate/src/files/parabolic_terms.jl create mode 100644 examples/dgmulti_1d/elixir_advection_gauss_sbp.jl create mode 100644 examples/dgmulti_2d/elixir_advection_diffusion.jl create mode 100644 examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl create mode 100644 examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl create mode 100644 examples/dgmulti_2d/elixir_navierstokes_convergence.jl create mode 100644 examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl create mode 100644 examples/tree_2d_dgsem/elixir_advection_diffusion.jl create mode 100644 examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl create mode 100644 examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl create mode 100644 examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl create mode 100644 src/equations/compressible_navier_stokes_2d.jl create mode 100644 src/equations/equations_parabolic.jl create mode 100644 src/equations/laplace_diffusion_2d.jl create mode 100644 src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl create mode 100644 src/solvers/dgmulti/dg_parabolic.jl create mode 100644 src/solvers/dgsem_tree/dg_2d_parabolic.jl create mode 100644 src/solvers/solvers_parabolic.jl create mode 100644 test/test_parabolic_2d.jl diff --git a/.github/workflows/Invalidations.yml b/.github/workflows/Invalidations.yml new file mode 100644 index 0000000000..ba81f83e0a --- /dev/null +++ b/.github/workflows/Invalidations.yml @@ -0,0 +1,40 @@ +name: Invalidations + +on: + pull_request: + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: always. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + no_additional_invalidations: + # Only run on PRs to the default branch. + # In the PR trigger above branches can be specified only explicitly whereas this check should work for master, main, or any other default branch + if: github.base_ref == github.event.repository.default_branch + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@v1 + with: + version: '1' + - uses: actions/checkout@v3 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-invalidations@v1 + id: invs_pr + + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.repository.default_branch }} + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-invalidations@v1 + id: invs_default + + - name: Report invalidation counts + run: | + echo "Invalidations on default branch: ${{ steps.invs_default.outputs.total }} (${{ steps.invs_default.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY + echo "This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY + - name: Check if the PR does increase number of invalidations + if: steps.invs_pr.outputs.total > steps.invs_default.outputs.total + run: exit 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f257da07a4..6aba503691 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,7 @@ jobs: - p4est_part1 - p4est_part2 - unstructured_dgmulti + - parabolic - paper_self_gravitating_gas_dynamics - misc_part1 - misc_part2 diff --git a/NEWS.md b/NEWS.md index 134173068b..c816bdfe56 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,22 @@ for human readability. #### Added +- Experimental support for 2D parabolic diffusion terms has been added. + * `LaplaceDiffusion2D` and `CompressibleNavierStokesDiffusion2D` can be used to add + diffusion to systems. `LaplaceDiffusion2D` can be used to add scalar diffusion to each + equation of a system, while `CompressibleNavierStokesDiffusion2D` can be used to add + Navier-Stokes diffusion to `CompressibleEulerEquations2D`. + * Parabolic boundary conditions can be imposed as well. For `LaplaceDiffusion2D`, both + `Dirichlet` and `Neumann` conditions are supported. For `CompressibleNavierStokesDiffusion2D`, + viscous no-slip velocity boundary conditions are supported, along with adiabatic and isothermal + temperature boundary conditions. See the boundary condition container + `BoundaryConditionNavierStokesWall` and boundary condition types `NoSlip`, `Adiabatic`, and + `Isothermal` for more information. + * `CompressibleNavierStokesDiffusion2D` can utilize both primitive variables (which are not + guaranteed to provably dissipate entropy) and entropy variables (which provably dissipate + entropy at the semi-discrete level). + * Please check the `examples` directory for further information about the supported setups. + Further documentation will be added later. - Numerical fluxes `flux_shima_etal_turbo` and `flux_ranocha_turbo` that are equivalent to their non-`_turbo` counterparts but may enable specialized methods making use of SIMD instructions to increase runtime efficiency diff --git a/Project.toml b/Project.toml index 1b1586060e..76f3898e84 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.4.42-pre" +version = "0.4.50-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" @@ -51,7 +51,7 @@ HDF5 = "0.14, 0.15, 0.16" IfElse = "0.1" LinearMaps = "2.7, 3.0" LoopVectorization = "0.12.118" -MPI = "0.19" +MPI = "0.20" MuladdMacro = "0.2.2" Octavian = "0.3.5" OffsetArrays = "1.3" @@ -62,8 +62,8 @@ Reexport = "1.0" Requires = "1.1" SciMLBase = "1.21" Setfield = "0.8, 1" -StartUpDG = "0.13.1" -Static = "0.3, 0.4, 0.5, 0.6" +StartUpDG = "0.14" +Static = "0.3, 0.4, 0.5, 0.6, 0.7" StaticArrays = "1" StrideArrays = "0.1.18" StructArrays = "0.6" diff --git a/README.md b/README.md index 39c6b3a668..93fbd7abc2 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,18 @@

+*** +**Trixi.jl at JuliaCon 2022**
+At this year's JuliaCon 2022, we have been present with two contributions that involve Trixi.jl: + +* [Running Julia code in parallel with MPI: Lessons learned](https://live.juliacon.org/talk/LUWYRJ), + 26th July 2022. [Watch on YouTube](https://youtu.be/fog1x9rs71Q?t=5172), [repo](https://github.com/JuliaParallel/juliacon-2022-julia-for-hpc-minisymposium) +* [From Mesh Generation to Adaptive Simulation: A Journey in Julia](https://live.juliacon.org/talk/YSLKZJ), + 27th July 2022. [Watch on YouTube](https://youtu.be/_N4ozHr-t9E), [repo](https://github.com/trixi-framework/talk-2022-juliacon_toolchain) + +If you have questions about Trixi.jl or our other projects, feel free to get in touch via Slack or open an issue ♥️ +*** + **Trixi.jl** is a numerical simulation framework for hyperbolic conservation laws written in [Julia](https://julialang.org). A key objective for the framework is to be useful to both scientists and students. Therefore, next to @@ -156,6 +168,13 @@ of a Julia method is typically slow, with subsequent runs being much faster. For instance, in the example above the first execution of `trixi_include` takes about 20 seconds, while subsequent runs require less than 60 *milli*seconds. +### Showcase of advanced features +The presentation [From Mesh Generation to Adaptive Simulation: A Journey in Julia](https://youtu.be/_N4ozHr-t9E), +originally given as part of JuliaCon 2022, outlines how to use Trixi for an adaptive simulation +of the compressible Euler equations in two spatial dimensions on a complex domain. More details +as well as code to run the simulation presented can be found at the +[reproducibility repository](https://github.com/trixi-framework/talk-2022-juliacon_toolchain) +for the presentation. ## Documentation Additional documentation is available that contains more information on how to diff --git a/docs/Project.toml b/docs/Project.toml index 5384679af9..d1466ac021 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -12,7 +12,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Trixi2Vtk = "bc1476a1-1ca6-4cc3-950b-c312b255ff95" [compat] -CairoMakie = "0.6, 0.7, 0.8" +CairoMakie = "0.6, 0.7, 0.8, 0.9" Documenter = "0.27" ForwardDiff = "0.10" HOHQMesh = "0.1, 0.2" diff --git a/docs/literate/src/files/DGSEM_FluxDiff.jl b/docs/literate/src/files/DGSEM_FluxDiff.jl index e508ebdb4b..3bd4995fd4 100644 --- a/docs/literate/src/files/DGSEM_FluxDiff.jl +++ b/docs/literate/src/files/DGSEM_FluxDiff.jl @@ -82,7 +82,13 @@ # When using the diagonal SBP property it is possible to rewrite the application of the derivative # operator $D$ in the calculation of the volume integral into a subcell based finite volume type # differencing formulation ([Fisher, Carpenter (2013)](https://doi.org/10.1016/j.jcp.2013.06.014)). -# We replace $D \underline{f}$ in the strong form by $2D \underline{f}_{vol}(u^-, u^+)$ with +# Generalizing +# ```math +# (D \underline{f})_i = \sum_j D_{i,j} \underline{f}_j +# = 2\sum_j \frac{1}{2} D_{i,j} (\underline{f}_j + \underline{f}_i) +# \eqqcolon 2\sum_j D_{i,j} f_\text{central}(u_i, u_j), +# ``` +# we replace $D \underline{f}$ in the strong form by $2D \underline{f}_{vol}(u^-, u^+)$ with # the consistent two-point volume flux $f_{vol}$ and receive the DGSEM formulation with flux differencing # (split form DGSEM) ([Gassner, Winters, Kopriva (2016)](https://doi.org/10.1016/j.jcp.2016.09.013)). diff --git a/docs/literate/src/files/adding_new_parabolic_terms.jl b/docs/literate/src/files/adding_new_parabolic_terms.jl new file mode 100644 index 0000000000..a6cecb351b --- /dev/null +++ b/docs/literate/src/files/adding_new_parabolic_terms.jl @@ -0,0 +1,160 @@ +#src # Adding new parabolic terms. + +# This demo illustrates the steps involved in adding new parabolic terms for the scalar +# advection equation. In particular, we will add an anisotropic diffusion. We begin by +# defining the hyperbolic (advection) part of the advection-diffusion equation. + +using OrdinaryDiffEq +using Trixi + + +advection_velocity = (1.0, 1.0) +equations_hyperbolic = LinearScalarAdvectionEquation2D(advection_velocity); + +# ## Define a new parabolic equation type +# +# Next, we define a 2D parabolic diffusion term type. This is similar to [`LaplaceDiffusion2D`](@ref) +# except that the `diffusivity` field refers to a spatially constant diffusivity matrix now. Note that +# `ConstantAnisotropicDiffusion2D` has a field for `equations_hyperbolic`. It is useful to have +# information about the hyperbolic system available to the parabolic part so that we can reuse +# functions defined for hyperbolic equations (such as `varnames`). + +struct ConstantAnisotropicDiffusion2D{E, T} <: Trixi.AbstractEquationsParabolic{2, 1} + diffusivity::T + equations_hyperbolic::E +end + +varnames(variable_mapping, equations_parabolic::ConstantAnisotropicDiffusion2D) = + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) + +# Next, we define the viscous flux function. We assume that the mixed hyperbolic-parabolic system +# is of the form +# ```math +# \partial_t u(t,x) + \partial_x (f_1(u) - g_1(u, \nabla u)) +# + \partial_y (f_2(u) - g_2(u, \nabla u)) = 0 +# ``` +# where ``f_1(u)``, ``f_2(u)`` are the hyperbolic fluxes and ``g_1(u, \nabla u)``, ``g_2(u, \nabla u)`` denote +# the viscous fluxes. For anisotropic diffusion, the viscous fluxes are the first and second components +# of the matrix-vector product involving `diffusivity` and the gradient vector. +# +# Here, we specialize the flux to our new parabolic equation type `ConstantAnisotropicDiffusion2D`. + +function Trixi.flux(u, gradients, orientation::Integer, equations_parabolic::ConstantAnisotropicDiffusion2D) + @unpack diffusivity = equations_parabolic + dudx, dudy = gradients + if orientation == 1 + return SVector(diffusivity[1, 1] * dudx + diffusivity[1, 2] * dudy) + else # if orientation == 2 + return SVector(diffusivity[2, 1] * dudx + diffusivity[2, 2] * dudy) + end +end + +# ## Defining boundary conditions + +# Trixi.jl's implementation of parabolic terms discretizes both the gradient and divergence +# using weak formulation. In other words, we discretize the system +# ```math +# \begin{aligned} +# \bm{q} &= \nabla u \\ +# \bm{\sigma} &= \begin{pmatrix} g_1(u, \bm{q}) \\ g_2(u, \bm{q}) \end{pmatrix} \\ +# \text{viscous contribution } &= \nabla \cdot \bm{\sigma} +# \end{aligned} +# ``` +# +# Boundary data must be specified for all spatial derivatives, e.g., for both the gradient +# equation ``\bm{q} = \nabla u`` and the divergence of the viscous flux +# ``\nabla \cdot \bm{\sigma}``. We account for this by introducing internal `Gradient` +# and `Divergence` types which are used to dispatch on each type of boundary condition. +# +# As an example, let us introduce a Dirichlet boundary condition with constant boundary data. + +struct BoundaryConditionConstantDirichlet{T <: Real} + boundary_value::T +end + +# This boundary condition contains only the field `boundary_value`, which we assume to be some +# real-valued constant which we will impose as the Dirichlet data on the boundary. +# +# Boundary conditions have generally been defined as "callable structs" (also known as "functors"). +# For each boundary condition, we need to specify the appropriate boundary data to return for both +# the `Gradient` and `Divergence`. Since the gradient is operating on the solution `u`, the boundary +# data should be the value of `u`, and we can directly impose Dirichlet data. + +@inline function (boundary_condition::BoundaryConditionConstantDirichlet)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Trixi.Gradient, + equations_parabolic::ConstantAnisotropicDiffusion2D) + return boundary_condition.boundary_value +end + +# While the gradient acts on the solution `u`, the divergence acts on the viscous flux ``\bm{\sigma}``. +# Thus, we have to supply boundary data for the `Divergence` operator that corresponds to ``\bm{\sigma}``. +# However, we've already imposed boundary data on `u` for a Dirichlet boundary condition, and imposing +# boundary data for ``\bm{\sigma}`` might overconstrain our problem. +# +# Thus, for the `Divergence` boundary data under a Dirichlet boundary condition, we simply return +# `flux_inner`, which is boundary data for ``\bm{\sigma}`` computed using the "inner" or interior solution. +# This way, we supply boundary data for the divergence operation without imposing any additional conditions. + +@inline function (boundary_condition::BoundaryConditionConstantDirichlet)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Trixi.Divergence, + equations_parabolic::ConstantAnisotropicDiffusion2D) + return flux_inner +end + +# ### A note on the choice of gradient variables +# +# It is often simpler to transform the solution variables (and solution gradients) to another set of +# variables prior to computing the viscous fluxes (see [`CompressibleNavierStokesDiffusion2D`](@ref) +# for an example of this). If this is done, then the boundary condition for the `Gradient` operator +# should be modified accordingly as well. +# +# ## Putting things together +# +# Finally, we can instantiate our new parabolic equation type, define boundary conditions, +# and run a simulation. The specific anisotropic diffusion matrix we use produces more +# dissipation in the direction ``(1, -1)`` as an isotropic diffusion. +# +# For boundary conditions, we impose that ``u=1`` on the left wall, ``u=2`` on the bottom +# wall, and ``u = 0`` on the outflow walls. The initial condition is taken to be ``u = 0``. +# Note that we use `BoundaryConditionConstantDirichlet` only for the parabolic boundary +# conditions, since we have not defined its behavior for the hyperbolic part. + +using Trixi: SMatrix +diffusivity = 5.0e-2 * SMatrix{2, 2}([2 -1; -1 2]) +equations_parabolic = ConstantAnisotropicDiffusion2D(diffusivity, equations_hyperbolic); + +boundary_conditions_hyperbolic = (; x_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(1.0)), + y_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(2.0)), + y_pos = boundary_condition_do_nothing, + x_pos = boundary_condition_do_nothing) + +boundary_conditions_parabolic = (; x_neg = BoundaryConditionConstantDirichlet(1.0), + y_neg = BoundaryConditionConstantDirichlet(2.0), + y_pos = BoundaryConditionConstantDirichlet(0.0), + x_pos = BoundaryConditionConstantDirichlet(0.0)); + +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=false, n_cells_max=30_000) # set maximum capacity of tree data structure + +initial_condition = (x, t, equations) -> SVector(0.0) + +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations_hyperbolic, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions_hyperbolic, + boundary_conditions_parabolic)) + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) +callbacks = CallbackSet(SummaryCallback()) +time_int_tol = 1.0e-6 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks); + +using Plots +plot(sol) + diff --git a/docs/literate/src/files/parabolic_terms.jl b/docs/literate/src/files/parabolic_terms.jl new file mode 100644 index 0000000000..aeceb7b7e6 --- /dev/null +++ b/docs/literate/src/files/parabolic_terms.jl @@ -0,0 +1,88 @@ +#src # Parabolic terms (advection-diffusion). + +# Experimental support for parabolic diffusion terms is available in Trixi.jl. +# This demo illustrates parabolic terms for the advection-diffusion equation. + +using OrdinaryDiffEq +using Trixi + +# ## Splitting a system into hyperbolic and parabolic parts. + +# For a mixed hyperbolic-parabolic system, we represent the hyperbolic and parabolic +# parts of the system separately. We first define the hyperbolic (advection) part of +# the advection-diffusion equation. + +advection_velocity = (1.5, 1.0) +equations_hyperbolic = LinearScalarAdvectionEquation2D(advection_velocity); + +# Next, we define the parabolic diffusion term. The constructor requires knowledge of +# `equations_hyperbolic` to be passed in because the [`LaplaceDiffusion2D`](@ref) applies +# diffusion to every variable of the hyperbolic system. + +diffusivity = 5.0e-2 +equations_parabolic = LaplaceDiffusion2D(diffusivity, equations_hyperbolic); + +# ## Boundary conditions + +# As with the equations, we define boundary conditions separately for the hyperbolic and +# parabolic part of the system. For this example, we impose inflow BCs for the hyperbolic +# system (no condition is imposed on the outflow), and we impose Dirichlet boundary conditions +# for the parabolic equations. Both `BoundaryConditionDirichlet` and `BoundaryConditionNeumann` +# are defined for `LaplaceDiffusion2D`. +# +# The hyperbolic and parabolic boundary conditions are assumed to be consistent with each other. + +boundary_condition_zero_dirichlet = BoundaryConditionDirichlet((x, t, equations) -> SVector(0.0)) + +boundary_conditions_hyperbolic = (; x_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + 0.5 * x[2])), + y_neg = boundary_condition_zero_dirichlet, + y_pos = boundary_condition_do_nothing, + x_pos = boundary_condition_do_nothing) + +boundary_conditions_parabolic = (; x_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + 0.5 * x[2])), + y_neg = boundary_condition_zero_dirichlet, + y_pos = boundary_condition_zero_dirichlet, + x_pos = boundary_condition_zero_dirichlet); + +# ## Defining the solver and mesh + +# The process of creating the DG solver and mesh is the same as for a purely +# hyperbolic system of equations. + +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=false, n_cells_max=30_000) # set maximum capacity of tree data structure + +initial_condition = (x, t, equations) -> SVector(0.0); + +# ## Semidiscretizing and solving + +# To semidiscretize a hyperbolic-parabolic system, we create a [`SemidiscretizationHyperbolicParabolic`](@ref). +# This differs from a [`SemidiscretizationHyperbolic`](@ref) in that we pass in a `Tuple` containing both the +# hyperbolic and parabolic equation, as well as a `Tuple` containing the hyperbolic and parabolic +# boundary conditions. + +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations_hyperbolic, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions_hyperbolic, + boundary_conditions_parabolic)) + +# The rest of the code is identical to the hyperbolic case. We create a system of ODEs through +# `semidiscretize`, defining callbacks, and then passing the system to OrdinaryDiffEq.jl. + +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan) +callbacks = CallbackSet(SummaryCallback()) +time_int_tol = 1.0e-6 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks); + +# We can now visualize the solution, which develops a boundary layer at the outflow boundaries. + +using Plots +plot(sol) + diff --git a/docs/literate/src/files/time_stepping.jl b/docs/literate/src/files/time_stepping.jl index 8fbebdf046..3a09fec452 100644 --- a/docs/literate/src/files/time_stepping.jl +++ b/docs/literate/src/files/time_stepping.jl @@ -46,6 +46,8 @@ # ```math # \Delta t_n = \text{CFL} * \min_i \frac{\Delta x_i}{\lambda_{\max}(u_i^n)} # ``` +# We compute $\Delta x_i$ by scaling the element size by a factor of $1/(N+1)$, cf. +# [Gassner and Kopriva (2011)](https://doi.org/10.1137/100807211), Section 5. # Trixi provides such a CFL-based step size control. It is implemented as the callback # [`StepsizeCallback`](@ref). diff --git a/docs/make.jl b/docs/make.jl index 5732167748..d8d1298fba 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -39,6 +39,8 @@ files = [ # Topic: equations "Adding a new scalar conservation law" => "adding_new_scalar_equations.jl", "Adding a non-conservative equation" => "adding_nonconservative_equation.jl", + "Parabolic terms" => "parabolic_terms.jl", + "Adding new parabolic terms" => "adding_new_parabolic_terms.jl", # Topic: meshes "Adaptive mesh refinement" => "adaptive_mesh_refinement.jl", "Structured mesh with curvilinear mapping" => "structured_mesh_mapping.jl", diff --git a/docs/src/index.md b/docs/src/index.md index c46ee9d501..481279155f 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -269,6 +269,13 @@ mean 3.94 mean 3.94 mean 3.94 mean 3.93 -------------------------------------------------------------------------------- ``` +### Showcase of advanced features +The presentation [From Mesh Generation to Adaptive Simulation: A Journey in Julia](https://youtu.be/_N4ozHr-t9E), +originally given as part of JuliaCon 2022, outlines how to use Trixi for an adaptive simulation +of the compressible Euler equations in two spatial dimensions on a complex domain. More details +as well as code to run the simulation presented can be found at the +[reproducibility repository](https://github.com/trixi-framework/talk-2022-juliacon_toolchain) +for the presentation. ## Referencing If you use Trixi in your own research or write a paper using results obtained diff --git a/docs/src/visualization.md b/docs/src/visualization.md index 2a9791fe19..90f612de01 100644 --- a/docs/src/visualization.md +++ b/docs/src/visualization.md @@ -221,8 +221,8 @@ This creates the following plot: ![ScalarPlotData2D_example](https://user-images.githubusercontent.com/1156048/133856590-a9f0be02-8200-483b-af96-eab4a69bf2c7.png) ### Plotting a 3D solution as a 2D plot -It is possible to plot 2D slices from 3D simulation data with the same commands -as above: +It is possible to plot 2D slices from 3D simulation data using the [`TreeMesh`](@ref) +with the same commands as above: ```julia julia> plot(sol) # `sol` is from a 3D simulation ``` diff --git a/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl new file mode 100644 index 0000000000..73a264544c --- /dev/null +++ b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl @@ -0,0 +1,69 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# setup the equations + +advection_velocity = 1.0 +equations = LinearScalarAdvectionEquation1D(advection_velocity) + +############################################################################### +# setup the GSBP DG discretization that uses the Gauss operators from Chan et al. + +surface_flux = FluxLaxFriedrichs() +dg = DGMulti(polydeg = 3, + element_type = Line(), + approximation_type = GaussSBP(), + surface_integral = SurfaceIntegralWeakForm(surface_flux), + volume_integral = VolumeIntegralWeakForm()) + +############################################################################### +# setup the 1D mesh + +mesh = DGMultiMesh(dg, + cells_per_dimension=(8,), + coordinates_min=(-1.0,), + coordinates_max=(1.0,), + periodicity=true) + +############################################################################### +# setup the test problem (no source term needed for linear advection) + +initial_condition = initial_condition_convergence_test + +############################################################################### +# setup the semidiscretization and ODE problem + +semi = SemidiscretizationHyperbolic(mesh, + equations, + initial_condition, + dg) + +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan) + +############################################################################### +# setup the callbacks + +# prints a summary of the simulation setup and resets the timers +summary_callback = SummaryCallback() + +# analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval=100, uEltype=real(dg)) + +# handles the re-calculcation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl=0.75) + +# collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), + dt=1.0, save_everystep=false, callback=callbacks); + +# Print the timer summary +summary_callback() + diff --git a/examples/dgmulti_2d/elixir_advection_diffusion.jl b/examples/dgmulti_2d/elixir_advection_diffusion.jl new file mode 100644 index 0000000000..1273e25859 --- /dev/null +++ b/examples/dgmulti_2d/elixir_advection_diffusion.jl @@ -0,0 +1,56 @@ +using Trixi, OrdinaryDiffEq + +dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), + surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralWeakForm()) + +equations = LinearScalarAdvectionEquation2D(1.5, 1.0) +equations_parabolic = LaplaceDiffusion2D(5.0e-2, equations) + +initial_condition_zero(x, t, equations::LinearScalarAdvectionEquation2D) = SVector(0.0) +initial_condition = initial_condition_zero + +# tag different boundary segments +left(x, tol=50*eps()) = abs(x[1] + 1) < tol +right(x, tol=50*eps()) = abs(x[1] - 1) < tol +bottom(x, tol=50*eps()) = abs(x[2] + 1) < tol +top(x, tol=50*eps()) = abs(x[2] - 1) < tol +is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom) +mesh = DGMultiMesh(dg, cells_per_dimension=(16, 16); is_on_boundary) + +# BC types +boundary_condition_left = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + 0.1 * x[2])) +boundary_condition_zero = BoundaryConditionDirichlet((x, t, equations) -> SVector(0.0)) +boundary_condition_neumann_zero = BoundaryConditionNeumann((x, t, equations) -> SVector(0.0)) + +# define inviscid boundary conditions +boundary_conditions = (; :left => boundary_condition_left, + :bottom => boundary_condition_zero, + :top => boundary_condition_do_nothing, + :right => boundary_condition_do_nothing) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; :left => boundary_condition_left, + :bottom => boundary_condition_zero, + :top => boundary_condition_zero, + :right => boundary_condition_neumann_zero) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) + +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-6 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl new file mode 100644 index 0000000000..bb22f49437 --- /dev/null +++ b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl @@ -0,0 +1,72 @@ +using Trixi, OrdinaryDiffEq + +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = Polynomial(), + surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralWeakForm()) + +diffusivity() = 5.0e-2 + +equations = LinearScalarAdvectionEquation2D(1.0, 0.0) +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +# Example setup taken from +# - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). +# Robust DPG methods for transient convection-diffusion. +# In: Building bridges: connections and challenges in modern approaches +# to numerical partial differential equations. +# [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). +function initial_condition_erikkson_johnson(x, t, equations) + l = 4 + epsilon = diffusivity() # Note: this requires epsilon < 0.6 due to the sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) +end +initial_condition = initial_condition_erikkson_johnson + +# tag different boundary segments +left(x, tol=50*eps()) = abs(x[1] + 1) < tol +right(x, tol=50*eps()) = abs(x[1]) < tol +bottom(x, tol=50*eps()) = abs(x[2] + 0.5) < tol +top(x, tol=50*eps()) = abs(x[2] - 0.5) < tol +entire_boundary(x, tol=50*eps()) = true +is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom, + :entire_boundary => entire_boundary) +mesh = DGMultiMesh(dg; coordinates_min=(-1.0, -0.5), coordinates_max=(0.0, 0.5), + cells_per_dimension=(16, 16), is_on_boundary) + +# BC types +boundary_condition = BoundaryConditionDirichlet(initial_condition) + +# define inviscid boundary conditions, enforce "do nothing" boundary condition at the outflow +boundary_conditions = (; :left => boundary_condition, + :top => boundary_condition, + :bottom => boundary_condition, + :right => boundary_condition_do_nothing) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; :entire_boundary => boundary_condition) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) + +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl new file mode 100644 index 0000000000..8058e15696 --- /dev/null +++ b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl @@ -0,0 +1,35 @@ +using Trixi, OrdinaryDiffEq + +dg = DGMulti(polydeg = 1, element_type = Tri(), approximation_type = Polynomial(), + surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralWeakForm()) + +equations = LinearScalarAdvectionEquation2D(0.0, 0.0) +equations_parabolic = LaplaceDiffusion2D(5.0e-1, equations) + +function initial_condition_sharp_gaussian(x, t, equations::LinearScalarAdvectionEquation2D) + return SVector(exp(-100 * (x[1]^2 + x[2]^2))) +end +initial_condition = initial_condition_sharp_gaussian + +mesh = DGMultiMesh(dg, cells_per_dimension = (16, 16), periodicity=true) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg) + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-6 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + dt = time_int_tol, save_everystep=false, callback=callbacks) + +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/dgmulti_2d/elixir_navierstokes_convergence.jl b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl new file mode 100644 index 0000000000..f703962723 --- /dev/null +++ b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl @@ -0,0 +1,205 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations2D(1.4) +# Note: If you change the Navier-Stokes parameters here, also change them in the initial condition +# I really do not like this structure but it should work for now +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), + gradient_variables=GradientVariablesPrimitive()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), + surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralWeakForm()) + +top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +is_on_boundary = Dict(:top_bottom => top_bottom) +mesh = DGMultiMesh(dg, cells_per_dimension=(16, 16); periodicity=(true, false), is_on_boundary) + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) +# and by the initial condition (which passes in `CompressibleEulerEquations2D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) + v2 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) + - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) + - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + # stress tensor from x-direction + - 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ + - v1_yy * mu_ + - v2_xy * mu_ ) + # y-momentum equation + du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + # stress tensor from y-direction + - v1_xy * mu_ + - v2_xx * mu_ + - 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_ ) + # total energy equation + du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + # stress tensor and temperature gradient terms from x-direction + - 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ + - 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ + - v1_xy * v2 * mu_ + - v2_xx * v2 * mu_ + - v1_y * v2_x * mu_ + - v2_x * v2_x * mu_ + - T_const * inv_rho_cubed * ( p_xx * rho * rho + - 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x + - p * rho * rho_xx ) * mu_ + # stress tensor and temperature gradient terms from y-direction + - v1_yy * v1 * mu_ + - v2_xy * v1 * mu_ + - v1_y * v1_y * mu_ + - v2_x * v1_y * mu_ + - 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ + - 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ + - T_const * inv_rho_cubed * ( p_yy * rho * rho + - 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y + - p * rho * rho_yy ) * mu_ ) + + return SVector(du1, du2, du3, du4) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) + +# define inviscid boundary conditions +boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl new file mode 100644 index 0000000000..0837cc2fd5 --- /dev/null +++ b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl @@ -0,0 +1,73 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 0.001 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), + Prandtl=prandtl_number()) + + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(), + surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) + +top(x, tol=50*eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol=50*eps()) = !top(x, tol) +is_on_boundary = Dict(:top => top, :rest_of_boundary => rest_of_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension=(16, 16); is_on_boundary) + +function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) +end +initial_condition = initial_condition_cavity + +# BC types +velocity_bc_lid = NoSlip((x, t, equations) -> SVector(1.0, 0.0)) +velocity_bc_cavity = NoSlip((x, t, equations) -> SVector(0.0, 0.0)) +heat_bc = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) +boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) + +# define inviscid boundary conditions +boundary_conditions = (; :top => boundary_condition_slip_wall, + :rest_of_boundary => boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; :top => boundary_condition_lid, + :rest_of_boundary => boundary_condition_cavity) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 10.0) +ode = semidiscretize(semi, tspan); + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl new file mode 100644 index 0000000000..e538f70191 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl @@ -0,0 +1,83 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +advection_velocity = (1.5, 1.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +diffusivity() = 5.0e-2 +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=true, + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Define initial condition +function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1/L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) +end +initial_condition = initial_condition_diffusive_convergence_test + +# define periodic boundary conditions everywhere +boundary_conditions = boundary_condition_periodic +boundary_conditions_parabolic = boundary_condition_periodic + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span from 0.0 to 1.5 +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) + + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) + +# Print the timer summary +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl new file mode 100644 index 0000000000..2ef0ffe766 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -0,0 +1,89 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 5.0e-2 +advection_velocity = (1.0, 0.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -0.5) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 0.0, 0.5) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=false, + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Example setup taken from +# - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). +# Robust DPG methods for transient convection-diffusion. +# In: Building bridges: connections and challenges in modern approaches +# to numerical partial differential equations. +# [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). +function initial_condition_eriksson_johnson(x, t, equations) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) +end +initial_condition = initial_condition_eriksson_johnson + +boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), + y_neg = BoundaryConditionDirichlet(initial_condition), + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing) + +boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 1.5) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) + + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) + +# Print the timer summary +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl index d259808a42..40e80bda06 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl @@ -92,7 +92,7 @@ save_solution = SaveSolutionCallback(interval=1000, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.4) +stepsize_callback = StepsizeCallback(cfl=0.35) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl new file mode 100644 index 0000000000..1145c22fca --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl @@ -0,0 +1,213 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), + gradient_variables=GradientVariablesPrimitive()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, + volume_integral=VolumeIntegralWeakForm()) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=(true, false), + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) +# and by the initial condition (which passes in `CompressibleEulerEquations2D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) + v2 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) + - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) + - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + # stress tensor from x-direction + - 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ + - v1_yy * mu_ + - v2_xy * mu_ ) + # y-momentum equation + du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + # stress tensor from y-direction + - v1_xy * mu_ + - v2_xx * mu_ + - 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_ ) + # total energy equation + du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + # stress tensor and temperature gradient terms from x-direction + - 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ + - 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ + - v1_xy * v2 * mu_ + - v2_xx * v2 * mu_ + - v1_y * v2_x * mu_ + - v2_x * v2_x * mu_ + - T_const * inv_rho_cubed * ( p_xx * rho * rho + - 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x + - p * rho * rho_xx ) * mu_ + # stress tensor and temperature gradient terms from y-direction + - v1_yy * v1 * mu_ + - v2_xy * v1 * mu_ + - v1_y * v1_y * mu_ + - v2_x * v1_y * mu_ + - 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ + - 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ + - T_const * inv_rho_cubed * ( p_yy * rho * rho + - 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y + - p * rho * rho_yy ) * mu_ ) + + return SVector(du1, du2, du3, du4) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) + +# define inviscid boundary conditions +boundary_conditions = (; x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_top_bottom, + y_pos = boundary_condition_top_bottom) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary + diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl new file mode 100644 index 0000000000..d94187eade --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl @@ -0,0 +1,79 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 0.001 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), + Prandtl=prandtl_number()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + periodicity=false, + n_cells_max=30_000) # set maximum capacity of tree data structure + + +function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) +end +initial_condition = initial_condition_cavity + +# BC types +velocity_bc_lid = NoSlip((x, t, equations) -> SVector(1.0, 0.0)) +velocity_bc_cavity = NoSlip((x, t, equations) -> SVector(0.0, 0.0)) +heat_bc = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) +boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) + +# define periodic boundary conditions everywhere +boundary_conditions = boundary_condition_slip_wall + +boundary_conditions_parabolic = (; x_neg = boundary_condition_cavity, + y_neg = boundary_condition_cavity, + y_pos = boundary_condition_lid, + x_pos = boundary_condition_cavity) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 25.0) +ode = semidiscretize(semi, tspan); + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=100) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(), abstol=time_int_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) +summary_callback() # print the timer summary + + diff --git a/src/Trixi.jl b/src/Trixi.jl index ff3e8c78d3..2b768d157e 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -26,7 +26,8 @@ using SparseArrays: AbstractSparseMatrix, AbstractSparseMatrixCSC, sparse, dropt using Reexport: @reexport using SciMLBase: CallbackSet, DiscreteCallback, - ODEProblem, ODESolution, ODEFunction + ODEProblem, ODESolution, ODEFunction, + SplitODEProblem import SciMLBase: get_du, get_tmp_cache, u_modified!, AbstractODEIntegrator, init, step!, check_error, get_proposed_dt, set_proposed_dt!, @@ -104,8 +105,10 @@ include("auxiliary/p4est.jl") include("equations/equations.jl") include("meshes/meshes.jl") include("solvers/solvers.jl") +include("equations/equations_parabolic.jl") # these depend on parabolic solver types include("semidiscretization/semidiscretization.jl") include("semidiscretization/semidiscretization_hyperbolic.jl") +include("semidiscretization/semidiscretization_hyperbolic_parabolic.jl") include("semidiscretization/semidiscretization_euler_acoustics.jl") include("callbacks_step/callbacks_step.jl") include("callbacks_stage/callbacks_stage.jl") @@ -131,6 +134,11 @@ export AcousticPerturbationEquations2D, LatticeBoltzmannEquations2D, LatticeBoltzmannEquations3D, ShallowWaterEquations1D, ShallowWaterEquations2D +export LaplaceDiffusion2D, + CompressibleNavierStokesDiffusion2D + +export GradientVariablesPrimitive, GradientVariablesEntropy + export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_godunov, flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner, flux_nonconservative_powell, @@ -151,11 +159,14 @@ export initial_condition_constant, initial_condition_density_wave, initial_condition_weak_blast_wave -export boundary_condition_periodic, +export boundary_condition_do_nothing, + boundary_condition_periodic, BoundaryConditionDirichlet, + BoundaryConditionNeumann, boundary_condition_noslip_wall, boundary_condition_slip_wall, - boundary_condition_wall + boundary_condition_wall, + BoundaryConditionNavierStokesWall, NoSlip, Adiabatic, Isothermal export initial_condition_convergence_test, source_terms_convergence_test export source_terms_harmonic @@ -186,6 +197,8 @@ export nelements, nnodes, nvariables, export SemidiscretizationHyperbolic, semidiscretize, compute_coefficients, integrate +export SemidiscretizationHyperbolicParabolic + export SemidiscretizationEulerAcoustics export SemidiscretizationEulerGravity, ParametersEulerGravity, @@ -216,6 +229,8 @@ export convergence_test, jacobian_fd, jacobian_ad_forward, linear_structure export DGMulti, estimate_dt, DGMultiMesh, GaussSBP export VertexMappedMesh # TODO: DGMulti, v0.5. Remove deprecated VertexMappedMesh in next release +export ViscousFormulationBassiRebay1, ViscousFormulationLocalDG + # Visualization-related exports export PlotData1D, PlotData2D, ScalarPlotData2D, getmesh, adapt_to_mesh_level!, adapt_to_mesh_level @@ -241,6 +256,7 @@ function __init__() # FIXME upstream. This is a hacky workaround for # https://github.com/trixi-framework/Trixi.jl/issues/628 + # https://github.com/trixi-framework/Trixi.jl/issues/1185 # The related upstream issues appear to be # https://github.com/JuliaLang/julia/issues/35800 # https://github.com/JuliaLang/julia/issues/32552 @@ -249,9 +265,12 @@ function __init__() let for T in (Float32, Float64) u_mortars_2d = zeros(T, 2, 2, 2, 2, 2) - view(u_mortars_2d, 1, :, 1, :, 1) + u_view_2d = view(u_mortars_2d, 1, :, 1, :, 1) + LoopVectorization.axes(u_view_2d) + u_mortars_3d = zeros(T, 2, 2, 2, 2, 2, 2) - view(u_mortars_3d, 1, :, 1, :, :, 1) + u_view_3d = view(u_mortars_3d, 1, :, 1, :, :, 1) + LoopVectorization.axes(u_view_3d) end end end diff --git a/src/auxiliary/auxiliary.jl b/src/auxiliary/auxiliary.jl index 2152727940..bc23e831a4 100644 --- a/src/auxiliary/auxiliary.jl +++ b/src/auxiliary/auxiliary.jl @@ -24,9 +24,9 @@ timer() = main_timer """ - PerformanceCounter + PerformanceCounter() -A `PerformanceCounter` be used to track the runtime performance of some calls. +A `PerformanceCounter` can be used to track the runtime performance of some calls. Add a new runtime measurement via `put!(counter, runtime)` and get the averaged runtime of all measurements added so far via `take!(counter)`, resetting the `counter`. @@ -51,6 +51,34 @@ function Base.put!(counter::PerformanceCounter, runtime::Real) end +""" + PerformanceCounterList{N}() + +A `PerformanceCounterList{N}` can be used to track the runtime performance of +calls to multiple functions, adding them up. +Add a new runtime measurement via `put!(counter.counters[i], runtime)` and get +the averaged runtime of all measurements added so far via `take!(counter)`, +resetting the `counter`. +""" +struct PerformanceCounterList{N} + counters::NTuple{N, PerformanceCounter} +end + +function PerformanceCounterList{N}() where {N} + counters = ntuple(_ -> PerformanceCounter(), Val{N}()) + return PerformanceCounterList{N}(counters) +end + +function Base.take!(counter::PerformanceCounterList) + time_per_call = 0.0 + for c in counter.counters + time_per_call += take!(c) + end + return time_per_call +end + + + """ examples_dir() diff --git a/src/basic_types.jl b/src/basic_types.jl index d6ae7f9fce..1116f3e6b6 100644 --- a/src/basic_types.jl +++ b/src/basic_types.jl @@ -70,5 +70,19 @@ const boundary_condition_periodic = BoundaryConditionPeriodic() Base.show(io::IO, ::BoundaryConditionPeriodic) = print(io, "boundary_condition_periodic") +""" + boundary_condition_do_nothing = BoundaryConditionDoNothing() + +Imposing no boundary condition just evaluates the flux at the inner state. +""" +struct BoundaryConditionDoNothing end + +@inline function (boundary_condition::BoundaryConditionDoNothing)(inner_flux_or_state, other_args...) + return inner_flux_or_state +end + +const boundary_condition_do_nothing = BoundaryConditionDoNothing() + +Base.show(io::IO, ::BoundaryConditionDoNothing) = print(io, "boundary_condition_do_nothing") end # @muladd diff --git a/src/callbacks_step/amr_dg.jl b/src/callbacks_step/amr_dg.jl index da9b259114..b154b9573e 100644 --- a/src/callbacks_step/amr_dg.jl +++ b/src/callbacks_step/amr_dg.jl @@ -68,7 +68,7 @@ function rebalance_solver!(u_ode::AbstractVector, mesh::ParallelP4estMesh, equat end # Wait for all non-blocking MPI send/receive operations to finish - MPI.Waitall!(requests) + MPI.Waitall(requests, MPI.Status) end end # GC.@preserve old_u_ode end diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 7a6d70162c..9f677d1dc4 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -66,7 +66,7 @@ function rebalance_solver!(u_ode::AbstractVector, mesh::TreeMesh{2}, equations, end # Wait for all non-blocking MPI send/receive operations to finish - MPI.Waitall!(requests) + MPI.Waitall(requests, MPI.Status) end end # GC.@preserve old_u_ode end diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index 65fd417c69..59b2d2e911 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -219,7 +219,11 @@ function (analysis_callback::AnalysisCallback)(integrator) # Calculate current time derivative (needed for semidiscrete entropy time derivative, residual, etc.) du_ode = first(get_tmp_cache(integrator)) - @notimeit timer() rhs!(du_ode, integrator.u, semi, t) + # `integrator.f` is usually just a call to `rhs!` + # However, we want to allow users to modify the ODE RHS outside of Trixi.jl + # and allow us to pass a combined ODE RHS to OrdinaryDiffEq, e.g., for + # hyperbolic-parabolic systems. + @notimeit timer() integrator.f(du_ode, integrator.u, semi, t) u = wrap_array(integrator.u, mesh, equations, solver, cache) du = wrap_array(du_ode, mesh, equations, solver, cache) l2_error, linf_error = analysis_callback(io, du, u, integrator.u, t, semi) diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index 89ec07558b..400650ed88 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -10,12 +10,12 @@ The compressible Euler equations ```math -\partial t +\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho e \end{pmatrix} + -\partial x +\frac{\partial}{\partial x} \begin{pmatrix} \rho v_1 \\ \rho v_1^2 + p \\ (\rho e +p) v_1 \end{pmatrix} diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index e4b283fdac..ff564b29e1 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -10,17 +10,17 @@ The compressible Euler equations ```math -\partial t +\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho v_2 \\ \rho e \end{pmatrix} + -\partial x +\frac{\partial}{\partial x} \begin{pmatrix} \rho v_1 \\ \rho v_1^2 + p \\ \rho v_1 v_2 \\ (\rho e +p) v_1 \end{pmatrix} + -\partial y +\frac{\partial}{\partial y} \begin{pmatrix} \rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + p \\ (\rho e +p) v_2 \end{pmatrix} @@ -36,7 +36,6 @@ Here, ``\rho`` is the density, ``v_1``,`v_2` the velocities, ``e`` the specific p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right) ``` the pressure. - """ struct CompressibleEulerEquations2D{RealT<:Real} <: AbstractCompressibleEulerEquations{2, 4} gamma::RealT # ratio of specific heats @@ -335,13 +334,14 @@ Should be used together with [`TreeMesh`](@ref). equations::CompressibleEulerEquations2D) # get the appropriate normal vector from the orientation if orientation == 1 - normal = SVector(1, 0) + normal_direction = SVector(1, 0) else # orientation == 2 - normal = SVector(0, 1) + normal_direction = SVector(0, 1) end # compute and return the flux using `boundary_condition_slip_wall` routine above - return boundary_condition_slip_wall(u_inner, normal, x, t, surface_flux_function, equations) + return boundary_condition_slip_wall(u_inner, normal_direction, direction, + x, t, surface_flux_function, equations) end """ @@ -1062,6 +1062,13 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end +@inline function isValidState(cons, equations::CompressibleEulerEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index d919c60011..1b93674c8a 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -10,22 +10,22 @@ The compressible Euler equations ```math -\partial t +\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho v_2 \\ \rho v_3 \\ \rho e \end{pmatrix} + -\partial x +\frac{\partial}{\partial x} \begin{pmatrix} \rho v_1 \\ \rho v_1^2 + p \\ \rho v_1 v_2 \\ \rho v_1 v_3 \\ ( \rho e +p) v_1 \end{pmatrix} + -\partial y +\frac{\partial}{\partial y} \begin{pmatrix} \rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + p \\ \rho v_1 v_3 \\ ( \rho e +p) v_2 \end{pmatrix} + -\partial z +\frac{\partial}{\partial z} \begin{pmatrix} \rho v_3 \\ \rho v_1 v_3 \\ \rho v_2 v_3 \\ \rho v_3^2 + p \\ ( \rho e +p) v_3 \end{pmatrix} diff --git a/src/equations/compressible_euler_multicomponent_1d.jl b/src/equations/compressible_euler_multicomponent_1d.jl index 39d8eb34f2..c5a3579ab3 100644 --- a/src/equations/compressible_euler_multicomponent_1d.jl +++ b/src/equations/compressible_euler_multicomponent_1d.jl @@ -10,12 +10,12 @@ Multicomponent version of the compressible Euler equations ```math -\partial t +\frac{\partial}{\partial t} \begin{pmatrix} \rho v_1 \\ \rho e \\ \rho_1 \\ \rho_2 \\ \vdots \\ \rho_{n} \end{pmatrix} + -\partial x +\frac{\partial}{\partial x} \begin{pmatrix} \rho v_1^2 + p \\ (\rho e +p) v_1 \\ \rho_1 v_1 \\ \rho_2 v_1 \\ \vdots \\ \rho_{n} v_1 \end{pmatrix} @@ -25,15 +25,15 @@ Multicomponent version of the compressible Euler equations 0 \\ 0 \\ 0 \\ 0 \\ \vdots \\ 0 \end{pmatrix} ``` -for calorically perfect gas in one space dimension. -Here, ``\rho_i`` is the density of component ``i``, ``\rho=\sum_{i=1}^n\rho_i`` the sum of the individual ``\rho_i``, +for calorically perfect gas in one space dimension. +Here, ``\rho_i`` is the density of component ``i``, ``\rho=\sum_{i=1}^n\rho_i`` the sum of the individual ``\rho_i``, ``v_1`` the velocity, ``e`` the specific total energy **rather than** specific internal energy, and ```math p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v_1^2 \right) ``` the pressure, ```math -\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}} +\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}} ``` total heat capacity ratio, ``\gamma_i`` heat capacity ratio of component ``i``, ```math diff --git a/src/equations/compressible_euler_multicomponent_2d.jl b/src/equations/compressible_euler_multicomponent_2d.jl index ad90969cf8..bb91cfbcb4 100644 --- a/src/equations/compressible_euler_multicomponent_2d.jl +++ b/src/equations/compressible_euler_multicomponent_2d.jl @@ -10,17 +10,17 @@ Multicomponent version of the compressible Euler equations ```math -\partial t +\frac{\partial}{\partial t} \begin{pmatrix} \rho v_1 \\ \rho v_2 \\ \rho e \\ \rho_1 \\ \rho_2 \\ \vdots \\ \rho_{n} \end{pmatrix} + -\partial x +\frac{\partial}{\partial x} \begin{pmatrix} \rho v_1^2 + p \\ \rho v_1 v_2 \\ ( \rho e +p) v_1 \\ \rho_1 v_1 \\ \rho_2 v_1 \\ \vdots \\ \rho_{n} v_1 \end{pmatrix} + -\partial y +\frac{\partial}{\partial y} \begin{pmatrix} \rho v_1 v_2 \\ \rho v_2^2 + p \\ ( \rho e +p) v_2 \\ \rho_1 v_2 \\ \rho_2 v_2 \\ \vdots \\ \rho_{n} v_2 \end{pmatrix} @@ -29,15 +29,15 @@ Multicomponent version of the compressible Euler equations 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ \vdots \\ 0 \end{pmatrix} ``` -for calorically perfect gas in two space dimensions. -Here, ``\rho_i`` is the density of component ``i``, ``\rho=\sum_{i=1}^n\rho_i`` the sum of the individual ``\rho_i``, +for calorically perfect gas in two space dimensions. +Here, ``\rho_i`` is the density of component ``i``, ``\rho=\sum_{i=1}^n\rho_i`` the sum of the individual ``\rho_i``, ``v_1``, ``v_2`` the velocities, ``e`` the specific total energy **rather than** specific internal energy, and ```math p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right) ``` the pressure, ```math -\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}} +\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}} ``` total heat capacity ratio, ``\gamma_i`` heat capacity ratio of component ``i``, ```math diff --git a/src/equations/compressible_navier_stokes_2d.jl b/src/equations/compressible_navier_stokes_2d.jl new file mode 100644 index 0000000000..9f7758aa47 --- /dev/null +++ b/src/equations/compressible_navier_stokes_2d.jl @@ -0,0 +1,407 @@ +@doc raw""" + CompressibleNavierStokesDiffusion2D(gamma, mu, Pr, equations, + gradient_variables=GradientVariablesPrimitive()) + +These equations contain the diffusion (i.e. parabolic) terms applied +to mass, momenta, and total energy together with the advective terms from +the [`CompressibleEulerEquations2D`](@ref). + +- `gamma`: adiabatic constant, +- `mu`: dynamic viscosity, +- `Pr`: Prandtl number, +- `equations`: instance of the [`CompressibleEulerEquations2D`](@ref) +- `gradient_variables`: which variables the gradients are taken with respect to. + Defaults to `GradientVariablesPrimitive()`. + +Fluid properties such as the dynamic viscosity ``\mu`` can be provided in any consistent unit system, e.g., +[``\mu``] = kg m⁻¹ s⁻¹. + +The particular form of the compressible Navier-Stokes implemented is +```math +\frac{\partial}{\partial t} +\begin{pmatrix} +\rho \\ \rho \mathbf{v} \\ \rho e +\end{pmatrix} ++ +\nabla \cdot +\begin{pmatrix} + \rho \mathbf{v} \\ \rho \mathbf{v}\mathbf{v}^T + p \underline{I} \\ (\rho e + p) \mathbf{v} +\end{pmatrix} += +\nabla \cdot +\begin{pmatrix} +0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \nabla q +\end{pmatrix} +``` +where the system is closed with the ideal gas assumption giving +```math +p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right) +``` +as the pressure. The terms on the right hand side of the system above +are built from the viscous stress tensor +```math +\underline{\tau} = \mu \left(\nabla\mathbf{v} + \left(\nabla\mathbf{v}\right)^T\right) - \frac{2}{3} \mu \left(\nabla\cdot\mathbf{v}\right)\underline{I} +``` +where ``\underline{I}`` is the ``2\times 2`` identity matrix and the heat flux is +```math +\nabla q = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho} +``` +where ``T`` is the temperature and ``\kappa`` is the thermal conductivity for Fick's law. +Under the assumption that the gas has a constant Prandtl number, +the thermal conductivity is +```math +\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}. +``` +From this combination of temperature ``T`` and thermal conductivity ``\kappa`` we see +that the gas constant `R` cancels and the heat flux becomes +```math +\nabla q = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right) +``` +which is the form implemented below in the [`flux`](@ref) function. + +In two spatial dimensions we require gradients for three quantities, e.g., +primitive quantities +```math +\nabla v_1,\, \nabla v_2,\, \nabla T +``` +or the entropy variables +```math +\nabla w_2,\, \nabla w_3,\, \nabla w_4 +``` +where +```math +w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = -\frac{\rho}{p} +``` + +#!!! warning "Experimental code" +# This code is experimental and may be changed or removed in any future release. +""" +struct CompressibleNavierStokesDiffusion2D{GradientVariables, RealT <: Real, E <: AbstractCompressibleEulerEquations{2}} <: AbstractCompressibleNavierStokesDiffusion{2, 4} + # TODO: parabolic + # 1) For now save gamma and inv(gamma-1) again, but could potentially reuse them from the Euler equations + # 2) Add NGRADS as a type parameter here and in AbstractEquationsParabolic, add `ngradients(...)` accessor function + gamma::RealT # ratio of specific heats + inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications + + mu::RealT # viscosity + Pr::RealT # Prandtl number + kappa::RealT # thermal diffusivity for Fick's law + + equations_hyperbolic::E # CompressibleEulerEquations2D + gradient_variables::GradientVariables # GradientVariablesPrimitive or GradientVariablesEntropy +end + +""" +#!!! warning "Experimental code" +# This code is experimental and may be changed or removed in any future release. + +`GradientVariablesPrimitive` and `GradientVariablesEntropy` are gradient variable type parameters +for `CompressibleNavierStokesDiffusion2D`. By default, the gradient variables are set to be +`GradientVariablesPrimitive`. Specifying `GradientVariablesEntropy` instead uses the entropy variable +formulation from +- Hughes, Mallet, Franca (1986) + A new finite element formulation for computational fluid dynamics: I. Symmetric forms of the + compressible Euler and Navier-Stokes equations and the second law of thermodynamics. + [https://doi.org/10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) + +Under `GradientVariablesEntropy`, the Navier-Stokes discretization is provably entropy stable. +""" +struct GradientVariablesPrimitive end +struct GradientVariablesEntropy end + +# default to primitive gradient variables +function CompressibleNavierStokesDiffusion2D(equations::CompressibleEulerEquations2D; + mu, Prandtl, + gradient_variables = GradientVariablesPrimitive()) + gamma = equations.gamma + inv_gamma_minus_one = equations.inv_gamma_minus_one + μ, Pr = promote(mu, Prandtl) + + # Under the assumption of constant Prandtl number the thermal conductivity + # constant is kappa = gamma μ / ((gamma-1) Pr). + # Important note! Factor of μ is accounted for later in `flux`. + kappa = gamma * inv_gamma_minus_one / Pr + + CompressibleNavierStokesDiffusion2D{typeof(gradient_variables), typeof(gamma), typeof(equations)}(gamma, inv_gamma_minus_one, + μ, Pr, kappa, + equations, gradient_variables) +end + +# TODO: parabolic +# This is the flexibility a user should have to select the different gradient variable types +# varnames(::typeof(cons2prim) , ::CompressibleNavierStokesDiffusion2D) = ("v1", "v2", "T") +# varnames(::typeof(cons2entropy), ::CompressibleNavierStokesDiffusion2D) = ("w2", "w3", "w4") + +varnames(variable_mapping, equations_parabolic::CompressibleNavierStokesDiffusion2D) = + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) + +# we specialize this function to compute gradients of primitive variables instead of +# conservative variables. +gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) = cons2prim +gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) = cons2entropy + + +# Explicit formulas for the diffusive Navier-Stokes fluxes are available, e.g., in Section 2 +# of the paper by Rueda-Ramíreza, Hennemann, Hindenlang, Winters, and Gassner +# "An Entropy Stable Nodal Discontinuous Galerkin Method for the resistive +# MHD Equations. Part II: Subcell Finite Volume Shock Capturing" +# where one sets the magnetic field components equal to 0. +function flux(u, gradients, orientation::Integer, equations::CompressibleNavierStokesDiffusion2D) + # Here, `u` is assumed to be the "transformed" variables specified by `gradient_variable_transformation`. + rho, v1, v2, _ = convert_transformed_to_primitive(u, equations) + # Here `gradients` is assumed to contain the gradients of the primitive variables (rho, v1, v2, T) + # either computed directly or reverse engineered from the gradient of the entropy vairables + # by way of the `convert_gradient_variables` function. + _, dv1dx, dv2dx, dTdx = convert_derivative_to_primitive(u, gradients[1], equations) + _, dv1dy, dv2dy, dTdy = convert_derivative_to_primitive(u, gradients[2], equations) + + # Components of viscous stress tensor + + # (4/3 * (v1)_x - 2/3 * (v2)_y) + tau_11 = 4.0 / 3.0 * dv1dx - 2.0 / 3.0 * dv2dy + # ((v1)_y + (v2)_x) + # stress tensor is symmetric + tau_12 = dv1dy + dv2dx # = tau_21 + # (4/3 * (v2)_y - 2/3 * (v1)_x) + tau_22 = 4.0 / 3.0 * dv2dy - 2.0 / 3.0 * dv1dx + + # Fick's law q = -kappa * grad(T) = -kappa * grad(p / (R rho)) + # with thermal diffusivity constant kappa = gamma μ R / ((gamma-1) Pr) + # Note, the gas constant cancels under this formulation, so it is not present + # in the implementation + q1 = equations.kappa * dTdx + q2 = equations.kappa * dTdy + + # Constant dynamic viscosity is copied to a variable for readibility. + # Offers flexibility for dynamic viscosity via Sutherland's law where it depends + # on temperature and reference values, Ts and Tref such that mu(T) + mu = equations.mu + + if orientation == 1 + # viscous flux components in the x-direction + f1 = zero(rho) + f2 = tau_11 * mu + f3 = tau_12 * mu + f4 = ( v1 * tau_11 + v2 * tau_12 + q1 ) * mu + + return SVector(f1, f2, f3, f4) + else # if orientation == 2 + # viscous flux components in the y-direction + # Note, symmetry is exploited for tau_12 = tau_21 + g1 = zero(rho) + g2 = tau_12 * mu # tau_21 * mu + g3 = tau_22 * mu + g4 = ( v1 * tau_12 + v2 * tau_22 + q2 ) * mu + + return SVector(g1, g2, g3, g4) + end +end + + +# Convert conservative variables to primitive +@inline function cons2prim(u, equations::CompressibleNavierStokesDiffusion2D) + rho, rho_v1, rho_v2, _ = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + T = temperature(u, equations) + + return SVector(rho, v1, v2, T) +end + +# Convert conservative variables to entropy +# TODO: parabolic. We can improve efficiency by not computing w_1, which involves logarithms +# This can be done by specializing `cons2entropy` and `entropy2cons` to `CompressibleNavierStokesDiffusion2D`, +# but this may be confusing to new users. +cons2entropy(u, equations::CompressibleNavierStokesDiffusion2D) = cons2entropy(u, equations.equations_hyperbolic) +entropy2cons(w, equations::CompressibleNavierStokesDiffusion2D) = entropy2cons(w, equations.equations_hyperbolic) + +# the `flux` function takes in transformed variables `u` which depend on the type of the gradient variables. +# For CNS, it is simplest to formulate the viscous terms in primitive variables, so we transform the transformed +# variables into primitive variables. +@inline function convert_transformed_to_primitive(u_transformed, equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + return u_transformed +end + +# TODO: parabolic. Make this more efficient! +@inline function convert_transformed_to_primitive(u_transformed, equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + # note: this uses CompressibleNavierStokesDiffusion2D versions of cons2prim and entropy2cons + return cons2prim(entropy2cons(u_transformed, equations), equations) +end + + +# Takes the solution values `u` and gradient of the entropy variables (w_2, w_3, w_4) and +# reverse engineers the gradients to be terms of the primitive variables (v1, v2, T). +# Helpful because then the diffusive fluxes have the same form as on paper. +# Note, the first component of `gradient_entropy_vars` contains gradient(rho) which is unused. +# TODO: parabolic; entropy stable viscous terms +@inline function convert_derivative_to_primitive(u, gradient, ::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + return gradient +end + +# the first argument is always the "transformed" variables. +@inline function convert_derivative_to_primitive(w, gradient_entropy_vars, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + + # TODO: parabolic. This is inefficient to pass in transformed variables but then transform them back. + # We can fix this if we directly compute v1, v2, T from the entropy variables + u = entropy2cons(w, equations) # calls a "modified" entropy2cons defined for CompressibleNavierStokesDiffusion2D + rho, rho_v1, rho_v2, _ = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + T = temperature(u, equations) + + return SVector(gradient_entropy_vars[1], + T * (gradient_entropy_vars[2] + v1 * gradient_entropy_vars[4]), # grad(u) = T*(grad(w_2)+v1*grad(w_4)) + T * (gradient_entropy_vars[3] + v2 * gradient_entropy_vars[4]), # grad(v) = T*(grad(w_3)+v2*grad(w_4)) + T * T * gradient_entropy_vars[4] # grad(T) = T^2*grad(w_4)) + ) +end + + +# This routine is required because `prim2cons` is called in `initial_condition`, which +# is called with `equations::CompressibleEulerEquations2D`. This means it is inconsistent +# with `cons2prim(..., ::CompressibleNavierStokesDiffusion2D)` as defined above. +# TODO: parabolic. Is there a way to clean this up? +@inline prim2cons(u, equations::CompressibleNavierStokesDiffusion2D) = + prim2cons(u, equations.equations_hyperbolic) + + +@inline function temperature(u, equations::CompressibleNavierStokesDiffusion2D) + rho, rho_v1, rho_v2, rho_e = u + + p = (equations.gamma - 1) * (rho_e - 0.5 * (rho_v1^2 + rho_v2^2) / rho) + T = p / rho + return T +end + +# TODO: can we generalize this to MHD? +""" + struct BoundaryConditionNavierStokesWall + +Creates a wall-type boundary conditions for the compressible Navier-Stokes equations. +The fields `boundary_condition_velocity` and `boundary_condition_heat_flux` are intended +to be boundary condition types such as the `NoSlip` velocity boundary condition and the +`Adiabatic` or `Isothermal` heat boundary condition. + +!!! warning "Experimental feature" + This is an experimental feature and may change in future releases. +""" +struct BoundaryConditionNavierStokesWall{V, H} + boundary_condition_velocity::V + boundary_condition_heat_flux::H +end + +""" + struct NoSlip + +Use to create a no-slip boundary condition with `BoundaryConditionNavierStokesWall`. The field `boundary_value_function` +should be a function with signature `boundary_value_function(x, t, equations)` +and should return a `SVector{NDIMS}` whose entries are the velocity vector at a +point `x` and time `t`. +""" +struct NoSlip{F} + boundary_value_function::F # value of the velocity vector on the boundary +end + +""" + struct Isothermal + +Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). +The field `boundary_value_function` should be a function with signature +`boundary_value_function(x, t, equations)` and return a scalar value for the +temperature at point `x` and time `t`. +""" +struct Isothermal{F} + boundary_value_function::F # value of the temperature on the boundary +end + +""" + struct Adiabatic + +Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). +The field `boundary_value_normal_flux_function` should be a function with signature +`boundary_value_normal_flux_function(x, t, equations)` and return a scalar value for the +normal heat flux at point `x` and time `t`. +""" +struct Adiabatic{F} + boundary_value_normal_flux_function::F # scaled heat flux 1/T * kappa * dT/dn +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + return SVector(u_inner[1], v1, v2, u_inner[4]) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + # rho, v1, v2, _ = u_inner + normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + _, tau_1n, tau_2n, _ = flux_inner # extract fluxes for 2nd and 3rd equations + normal_energy_flux = v1 * tau_1n + v2 * tau_2n + normal_heat_flux + return SVector(flux_inner[1], flux_inner[2], flux_inner[3], normal_energy_flux) +end + + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, equations) + return SVector(u_inner[1], v1, v2, T) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + return flux_inner +end + +# specialized BC impositions for GradientVariablesEntropy. + +# This should return a SVector containing the boundary values of entropy variables. +# Here, `w_inner` are the transformed variables (e.g., entropy variables). +# +# Taken from "Entropy stable modal discontinuous Galerkin schemes and wall boundary conditions +# for the compressible Navier-Stokes equations" by Chan, Lin, Warburton 2022. +# DOI: 10.1016/j.jcp.2021.110723 +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + negative_rho_inv_p = w_inner[4] # w_4 = -rho / p + return SVector(w_inner[1], -v1 * negative_rho_inv_p, -v2 * negative_rho_inv_p, negative_rho_inv_p) +end + +# this is actually identical to the specialization for GradientVariablesPrimitive, but included for completeness. +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + _, tau_1n, tau_2n, _ = flux_inner # extract fluxes for 2nd and 3rd equations + normal_energy_flux = v1 * tau_1n + v2 * tau_2n + normal_heat_flux + return SVector(flux_inner[1], flux_inner[2], flux_inner[3], normal_energy_flux) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) + T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, equations) + + # the entropy variables w2 = rho * v1 / p = v1 / T = -v1 * w4. Similarly for w3 + w4 = -1 / T + return SVector(w_inner[1], -v1 * w4, -v2 * w4, w4) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + return SVector(flux_inner[1], flux_inner[2], flux_inner[3], flux_inner[4]) +end diff --git a/src/equations/equations.jl b/src/equations/equations.jl index dc3bfffba3..f5fbd8cb41 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -175,6 +175,25 @@ end return flux end +# operator types used for dispatch on parabolic boundary fluxes +struct Gradient end +struct Divergence end + +""" + BoundaryConditionNeumann(boundary_normal_flux_function) + +Similar to `BoundaryConditionDirichlet`, but creates a Neumann boundary condition for parabolic +equations that uses the function `boundary_normal_flux_function` to specify the values of the normal +flux at the boundary. +The passed boundary value function will be called with the same arguments as an initial condition function is called, i.e., as +```julia +boundary_normal_flux_function(x, t, equations) +``` +where `x` specifies the coordinates, `t` is the current time, and `equation` is the corresponding system of equations. +""" +struct BoundaryConditionNeumann{B} + boundary_normal_flux_function::B +end # set sensible default values that may be overwritten by specific equations """ @@ -329,5 +348,6 @@ include("lattice_boltzmann_3d.jl") abstract type AbstractAcousticPerturbationEquations{NDIMS, NVARS} <: AbstractEquations{NDIMS, NVARS} end include("acoustic_perturbation_2d.jl") +abstract type AbstractEquationsParabolic{NDIMS, NVARS} <: AbstractEquations{NDIMS, NVARS} end end # @muladd diff --git a/src/equations/equations_parabolic.jl b/src/equations/equations_parabolic.jl new file mode 100644 index 0000000000..340cf0e429 --- /dev/null +++ b/src/equations/equations_parabolic.jl @@ -0,0 +1,11 @@ +# specify transformation of conservative variables prior to taking gradients. +# specialize this function to compute gradients e.g., of primitive variables instead of conservative +gradient_variable_transformation(::AbstractEquationsParabolic) = cons2cons + +# Linear scalar diffusion for use in linear scalar advection-diffusion problems +abstract type AbstractLaplaceDiffusion{NDIMS, NVARS} <: AbstractEquationsParabolic{NDIMS, NVARS} end +include("laplace_diffusion_2d.jl") + +# Compressible Navier-Stokes equations +abstract type AbstractCompressibleNavierStokesDiffusion{NDIMS, NVARS} <: AbstractEquationsParabolic{NDIMS, NVARS} end +include("compressible_navier_stokes_2d.jl") diff --git a/src/equations/laplace_diffusion_2d.jl b/src/equations/laplace_diffusion_2d.jl new file mode 100644 index 0000000000..2f1afe25a6 --- /dev/null +++ b/src/equations/laplace_diffusion_2d.jl @@ -0,0 +1,58 @@ +@doc raw""" + LaplaceDiffusion2D(diffusivity, equations) + +`LaplaceDiffusion2D` represents a scalar diffusion term ``\nabla \cdot (\kappa\nabla u))`` +with diffusivity ``\kappa`` applied to each solution component defined by `equations`. +""" +struct LaplaceDiffusion2D{E, N, T} <: AbstractLaplaceDiffusion{2, N} + diffusivity::T + equations_hyperbolic::E +end + +LaplaceDiffusion2D(diffusivity, equations_hyperbolic) = + LaplaceDiffusion2D{typeof(equations_hyperbolic), nvariables(equations_hyperbolic), typeof(diffusivity)}(diffusivity, equations_hyperbolic) + +varnames(variable_mapping, equations_parabolic::LaplaceDiffusion2D) = + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) + +# no orientation specified since the flux is vector-valued +function flux(u, gradients, orientation::Integer, equations_parabolic::LaplaceDiffusion2D) + dudx, dudy = gradients + if orientation == 1 + return SVector(equations_parabolic.diffusivity * dudx) + else # if orientation == 2 + return SVector(equations_parabolic.diffusivity * dudy) + end +end + +# TODO: parabolic; should this remain in the equations file, be moved to solvers, or live in the elixir? +# The penalization depends on the solver, but also depends explicitly on physical parameters, +# and would probably need to be specialized for every different equation. +function penalty(u_outer, u_inner, inv_h, equations_parabolic::LaplaceDiffusion2D, dg::ViscousFormulationLocalDG) + return dg.penalty_parameter * (u_outer - u_inner) * equations_parabolic.diffusivity * inv_h +end + +# Dirichlet-type boundary condition for use with a parabolic solver in weak form +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations_parabolic::LaplaceDiffusion2D) + return boundary_condition.boundary_value_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations_parabolic::LaplaceDiffusion2D) + return flux_inner +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Divergence, + equations_parabolic::LaplaceDiffusion2D) + return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, normal::AbstractVector, + x, t, operator_type::Gradient, + equations_parabolic::LaplaceDiffusion2D) + return flux_inner +end diff --git a/src/equations/linear_scalar_advection_1d.jl b/src/equations/linear_scalar_advection_1d.jl index e8094c94a4..0f2ae4b7c9 100644 --- a/src/equations/linear_scalar_advection_1d.jl +++ b/src/equations/linear_scalar_advection_1d.jl @@ -140,7 +140,7 @@ end # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation -@inline function max_abs_speed_naive(u_ll, u_rr, orientation, equation::LinearScalarAdvectionEquation1D) +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Int, equation::LinearScalarAdvectionEquation1D) λ_max = abs(equation.advection_velocity[orientation]) end diff --git a/src/semidiscretization/semidiscretization.jl b/src/semidiscretization/semidiscretization.jl index 5c4138d920..56c73c379b 100644 --- a/src/semidiscretization/semidiscretization.jl +++ b/src/semidiscretization/semidiscretization.jl @@ -72,7 +72,8 @@ function semidiscretize(semi::AbstractSemidiscretization, tspan) # TODO: MPI, do we want to synchonize loading and print debug statements, e.g. using # mpi_isparallel() && MPI.Barrier(mpi_comm()) # See https://github.com/trixi-framework/Trixi.jl/issues/328 - return ODEProblem(rhs!, u0_ode, tspan, semi) + iip = true # is-inplace, i.e., we modify a vector when calling rhs! + return ODEProblem{iip}(rhs!, u0_ode, tspan, semi) end @@ -88,7 +89,8 @@ function semidiscretize(semi::AbstractSemidiscretization, tspan, restart_file::A # TODO: MPI, do we want to synchonize loading and print debug statements, e.g. using # mpi_isparallel() && MPI.Barrier(mpi_comm()) # See https://github.com/trixi-framework/Trixi.jl/issues/328 - return ODEProblem(rhs!, u0_ode, tspan, semi) + iip = true # is-inplace, i.e., we modify a vector when calling rhs! + return ODEProblem{iip}(rhs!, u0_ode, tspan, semi) end diff --git a/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl b/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl new file mode 100644 index 0000000000..c1f9534162 --- /dev/null +++ b/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl @@ -0,0 +1,264 @@ +# 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 + + +""" + SemidiscretizationHyperbolicParabolic + +A struct containing everything needed to describe a spatial semidiscretization +of a mixed hyperbolic-parabolic conservation law. +""" +struct SemidiscretizationHyperbolicParabolic{Mesh, Equations, EquationsParabolic, InitialCondition, + BoundaryConditions, BoundaryConditionsParabolic, + SourceTerms, Solver, SolverParabolic, Cache, CacheParabolic} <: AbstractSemidiscretization + + mesh::Mesh + + equations::Equations + equations_parabolic::EquationsParabolic + + # This guy is a bit messy since we abuse it as some kind of "exact solution" + # although this doesn't really exist... + initial_condition::InitialCondition + + boundary_conditions::BoundaryConditions + boundary_conditions_parabolic::BoundaryConditionsParabolic + + source_terms::SourceTerms + + solver::Solver + solver_parabolic::SolverParabolic + + cache::Cache + cache_parabolic::CacheParabolic + + performance_counter::PerformanceCounterList{2} + + function SemidiscretizationHyperbolicParabolic{Mesh, Equations, EquationsParabolic, InitialCondition, BoundaryConditions, BoundaryConditionsParabolic, SourceTerms, Solver, SolverParabolic, Cache, CacheParabolic}( + mesh::Mesh, equations::Equations, equations_parabolic::EquationsParabolic, initial_condition::InitialCondition, + boundary_conditions::BoundaryConditions, boundary_conditions_parabolic::BoundaryConditionsParabolic, + source_terms::SourceTerms, solver::Solver, solver_parabolic::SolverParabolic, cache::Cache, cache_parabolic::CacheParabolic) where {Mesh, Equations, EquationsParabolic, InitialCondition, BoundaryConditions, BoundaryConditionsParabolic, SourceTerms, Solver, SolverParabolic, Cache, CacheParabolic} + @assert ndims(mesh) == ndims(equations) + + # Todo: assert nvariables(equations)==nvariables(equations_parabolic) + + performance_counter = PerformanceCounterList{2}() + + new(mesh, equations, equations_parabolic, initial_condition, + boundary_conditions, boundary_conditions_parabolic, + source_terms, solver, solver_parabolic, cache, cache_parabolic, performance_counter) + end +end + +""" + SemidiscretizationHyperbolicParabolic(mesh, both_equations, initial_condition, solver; + solver_parabolic=default_parabolic_solver(), + source_terms=nothing, + both_boundary_conditions=(boundary_condition_periodic, boundary_condition_periodic), + RealT=real(solver), + uEltype=RealT, + both_initial_caches=(NamedTuple(), NamedTuple())) + +Construct a semidiscretization of a hyperbolic-parabolic PDE. +""" +function SemidiscretizationHyperbolicParabolic(mesh, equations::Tuple, + initial_condition, solver; + solver_parabolic=default_parabolic_solver(), + source_terms=nothing, + boundary_conditions=(boundary_condition_periodic, boundary_condition_periodic), + # `RealT` is used as real type for node locations etc. + # while `uEltype` is used as element type of solutions etc. + RealT=real(solver), uEltype=RealT, + initial_caches=(NamedTuple(), NamedTuple())) + + equations_hyperbolic, equations_parabolic = equations + boundary_conditions_hyperbolic, boundary_conditions_parabolic = boundary_conditions + initial_hyperbolic_cache, initial_cache_parabolic = initial_caches + + return SemidiscretizationHyperbolicParabolic(mesh, equations_hyperbolic, equations_parabolic, + initial_condition, solver; solver_parabolic, source_terms, + boundary_conditions=boundary_conditions_hyperbolic, + boundary_conditions_parabolic=boundary_conditions_parabolic, + RealT, uEltype, initial_cache=initial_hyperbolic_cache, + initial_cache_parabolic=initial_cache_parabolic) +end + +function SemidiscretizationHyperbolicParabolic(mesh, equations, equations_parabolic, + initial_condition, solver; + solver_parabolic=default_parabolic_solver(), + source_terms=nothing, + boundary_conditions=boundary_condition_periodic, + boundary_conditions_parabolic=boundary_condition_periodic, + # `RealT` is used as real type for node locations etc. + # while `uEltype` is used as element type of solutions etc. + RealT=real(solver), uEltype=RealT, + initial_cache=NamedTuple(), + initial_cache_parabolic=NamedTuple()) + + cache = (; create_cache(mesh, equations, solver, RealT, uEltype)..., initial_cache...) + _boundary_conditions = digest_boundary_conditions(boundary_conditions, mesh, solver, cache) + _boundary_conditions_parabolic = digest_boundary_conditions(boundary_conditions_parabolic, mesh, solver, cache) + + cache_parabolic = (; create_cache_parabolic(mesh, equations, equations_parabolic, + solver, solver_parabolic, RealT, uEltype)..., + initial_cache_parabolic...) + + SemidiscretizationHyperbolicParabolic{typeof(mesh), typeof(equations), typeof(equations_parabolic), + typeof(initial_condition), typeof(_boundary_conditions), typeof(_boundary_conditions_parabolic), + typeof(source_terms), typeof(solver), typeof(solver_parabolic), typeof(cache), typeof(cache_parabolic)}( + mesh, equations, equations_parabolic, initial_condition, + _boundary_conditions, _boundary_conditions_parabolic, source_terms, + solver, solver_parabolic, cache, cache_parabolic) +end + + +# Create a new semidiscretization but change some parameters compared to the input. +# `Base.similar` follows a related concept but would require us to `copy` the `mesh`, +# which would impact the performance. Instead, `SciMLBase.remake` has exactly the +# semantics we want to use here. In particular, it allows us to re-use mutable parts, +# e.g. `remake(semi).mesh === semi.mesh`. +function remake(semi::SemidiscretizationHyperbolicParabolic; uEltype=real(semi.solver), + mesh=semi.mesh, + equations=semi.equations, + equations_parabolic=semi.equations_parabolic, + initial_condition=semi.initial_condition, + solver=semi.solver, + solver_parabolic=semi.solver_parabolic, + source_terms=semi.source_terms, + boundary_conditions=semi.boundary_conditions, + boundary_conditions_parabolic=semi.boundary_conditions_parabolic + ) + # TODO: Which parts do we want to `remake`? At least the solver needs some + # special care if shock-capturing volume integrals are used (because of + # the indicators and their own caches...). + SemidiscretizationHyperbolicParabolic( + mesh, equations, equations_parabolic, initial_condition, solver; solver_parabolic, source_terms, boundary_conditions, boundary_conditions_parabolic, uEltype) +end + +function Base.show(io::IO, semi::SemidiscretizationHyperbolicParabolic) + @nospecialize semi # reduce precompilation time + + print(io, "SemidiscretizationHyperbolicParabolic(") + print(io, semi.mesh) + print(io, ", ", semi.equations) + print(io, ", ", semi.equations_parabolic) + print(io, ", ", semi.initial_condition) + print(io, ", ", semi.boundary_conditions) + print(io, ", ", semi.boundary_conditions_parabolic) + print(io, ", ", semi.source_terms) + print(io, ", ", semi.solver) + print(io, ", ", semi.solver_parabolic) + print(io, ", cache(") + for (idx,key) in enumerate(keys(semi.cache)) + idx > 1 && print(io, " ") + print(io, key) + end + print(io, "))") +end + +function Base.show(io::IO, ::MIME"text/plain", semi::SemidiscretizationHyperbolicParabolic) + @nospecialize semi # reduce precompilation time + + if get(io, :compact, false) + show(io, semi) + else + summary_header(io, "SemidiscretizationHyperbolicParabolic") + summary_line(io, "#spatial dimensions", ndims(semi.equations)) + summary_line(io, "mesh", semi.mesh) + summary_line(io, "hyperbolic equations", semi.equations |> typeof |> nameof) + summary_line(io, "parabolic equations", semi.equations_parabolic |> typeof |> nameof) + summary_line(io, "initial condition", semi.initial_condition) + + # print_boundary_conditions(io, semi) + + summary_line(io, "source terms", semi.source_terms) + summary_line(io, "solver", semi.solver |> typeof |> nameof) + summary_line(io, "parabolic solver", semi.solver_parabolic |> typeof |> nameof) + summary_line(io, "total #DOFs", ndofs(semi)) + summary_footer(io) + end +end + +@inline Base.ndims(semi::SemidiscretizationHyperbolicParabolic) = ndims(semi.mesh) + +@inline nvariables(semi::SemidiscretizationHyperbolicParabolic) = nvariables(semi.equations) + +@inline Base.real(semi::SemidiscretizationHyperbolicParabolic) = real(semi.solver) + +# retain dispatch on hyperbolic equations only +@inline function mesh_equations_solver_cache(semi::SemidiscretizationHyperbolicParabolic) + @unpack mesh, equations, solver, cache = semi + return mesh, equations, solver, cache +end + + +function calc_error_norms(func, u_ode, t, analyzer, semi::SemidiscretizationHyperbolicParabolic, cache_analysis) + @unpack mesh, equations, initial_condition, solver, cache = semi + u = wrap_array(u_ode, mesh, equations, solver, cache) + + calc_error_norms(func, u, t, analyzer, mesh, equations, initial_condition, solver, cache, cache_analysis) +end + + +function compute_coefficients(t, semi::SemidiscretizationHyperbolicParabolic) + # Call `compute_coefficients` in `src/semidiscretization/semidiscretization.jl` + compute_coefficients(semi.initial_condition, t, semi) +end + +function compute_coefficients!(u_ode, t, semi::SemidiscretizationHyperbolicParabolic) + compute_coefficients!(u_ode, semi.initial_condition, t, semi) +end + +""" + semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan) + +Wrap the semidiscretization `semi` as a Split ODE problem in the time interval `tspan` +that can be passed to `solve` from the [SciML ecosystem](https://diffeq.sciml.ai/latest/). +""" +function semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan) + u0_ode = compute_coefficients(first(tspan), semi) + # TODO: MPI, do we want to synchonize loading and print debug statements, e.g. using + # mpi_isparallel() && MPI.Barrier(mpi_comm()) + # See https://github.com/trixi-framework/Trixi.jl/issues/328 + iip = true # is-inplace, i.e., we modify a vector when calling rhs!, rhs_parabolic! + return SplitODEProblem{iip}(rhs!, rhs_parabolic!, u0_ode, tspan, semi) +end + +function rhs!(du_ode, u_ode, semi::SemidiscretizationHyperbolicParabolic, t) + @unpack mesh, equations, initial_condition, boundary_conditions, source_terms, solver, cache = semi + + u = wrap_array(u_ode, mesh, equations, solver, cache) + du = wrap_array(du_ode, mesh, equations, solver, cache) + + # TODO: Taal decide, do we need to pass the mesh? + time_start = time_ns() + @trixi_timeit timer() "rhs!" rhs!(du, u, t, mesh, equations, initial_condition, + boundary_conditions, source_terms, solver, cache) + runtime = time_ns() - time_start + put!(semi.performance_counter.counters[1], runtime) + + return nothing +end + +function rhs_parabolic!(du_ode, u_ode, semi::SemidiscretizationHyperbolicParabolic, t) + @unpack mesh, equations_parabolic, initial_condition, boundary_conditions_parabolic, source_terms, solver, solver_parabolic, cache, cache_parabolic = semi + + u = wrap_array(u_ode, mesh, equations_parabolic, solver, cache_parabolic) + du = wrap_array(du_ode, mesh, equations_parabolic, solver, cache_parabolic) + + # TODO: Taal decide, do we need to pass the mesh? + time_start = time_ns() + @trixi_timeit timer() "parabolic rhs!" rhs_parabolic!(du, u, t, mesh, equations_parabolic, initial_condition, + boundary_conditions_parabolic, source_terms, + solver, solver_parabolic, cache, cache_parabolic) + runtime = time_ns() - time_start + put!(semi.performance_counter.counters[2], runtime) + + return nothing +end + + +end # @muladd diff --git a/src/solvers/dgmulti.jl b/src/solvers/dgmulti.jl index d5c8f12d39..318a11b678 100644 --- a/src/solvers/dgmulti.jl +++ b/src/solvers/dgmulti.jl @@ -9,3 +9,6 @@ include("dgmulti/sbp.jl") # specialization of DGMulti to specific equations include("dgmulti/flux_differencing_compressible_euler.jl") + +# parabolic terms for DGMulti solvers +include("dgmulti/dg_parabolic.jl") \ No newline at end of file diff --git a/src/solvers/dgmulti/dg.jl b/src/solvers/dgmulti/dg.jl index e4d25920ea..25135b784f 100644 --- a/src/solvers/dgmulti/dg.jl +++ b/src/solvers/dgmulti/dg.jl @@ -31,33 +31,32 @@ mul_by_accum!(A::UniformScaling) = MulByAccumUniformScaling() # solution storage formats. @inline apply_to_each_field(f::MulByUniformScaling, out, x, args...) = copy!(out, x) @inline function apply_to_each_field(f::MulByAccumUniformScaling, out, x, args...) - # TODO: DGMulti speed up using threads - for (i, x_i) in enumerate(x) - out[i] = out[i] + x_i + @threaded for i in eachindex(x) + out[i] = out[i] + x[i] end end @inline eachdim(mesh) = Base.OneTo(ndims(mesh)) # iteration over all elements in a mesh -@inline ndofs(mesh::DGMultiMesh, dg::DGMulti, cache) = dg.basis.Np * mesh.md.num_elements -@inline eachelement(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(mesh.md.num_elements) +@inline ndofs(mesh::DGMultiMesh, dg::DGMulti, other_args...) = dg.basis.Np * mesh.md.num_elements +@inline eachelement(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(mesh.md.num_elements) # iteration over quantities in a single element @inline nnodes(basis::RefElemData) = basis.Np -@inline each_face_node(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(dg.basis.Nfq) -@inline each_quad_node(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(dg.basis.Nq) +@inline each_face_node(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(dg.basis.Nfq) +@inline each_quad_node(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(dg.basis.Nq) # iteration over quantities over the entire mesh (dofs, quad nodes, face nodes). -@inline each_dof_global(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(ndofs(mesh, dg, cache)) -@inline each_quad_node_global(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(dg.basis.Nq * mesh.md.num_elements) -@inline each_face_node_global(mesh::DGMultiMesh, dg::DGMulti, cache) = Base.OneTo(dg.basis.Nfq * mesh.md.num_elements) +@inline each_dof_global(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(ndofs(mesh, dg, other_args...)) +@inline each_quad_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(dg.basis.Nq * mesh.md.num_elements) +@inline each_face_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...) = Base.OneTo(dg.basis.Nfq * mesh.md.num_elements) # interface with semidiscretization_hyperbolic wrap_array(u_ode, mesh::DGMultiMesh, equations, dg::DGMulti, cache) = u_ode wrap_array_native(u_ode, mesh::DGMultiMesh, equations, dg::DGMulti, cache) = u_ode -function digest_boundary_conditions(boundary_conditions::NamedTuple{Keys,ValueTypes}, mesh::DGMultiMesh, - dg::DGMulti, cache) where {Keys,ValueTypes<:NTuple{N,Any}} where {N} +function digest_boundary_conditions(boundary_conditions::NamedTuple{Keys, ValueTypes}, mesh::DGMultiMesh, + dg::DGMulti, cache) where {Keys, ValueTypes<:NTuple{N, Any}} where {N} return boundary_conditions end @@ -67,7 +66,7 @@ function allocate_nested_array(uEltype, nvars, array_dimensions, dg) return StructArray{SVector{nvars, uEltype}}(ntuple(_->zeros(uEltype, array_dimensions...), nvars)) end -function reset_du!(du, dg::DGMulti, cache) +function reset_du!(du, dg::DGMulti, other_args...) @threaded for i in eachindex(du) du[i] = zero(eltype(du)) end @@ -92,7 +91,7 @@ function create_cache(mesh::DGMultiMesh, equations, dg::DGMultiWeakForm, RealT, u_values = allocate_nested_array(uEltype, nvars, size(md.xq), dg) u_face_values = allocate_nested_array(uEltype, nvars, size(md.xf), dg) flux_face_values = allocate_nested_array(uEltype, nvars, size(md.xf), dg) - if typeof(rd.approximationType) <: Union{SBP, AbstractNonperiodicDerivativeOperator} + if typeof(rd.approximation_type) <: Union{SBP, AbstractNonperiodicDerivativeOperator} lift_scalings = rd.wf ./ rd.wq[rd.Fmask] # lift scalings for diag-norm SBP operators else lift_scalings = nothing @@ -158,7 +157,31 @@ function max_dt(u, t, mesh::DGMultiMesh, return 2 * dt_min / (polydeg + 1) end +function max_dt(u, t, mesh::DGMultiMesh, + constant_speed::Val{true}, equations, dg::DGMulti{NDIMS}, cache) where {NDIMS} + + @unpack md = mesh + rd = dg.basis + + dt_min = Inf + for e in eachelement(mesh, dg, cache) + h_e = StartUpDG.estimate_h(e, rd, md) + max_speeds = ntuple(_->nextfloat(zero(t)), NDIMS) + for i in Base.OneTo(rd.Np) # loop over nodes + max_speeds = max.(max_abs_speeds(equations), max_speeds) + end + dt_min = min(dt_min, h_e / sum(max_speeds)) + end + # This mimics `max_dt` for `TreeMesh`, except that `nnodes(dg)` is replaced by + # `polydeg+1`. This is because `nnodes(dg)` returns the total number of + # multi-dimensional nodes for DGMulti solver types, while `nnodes(dg)` returns + # the number of 1D nodes for `DGSEM` solvers. + polydeg = rd.N + return 2 * dt_min / (polydeg + 1) +end + # interpolates from solution coefficients to face quadrature points +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::DGMultiMesh, equations, surface_integral, dg::DGMulti) rd = dg.basis @@ -208,13 +231,9 @@ function calc_interface_flux!(cache, surface_integral::SurfaceIntegralWeakForm, # inner (idM -> minus) and outer (idP -> plus) indices idM, idP = mapM[face_node_index], mapP[face_node_index] uM = u_face_values[idM] - - # compute flux if node is not a boundary node - if idM != idP - uP = u_face_values[idP] - normal = SVector{NDIMS}(getindex.(nxyzJ, idM)) / Jf[idM] - flux_face_values[idM] = surface_flux(uM, uP, normal, equations) * Jf[idM] - end + uP = u_face_values[idP] + normal = SVector{NDIMS}(getindex.(nxyzJ, idM)) / Jf[idM] + flux_face_values[idM] = surface_flux(uM, uP, normal, equations) * Jf[idM] end end @@ -264,6 +283,7 @@ function calc_surface_integral!(du, u, surface_integral::SurfaceIntegralWeakForm end # Specialize for nodal SBP discretizations. Uses that Vf*u = u[Fmask,:] +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::DGMultiMesh, equations, surface_integral, dg::DGMultiSBP) rd = dg.basis @@ -353,9 +373,10 @@ end # Todo: DGMulti. Specialize for modal DG on curved meshes using WADG -function invert_jacobian!(du, mesh::DGMultiMesh, equations, dg::DGMulti, cache) +# inverts Jacobian and scales by -1.0 +function invert_jacobian!(du, mesh::DGMultiMesh, equations, dg::DGMulti, cache; scaling=-1) @threaded for i in each_dof_global(mesh, dg, cache) - du[i] *= -cache.invJ[i] + du[i] *= scaling * cache.invJ[i] end end diff --git a/src/solvers/dgmulti/dg_parabolic.jl b/src/solvers/dgmulti/dg_parabolic.jl new file mode 100644 index 0000000000..50cfd8ab17 --- /dev/null +++ b/src/solvers/dgmulti/dg_parabolic.jl @@ -0,0 +1,322 @@ +function create_cache_parabolic(mesh::DGMultiMesh, + equations_hyperbolic::AbstractEquations, + equations_parabolic::AbstractEquationsParabolic, + dg::DGMulti, parabolic_scheme, RealT, uEltype) + # default to taking derivatives of all hyperbolic terms + # TODO: parabolic; utilize the parabolic variables in `equations_parabolic` to reduce memory usage in the parabolic cache + nvars = nvariables(equations_hyperbolic) + + @unpack M, Drst = dg.basis + weak_differentiation_matrices = map(A -> -M \ (A' * M), Drst) + + # u_transformed stores "transformed" variables for computing the gradient + @unpack md = mesh + u_transformed = allocate_nested_array(uEltype, nvars, size(md.x), dg) + gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) + flux_viscous = similar.(gradients) + + u_face_values = allocate_nested_array(uEltype, nvars, size(md.xf), dg) + scalar_flux_face_values = similar(u_face_values) + gradients_face_values = ntuple(_ -> similar(u_face_values), ndims(mesh)) + + local_u_values_threaded = [similar(u_transformed, dg.basis.Nq) for _ in 1:Threads.nthreads()] + local_flux_viscous_threaded = [ntuple(_ -> similar(u_transformed, dg.basis.Nq), ndims(mesh)) for _ in 1:Threads.nthreads()] + local_flux_face_values_threaded = [similar(scalar_flux_face_values[:, 1]) for _ in 1:Threads.nthreads()] + + # precompute 1 / h for penalty terms + inv_h = similar(mesh.md.Jf) + J = dg.basis.Vf * mesh.md.J # interp to face nodes + for e in eachelement(mesh, dg) + for i in each_face_node(mesh, dg) + inv_h[i, e] = mesh.md.Jf[i, e] / J[i, e] + end + end + + return (; u_transformed, gradients, flux_viscous, + weak_differentiation_matrices, inv_h, + u_face_values, gradients_face_values, scalar_flux_face_values, + local_u_values_threaded, local_flux_viscous_threaded, local_flux_face_values_threaded) +end + +# Transform solution variables prior to taking the gradient +# (e.g., conservative to primitive variables). Defaults to doing nothing. +# TODO: can we avoid copying data? +function transform_variables!(u_transformed, u, mesh, equations_parabolic::AbstractEquationsParabolic, + dg::DGMulti, parabolic_scheme, cache, cache_parabolic) + @threaded for i in eachindex(u) + u_transformed[i] = gradient_variable_transformation(equations_parabolic)(u[i], equations_parabolic) + end +end + +# interpolates from solution coefficients to face quadrature points +# We pass the `surface_integral` argument solely for dispatch +function prolong2interfaces!(u_face_values, u, mesh::DGMultiMesh, equations::AbstractEquationsParabolic, + surface_integral, dg::DGMulti, cache) + apply_to_each_field(mul_by!(dg.basis.Vf), u_face_values, u) +end + +function calc_gradient_surface_integral(gradients, u, scalar_flux_face_values, + mesh, equations::AbstractEquationsParabolic, + dg::DGMulti, cache, cache_parabolic) + @unpack local_flux_face_values_threaded = cache_parabolic + @threaded for e in eachelement(mesh, dg) + local_flux_values = local_flux_face_values_threaded[Threads.threadid()] + for dim in eachdim(mesh) + for i in eachindex(local_flux_values) + # compute flux * (nx, ny, nz) + local_flux_values[i] = scalar_flux_face_values[i, e] * mesh.md.nxyzJ[dim][i, e] + end + apply_to_each_field(mul_by_accum!(dg.basis.LIFT), view(gradients[dim], :, e), local_flux_values) + end + end +end + +function calc_gradient!(gradients, u::StructArray, t, mesh::DGMultiMesh, + equations::AbstractEquationsParabolic, + boundary_conditions, dg::DGMulti, cache, cache_parabolic) + + @unpack weak_differentiation_matrices = cache_parabolic + + for dim in eachindex(gradients) + reset_du!(gradients[dim], dg) + end + + # compute volume contributions to gradients + @threaded for e in eachelement(mesh, dg) + for i in eachdim(mesh), j in eachdim(mesh) + dxidxhatj = mesh.md.rstxyzJ[i, j][1, e] # TODO: DGMulti. Assumes mesh is affine here. + apply_to_each_field(mul_by_accum!(weak_differentiation_matrices[j], dxidxhatj), + view(gradients[i], :, e), view(u, :, e)) + end + end + + @unpack u_face_values = cache_parabolic + prolong2interfaces!(u_face_values, u, mesh, equations, dg.surface_integral, dg, cache) + + # compute fluxes at interfaces + @unpack scalar_flux_face_values = cache_parabolic + @unpack mapM, mapP, Jf = mesh.md + @threaded for face_node_index in each_face_node_global(mesh, dg) + idM, idP = mapM[face_node_index], mapP[face_node_index] + uM = u_face_values[idM] + uP = u_face_values[idP] + scalar_flux_face_values[idM] = 0.5 * (uP + uM) # TODO: use strong/weak formulation for curved meshes? + end + + calc_boundary_flux!(scalar_flux_face_values, u_face_values, t, Gradient(), boundary_conditions, + mesh, equations, dg, cache, cache_parabolic) + + # compute surface contributions + calc_gradient_surface_integral(gradients, u, scalar_flux_face_values, + mesh, equations, dg, cache, cache_parabolic) + + for dim in eachdim(mesh) + invert_jacobian!(gradients[dim], mesh, equations, dg, cache; scaling=1.0) + end +end + +# do nothing for periodic domains +function calc_boundary_flux!(flux, u, t, operator_type, ::BoundaryConditionPeriodic, + mesh, equations::AbstractEquationsParabolic, dg::DGMulti, + cache, cache_parabolic) + return nothing +end + +# "lispy tuple programming" instead of for loop for type stability +function calc_boundary_flux!(flux, u, t, operator_type, boundary_conditions, + mesh, equations, dg::DGMulti, cache, cache_parabolic) + + # peel off first boundary condition + calc_single_boundary_flux!(flux, u, t, operator_type, first(boundary_conditions), first(keys(boundary_conditions)), + mesh, equations, dg, cache, cache_parabolic) + + # recurse on the remainder of the boundary conditions + calc_boundary_flux!(flux, u, t, operator_type, Base.tail(boundary_conditions), + mesh, equations, dg, cache, cache_parabolic) +end + +# terminate recursion +calc_boundary_flux!(flux, u, t, operator_type, boundary_conditions::NamedTuple{(),Tuple{}}, + mesh, equations, dg::DGMulti, cache, cache_parabolic) = nothing + +# TODO: DGMulti. Decide if we want to use the input `u_face_values` (currently unused) +function calc_single_boundary_flux!(flux_face_values, u_face_values, t, + operator_type, boundary_condition, boundary_key, + mesh, equations, dg::DGMulti{NDIMS}, cache, cache_parabolic) where {NDIMS} + rd = dg.basis + md = mesh.md + + num_pts_per_face = rd.Nfq ÷ rd.Nfaces + @unpack xyzf, nxyzJ, Jf = md + for f in mesh.boundary_faces[boundary_key] + for i in Base.OneTo(num_pts_per_face) + + # reverse engineer element + face node indices (avoids reshaping arrays) + e = ((f-1) ÷ rd.Nfaces) + 1 + fid = i + ((f-1) % rd.Nfaces) * num_pts_per_face + + face_normal = SVector{NDIMS}(getindex.(nxyzJ, fid, e)) / Jf[fid,e] + face_coordinates = SVector{NDIMS}(getindex.(xyzf, fid, e)) + + # for both the gradient and the divergence, the boundary flux is scalar valued. + # for the gradient, it is the solution; for divergence, it is the normal flux. + flux_face_values[fid,e] = boundary_condition(flux_face_values[fid,e], u_face_values[fid,e], + face_normal, face_coordinates, t, + operator_type, equations) + end + end + return nothing +end + +function calc_viscous_fluxes!(flux_viscous, u, gradients, mesh::DGMultiMesh, + equations::AbstractEquationsParabolic, + dg::DGMulti, cache, cache_parabolic) + + for dim in eachdim(mesh) + reset_du!(flux_viscous[dim], dg) + end + + @unpack local_flux_viscous_threaded, local_u_values_threaded = cache_parabolic + + @threaded for e in eachelement(mesh, dg) + + # reset local storage for each element + local_flux_viscous = local_flux_viscous_threaded[Threads.threadid()] + local_u_values = local_u_values_threaded[Threads.threadid()] + fill!(local_u_values, zero(eltype(local_u_values))) + for dim in eachdim(mesh) + fill!(local_flux_viscous[dim], zero(eltype(local_flux_viscous[dim]))) + end + + # interpolate u and gradient to quadrature points, store in `local_flux_viscous` + apply_to_each_field(mul_by!(dg.basis.Vq), local_u_values, view(u, :, e)) # TODO: DGMulti. Specialize for nodal collocation methods (SBP, GaussSBP) + for dim in eachdim(mesh) + apply_to_each_field(mul_by!(dg.basis.Vq), local_flux_viscous[dim], view(gradients[dim], :, e)) + end + + # compute viscous flux at quad points + for i in eachindex(local_u_values) + u_i = local_u_values[i] + gradients_i = getindex.(local_flux_viscous, i) + for dim in eachdim(mesh) + flux_viscous_i = flux(u_i, gradients_i, dim, equations) + setindex!(local_flux_viscous[dim], flux_viscous_i, i) + end + end + + # project back to the DG approximation space + for dim in eachdim(mesh) + apply_to_each_field(mul_by!(dg.basis.Pq), view(flux_viscous[dim], :, e), local_flux_viscous[dim]) + end + end +end + +# no penalization for a BR1 parabolic solver +function calc_viscous_penalty!(scalar_flux_face_values, u_face_values, t, boundary_conditions, + mesh, equations::AbstractEquationsParabolic, dg::DGMulti, + parabolic_scheme::ViscousFormulationBassiRebay1, cache, cache_parabolic) + return nothing +end + +function calc_viscous_penalty!(scalar_flux_face_values, u_face_values, t, boundary_conditions, + mesh, equations::AbstractEquationsParabolic, dg::DGMulti, + parabolic_scheme, cache, cache_parabolic) + # compute fluxes at interfaces + @unpack scalar_flux_face_values, inv_h = cache_parabolic + @unpack mapM, mapP = mesh.md + @threaded for face_node_index in each_face_node_global(mesh, dg) + idM, idP = mapM[face_node_index], mapP[face_node_index] + uM, uP = u_face_values[idM], u_face_values[idP] + inv_h_face = inv_h[face_node_index] + scalar_flux_face_values[idM] = scalar_flux_face_values[idM] + penalty(uP, uM, inv_h_face, equations, parabolic_scheme) + end + return nothing +end + + +function calc_divergence!(du, u::StructArray, t, flux_viscous, mesh::DGMultiMesh, + equations::AbstractEquationsParabolic, + boundary_conditions, dg::DGMulti, parabolic_scheme, cache, cache_parabolic) + + @unpack weak_differentiation_matrices = cache_parabolic + + reset_du!(du, dg) + + # compute volume contributions to divergence + @threaded for e in eachelement(mesh, dg) + for i in eachdim(mesh), j in eachdim(mesh) + dxidxhatj = mesh.md.rstxyzJ[i, j][1, e] # assumes mesh is affine + apply_to_each_field(mul_by_accum!(weak_differentiation_matrices[j], dxidxhatj), + view(du, :, e), view(flux_viscous[i], :, e)) + end + end + + # interpolates from solution coefficients to face quadrature points + flux_viscous_face_values = cache_parabolic.gradients_face_values # reuse storage + for dim in eachdim(mesh) + prolong2interfaces!(flux_viscous_face_values[dim], flux_viscous[dim], mesh, equations, + dg.surface_integral, dg, cache) + end + + # compute fluxes at interfaces + @unpack scalar_flux_face_values = cache_parabolic + @unpack mapM, mapP, nxyzJ = mesh.md + @threaded for face_node_index in each_face_node_global(mesh, dg, cache, cache_parabolic) + idM, idP = mapM[face_node_index], mapP[face_node_index] + + # compute f(u, ∇u) ⋅ n + flux_face_value = zero(eltype(scalar_flux_face_values)) + for dim in eachdim(mesh) + uM = flux_viscous_face_values[dim][idM] + uP = flux_viscous_face_values[dim][idP] + # TODO: use strong/weak formulation to ensure stability on curved meshes? + flux_face_value = flux_face_value + 0.5 * (uP + uM) * nxyzJ[dim][face_node_index] + end + scalar_flux_face_values[idM] = flux_face_value + end + + calc_boundary_flux!(scalar_flux_face_values, cache_parabolic.u_face_values, t, Divergence(), + boundary_conditions, mesh, equations, dg, cache, cache_parabolic) + + calc_viscous_penalty!(scalar_flux_face_values, cache_parabolic.u_face_values, t, + boundary_conditions, mesh, equations, dg, parabolic_scheme, + cache, cache_parabolic) + + # surface contributions + apply_to_each_field(mul_by_accum!(dg.basis.LIFT), du, scalar_flux_face_values) + + # Note: we do not flip the sign of the geometric Jacobian here. + # This is because the parabolic fluxes are assumed to be of the form + # `du/dt + df/dx = dg/dx + source(x,t)`, + # where f(u) is the inviscid flux and g(u) is the viscous flux. + invert_jacobian!(du, mesh, equations, dg, cache; scaling=1.0) +end + +# assumptions: parabolic terms are of the form div(f(u, grad(u))) and +# will be discretized first order form as follows: +# 1. compute grad(u) +# 2. compute f(u, grad(u)) +# 3. compute div(u) +# boundary conditions will be applied to both grad(u) and div(u). +function rhs_parabolic!(du, u, t, mesh::DGMultiMesh, equations_parabolic::AbstractEquationsParabolic, + initial_condition, boundary_conditions, source_terms, + dg::DGMulti, parabolic_scheme, cache, cache_parabolic) + + reset_du!(du, dg) + + @unpack u_transformed, gradients, flux_viscous = cache_parabolic + transform_variables!(u_transformed, u, mesh, equations_parabolic, + dg, parabolic_scheme, cache, cache_parabolic) + + calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, + boundary_conditions, dg, cache, cache_parabolic) + + calc_viscous_fluxes!(flux_viscous, u_transformed, gradients, + mesh, equations_parabolic, dg, cache, cache_parabolic) + + calc_divergence!(du, u_transformed, t, flux_viscous, mesh, equations_parabolic, + boundary_conditions, dg, parabolic_scheme, cache, cache_parabolic) + + return nothing + +end diff --git a/src/solvers/dgmulti/flux_differencing.jl b/src/solvers/dgmulti/flux_differencing.jl index abdc48513b..d8fc85f810 100644 --- a/src/solvers/dgmulti/flux_differencing.jl +++ b/src/solvers/dgmulti/flux_differencing.jl @@ -383,22 +383,20 @@ end # Designed to be extendable to include specialized `approximation_types` too. @inline function has_sparse_operators(dg::DGMultiFluxDiff) rd = dg.basis - return has_sparse_operators(rd.elementType, rd.approximationType) + return has_sparse_operators(rd.elementType, rd.approximation_type) end -# The general fallback does not assume sparse operators -@inline has_sparse_operators(element_type, approximation_type) = Val{false}() +# General fallback for DGMulti solvers: +# Polynomial-based solvers use hybridized SBP operators, which have blocks scaled by outward +# normal components. This implies that operators for different coordinate directions have +# different sparsity patterns. We default to using sum factorization (which is faster when +# operators are sparse) for all `DGMulti` / `StartUpDG.jl` approximation types. +@inline has_sparse_operators(element_type, approx_type) = Val{true}() # For traditional SBP operators on triangles, the operators are fully dense. We avoid using # sum factorization here, which is slower for fully dense matrices. @inline has_sparse_operators(::Union{Tri, Tet}, approx_type::AT) where {AT <: SBP} = Val{false}() -# Polynomial-based solvers use hybridized SBP operators, which have blocks scaled by outward -# normal components. This implies that operators for different coordinate directions have -# different sparsity patterns. We default to using sum factorization (which is faster when -# operators are sparse) for all `<:Polynomial` approximation types. -@inline has_sparse_operators(element_type, approx_type::Polynomial) = Val{true}() - # SBP/GaussSBP operators on quads/hexes use tensor-product operators. Thus, sum factorization is # more efficient and we use the sparsity structure. @inline has_sparse_operators(::Union{Quad, Hex}, approx_type::AT) where {AT <: SBP} = Val{true}() @@ -413,7 +411,7 @@ end @inline function local_flux_differencing!(fluxdiff_local, u_local, element_index, has_nonconservative_terms::Val{false}, volume_integral, has_sparse_operators::Val{false}, mesh, - equations, dg, cache) where {Flux} + equations, dg, cache) @unpack volume_flux = volume_integral for dim in eachdim(mesh) Qi_skew = build_lazy_physical_derivative(element_index, dim, mesh, dg, cache) @@ -427,7 +425,7 @@ end @inline function local_flux_differencing!(fluxdiff_local, u_local, element_index, has_nonconservative_terms::Val{true}, volume_integral, has_sparse_operators::Val{false}, mesh, - equations, dg, cache) where {Flux} + equations, dg, cache) flux_conservative, flux_nonconservative = volume_integral.volume_flux for dim in eachdim(mesh) Qi_skew = build_lazy_physical_derivative(element_index, dim, mesh, dg, cache) @@ -503,10 +501,12 @@ end end end - +# calculates volume integral for <:Polynomial approximation types. We +# do not assume any additional structure (such as collocated volume or +# face nodes, tensor product structure, etc) in `DGMulti`. function calc_volume_integral!(du, u, mesh::DGMultiMesh, have_nonconservative_terms, equations, - volume_integral, dg::DGMultiFluxDiff{<:Polynomial}, + volume_integral, dg::DGMultiFluxDiff, cache) @unpack entropy_projected_u_values, Ph = cache @@ -573,7 +573,7 @@ end # an entropy conservative/stable discretization. For modal DG schemes, an extra `entropy_projection!` # is required (see https://doi.org/10.1016/j.jcp.2018.02.033, Section 4.3). function rhs!(du, u, t, mesh, equations, initial_condition, boundary_conditions::BC, - source_terms::Source, dg::DGMultiFluxDiff{<:Union{Polynomial, GaussSBP}}, cache) where {Source, BC} + source_terms::Source, dg::DGMultiFluxDiff, cache) where {Source, BC} @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) @@ -598,11 +598,48 @@ function rhs!(du, u, t, mesh, equations, initial_condition, boundary_conditions: @trixi_timeit timer() "Jacobian" invert_jacobian!(du, mesh, equations, dg, cache) - @trixi_timeit timer() "sources terms" calc_sources!(du, u, t, source_terms, + @trixi_timeit timer() "source terms" calc_sources!(du, u, t, source_terms, mesh, equations, dg, cache) return nothing end +# Specializes on SBP (e.g., nodal/collocation) DG methods with a flux differencing volume +# integral, e.g., an entropy conservative/stable discretization. The implementation of `rhs!` +# for such schemes is very similar to the implementation of `rhs!` for standard DG methods, +# but specializes `calc_volume_integral`. +function rhs!(du, u, t, mesh, equations, + initial_condition, boundary_conditions::BC, source_terms::Source, + dg::DGMultiFluxDiffSBP, cache) where {BC, Source} + + @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) + + @trixi_timeit timer() "volume integral" calc_volume_integral!( + du, u, mesh, have_nonconservative_terms(equations), equations, + dg.volume_integral, dg, cache) + + @trixi_timeit timer() "prolong2interfaces" prolong2interfaces!( + cache, u, mesh, equations, dg.surface_integral, dg) + + @trixi_timeit timer() "interface flux" calc_interface_flux!( + cache, dg.surface_integral, mesh, + have_nonconservative_terms(equations), equations, dg) + + @trixi_timeit timer() "boundary flux" calc_boundary_flux!( + cache, t, boundary_conditions, mesh, equations, dg) + + @trixi_timeit timer() "surface integral" calc_surface_integral!( + du, u, dg.surface_integral, mesh, equations, dg, cache) + + @trixi_timeit timer() "Jacobian" invert_jacobian!( + du, mesh, equations, dg, cache) + + @trixi_timeit timer() "source terms" calc_sources!( + du, u, t, source_terms, mesh, equations, dg, cache) + + return nothing +end + + end # @muladd diff --git a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl index f28a46dc3f..b7cf727132 100644 --- a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl +++ b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl @@ -308,13 +308,36 @@ end end end -# Specialized constructor for GaussSBP approximation type on quad elements. Restricting to -# VolumeIntegralFluxDifferencing for now since there isn't a way to exploit this structure -# for VolumeIntegralWeakForm yet. +function DGMulti(element_type::Line, + approximation_type::GaussSBP, + volume_integral, surface_integral; + polydeg::Integer, + surface_flux=flux_central, + kwargs...) + + # explicitly specify Gauss quadrature rule with polydeg+1 points + rd = RefElemData(element_type, Polynomial(), polydeg, + quad_rule_vol=StartUpDG.gauss_quad(0, 0, polydeg), + kwargs...) + + # Since there is no dedicated GaussSBP approximation type implemented in StartUpDG, we simply + # initialize `rd = RefElemData(...)` with the appropriate quadrature rules and modify the + # rd.approximation_type manually so we can dispatch on the `GaussSBP` type. + # This uses the Setfield @set macro, which behaves similarly to `Trixi.remake`. + rd_gauss = @set rd.approximation_type = GaussSBP() + + # We will modify the face interpolation operator of rd_gauss later, but want to do so only after + # the mesh is initialized, since the face interpolation operator is used for that. + return DG(rd_gauss, nothing #= mortar =#, surface_integral, volume_integral) +end + +# Specialized constructor for GaussSBP approximation type on quad elements. +# TODO: I believe this is restricted to `VolumeIntegralFluxDifferencing` for now +# since there isn't a way to exploit this structure for VolumeIntegralWeakForm yet. + function DGMulti(element_type::Union{Quad, Hex}, approximation_type::GaussSBP, - volume_integral::VolumeIntegralFluxDifferencing, - surface_integral=SurfaceIntegralWeakForm(surface_flux); + volume_integral, surface_integral; polydeg::Integer, surface_flux=flux_central, kwargs...) @@ -331,9 +354,9 @@ function DGMulti(element_type::Union{Quad, Hex}, # Since there is no dedicated GaussSBP approximation type implemented in StartUpDG, we simply # initialize `rd = RefElemData(...)` with the appropriate quadrature rules and modify the - # rd.approximationType manually so we can dispatch on the `GaussSBP` type. + # rd.approximation_type manually so we can dispatch on the `GaussSBP` type. # This uses the Setfield @set macro, which behaves similarly to `Trixi.remake`. - rd_gauss = @set rd.approximationType = GaussSBP() + rd_gauss = @set rd.approximation_type = GaussSBP() # We will modify the face interpolation operator of rd_gauss later, but want to do so only after # the mesh is initialized, since the face interpolation operator is used for that. diff --git a/src/solvers/dgmulti/sbp.jl b/src/solvers/dgmulti/sbp.jl index 49bad9d854..d1b4070202 100644 --- a/src/solvers/dgmulti/sbp.jl +++ b/src/solvers/dgmulti/sbp.jl @@ -297,17 +297,17 @@ end function Base.show(io::IO, mime::MIME"text/plain", rd::RefElemData{NDIMS, ElementType, ApproximationType}) where {NDIMS, ElementType<:StartUpDG.AbstractElemShape, ApproximationType<:AbstractDerivativeOperator} @nospecialize rd print(io, "RefElemData for an approximation using an ") - show(IOContext(io, :compact => true), rd.approximationType) + show(IOContext(io, :compact => true), rd.approximation_type) print(io, " on $(rd.elementType) element") end function Base.show(io::IO, rd::RefElemData{NDIMS, ElementType, ApproximationType}) where {NDIMS, ElementType<:StartUpDG.AbstractElemShape, ApproximationType<:AbstractDerivativeOperator} @nospecialize rd - print(io, "RefElemData{", summary(rd.approximationType), ", ", rd.elementType, "}") + print(io, "RefElemData{", summary(rd.approximation_type), ", ", rd.elementType, "}") end function StartUpDG.inverse_trace_constant(rd::RefElemData{NDIMS, ElementType, ApproximationType}) where {NDIMS, ElementType<:Union{Line, Quad, Hex}, ApproximationType<:AbstractDerivativeOperator} - D = rd.approximationType + D = rd.approximation_type # the inverse trace constant is the maximum eigenvalue corresponding to # M_f * v = λ * M * v @@ -393,7 +393,9 @@ function DGMultiMesh(dg::DGMultiPeriodicFDSBP{NDIMS}; periodicity = ntuple(_ -> true, NDIMS) - md = MeshData(VXYZ, EToV, FToF, xyz, xyzf, xyzq, wJq, + mesh_type = rd.approximation_type + + md = MeshData(mesh_type, VXYZ, EToV, FToF, xyz, xyzf, xyzq, wJq, mapM, mapP, mapB, rstxyzJ, J, nxyzJ, Jf, periodicity) @@ -412,7 +414,7 @@ end # based on the reference grid provided by SummationByPartsOperators.jl and information about the domain size # provided by `md::MeshData``. function StartUpDG.estimate_h(e, rd::RefElemData{NDIMS, ElementType, ApproximationType}, md::MeshData) where {NDIMS, ElementType<:StartUpDG.AbstractElemShape, ApproximationType<:SummationByPartsOperators.AbstractPeriodicDerivativeOperator} - D = rd.approximationType + D = rd.approximation_type x = grid(D) # we assume all SummationByPartsOperators.jl reference grids are rescaled to [-1, 1] @@ -433,6 +435,7 @@ function estimate_dt(mesh::DGMultiMesh, dg::DGMultiPeriodicFDSBP) end # do nothing for interface terms if using a periodic operator +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::DGMultiMesh, equations, surface_integral, dg::DGMultiPeriodicFDSBP) @assert nelements(mesh, dg, cache) == 1 diff --git a/src/solvers/dgsem_p4est/dg_2d.jl b/src/solvers/dgsem_p4est/dg_2d.jl index e410390964..68ff171b44 100644 --- a/src/solvers/dgsem_p4est/dg_2d.jl +++ b/src/solvers/dgsem_p4est/dg_2d.jl @@ -56,6 +56,7 @@ end end end +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::P4estMesh{2}, equations, surface_integral, dg::DG) diff --git a/src/solvers/dgsem_p4est/dg_3d.jl b/src/solvers/dgsem_p4est/dg_3d.jl index 8723c5c70e..66df88f0e7 100644 --- a/src/solvers/dgsem_p4est/dg_3d.jl +++ b/src/solvers/dgsem_p4est/dg_3d.jl @@ -83,6 +83,7 @@ end return (i1, i2) end +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::P4estMesh{3}, equations, surface_integral, dg::DG) diff --git a/src/solvers/dgsem_p4est/dg_parallel.jl b/src/solvers/dgsem_p4est/dg_parallel.jl index 3869c8c20d..1e7e18f8aa 100644 --- a/src/solvers/dgsem_p4est/dg_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_parallel.jl @@ -102,7 +102,7 @@ end function finish_mpi_send!(mpi_cache::P4estMPICache) - MPI.Waitall!(mpi_cache.mpi_send_requests) + MPI.Waitall(mpi_cache.mpi_send_requests, MPI.Status) end @@ -112,8 +112,8 @@ function finish_mpi_receive!(mpi_cache::P4estMPICache, mesh, equations, dg, cach n_positions = n_small_elements + 1 # Start receiving and unpack received data until all communication is finished - d, _ = MPI.Waitany!(mpi_cache.mpi_recv_requests) - while d != 0 + d = MPI.Waitany(mpi_cache.mpi_recv_requests) + while d !== nothing recv_buffer = mpi_cache.mpi_recv_buffers[d] for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) @@ -148,7 +148,7 @@ function finish_mpi_receive!(mpi_cache::P4estMPICache, mesh, equations, dg, cach end end - d, _ = MPI.Waitany!(mpi_cache.mpi_recv_requests) + d = MPI.Waitany(mpi_cache.mpi_recv_requests) end return nothing @@ -507,8 +507,8 @@ function exchange_normal_directions!(mpi_mortars, mpi_cache, mesh::ParallelP4est end # Unpack data from receive buffers - d, _ = MPI.Waitany!(recv_requests) - while d != 0 + d = MPI.Waitany(recv_requests) + while d !== nothing recv_buffer = recv_buffers[d] for (index, mortar) in enumerate(mpi_neighbor_mortars[d]) @@ -526,11 +526,11 @@ function exchange_normal_directions!(mpi_mortars, mpi_cache, mesh::ParallelP4est end end - d, _ = MPI.Waitany!(recv_requests) + d = MPI.Waitany(recv_requests) end # Wait for communication to finish - MPI.Waitall!(send_requests) + MPI.Waitall(send_requests, MPI.Status) return nothing end diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index abc054b572..4e0296a0f0 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -16,7 +16,7 @@ function apply_smoothing!(mesh::StructuredMesh{2}, alpha, alpha_tmp, dg, cache) for element in eachelement(dg,cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] + lower = cache.elements.left_neighbors[2, element] # Apply smoothing alpha[left] = max(alpha_tmp[left], 0.5 * alpha_tmp[element], alpha[left]) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 9d3b1aa593..2f168d232b 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -70,6 +70,7 @@ include("dg_1d.jl") # 2D DG implementation include("dg_2d.jl") include("dg_2d_parallel.jl") +include("dg_2d_parabolic.jl") # 3D DG implementation include("dg_3d.jl") diff --git a/src/solvers/dgsem_tree/dg_1d.jl b/src/solvers/dgsem_tree/dg_1d.jl index 1649500056..469bc072a3 100644 --- a/src/solvers/dgsem_tree/dg_1d.jl +++ b/src/solvers/dgsem_tree/dg_1d.jl @@ -26,7 +26,6 @@ function create_cache(mesh::TreeMesh{1}, equations, # Add specialized parts of the cache required to compute the volume integral etc. cache = (;cache..., create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) - cache = (;cache..., create_cache(mesh, equations, dg.mortar, uEltype)...) return cache end @@ -68,13 +67,6 @@ function create_cache(mesh::Union{TreeMesh{1}, StructuredMesh{1}, P4estMesh{1}}, end -# The methods below are specialized on the mortar type -# and called from the basic `create_cache` method at the top. -function create_cache(mesh::Union{TreeMesh{1}, StructuredMesh{1}, P4estMesh{1}}, equations, mortar_l2::LobattoLegendreMortarL2, uEltype) - NamedTuple() -end - - # TODO: Taal discuss/refactor timer, allowing users to pass a custom timer? function rhs!(du, u, t, @@ -371,6 +363,7 @@ end end +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{1}, equations, surface_integral, dg::DG) @unpack interfaces = cache diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e0b1d3e5ea..2e8dbf33fd 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1064,25 +1064,37 @@ end @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - @unpack inverse_weights = solver.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) - @unpack alpha1, alpha2 = semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(solver, cache) + perform_IDP_correction(u, dt, mesh, equations, solver, cache, indicator) + + return nothing +end + +@inline function perform_IDP_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache, indicator) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + if indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end + + # Loop over blended DG-FV elements + @threaded for element in elements inverse_jacobian = -cache.elements.inverse_jacobian[element] - # Calculate volume integral contribution - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - for j in eachnode(solver), i in eachnode(solver) - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, solver, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, solver, i, j+1, element) + for j in eachnode(dg), i in eachnode(dg) + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) for v in eachvariable(equations) u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + @@ -1256,6 +1268,7 @@ end end +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) @unpack interfaces = cache @@ -1727,6 +1740,7 @@ end end +# we pass in the hyperbolic `dg.surface_integral` as a dummy argument for dispatch function calc_surface_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, surface_integral::SurfaceIntegralWeakForm, dg::DG, cache) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl new file mode 100644 index 0000000000..ca6394172a --- /dev/null +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -0,0 +1,605 @@ +# 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 + +# This file collects all methods that have been updated to work with parabolic systems of equations +# +# assumptions: parabolic terms are of the form div(f(u, grad(u))) and +# will be discretized first order form as follows: +# 1. compute grad(u) +# 2. compute f(u, grad(u)) +# 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) +# boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). +function rhs_parabolic!(du, u, t, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + initial_condition, boundary_conditions_parabolic, source_terms, + dg::DG, parabolic_scheme, cache, cache_parabolic) + @unpack u_transformed, gradients, flux_viscous = cache_parabolic + + # Convert conservative variables to a form more suitable for viscous flux calculations + @trixi_timeit timer() "transform variables" transform_variables!( + u_transformed, u, mesh, equations_parabolic, dg, parabolic_scheme, cache, cache_parabolic) + + # Compute the gradients of the transformed variables + @trixi_timeit timer() "calculate gradient" calc_gradient!( + gradients, u_transformed, t, mesh, equations_parabolic, boundary_conditions_parabolic, dg, + cache, cache_parabolic) + + # Compute and store the viscous fluxes + @trixi_timeit timer() "calculate viscous fluxes" calc_viscous_fluxes!( + flux_viscous, gradients, u_transformed, mesh, equations_parabolic, dg, cache, cache_parabolic) + + # The remainder of this function is essentially a regular rhs! for parabolic equations (i.e., it + # computes the divergence of the viscous fluxes) + # + # OBS! In `calc_viscous_fluxes!`, the viscous flux values at the volume nodes of each element have + # been computed and stored in `fluxes_viscous`. In the following, we *reuse* (abuse) the + # `interfaces` and `boundaries` containers in `cache_parabolic` to interpolate and store the + # *fluxes* at the element surfaces, as opposed to interpolating and storing the *solution* (as it + # is done in the hyperbolic operator). That is, `interfaces.u`/`boundaries.u` store *viscous flux values* + # and *not the solution*. The advantage is that a) we do not need to allocate more storage, b) we + # do not need to recreate the existing data structure only with a different name, and c) we do not + # need to interpolate solutions *and* gradients to the surfaces. + + # TODO: parabolic; reconsider current data structure reuse strategy + + # Reset du + @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) + + # Calculate volume integral + @trixi_timeit timer() "volume integral" calc_volume_integral!( + du, flux_viscous, mesh, equations_parabolic, dg, cache) + + # Prolong solution to interfaces + @trixi_timeit timer() "prolong2interfaces" prolong2interfaces!( + cache_parabolic, flux_viscous, mesh, equations_parabolic, dg.surface_integral, dg, cache) + + # Calculate interface fluxes + @trixi_timeit timer() "interface flux" calc_interface_flux!( + cache_parabolic.elements.surface_flux_values, mesh, equations_parabolic, dg, cache_parabolic) + + # Prolong solution to boundaries + @trixi_timeit timer() "prolong2boundaries" prolong2boundaries!( + cache_parabolic, flux_viscous, mesh, equations_parabolic, dg.surface_integral, dg, cache) + + # Calculate boundary fluxes + @trixi_timeit timer() "boundary flux" calc_boundary_flux_divergence!( + cache_parabolic, t, boundary_conditions_parabolic, mesh, equations_parabolic, + dg.surface_integral, dg) + + # TODO: parabolic; extend to mortars + @assert nmortars(dg, cache) == 0 + + # Calculate surface integrals + @trixi_timeit timer() "surface integral" calc_surface_integral!( + du, u, mesh, equations_parabolic, dg.surface_integral, dg, cache_parabolic) + + # Apply Jacobian from mapping to reference element + @trixi_timeit timer() "Jacobian" apply_jacobian!( + du, mesh, equations_parabolic, dg, cache_parabolic) + + return nothing +end + +# Transform solution variables prior to taking the gradient +# (e.g., conservative to primitive variables). Defaults to doing nothing. +# TODO: can we avoid copying data? +function transform_variables!(u_transformed, u, mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + dg::DG, parabolic_scheme, cache, cache_parabolic) + @threaded for element in eachelement(dg, cache) + # Calculate volume terms in one element + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations_parabolic, dg, i, j, element) + u_transformed_node = gradient_variable_transformation(equations_parabolic)(u_node, equations_parabolic) + set_node_vars!(u_transformed, u_transformed_node, equations_parabolic, dg, i, j, element) + end + end +end + +# This is the version used when calculating the divergence of the viscous fluxes +function calc_volume_integral!(du, flux_viscous, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + dg::DGSEM, cache) + @unpack derivative_dhat = dg.basis + flux_viscous_x, flux_viscous_y = flux_viscous + + @threaded for element in eachelement(dg, cache) + # Calculate volume terms in one element + for j in eachnode(dg), i in eachnode(dg) + flux_1_node = get_node_vars(flux_viscous_x, equations_parabolic, dg, i, j, element) + flux_2_node = get_node_vars(flux_viscous_y, equations_parabolic, dg, i, j, element) + + for ii in eachnode(dg) + multiply_add_to_node_vars!(du, derivative_dhat[ii, i], flux_1_node, equations_parabolic, dg, ii, j, element) + end + + for jj in eachnode(dg) + multiply_add_to_node_vars!(du, derivative_dhat[jj, j], flux_2_node, equations_parabolic, dg, i, jj, element) + end + end + end + + return nothing +end + + +# This is the version used when calculating the divergence of the viscous fluxes +# We pass the `surface_integral` argument solely for dispatch +function prolong2interfaces!(cache_parabolic, flux_viscous, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache) + @unpack interfaces = cache_parabolic + @unpack orientations = interfaces + + flux_viscous_x, flux_viscous_y = flux_viscous + + @threaded for interface in eachinterface(dg, cache) + left_element = interfaces.neighbor_ids[1, interface] + right_element = interfaces.neighbor_ids[2, interface] + + if orientations[interface] == 1 + # interface in x-direction + for j in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! + interfaces.u[1, v, j, interface] = flux_viscous_x[v, nnodes(dg), j, left_element] + interfaces.u[2, v, j, interface] = flux_viscous_x[v, 1, j, right_element] + end + else # if orientations[interface] == 2 + # interface in y-direction + for i in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! + interfaces.u[1, v, i, interface] = flux_viscous_y[v, i, nnodes(dg), left_element] + interfaces.u[2, v, i, interface] = flux_viscous_y[v, i, 1, right_element] + end + end + end + + return nothing +end + + +# This is the version used when calculating the divergence of the viscous fluxes +function calc_interface_flux!(surface_flux_values, + mesh::TreeMesh{2}, equations_parabolic, + dg::DG, cache_parabolic) + @unpack neighbor_ids, orientations = cache_parabolic.interfaces + + @threaded for interface in eachinterface(dg, cache_parabolic) + # Get neighboring elements + left_id = neighbor_ids[1, interface] + right_id = neighbor_ids[2, interface] + + # Determine interface direction with respect to elements: + # orientation = 1: left -> 2, right -> 1 + # orientation = 2: left -> 4, right -> 3 + left_direction = 2 * orientations[interface] + right_direction = 2 * orientations[interface] - 1 + + for i in eachnode(dg) + # Get precomputed fluxes at interfaces + flux_ll, flux_rr = get_surface_node_vars(cache_parabolic.interfaces.u, equations_parabolic, + dg, i, interface) + + # Compute interface flux as mean of left and right viscous fluxes + # TODO: parabolic; only BR1 at the moment + flux = 0.5 * (flux_ll + flux_rr) + + # Copy flux to left and right element storage + for v in eachvariable(equations_parabolic) + surface_flux_values[v, i, left_direction, left_id] = flux[v] + surface_flux_values[v, i, right_direction, right_id] = flux[v] + end + end + end + + return nothing +end + + +# This is the version used when calculating the divergence of the viscous fluxes +function prolong2boundaries!(cache_parabolic, flux_viscous, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache) + @unpack boundaries = cache_parabolic + @unpack orientations, neighbor_sides = boundaries + flux_viscous_x, flux_viscous_y = flux_viscous + + @threaded for boundary in eachboundary(dg, cache_parabolic) + element = boundaries.neighbor_ids[boundary] + + if orientations[boundary] == 1 + # boundary in x-direction + if neighbor_sides[boundary] == 1 + # element in -x direction of boundary + for l in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! + boundaries.u[1, v, l, boundary] = flux_viscous_x[v, nnodes(dg), l, element] + end + else # Element in +x direction of boundary + for l in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! + boundaries.u[2, v, l, boundary] = flux_viscous_x[v, 1, l, element] + end + end + else # if orientations[boundary] == 2 + # boundary in y-direction + if neighbor_sides[boundary] == 1 + # element in -y direction of boundary + for l in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! + boundaries.u[1, v, l, boundary] = flux_viscous_y[v, l, nnodes(dg), element] + end + else + # element in +y direction of boundary + for l in eachnode(dg), v in eachvariable(equations_parabolic) + # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! + boundaries.u[2, v, l, boundary] = flux_viscous_y[v, l, 1, element] + end + end + end + end + + return nothing +end + + +function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + dg::DG, cache, cache_parabolic) + gradients_x, gradients_y = gradients + flux_viscous_x, flux_viscous_y = flux_viscous # output arrays + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + # Get solution and gradients + u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, element) + gradients_1_node = get_node_vars(gradients_x, equations_parabolic, dg, i, j, element) + gradients_2_node = get_node_vars(gradients_y, equations_parabolic, dg, i, j, element) + + # Calculate viscous flux and store each component for later use + flux_viscous_node_x = flux(u_node, (gradients_1_node, gradients_2_node), 1, equations_parabolic) + flux_viscous_node_y = flux(u_node, (gradients_1_node, gradients_2_node), 2, equations_parabolic) + set_node_vars!(flux_viscous_x, flux_viscous_node_x, equations_parabolic, dg, i, j, element) + set_node_vars!(flux_viscous_y, flux_viscous_node_y, equations_parabolic, dg, i, j, element) + end + end +end + + +# TODO: parabolic; decide if we should keep this, and if so, extend to 3D. +function get_unsigned_normal_vector_2d(direction) + if direction > 4 || direction < 1 + error("Direction = $direction; in 2D, direction should be 1, 2, 3, or 4.") + end + if direction == 1 || direction == 2 + return SVector(1.0, 0.0) + else + return SVector(0.0, 1.0) + end +end + +function calc_boundary_flux_gradients!(cache, t, boundary_conditions_parabolic::BoundaryConditionPeriodic, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG) + return nothing +end + +function calc_boundary_flux_divergence!(cache, t, boundary_conditions_parabolic::BoundaryConditionPeriodic, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG) + return nothing +end + +function calc_boundary_flux_gradients!(cache, t, boundary_conditions_parabolic::NamedTuple, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG) + @unpack surface_flux_values = cache.elements + @unpack n_boundaries_per_direction = cache.boundaries + + # Calculate indices + lasts = accumulate(+, n_boundaries_per_direction) + firsts = lasts - n_boundaries_per_direction .+ 1 + + # Calc boundary fluxes in each direction + calc_boundary_flux_by_direction_gradient!(surface_flux_values, t, boundary_conditions_parabolic[1], + equations_parabolic, surface_integral, dg, cache, + 1, firsts[1], lasts[1]) + calc_boundary_flux_by_direction_gradient!(surface_flux_values, t, boundary_conditions_parabolic[2], + equations_parabolic, surface_integral, dg, cache, + 2, firsts[2], lasts[2]) + calc_boundary_flux_by_direction_gradient!(surface_flux_values, t, boundary_conditions_parabolic[3], + equations_parabolic, surface_integral, dg, cache, + 3, firsts[3], lasts[3]) + calc_boundary_flux_by_direction_gradient!(surface_flux_values, t, boundary_conditions_parabolic[4], + equations_parabolic, surface_integral, dg, cache, + 4, firsts[4], lasts[4]) +end +function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{<:Any,4}, t, + boundary_condition, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + direction, first_boundary, last_boundary) + @unpack surface_flux = surface_integral + @unpack u, neighbor_ids, neighbor_sides, node_coordinates, orientations = cache.boundaries + + @threaded for boundary in first_boundary:last_boundary + # Get neighboring element + neighbor = neighbor_ids[boundary] + + for i in eachnode(dg) + # Get boundary flux + u_ll, u_rr = get_surface_node_vars(u, equations_parabolic, dg, i, boundary) + if neighbor_sides[boundary] == 1 # Element is on the left, boundary on the right + u_inner = u_ll + else # Element is on the right, boundary on the left + u_inner = u_rr + end + + # TODO: revisit if we want more general boundary treatments. + # This assumes the gradient numerical flux at the boundary is the gradient variable, + # which is consistent with BR1, LDG. + flux_inner = u_inner + + x = get_node_coords(node_coordinates, equations_parabolic, dg, i, boundary) + flux = boundary_condition(flux_inner, u_inner, get_unsigned_normal_vector_2d(direction), + x, t, Gradient(), equations_parabolic) + + # Copy flux to left and right element storage + for v in eachvariable(equations_parabolic) + surface_flux_values[v, i, direction, neighbor] = flux[v] + end + end + end + + return nothing +end + +function calc_boundary_flux_divergence!(cache, t, boundary_conditions_parabolic::NamedTuple, + mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG) + @unpack surface_flux_values = cache.elements + @unpack n_boundaries_per_direction = cache.boundaries + + # Calculate indices + lasts = accumulate(+, n_boundaries_per_direction) + firsts = lasts - n_boundaries_per_direction .+ 1 + + # Calc boundary fluxes in each direction + calc_boundary_flux_by_direction_divergence!(surface_flux_values, t, boundary_conditions_parabolic[1], + equations_parabolic, surface_integral, dg, cache, + 1, firsts[1], lasts[1]) + calc_boundary_flux_by_direction_divergence!(surface_flux_values, t, boundary_conditions_parabolic[2], + equations_parabolic, surface_integral, dg, cache, + 2, firsts[2], lasts[2]) + calc_boundary_flux_by_direction_divergence!(surface_flux_values, t, boundary_conditions_parabolic[3], + equations_parabolic, surface_integral, dg, cache, + 3, firsts[3], lasts[3]) + calc_boundary_flux_by_direction_divergence!(surface_flux_values, t, boundary_conditions_parabolic[4], + equations_parabolic, surface_integral, dg, cache, + 4, firsts[4], lasts[4]) +end +function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{<:Any,4}, t, + boundary_condition, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + direction, first_boundary, last_boundary) + @unpack surface_flux = surface_integral + + # Note: cache.boundaries.u contains the unsigned normal component (using "orientation", not "direction") + # of the viscous flux, as computed in `prolong2boundaries!` + @unpack u, neighbor_ids, neighbor_sides, node_coordinates, orientations = cache.boundaries + + @threaded for boundary in first_boundary:last_boundary + # Get neighboring element + neighbor = neighbor_ids[boundary] + + for i in eachnode(dg) + # Get viscous boundary fluxes + flux_ll, flux_rr = get_surface_node_vars(u, equations_parabolic, dg, i, boundary) + if neighbor_sides[boundary] == 1 # Element is on the left, boundary on the right + flux_inner = flux_ll + else # Element is on the right, boundary on the left + flux_inner = flux_rr + end + + x = get_node_coords(node_coordinates, equations_parabolic, dg, i, boundary) + + # TODO: add a field in `cache.boundaries` for gradient information. + # Here, we pass in `u_inner = nothing` since we overwrite cache.boundaries.u with gradient information. + # This currently works with Dirichlet/Neuman boundary conditions for LaplaceDiffusion2D and + # NoSlipWall/Adiabatic boundary conditions for CompressibleNavierStokesDiffusion2D as of 2022-6-27. + # It will not work with implementations which utilize `u_inner` to impose boundary conditions. + flux = boundary_condition(flux_inner, nothing, get_unsigned_normal_vector_2d(direction), + x, t, Divergence(), equations_parabolic) + + # Copy flux to left and right element storage + for v in eachvariable(equations_parabolic) + surface_flux_values[v, i, direction, neighbor] = flux[v] + end + end + end + + return nothing +end + + +# Calculate the gradient of the transformed variables +function calc_gradient!(gradients, u_transformed, t, + mesh::TreeMesh{2}, equations_parabolic, + boundary_conditions_parabolic, dg::DG, cache, cache_parabolic) + + gradients_x, gradients_y = gradients + + # Reset du + @trixi_timeit timer() "reset gradients" begin + reset_du!(gradients_x, dg, cache) + reset_du!(gradients_y, dg, cache) + end + + # Calculate volume integral + @trixi_timeit timer() "volume integral" begin + @unpack derivative_dhat = dg.basis + @threaded for element in eachelement(dg, cache) + + # Calculate volume terms in one element + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, element) + + for ii in eachnode(dg) + multiply_add_to_node_vars!(gradients_x, derivative_dhat[ii, i], u_node, equations_parabolic, dg, ii, j, element) + end + + for jj in eachnode(dg) + multiply_add_to_node_vars!(gradients_y, derivative_dhat[jj, j], u_node, equations_parabolic, dg, i, jj, element) + end + end + end + end + + # Prolong solution to interfaces + @trixi_timeit timer() "prolong2interfaces" prolong2interfaces!( + cache_parabolic, u_transformed, mesh, equations_parabolic, dg.surface_integral, dg) + + # Calculate interface fluxes + @trixi_timeit timer() "interface flux" begin + @unpack surface_flux_values = cache_parabolic.elements + @unpack neighbor_ids, orientations = cache_parabolic.interfaces + + @threaded for interface in eachinterface(dg, cache_parabolic) + # Get neighboring elements + left_id = neighbor_ids[1, interface] + right_id = neighbor_ids[2, interface] + + # Determine interface direction with respect to elements: + # orientation = 1: left -> 2, right -> 1 + # orientation = 2: left -> 4, right -> 3 + left_direction = 2 * orientations[interface] + right_direction = 2 * orientations[interface] - 1 + + for i in eachnode(dg) + # Call pointwise Riemann solver + u_ll, u_rr = get_surface_node_vars(cache_parabolic.interfaces.u, + equations_parabolic, dg, i, interface) + flux = 0.5 * (u_ll + u_rr) + + # Copy flux to left and right element storage + for v in eachvariable(equations_parabolic) + surface_flux_values[v, i, left_direction, left_id] = flux[v] + surface_flux_values[v, i, right_direction, right_id] = flux[v] + end + end + end + end + + # Prolong solution to boundaries + @trixi_timeit timer() "prolong2boundaries" prolong2boundaries!( + cache_parabolic, u_transformed, mesh, equations_parabolic, dg.surface_integral, dg) + + # Calculate boundary fluxes + @trixi_timeit timer() "boundary flux" calc_boundary_flux_gradients!( + cache_parabolic, t, boundary_conditions_parabolic, mesh, equations_parabolic, + dg.surface_integral, dg) + + # TODO: parabolic; mortars + + # Calculate surface integrals + @trixi_timeit timer() "surface integral" begin + @unpack boundary_interpolation = dg.basis + @unpack surface_flux_values = cache_parabolic.elements + + # Note that all fluxes have been computed with outward-pointing normal vectors. + # Access the factors only once before beginning the loop to increase performance. + # We also use explicit assignments instead of `+=` to let `@muladd` turn these + # into FMAs (see comment at the top of the file). + factor_1 = boundary_interpolation[1, 1] + factor_2 = boundary_interpolation[nnodes(dg), 2] + @threaded for element in eachelement(dg, cache) + for l in eachnode(dg) + for v in eachvariable(equations_parabolic) + # surface at -x + gradients_x[v, 1, l, element] = ( + gradients_x[v, 1, l, element] - surface_flux_values[v, l, 1, element] * factor_1) + + # surface at +x + gradients_x[v, nnodes(dg), l, element] = ( + gradients_x[v, nnodes(dg), l, element] + surface_flux_values[v, l, 2, element] * factor_2) + + # surface at -y + gradients_y[v, l, 1, element] = ( + gradients_y[v, l, 1, element] - surface_flux_values[v, l, 3, element] * factor_1) + + # surface at +y + gradients_y[v, l, nnodes(dg), element] = ( + gradients_y[v, l, nnodes(dg), element] + surface_flux_values[v, l, 4, element] * factor_2) + end + end + end + end + + # Apply Jacobian from mapping to reference element + @trixi_timeit timer() "Jacobian" begin + apply_jacobian!(gradients_x, mesh, equations_parabolic, dg, cache_parabolic) + apply_jacobian!(gradients_y, mesh, equations_parabolic, dg, cache_parabolic) + end + + return nothing +end + + +# This method is called when a SemidiscretizationHyperbolic is constructed. +# It constructs the basic `cache` used throughout the simulation to compute +# the RHS etc. +function create_cache_parabolic(mesh::TreeMesh{2}, equations_hyperbolic::AbstractEquations, + equations_parabolic::AbstractEquationsParabolic, + dg::DG, parabolic_scheme, RealT, uEltype) + # Get cells for which an element needs to be created (i.e. all leaf cells) + leaf_cell_ids = local_leaf_cells(mesh.tree) + + elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) + + n_vars = nvariables(equations_hyperbolic) + n_nodes = nnodes(elements) + n_elements = nelements(elements) + u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_elements) + gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) + flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) + + interfaces = init_interfaces(leaf_cell_ids, mesh, elements) + + boundaries = init_boundaries(leaf_cell_ids, mesh, elements) + + # mortars = init_mortars(leaf_cell_ids, mesh, elements, dg.mortar) + + # cache = (; elements, interfaces, boundaries, mortars) + cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + + # Add specialized parts of the cache required to compute the mortars etc. + # cache = (;cache..., create_cache(mesh, equations_parabolic, dg.mortar, uEltype)...) + + return cache +end + + +# Needed to *not* flip the sign of the inverse Jacobian. +# This is because the parabolic fluxes are assumed to be of the form +# `du/dt + df/dx = dg/dx + source(x,t)`, +# where f(u) is the inviscid flux and g(u) is the viscous flux. +function apply_jacobian!(du, mesh::TreeMesh{2}, + equations::AbstractEquationsParabolic, dg::DG, cache) + + @threaded for element in eachelement(dg, cache) + factor = cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + du[v, i, j, element] *= factor + end + end + end + + return nothing +end + +end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d_parallel.jl b/src/solvers/dgsem_tree/dg_2d_parallel.jl index 10c198f9be..2385b61f31 100644 --- a/src/solvers/dgsem_tree/dg_2d_parallel.jl +++ b/src/solvers/dgsem_tree/dg_2d_parallel.jl @@ -142,7 +142,7 @@ end # TODO: MPI dimension agnostic function finish_mpi_send!(mpi_cache::MPICache) - MPI.Waitall!(mpi_cache.mpi_send_requests) + MPI.Waitall(mpi_cache.mpi_send_requests, MPI.Status) end @@ -151,8 +151,8 @@ function finish_mpi_receive!(mpi_cache::MPICache, mesh, equations, dg, cache) data_size = nvariables(equations) * nnodes(dg)^(ndims(mesh) - 1) # Start receiving and unpack received data until all communication is finished - d, _ = MPI.Waitany!(mpi_cache.mpi_recv_requests) - while d != 0 + d = MPI.Waitany(mpi_cache.mpi_recv_requests) + while d !== nothing recv_buffer = mpi_cache.mpi_recv_buffers[d] for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) @@ -221,7 +221,7 @@ function finish_mpi_receive!(mpi_cache::MPICache, mesh, equations, dg, cache) end end - d, _ = MPI.Waitany!(mpi_cache.mpi_recv_requests) + d = MPI.Waitany(mpi_cache.mpi_recv_requests) end return nothing diff --git a/src/solvers/dgsem_tree/dg_3d.jl b/src/solvers/dgsem_tree/dg_3d.jl index 611691f9f8..acd1b31d64 100644 --- a/src/solvers/dgsem_tree/dg_3d.jl +++ b/src/solvers/dgsem_tree/dg_3d.jl @@ -544,6 +544,7 @@ end end +# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{3}, equations, surface_integral, dg::DG) @unpack interfaces = cache diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 670983722d..ea87584007 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -235,7 +235,7 @@ IndicatorMCL """ struct IndicatorMCL{Cache} <: AbstractIndicator cache::Cache - IDPPressureTVD::Bool + IDPPressureTVD::Bool # synchronized pressure limiting IDPCheckBounds::Bool end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 630fc8921d..bd20af2391 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -213,18 +213,18 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab dt, cache; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator - alpha .= 0.0 # TODO: Correct that we save only the alpha's of the last RK stage. + alpha .= 0.0 indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, equations, dg, dt, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP @@ -245,51 +245,107 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab for j in 2:nnodes(dg), i in eachnode(dg) alpha2[i, j, element] = max(alpha[i, j-1, element], alpha[i, j, element]) end - alpha1[1, :, element] .= zero(eltype(alpha1)) + alpha1[1, :, element] .= zero(eltype(alpha1)) alpha1[nnodes(dg)+1, :, element] .= zero(eltype(alpha1)) - alpha2[:, 1, element] .= zero(eltype(alpha2)) + alpha2[:, 1, element] .= zero(eltype(alpha2)) alpha2[:, nnodes(dg)+1, element] .= zero(eltype(alpha2)) end return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator +@inline function calc_bounds_2sided!(var_min, var_max, variable, u, mesh, equations, dg, cache) + # Values inside each element + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + # Calculate indicator variables at Gauss-Lobatto nodes + for j in eachnode(dg), i in eachnode(dg) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_min[i, j, element] = min(var_min[i, j, element], var) + var_max[i, j, element] = max(var_max[i, j, element], var) - rho_min = var_bounds[1] - rho_max = var_bounds[2] + if i > 1 + var_min[i-1, j, element] = min(var_min[i-1, j, element], var) + var_max[i-1, j, element] = max(var_max[i-1, j, element], var) + end + if i < nnodes(dg) + var_min[i+1, j, element] = min(var_min[i+1, j, element], var) + var_max[i+1, j, element] = max(var_max[i+1, j, element], var) + end + if j > 1 + var_min[i, j-1, element] = min(var_min[i, j-1, element], var) + var_max[i, j-1, element] = max(var_max[i, j-1, element], var) + end + if j < nnodes(dg) + var_min[i, j+1, element] = min(var_min[i, j+1, element], var) + var_max[i, j+1, element] = max(var_max[i, j+1, element], var) + end + end + end + + # Values at element boundary + calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh, equations, dg, cache) +end + +@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::TreeMesh2D, equations, dg, cache) + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + if orientation == 1 + index_left = (nnodes(dg), i, left) + index_right = (1, i, right) + else + index_left = (i, nnodes(dg), left) + index_right = (i, 1, right) + end + var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) + var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) + + var_min[index_right...] = min(var_min[index_right...], var_left) + var_max[index_right...] = max(var_max[index_right...], var_left) + + var_min[index_left...] = min(var_min[index_left...], var_right) + var_max[index_left...] = max(var_max[index_left...], var_right) + end + end +end - # Calculate bound: rho_min, rho_max +@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, mesh, equations, dg, cache) + # Values inside each element @threaded for element in eachelement(dg, cache) - rho_min[:, :, element] .= typemax(eltype(rho_min)) - rho_max[:, :, element] .= typemin(eltype(rho_max)) + var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) + # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - rho = u_safe[1, i, j, element] - rho_min[i, j, element] = min(rho_min[i, j, element], rho) - rho_max[i, j, element] = max(rho_max[i, j, element], rho) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) if i > 1 - rho_min[i-1, j, element] = min(rho_min[i-1, j, element], rho) - rho_max[i-1, j, element] = max(rho_max[i-1, j, element], rho) + var_minmax[i-1, j, element] = minmax(var_minmax[i-1, j, element], var) end if i < nnodes(dg) - rho_min[i+1, j, element] = min(rho_min[i+1, j, element], rho) - rho_max[i+1, j, element] = max(rho_max[i+1, j, element], rho) + var_minmax[i+1, j, element] = minmax(var_minmax[i+1, j, element], var) end if j > 1 - rho_min[i, j-1, element] = min(rho_min[i, j-1, element], rho) - rho_max[i, j-1, element] = max(rho_max[i, j-1, element], rho) + var_minmax[i, j-1, element] = minmax(var_minmax[i, j-1, element], var) end if j < nnodes(dg) - rho_min[i, j+1, element] = min(rho_min[i, j+1, element], rho) - rho_max[i, j+1, element] = max(rho_max[i, j+1, element], rho) + var_minmax[i, j+1, element] = minmax(var_minmax[i, j+1, element], var) end end end - # Loop over interfaces + # Values at element boundary + calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh, equations, dg, cache) +end + +@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::TreeMesh2D, equations, dg, cache) for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] @@ -305,16 +361,21 @@ end index_left = (i, nnodes(dg), left) index_right = (i, 1, right) end - rho_left = u_safe[1, index_left...] - rho_right = u_safe[1, index_right...] + var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) + var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) - rho_min[index_right...] = min(rho_min[index_right...], rho_left) - rho_max[index_right...] = max(rho_max[index_right...], rho_left) - - rho_min[index_left...] = min(rho_min[index_left...], rho_right) - rho_max[index_left...] = max(rho_max[index_left...], rho_right) + var_minmax[index_right...] = minmax(var_minmax[index_right...], var_left) + var_minmax[index_left...] = minmax(var_minmax[index_left...], var_right) end end +end + +@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + rho_min = var_bounds[1] + rho_max = var_bounds[2] + calc_bounds_2sided!(rho_min, rho_max, density, u_safe, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -363,7 +424,7 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -371,62 +432,7 @@ end offset = 2 * indicator_IDP.IDPDensityTVD p_min = var_bounds[1 + offset] p_max = var_bounds[2 + offset] - - # Calculate bound: p_min, p_max - @threaded for element in eachelement(dg, cache) - p_min[:, :, element] .= typemax(eltype(p_min)) - p_max[:, :, element] .= typemin(eltype(p_max)) - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - - if i > 1 - p_min[i-1, j, element] = min(p_min[i-1, j, element], p) - p_max[i-1, j, element] = max(p_max[i-1, j, element], p) - end - if i < nnodes(dg) - p_min[i+1, j, element] = min(p_min[i+1, j, element], p) - p_max[i+1, j, element] = max(p_max[i+1, j, element], p) - end - if j > 1 - p_min[i, j-1, element] = min(p_min[i, j-1, element], p) - p_max[i, j-1, element] = max(p_max[i, j-1, element], p) - end - if j < nnodes(dg) - p_min[i, j+1, element] = min(p_min[i, j+1, element], p) - p_max[i, j+1, element] = max(p_max[i, j+1, element], p) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - p_left = pressure(get_node_vars(u_safe, equations, dg, index_left...), equations) - p_right = pressure(get_node_vars(u_safe, equations, dg, index_right...), equations) - - p_min[index_right...] = min(p_min[index_right...], p_left) - p_max[index_right...] = max(p_max[index_right...], p_left) - - p_min[index_left...] = min(p_min[index_left...], p_right) - p_max[index_left...] = max(p_max[index_left...], p_right) - end - end + calc_bounds_2sided!(p_min, p_max, pressure, u_safe, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -484,59 +490,13 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) s_min = var_bounds[offset + 1] - - # Calculate bound: s_min - @threaded for element in eachelement(dg, cache) - s_min[:, :, element] .= typemax(eltype(s_min)) - for j in eachnode(dg), i in eachnode(dg) - - # Get limit states - s = entropy_spec(get_node_vars(u_old, equations, dg, i, j, element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - if i > 1 - s_min[i-1, j, element] = min(s_min[i-1, j, element], s) - end - if i < nnodes(dg) - s_min[i+1, j, element] = min(s_min[i+1, j, element], s) - end - if j > 1 - s_min[i, j-1, element] = min(s_min[i, j-1, element], s) - end - if j < nnodes(dg) - s_min[i, j+1, element] = min(s_min[i, j+1, element], s) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - s_left = entropy_spec(get_node_vars(u_old, equations, dg, index_left...), equations) - s_right = entropy_spec(get_node_vars(u_old, equations, dg, index_right...), equations) - - s_min[index_right...] = min(s_min[index_right...], s_left) - s_min[index_left...] = min(s_min[index_left...], s_right) - end - end + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -544,7 +504,7 @@ end u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -555,60 +515,14 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, equations, dg, dt, cache) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) s_max = var_bounds[offset + 1] - - # Calculate bound: s_max - @threaded for element in eachelement(dg, cache) - s_max[:, :, element] .= typemin(eltype(s_max)) - for j in eachnode(dg), i in eachnode(dg) - - # Get limit states - s = entropy_math(get_node_vars(u_old, equations, dg, i, j, element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - if i > 1 - s_max[i-1, j, element] = max(s_max[i-1, j, element], s) - end - if i < nnodes(dg) - s_max[i+1, j, element] = max(s_max[i+1, j, element], s) - end - if j > 1 - s_max[i, j-1, element] = max(s_max[i, j-1, element], s) - end - if j < nnodes(dg) - s_max[i, j+1, element] = max(s_max[i, j+1, element], s) - end - end - end - - # Loop over interfaces - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) - end - s_left = entropy_math(get_node_vars(u_old, equations, dg, index_left...), equations) - s_right = entropy_math(get_node_vars(u_old, equations, dg, index_right...), equations) - - s_max[index_right...] = max(s_max[index_right...], s_left) - s_max[index_left...] = max(s_max[index_left...], s_right) - end - end + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -616,7 +530,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -627,7 +541,7 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, equations, dg, dt, cache) +@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -711,7 +625,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) end end @@ -725,7 +639,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma @inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - equations, dg, dt, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator_IDP) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -754,6 +668,8 @@ end @inline function newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_reltol, newton_abstol = indicator_IDP.newton_tol + beta = 1.0 - alpha[i, j, element] beta_L = 0.0 # alpha = 1 @@ -761,18 +677,23 @@ end u_curr = u_safe + beta * dt * antidiffusive_flux - # Perform initial Check - as = goal_fct(bound, u_curr, equations) + # If state is valid, perform initial check and return if correction is not needed + if isValidState(u_curr, equations) + as = goal_fct(bound, u_curr, equations) - newton_reltol, newton_abstol = indicator_IDP.newton_tol - initialCheck(bound, as, newton_abstol) && return nothing + initialCheck(bound, as, newton_abstol) && return nothing + end # Newton iterations for iter in 1:indicator_IDP.IDPMaxIter beta_old = beta - # Evaluate d(goal)/d(beta) - dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + # If the state is valid, evaluate d(goal)/d(beta) + if isValidState(u_curr, equations) + dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + else # Otherwise, perform a bisection step + dSdbeta = 0.0 + end if dSdbeta != 0.0 # Update beta with Newton's method @@ -785,6 +706,13 @@ end beta = 0.5 * (beta_L + beta_R) # Get new u u_curr = u_safe + beta * dt * antidiffusive_flux + + # If the state is invalid, finish bisection step without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + # Check new beta for condition and update bounds as = goal_fct(bound, u_curr, equations) if initialCheck(bound, as, newton_abstol) @@ -795,6 +723,13 @@ end else # Get new u u_curr = u_safe + beta * dt * antidiffusive_flux + + # If the state is invalid, redefine right bound without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + # Evaluate goal function as = goal_fct(bound, u_curr, equations) end @@ -822,6 +757,16 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) +@inline function update_alpha_per_timestep!(alpha_max_per_timestep, alpha_mean_per_timestep, alpha, + timestep, n_stages, semi) + _, equations, solver, cache = mesh_equations_solver_cache(semi) + n_elements = nelements(solver, cache) + n_nodes = nnodes(solver)^ndims(equations) + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_mean_per_timestep[timestep] += 1/(n_stages * n_nodes * n_elements) * sum(alpha) + + return nothing +end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/solvers/dgsem_unstructured/dg_2d.jl b/src/solvers/dgsem_unstructured/dg_2d.jl index 4128e1c629..f2872652c8 100644 --- a/src/solvers/dgsem_unstructured/dg_2d.jl +++ b/src/solvers/dgsem_unstructured/dg_2d.jl @@ -81,6 +81,7 @@ end # prolong the solution into the convenience array in the interior interface container +# We pass the `surface_integral` argument solely for dispatch # Note! this routine is for quadrilateral elements with "right-handed" orientation function prolong2interfaces!(cache, u, mesh::UnstructuredMesh2D, diff --git a/src/solvers/solvers.jl b/src/solvers/solvers.jl index a52f717a61..465e051482 100644 --- a/src/solvers/solvers.jl +++ b/src/solvers/solvers.jl @@ -4,9 +4,10 @@ # See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. @muladd begin +# define types for parabolic solvers +include("solvers_parabolic.jl") include("dg.jl") include("dgmulti.jl") - end # @muladd diff --git a/src/solvers/solvers_parabolic.jl b/src/solvers/solvers_parabolic.jl new file mode 100644 index 0000000000..f253cdbd03 --- /dev/null +++ b/src/solvers/solvers_parabolic.jl @@ -0,0 +1,31 @@ +""" + ViscousFormulationBassiRebay1() + +The classical BR1 flux from + +- F. Bassi, S. Rebay (1997) + A High-Order Accurate Discontinuous Finite Element Method for + the Numerical Solution of the Compressible Navier-Stokes Equations + [DOI: 10.1006/jcph.1996.5572](https://doi.org/10.1006/jcph.1996.5572) +""" +struct ViscousFormulationBassiRebay1 end + +""" + ViscousFormulationLocalDG(penalty_parameter) + +The local DG (LDG) flux from "The Local Discontinuous Galerkin Method for Time-Dependent +Convection-Diffusion Systems" by Cockburn and Shu (1998). + +Note that, since this implementation does not involve the parabolic "upwinding" vector, +the LDG solver is equivalent to [`ViscousFormulationBassiRebay1`](@ref) with an LDG-type penalization. + +- Cockburn and Shu (1998). + The Local Discontinuous Galerkin Method for Time-Dependent + Convection-Diffusion Systems + [DOI: 10.1137/S0036142997316712](https://doi.org/10.1137/S0036142997316712) +""" +struct ViscousFormulationLocalDG{P} + penalty_parameter::P +end + +default_parabolic_solver() = ViscousFormulationBassiRebay1() \ No newline at end of file diff --git a/src/time_integration/methods_2N.jl b/src/time_integration/methods_2N.jl index 5af93613a0..47a83fddf2 100644 --- a/src/time_integration/methods_2N.jl +++ b/src/time_integration/methods_2N.jl @@ -76,7 +76,7 @@ end # This implements the interface components described at # https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 # which are used in Trixi. -mutable struct SimpleIntegrator2N{RealT<:Real, uType, Params, Sol, Alg, SimpleIntegrator2NOptions} +mutable struct SimpleIntegrator2N{RealT<:Real, uType, Params, Sol, F, Alg, SimpleIntegrator2NOptions} u::uType # du::uType u_tmp::uType @@ -86,6 +86,7 @@ mutable struct SimpleIntegrator2N{RealT<:Real, uType, Params, Sol, Alg, SimpleIn iter::Int # current number of time steps (iteration) p::Params # will be the semidiscretization from Trixi sol::Sol # faked + f::F alg::Alg opts::SimpleIntegrator2NOptions finalstep::Bool # added for convenience @@ -109,7 +110,7 @@ function solve(ode::ODEProblem, alg::T; t = first(ode.tspan) iter = 0 integrator = SimpleIntegrator2N(u, du, u_tmp, t, dt, zero(dt), iter, ode.p, - (prob=ode,), alg, + (prob=ode,), ode.f, alg, SimpleIntegrator2NOptions(callback, ode.tspan; kwargs...), false) # initialize callbacks @@ -149,7 +150,7 @@ function solve!(integrator::SimpleIntegrator2N) integrator.u_tmp .= 0 for stage in eachindex(alg.c) t_stage = integrator.t + integrator.dt * alg.c[stage] - prob.f(integrator.du, integrator.u, prob.p, t_stage) + integrator.f(integrator.du, integrator.u, prob.p, t_stage) a_stage = alg.a[stage] b_stage_dt = alg.b[stage] * integrator.dt diff --git a/src/time_integration/methods_3Sstar.jl b/src/time_integration/methods_3Sstar.jl index e3317bd800..416d6dca9c 100644 --- a/src/time_integration/methods_3Sstar.jl +++ b/src/time_integration/methods_3Sstar.jl @@ -105,7 +105,7 @@ function SimpleIntegrator3SstarOptions(callback, tspan; maxiters=typemax(Int), k callback, false, Inf, maxiters, [last(tspan)]) end -mutable struct SimpleIntegrator3Sstar{RealT<:Real, uType, Params, Sol, Alg, SimpleIntegrator3SstarOptions} +mutable struct SimpleIntegrator3Sstar{RealT<:Real, uType, Params, Sol, F, Alg, SimpleIntegrator3SstarOptions} u::uType # du::uType u_tmp1::uType @@ -116,6 +116,7 @@ mutable struct SimpleIntegrator3Sstar{RealT<:Real, uType, Params, Sol, Alg, Simp iter::Int # current number of time step (iteration) p::Params # will be the semidiscretization from Trixi sol::Sol # faked + f::F alg::Alg opts::SimpleIntegrator3SstarOptions finalstep::Bool # added for convenience @@ -140,7 +141,7 @@ function solve(ode::ODEProblem, alg::T; t = first(ode.tspan) iter = 0 integrator = SimpleIntegrator3Sstar(u, du, u_tmp1, u_tmp2, t, dt, zero(dt), iter, ode.p, - (prob=ode,), alg, + (prob=ode,), ode.f, alg, SimpleIntegrator3SstarOptions(callback, ode.tspan; kwargs...), false) # initialize callbacks diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index e92cf792d4..cab7f07da0 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -58,7 +58,7 @@ end # This implements the interface components described at # https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 # which are used in Trixi. -mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, Alg, SimpleIntegratorSSPOptions} +mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, F, Alg, SimpleIntegratorSSPOptions} u::uType du::uType u_safe::uType @@ -69,6 +69,7 @@ mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, Alg, SimpleI iter::Int # current number of time steps (iteration) p::Params # will be the semidiscretization from Trixi sol::Sol # faked + f::F alg::Alg opts::SimpleIntegratorSSPOptions finalstep::Bool # added for convenience @@ -101,7 +102,7 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, t = first(ode.tspan) iter = 0 integrator = SimpleIntegratorSSP(u, du, u_safe, u_old, t, dt, zero(dt), iter, ode.p, - (prob=ode,), alg, + (prob=ode,), ode.f, alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) # Resize container @@ -144,7 +145,7 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_safe = integrator.u for stage in eachindex(alg.c) t_stage = integrator.t + integrator.dt * alg.c[stage] - prob.f(integrator.du, integrator.u_safe, integrator.p, t_stage) + integrator.f(integrator.du, integrator.u_safe, integrator.p, t_stage) @trixi_timeit timer() "Runge-Kutta stage" begin @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe @@ -152,6 +153,13 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) + if indicator isa IndicatorIDP + update_alpha_per_timestep!(indicator.cache.alpha_max_per_timestep, + indicator.cache.alpha_mean_per_timestep, + indicator.cache.ContainerShockCapturingIndicator.alpha, + integrator.iter+1, length(alg.c), integrator.p) + end + # Check that we are within bounds if indicator.IDPCheckBounds @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) @@ -168,18 +176,12 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. - if integrator.iter == length(indicator.cache.alpha_max_per_timestep) + if integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep new_length = length(indicator.cache.alpha_max_per_timestep) + 200 resize!(indicator.cache.alpha_max_per_timestep, new_length) resize!(indicator.cache.alpha_mean_per_timestep, new_length) - end - - if indicator isa IndicatorIDP - indicator.cache.alpha_max_per_timestep[integrator.iter+1] = - maximum(indicator.cache.ContainerShockCapturingIndicator.alpha) - indicator.cache.alpha_mean_per_timestep[integrator.iter+1] = - (1/(nnodes(integrator.p.solver)^ndims(integrator.p.equations) * nelements(integrator.p.solver, integrator.p.cache))) * - sum(indicator.cache.ContainerShockCapturingIndicator.alpha) + indicator.cache.alpha_max_per_timestep[new_length - 199:new_length] .= 0.0 + indicator.cache.alpha_mean_per_timestep[new_length - 199:new_length] .= 0.0 end integrator.iter += 1 diff --git a/test/Project.toml b/test/Project.toml index 73b6595195..fba5f4df67 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -13,9 +13,9 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] BSON = "0.3.3" -CairoMakie = "0.6, 0.7, 0.8" +CairoMakie = "0.6, 0.7, 0.8, 0.9" Flux = "0.13" ForwardDiff = "0.10" -MPI = "0.19" +MPI = "0.20" OrdinaryDiffEq = "5.65, 6" Plots = "1.16" diff --git a/test/runtests.jl b/test/runtests.jl index e294d10746..79a8e54e79 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -86,6 +86,10 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) include("test_dgmulti_3d.jl") end + @time if TRIXI_TEST == "all" || TRIXI_TEST == "parabolic" + include("test_parabolic_2d.jl") + end + @time if TRIXI_TEST == "all" || TRIXI_TEST == "misc_part1" include("test_unit.jl") include("test_visualization.jl") diff --git a/test/test_dgmulti_1d.jl b/test/test_dgmulti_1d.jl index 62513749c2..7135781d3a 100644 --- a/test/test_dgmulti_1d.jl +++ b/test/test_dgmulti_1d.jl @@ -12,6 +12,15 @@ outdir = "out" isdir(outdir) && rm(outdir, recursive=true) @testset "DGMulti 1D" begin + + @trixi_testset "elixir_advection_gauss_sbp.jl " begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_gauss_sbp.jl"), + cells_per_dimension = (8,), + l2 = [2.9953644500009865e-5], + linf = [4.467840577382365e-5] + ) + end + @trixi_testset "elixir_euler_flux_diff.jl " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), cells_per_dimension = (16,), diff --git a/test/test_dgmulti_2d.jl b/test/test_dgmulti_2d.jl index d406be33c3..d3aa1ab0f7 100644 --- a/test/test_dgmulti_2d.jl +++ b/test/test_dgmulti_2d.jl @@ -12,6 +12,7 @@ outdir = "out" isdir(outdir) && rm(outdir, recursive=true) @testset "DGMulti 2D" begin + @trixi_testset "elixir_euler_weakform.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), cells_per_dimension = (4, 4), @@ -86,7 +87,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - l2 = [1.5914065936559232e-5, 1.4757575957005155e-5, 1.4757575956508324e-5, 4.511709781155535e-5], + l2 = [1.720476068165337e-5, 1.592168205710526e-5, 1.592168205812963e-5, 4.894094865697305e-5], linf = [0.00010525416930584619, 0.00010003778091061122, 0.00010003778085621029, 0.00036426282101720275] ) end @@ -94,7 +95,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, GaussSBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), approximation_type = GaussSBP(), - l2 = [3.578819171269236e-6, 3.4797454435720057e-6, 3.4797454434088854e-6, 1.0812715223492364e-5], + l2 = [3.890039406408632e-6, 3.7759123007255403e-6, 3.775912300349982e-6, 1.176119366880501e-5], linf = [1.2963211813321607e-5, 1.2570312152959673e-5, 1.2570312227122571e-5, 3.9389540817946767e-5] ) end diff --git a/test/test_dgmulti_3d.jl b/test/test_dgmulti_3d.jl index bb64ed5e8f..e16fdde82f 100644 --- a/test/test_dgmulti_3d.jl +++ b/test/test_dgmulti_3d.jl @@ -42,7 +42,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_curved.jl (Hex elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - l2 = [0.017961080040863775, 0.02438643929447948, 0.024389821246679343, 0.01777718061608107, 0.038341344239528286], + l2 = [0.018354883045936066, 0.024412704052042846, 0.024408520416087945, 0.01816314570880129, 0.039342805507972006], linf = [0.14862225990775757, 0.28952368161864683, 0.2912054484817035, 0.1456603133854122, 0.3315354586775472] ) end @@ -50,7 +50,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_curved.jl (Hex elements, GaussSBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), approximation_type=GaussSBP(), - l2 = [0.0024979831949245874, 0.002767595957893527, 0.0027679562814758533, 0.0025023258886203666, 0.006657643337169548], + l2 = [0.0026494857810114266, 0.002939931029796175, 0.0029403438438330687, 0.002646448702532443, 0.007067017671076421], linf = [0.021424273409065275, 0.02133519628006386, 0.021304710093764, 0.02080983064200792, 0.05344736080482182] ) end diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl new file mode 100644 index 0000000000..d9c3967315 --- /dev/null +++ b/test/test_parabolic_2d.jl @@ -0,0 +1,185 @@ +module TestExamplesParabolic2D + +using Test +using Trixi + +include("test_trixi.jl") + +EXAMPLES_DIR = joinpath(examples_dir(), "dgmulti_2d") + +# Start with a clean environment: remove Trixi output directory if it exists +outdir = "out" +isdir(outdir) && rm(outdir, recursive=true) + +@testset "SemidiscretizationHyperbolicParabolic" begin + + @trixi_testset "DGMulti 2D rhs_parabolic!" begin + + dg = DGMulti(polydeg = 2, element_type = Quad(), approximation_type = Polynomial(), + surface_integral = SurfaceIntegralWeakForm(flux_central), + volume_integral = VolumeIntegralWeakForm()) + mesh = DGMultiMesh(dg, cells_per_dimension=(2, 2)) + + # test with polynomial initial condition x^2 * y + # test if we recover the exact second derivative + initial_condition = (x, t, equations) -> SVector(x[1]^2 * x[2]) + + equations = LinearScalarAdvectionEquation2D(1.0, 1.0) + equations_parabolic = LaplaceDiffusion2D(1.0, equations) + + semi = SemidiscretizationHyperbolicParabolic(mesh, equations, equations_parabolic, initial_condition, dg) + @test_nowarn_debug show(stdout, semi) + @test_nowarn_debug show(stdout, MIME"text/plain"(), semi) + @test_nowarn_debug show(stdout, boundary_condition_do_nothing) + + @test nvariables(semi)==nvariables(equations) + @test Base.ndims(semi)==Base.ndims(mesh) + @test Base.real(semi)==Base.real(dg) + + ode = semidiscretize(semi, (0.0, 0.01)) + u0 = similar(ode.u0) + Trixi.compute_coefficients!(u0, 0.0, semi) + @test u0 ≈ ode.u0 + + # test "do nothing" BC just returns first argument + @test boundary_condition_do_nothing(u0, nothing) == u0 + + @unpack cache, cache_parabolic, equations_parabolic = semi + @unpack gradients = cache_parabolic + for dim in eachindex(gradients) + fill!(gradients[dim], zero(eltype(gradients[dim]))) + end + + t = 0.0 + # pass in `boundary_condition_periodic` to skip boundary flux/integral evaluation + Trixi.calc_gradient!(gradients, ode.u0, t, mesh, equations_parabolic, + boundary_condition_periodic, dg, cache, cache_parabolic) + @unpack x, y = mesh.md + @test getindex.(gradients[1], 1) ≈ 2 * x .* y + @test getindex.(gradients[2], 1) ≈ x.^2 + + u_flux = similar.(gradients) + Trixi.calc_viscous_fluxes!(u_flux, ode.u0, gradients, mesh, equations_parabolic, + dg, cache, cache_parabolic) + @test u_flux[1] ≈ gradients[1] + @test u_flux[2] ≈ gradients[2] + + du = similar(ode.u0) + Trixi.calc_divergence!(du, ode.u0, t, u_flux, mesh, equations_parabolic, boundary_condition_periodic, + dg, semi.solver_parabolic, cache, cache_parabolic) + @test getindex.(du, 1) ≈ 2 * y + end + + @trixi_testset "DGMulti: elixir_advection_diffusion.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion.jl"), + cells_per_dimension = (4, 4), tspan=(0.0, 0.1), + l2 = [0.2485803335154642], + linf = [1.079606969242132] + ) + end + + @trixi_testset "DGMulti: elixir_advection_diffusion_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion_periodic.jl"), + cells_per_dimension = (4, 4), tspan=(0.0, 0.1), + l2 = [0.03180371984888462], + linf = [0.2136821621370909] + ) + end + + @trixi_testset "DGMulti: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion_nonperiodic.jl"), + cells_per_dimension = (4, 4), tspan=(0.0, 0.1), + l2 = [0.002123168335604323], + linf = [0.00963640423513712] + ) + end + + @trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_navierstokes_convergence.jl"), + cells_per_dimension = (4, 4), tspan=(0.0, 0.1), + l2 = [0.0015355076812510957, 0.0033843168272696756, 0.0036531858107443434, 0.009948436427519214], + linf = [0.005522560467190019, 0.013425258500730508, 0.013962115643482154, 0.027483102120502423] + ) + end + + @trixi_testset "DGMulti: elixir_navierstokes_lid_driven_cavity.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_navierstokes_lid_driven_cavity.jl"), + cells_per_dimension = (4, 4), tspan=(0.0, 0.5), + l2 = [0.00022156125227115747, 0.028318325921401, 0.009509168701070296, 0.028267900513550506], + linf = [0.001562278941298234, 0.14886653390744856, 0.0716323565533752, 0.19472785105241996] + ) + end + + @trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.4), polydeg=5, + l2 = [4.0915532997994255e-6], + linf = [2.3040850347877395e-5] + ) + end + + @trixi_testset "TreeMesh2D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.1), + l2 = [0.007646800618485118], + linf = [0.10067621050468958] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.1), + l2 = [0.002111672530658797, 0.0034322351490857846, 0.0038742528195910416, 0.012469246082568561], + linf = [0.012006418939223495, 0.035520871209746126, 0.024512747492231427, 0.11191122588756564] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.1), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), + l2 = [0.002103629650383915, 0.003435843933396454, 0.00386735987813341, 0.012670355349235728], + linf = [0.012006261793147788, 0.03550212518982032, 0.025107947319661185, 0.11647078036571124] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), + l2 = [0.0021403742517389513, 0.0034258287094908572, 0.0038915122886898517, 0.012506862343013842], + linf = [0.012244412004628336, 0.03507559186162224, 0.024580892345558894, 0.11425600758350107] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), + l2 = [0.0021349737347844907, 0.0034301388278203033, 0.0038928324474291572, 0.012693611436230873], + linf = [0.01224423627586213, 0.035054066314102905, 0.025099598504931965, 0.11795616324751634] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (flux differencing)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.1), + volume_integral=VolumeIntegralFluxDifferencing(flux_central), + l2 = [0.0021116725306633594, 0.0034322351490827557, 0.0038742528196093542, 0.012469246082526909], + linf = [0.012006418939291663, 0.035520871209594115, 0.024512747491801577, 0.11191122588591007] + ) + end + + @trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_lid_driven_cavity.jl"), + initial_refinement_level = 2, tspan=(0.0, 0.5), + l2 = [0.00015144571529699053, 0.018766076072331623, 0.007065070765652574, 0.0208399005734258], + linf = [0.0014523369373669048, 0.12366779944955864, 0.05532450997115432, 0.16099927805328207] + ) + end + +end + +# Clean up afterwards: delete Trixi output directory +@test_nowarn isdir(outdir) && rm(outdir, recursive=true) + +end # module diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index a5ac74bb6e..bee54b1320 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -165,8 +165,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.49171288879147707, 0.16540604409411028, 0.165403281995138, 0.6346743704341865], - linf = [2.523187390223829, 1.1676864180461144, 1.1676912091995713, 6.469768610580735], + l2 = [0.49170711532017397, 0.16545207388505218, 0.16545210945870265, 0.6347169459573236], + linf = [2.525440391740859, 1.167550417094284, 1.1675492773007656, 6.468729876521227], tspan = (0.0, 1.0), initial_refinement_level=5, coverage_override = (maxiters=3,)) @@ -190,8 +190,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_blob_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_sc_subcell.jl"), - l2 = [0.23649189278780317, 0.6993516078054665, 0.24313747935314953, 3.071644108599621], - linf = [7.850214101046176, 21.245196819766562, 10.004355873576252, 76.18578781492629], + l2 = [0.22952600868491232, 0.6598694971331289, 0.2375222572511259, 3.0485750678229198], + linf = [7.661392002055745, 19.336398494293007, 9.378519483511768, 79.18768909325449], tspan = (0.0, 0.5), initial_refinement_level=5) end @@ -255,8 +255,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.006567503201406924, 0.045494701197468755, 1.5604684539276876e-6, 0.624781570252251], - linf = [0.1448916669656563, 0.5279925643783724, 8.77139846451784e-5, 12.03029820002121], + l2 = [0.006577159539817667, 0.04554740746415583, 1.4554079130334693e-6, 0.6258024941421835], + linf = [0.14555535078246196, 0.5306125024728012, 8.590620121863414e-5, 12.092753540073211], tspan = (0.0, 0.1), coverage_override = (maxiters=2,)) end @@ -271,8 +271,8 @@ EXAMPLES_DIR = joinpath(pathof(Trixi) |> dirname |> dirname, "examples", "tree_2 @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), - l2 = [0.442412359159042, 353.54254537346463, 14.195423442065804, 138996.0083518854], - linf = [7.729364707886681, 5819.848679298194, 659.5925327100372, 2.1869838429080946e6], + l2 = [0.4399267169815457, 352.321452114897, 14.089381141646252, 138648.81629357373], + linf = [7.532813790308049, 5594.80343019963, 626.966037014211, 2.154789660969525e6], tspan = (2.5e-6, 1.0e-4), coverage_override = (maxiters=6,)) end From cc2d9cf9353feeb0e69d3fd650e9778eef943547 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 8 Nov 2022 17:46:00 +0100 Subject: [PATCH 085/423] Merge all version and stashes --- src/callbacks_step/save_solution.jl | 10 +- src/callbacks_step/save_solution_dg.jl | 35 ++- src/semidiscretization/semidiscretization.jl | 4 + src/solvers/dg.jl | 20 ++ src/solvers/dgsem_structured/dg_2d.jl | 278 ++++++++++++++++++ src/solvers/dgsem_structured/indicators_2d.jl | 87 ++++++ src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 123 +++++++- src/solvers/dgsem_tree/indicators.jl | 71 ++++- src/solvers/dgsem_tree/indicators_2d.jl | 182 ++++++++---- src/time_integration/methods_SSP.jl | 12 +- utils/trixi2txt.jl | 13 +- 12 files changed, 739 insertions(+), 98 deletions(-) diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 1efa2146ca..9072ac9bbc 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -133,7 +133,10 @@ function (solution_callback::SaveSolutionCallback)(integrator) end end - @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, element_variables) + node_variables = Dict{Symbol, Any}() + @trixi_timeit timer() "get node variables" get_node_variables!(node_variables, semi) + + @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, element_variables, node_variables) end # avoid re-evaluating possible FSAL stages @@ -144,10 +147,11 @@ end @inline function save_solution_file(u_ode, t, dt, iter, semi::AbstractSemidiscretization, solution_callback, - element_variables=Dict{Symbol,Any}()) + element_variables=Dict{Symbol,Any}(), + node_variables=Dict{Symbol,Any}()) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array_native(u_ode, mesh, equations, solver, cache) - save_solution_file(u, t, dt, iter, mesh, equations, solver, cache, solution_callback, element_variables) + save_solution_file(u, t, dt, iter, mesh, equations, solver, cache, solution_callback, element_variables, node_variables) end diff --git a/src/callbacks_step/save_solution_dg.jl b/src/callbacks_step/save_solution_dg.jl index c1708ca682..9caad40985 100644 --- a/src/callbacks_step/save_solution_dg.jl +++ b/src/callbacks_step/save_solution_dg.jl @@ -8,7 +8,9 @@ function save_solution_file(u, time, dt, timestep, mesh::Union{SerialTreeMesh, StructuredMesh, UnstructuredMesh2D, SerialP4estMesh}, equations, dg::DG, cache, - solution_callback, element_variables=Dict{Symbol,Any}(); + solution_callback, + element_variables=Dict{Symbol,Any}(), + node_variables=Dict{Symbol,Any}(); system="") @unpack output_directory, solution_variables = solution_callback @@ -68,6 +70,16 @@ function save_solution_file(u, time, dt, timestep, var = file["element_variables_$v"] attributes(var)["name"] = string(key) end + + # Store node variables + for (v, (key, node_variable)) in enumerate(node_variables) + # Add to file + file["node_variables_$v"] = node_variable + + # Add variable name as attribute + var = file["node_variables_$v"] + attributes(var)["name"] = string(key) + end end return filename @@ -76,7 +88,9 @@ end function save_solution_file(u, time, dt, timestep, mesh::Union{ParallelTreeMesh, ParallelP4estMesh}, equations, dg::DG, cache, - solution_callback, element_variables=Dict{Symbol,Any}(); + solution_callback, + element_variables=Dict{Symbol,Any}(), + node_variables=Dict{Symbol,Any}(); system="") @unpack output_directory, solution_variables = solution_callback @@ -120,6 +134,11 @@ function save_solution_file(u, time, dt, timestep, MPI.Gatherv!(element_variable, nothing, mpi_root(), mpi_comm()) end + # Send node data to root + for (key, node_variable) in node_variables + MPI.Gatherv!(node_variable, nothing, mpi_root(), mpi_comm()) + end + return filename end @@ -160,6 +179,18 @@ function save_solution_file(u, time, dt, timestep, var = file["element_variables_$v"] attributes(var)["name"] = string(key) end + + # Store node variables + for (v, (key, node_variable)) in enumerate(node_variables) + # Add to file + recv = Vector{eltype(data)}(undef, sum(node_counts)) + MPI.Gatherv!(node_variable, MPI.VBuffer(recv, node_counts), mpi_root(), mpi_comm()) + file["node_variables_$v"] = recv + + # Add variable name as attribute + var = file["node_variables_$v"] + attributes(var)["name"] = string(key) + end end return filename diff --git a/src/semidiscretization/semidiscretization.jl b/src/semidiscretization/semidiscretization.jl index 56c73c379b..2313c0df0b 100644 --- a/src/semidiscretization/semidiscretization.jl +++ b/src/semidiscretization/semidiscretization.jl @@ -310,6 +310,10 @@ function get_element_variables!(element_variables, u_ode, semi::AbstractSemidisc get_element_variables!(element_variables, u, mesh_equations_solver_cache(semi)...) end +function get_node_variables!(node_variables, semi::AbstractSemidiscretization) + get_node_variables!(node_variables, mesh_equations_solver_cache(semi)...) +end + # To implement AMR and use OrdinaryDiffEq.jl etc., we have to be a bit creative. # Since the caches of the SciML ecosystem are immutable structs, we cannot simply diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index d7280416c5..e9b3405682 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -10,6 +10,9 @@ abstract type AbstractVolumeIntegral end get_element_variables!(element_variables, u, mesh, equations, volume_integral::AbstractVolumeIntegral, dg, cache) = nothing +get_node_variables!(node_variables, mesh, equations, + volume_integral::AbstractVolumeIntegral, dg, cache) = nothing + """ VolumeIntegralStrongForm @@ -191,6 +194,19 @@ function get_element_variables!(element_variables, u, mesh, equations, get_element_variables!(element_variables, volume_integral.indicator, volume_integral) end +function get_element_variables!(element_variables, u, mesh, equations, + volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + if volume_integral.indicator.indicator_smooth + # call the indicator to get up-to-date values for IO + volume_integral.indicator.IndicatorHG(u, mesh, equations, dg, cache) + get_element_variables!(element_variables, volume_integral.indicator, volume_integral) + end +end + +function get_node_variables!(node_variables, mesh, equations, + volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + get_node_variables!(node_variables, volume_integral.indicator, volume_integral, equations) +end @@ -309,6 +325,10 @@ function get_element_variables!(element_variables, u, mesh, equations, dg::DG, c get_element_variables!(element_variables, u, mesh, equations, dg.volume_integral, dg, cache) end +function get_node_variables!(node_variables, mesh, equations, dg::DG, cache) + get_node_variables!(node_variables, mesh, equations, dg.volume_integral, dg, cache) +end + const MeshesDGSEM = Union{TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh} diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 1a351ed874..c5269e4708 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -327,6 +327,284 @@ end return nothing end +@inline function calcflux_fhat!(fhat1, fhat2, u, + mesh::StructuredMesh{2}, nonconservative_terms::Val{false}, equations, + volume_flux, dg::DGSEM, element, cache) + + @unpack contravariant_vectors = cache.elements + @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded = cache + + flux_temp = flux_temp_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fhat_(0,1) = w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # pull the contravariant vectors in each coordinate direction + Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, element) # x direction + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of the `volume_flux` to save half of the possible two-point flux + # computations. + + # x direction + for ii in (i+1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + # pull the contravariant vectors and compute the average + Ja1_node_ii = get_contravariant_vector(1, contravariant_vectors, ii, j, element) + Ja1_avg = 0.5 * (Ja1_node + Ja1_node_ii) + + # compute the contravariant sharp flux in the direction of the averaged contravariant vector + fluxtilde1 = volume_flux(u_node, u_node_ii, Ja1_avg, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], fluxtilde1, equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], fluxtilde1, equations, dg, ii, j) + end + end + + # FV-form flux `fhat` in x direction + fhat1[:, 1, :] .= zero(eltype(fhat1)) + fhat1[:, nnodes(dg)+1, :] .= zero(eltype(fhat1)) + + for j in eachnode(dg), i in 1:nnodes(dg)-1, v in eachvariable(equations) + fhat1[v, i+1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + end + + # Split form volume flux in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # pull the contravariant vectors in each coordinate direction + Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, element) + + # y direction + for jj in (j+1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + # pull the contravariant vectors and compute the average + Ja2_node_jj = get_contravariant_vector(2, contravariant_vectors, i, jj, element) + Ja2_avg = 0.5 * (Ja2_node + Ja2_node_jj) + # compute the contravariant sharp flux in the direction of the averaged contravariant vector + fluxtilde2 = volume_flux(u_node, u_node_jj, Ja2_avg, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], fluxtilde2, equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], fluxtilde2, equations, dg, i, jj) + end + end + + # FV-form flux `fhat` in y direction + fhat2[:, :, 1 ] .= zero(eltype(fhat2)) + fhat2[:, :, nnodes(dg)+1] .= zero(eltype(fhat2)) + + for j in 1:nnodes(dg)-1, i in eachnode(dg), v in eachvariable(equations) + fhat2[v, i, j+1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + end + + return nothing +end + + +@inline function calc_var_bounds_interface!(u, mesh::StructuredMesh, nonconservative_terms, equations, indicator, dg, cache) + @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + @unpack contravariant_vectors = cache.elements + + for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) + u_element = get_node_vars(u, equations, dg, 1, i, element) + + # Ja1_left = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), i, left) + Ja1_element = get_contravariant_vector(1, contravariant_vectors, 1, i, element) + # Ja1_avg = 0.5 * (Ja1_left + Ja1_element) + + flux_left = flux(u_left, Ja1_element, equations) + flux_element = flux(u_element, Ja1_element, equations) + lambda = lambda1[1, i, element] + + bar_state_rho = 0.5 * (u_element[1] + u_left[1]) - 0.5 * (flux_element[1] - flux_left[1]) / lambda + var_min[1, nnodes(dg), i, left] = min(var_min[1, nnodes(dg), i, left], bar_state_rho) + var_max[1, nnodes(dg), i, left] = max(var_max[1, nnodes(dg), i, left], bar_state_rho) + var_min[1, 1, i, element] = min(var_min[1, 1, i, element], bar_state_rho) + var_max[1, 1, i, element] = max(var_max[1, 1, i, element], bar_state_rho) + for v in 2:nvariables(equations) + bar_state_phi = 0.5 * (u_element[v] + u_left[v]) - 0.5 * (flux_element[v] - flux_left[v]) / lambda + bar_state_phi = bar_state_phi / bar_state_rho + var_min[v, nnodes(dg), i, left] = min(var_min[v, nnodes(dg), i, left], bar_state_phi) + var_max[v, nnodes(dg), i, left] = max(var_max[v, nnodes(dg), i, left], bar_state_phi) + var_min[v, 1, i, element] = min(var_min[v, 1, i, element], bar_state_phi) + var_max[v, 1, i, element] = max(var_max[v, 1, i, element], bar_state_phi) + end + end + end + if lower != 0 + for i in eachnode(dg) + u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) + u_element = get_node_vars(u, equations, dg, i, 1, element) + + # Ja2_lower = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), lower) + Ja2_element = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + # Ja2_avg = 0.5 * (Ja2_lower + Ja2_element) + + flux_lower = flux(u_lower, Ja2_element, equations) + flux_element = flux(u_element, Ja2_element, equations) + lambda = lambda1[i, 1, element] + + bar_state_rho = 0.5 * (u_element[1] + u_lower[1]) - 0.5 * (flux_element[1] - flux_lower[1]) / lambda + var_min[1, i, nnodes(dg), lower] = min(var_min[1, i, nnodes(dg), lower], bar_state_rho) + var_max[1, i, nnodes(dg), lower] = max(var_max[1, i, nnodes(dg), lower], bar_state_rho) + var_min[1, i, 1, element] = min(var_min[1, i, 1, element], bar_state_rho) + var_max[1, i, 1, element] = max(var_max[1, i, 1, element], bar_state_rho) + for v in 2:nvariables(equations) + bar_state_phi = 0.5 * (u_element[v] + u_lower[v]) - 0.5 * (flux_element[v] - flux_lower[v]) / lambda + bar_state_phi = bar_state_phi / bar_state_rho + var_min[v, i, nnodes(dg), lower] = min(var_min[v, i, nnodes(dg), lower], bar_state_phi) + var_max[v, i, nnodes(dg), lower] = max(var_max[v, i, nnodes(dg), lower], bar_state_phi) + var_min[v, i, 1, element] = min(var_min[v, i, 1, element], bar_state_phi) + var_max[v, i, 1, element] = max(var_max[v, i, 1, element], bar_state_phi) + end + end + end + end + + return nothing +end + + +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh::StructuredMesh, equations, dg, cache, indicator::IndicatorMCL) + @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + @unpack contravariant_vectors = cache.elements + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + + Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, element) + Ja1_node_im1 = get_contravariant_vector(1, contravariant_vectors, i-1, j, element) + Ja1_avg = 0.5 * (Ja1_node + Ja1_node_im1) + + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, Ja1_avg, equations) + end + + for j in 2:nnodes(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, element) + Ja2_node_jm1 = get_contravariant_vector(2, contravariant_vectors, i, j-1, element) + Ja2_avg = 0.5 * (Ja2_node + Ja2_node_jm1) + + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, Ja2_avg, equations) + end + end + + @threaded for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) + u_element = get_node_vars(u, equations, dg, 1, i, element) + + # Ja1_left = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), i, left) + Ja1_element = get_contravariant_vector(1, contravariant_vectors, 1, i, element) + # Ja1_avg = 0.5 * (Ja1_left + Ja1_element) + lambda = max_abs_speed_naive(u_left, u_element, Ja1_element, equations) + + lambda1[nnodes(dg)+1, i, left] = lambda + lambda1[1, i, element] = lambda + end + end + if lower != 0 + for i in eachnode(dg) + u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) + u_element = get_node_vars(u, equations, dg, i, 1, element) + + # Ja2_lower = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), lower) + Ja2_element = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + # Ja2_avg = 0.5 * (Ja2_lower + Ja2_element) + lambda = max_abs_speed_naive(u_lower, u_element, Ja2_element, equations) + + lambda2[i, nnodes(dg)+1, lower] = lambda + lambda2[i, 1, element] = lambda + end + end + end + + linear_indices = LinearIndices(size(mesh)) + # x-direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + left = cache.elements.left_neighbors[1, element] + if left == 0 # element is at boundary + lambda1[1, :, element] .= zero(eltype(lambda1)) + lambda1[nnodes(dg)+1, :, linear_indices[end, cell_y]] .= zero(eltype(lambda1)) + end + end + # y-direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + lower = cache.elements.left_neighbors[2, element] + if lower == 0 # element is at boundary + lambda2[:, 1, element] .= zero(eltype(lambda2)) + lambda2[:, nnodes(dg)+1, linear_indices[cell_x, end]] .= zero(eltype(lambda2)) + end + end + + return nothing +end + + +@inline function perform_IDP_correction(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + + if dg.volume_integral.indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end + + @threaded for element in elements + # @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + inverse_jacobian = -cache.elements.inverse_jacobian[i, j, element] + + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) + end + end + end + + return nothing +end + function calc_interface_flux!(cache, u, mesh::StructuredMesh{2}, diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 4e0296a0f0..e59baa44fe 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -27,4 +27,91 @@ function apply_smoothing!(mesh::StructuredMesh{2}, alpha, alpha_tmp, dg, cache) end end + +function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::StructuredMesh{2}, equations, dg, cache) + for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for i in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), i, left), equations) + var_element = variable(get_node_vars(u, equations, dg, 1, i, element), equations) + + var_min[nnodes(dg), i, left] = min(var_min[nnodes(dg), i, left], var_element) + var_max[nnodes(dg), i, left] = max(var_max[nnodes(dg), i, left], var_element) + + var_min[1, i, element] = min(var_min[1, i, element], var_left) + var_max[1, i, element] = max(var_max[1, i, element], var_left) + end + end + if lower != 0 + for i in eachnode(dg) + var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) + var_element = variable(get_node_vars(u, equations, dg, i, 1, element), equations) + + var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], var_element) + var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], var_element) + + var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) + var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) + end + end + end + + return nothing +end + +@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh) + _, _, solver, cache = mesh_equations_solver_cache(semi) + @unpack weights = solver.basis + @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_avg = zero(eltype(alpha)) + total_volume = zero(eltype(alpha)) + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) + alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + + return nothing +end + +function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::StructuredMesh{2}, equations, dg, cache) + for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for i in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), i, left), equations) + var_element = variable(get_node_vars(u, equations, dg, 1, i, element), equations) + + var_minmax[nnodes(dg), i, left] = minmax(var_minmax[nnodes(dg), i, left], var_element) + var_minmax[1, i, element] = minmax(var_minmax[1, i, element], var_left) + end + end + if lower != 0 + for i in eachnode(dg) + var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) + var_element = variable(get_node_vars(u, equations, dg, i, 1, element), equations) + + var_minmax[i, nnodes(dg), lower] = minmax(var_minmax[i, nnodes(dg), lower], var_element) + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_lower) + end + end + end + + return nothing +end + + end # @muladd diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 2f168d232b..65bd56defa 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -27,7 +27,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) - dg_only = isapprox(alpha[element], 0, atol=1e-12) + dg_only = isapprox(alpha[element], 0, atol=0.1) if dg_only push!(element_ids_dg, element) else diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ba1c86b0bf..873119820f 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -79,12 +79,17 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMe end -function create_cache(mesh::TreeMesh{2}, equations, +function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) + if volume_integral.indicator.indicator_smooth + element_ids_dg = Int[] + element_ids_dgfv = Int[] + cache = (; cache..., element_ids_dg, element_ids_dgfv) + end A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} @@ -513,7 +518,7 @@ end function calc_volume_integral!(du, u, - mesh::TreeMesh{2}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) @@ -526,6 +531,8 @@ function calc_volume_integral!(du, u, # Remove 2, the first entropy analysis of the analysis_callback doesn't work. # And we get different result because otherwise the lambdas are only updated once in a RK step. # -> 4 times per timestep is actually not that bad. (3 times would be optimal) + # -- With option 1: I don't need to save all lambdas, just use threaded vector of 2 dimensions [i, j] + # (wrong!, because I need the lambdas to calculate the bar states here) # Option two: Calculate lambdas after each RK stage plus in the init_stepsize_callback. # Problem: Entropy change at t=0 only works if the stepsize callback is listed before analysis callback (to calculate the lambdas before) @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, volume_integral.indicator) @@ -534,16 +541,44 @@ function calc_volume_integral!(du, u, # Calculate boundaries @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) - @trixi_timeit timer() "subcell_limiting_kernel!" @threaded for element in eachelement(dg, cache) - subcell_limiting_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral, volume_integral.indicator, - dg, cache) + @unpack indicator = volume_integral + if indicator.indicator_smooth + @unpack element_ids_dg, element_ids_dgfv = cache + # Calculate element-wise blending factors α + alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, mesh, equations, dg, cache) + + # Determine element ids for DG-only and subcell-wise blended DG-FV volume integral + pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, dg, cache) + + # Loop over pure DG elements + @trixi_timeit timer() "pure DG" @threaded for idx_element in eachindex(element_ids_dg) + element = element_ids_dg[idx_element] + split_form_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral.volume_flux_dg, dg, cache) + end + + # Loop over blended DG-FV elements + @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for idx_element in eachindex(element_ids_dgfv) + element = element_ids_dgfv[idx_element] + subcell_limiting_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, indicator, + dg, cache) + end + else # indicator.indicator_smooth == false + # Loop over all elements + @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for element in eachelement(dg, cache) + subcell_limiting_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, indicator, + dg, cache) + end end end @inline function subcell_limiting_kernel!(du, u, - element, mesh::TreeMesh{2}, + element, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms::Val{false}, equations, volume_integral, indicator::IndicatorIDP, dg::DGSEM, cache) @@ -585,7 +620,7 @@ end end @inline function subcell_limiting_kernel!(du, u, - element, mesh::TreeMesh{2}, + element, mesh::Union{TreeMesh{2},StructuredMesh{2}}, nonconservative_terms::Val{false}, equations, volume_integral, indicator::IndicatorMCL, dg::DGSEM, cache) @@ -626,6 +661,17 @@ end end end + if indicator.Plotting + @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + volume_flux_difference[v, i, j, element] = abs(du[v, i, j, element] - + (inverse_weights[i] * (fhat1[v, i+1, j] - fhat1[v, i, j]) + + inverse_weights[j] * (fhat2[v, i, j+1] - fhat2[v, i, j]))) + end + end + end + return nothing end @@ -813,6 +859,13 @@ end end end + calc_var_bounds_interface!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) + + return nothing +end + +@inline function calc_var_bounds_interface!(u, mesh::TreeMesh2D, nonconservative_terms, equations, indicator, dg, cache) + @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator for interface in eachinterface(dg, cache) # Get neighboring element ids left_id = cache.interfaces.neighbor_ids[1, interface] @@ -894,6 +947,12 @@ end rho_limited_im1 * (phi - var_max[v, i-1, j, element])) g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), rho_limited_im1 * (phi - var_min[v, i-1, j, element])) + # if isapprox(g_min, 0.0, atol=eps()) + # g_min = 0.0 + # end + # if isapprox(g_max, 0.0, atol=eps()) + # g_max = 0.0 + # end antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + max(g_min, min(g, g_max)) end @@ -933,6 +992,12 @@ end rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) + # if isapprox(g_min, 0.0, atol=eps()) + # g_min = 0.0 + # end + # if isapprox(g_max, 0.0, atol=eps()) + # g_max = 0.0 + # end antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + max(g_min, min(g, g_max)) end @@ -940,6 +1005,10 @@ end # Limit pressure if indicator.IDPPressureTVD + @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting + alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) + end for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 @@ -947,6 +1016,15 @@ end Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) + # exact calculation of max(R_ij, R_ji) + # R_max = lambda1[i, j, element] * + # abs(bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + + # bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - + # bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - + # bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) + # R_max += max(0, 0.5 * flux_velocity - + # antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) + # approximation R_max R_max = lambda1[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + @@ -957,6 +1035,10 @@ end if R_max > Q alpha = Q / R_max + if indicator.Plotting + alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + end for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] *= alpha end @@ -970,6 +1052,15 @@ end Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) + # exact calculation of max(R_ij, R_ji) + # R_max = lambda2[i, j, element] * + # abs(bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + + # bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - + # bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - + # bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + # R_max += max(0, 0.5 * flux_velocity - + # antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + # approximation R_max R_max = lambda2[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + @@ -980,6 +1071,10 @@ end if R_max > Q alpha = Q / R_max + if indicator.Plotting + alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + end for v in eachvariable(equations) antidiffusive_flux2[v, i, j, element] *= alpha end @@ -995,7 +1090,7 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator::IndicatorMCL) +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh::TreeMesh2D, equations, dg, cache, indicator::IndicatorMCL) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(dg, cache) @@ -1079,8 +1174,14 @@ end @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + if dg.volume_integral.indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end - @threaded for element in eachelement(dg, cache) + # Loop over blended DG-FV elements + @threaded for element in elements inverse_jacobian = -cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index ea87584007..befd008902 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -16,6 +16,36 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end +function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) + element_variables[:smooth_indicator_elementwise] = indicator.IndicatorHG.cache.alpha + return nothing +end + +function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) + node_variables[:indicator_shock_capturing] = indicator.cache.ContainerShockCapturingIndicator.alpha + # TODO BB: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. + return nothing +end + +function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) + if !indicator.Plotting + return nothing + end + @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator + variables = varnames(cons2cons, equations) + for v in eachvariable(equations) + s = Symbol("shock_capturing_delta_volume_flux_", variables[v]) + node_variables[s] = volume_flux_difference[v, ntuple(_ -> :, nvariables(equations) + 1)...] + end + + if indicator.IDPPressureTVD + @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + node_variables[:indicator_shock_capturing_pressure] = alpha_pressure + end + + return nothing +end + """ @@ -164,7 +194,7 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator +struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator alpha_maxIDP::RealT IDPDensityTVD::Bool IDPPressureTVD::Bool @@ -178,6 +208,8 @@ struct IndicatorIDP{RealT<:Real, Cache} <: AbstractIndicator IDPgamma::RealT # Constant for the subcell limiting of convex (nonlinear) constraints # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) IDPCheckBounds::Bool + indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + IndicatorHG::Indicator end # this method is used when the indicator is constructed as for shock-capturing volume integrals @@ -190,7 +222,9 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPMathEntropy=false, positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), - IDPCheckBounds=false) + IDPCheckBounds=false, + indicator_smooth=true, + variable_smooth=density_pressure) if IDPMathEntropy && IDPSpecEntropy error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") @@ -200,9 +234,17 @@ function IndicatorIDP(equations::AbstractEquations, basis; min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) cache = create_cache(IndicatorIDP, equations, basis, length) - IndicatorIDP{typeof(alpha_maxIDP), typeof(cache)}(alpha_maxIDP, + + if indicator_smooth + IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max=1.0, alpha_smooth=false, + variable=variable_smooth) + else + IndicatorHG = nothing + end + IndicatorIDP{typeof(alpha_maxIDP), typeof(cache), typeof(IndicatorHG)}(alpha_maxIDP, IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy, - cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds) + cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, + indicator_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -233,19 +275,31 @@ IndicatorMCL !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorMCL{Cache} <: AbstractIndicator +struct IndicatorMCL{Cache, Indicator} <: AbstractIndicator cache::Cache IDPPressureTVD::Bool # synchronized pressure limiting IDPCheckBounds::Bool + indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + IndicatorHG::Indicator + Plotting::Bool end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorMCL(equations::AbstractEquations, basis; - IDPPressureTVD=true, - IDPCheckBounds=false) + IDPPressureTVD=false, + IDPCheckBounds=false, + indicator_smooth=true, + variable_smooth=density_pressure, + Plotting=false) cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)+IDPPressureTVD) - IndicatorMCL{typeof(cache)}(cache, IDPPressureTVD, IDPCheckBounds) + if indicator_smooth + IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, + variable=variable_smooth) + else + IndicatorHG = nothing + end + IndicatorMCL{typeof(cache), typeof(IndicatorHG)}(cache, IDPPressureTVD, IDPCheckBounds, indicator_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @@ -254,6 +308,7 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, "IndicatorMCL(") print(io, "density, velocity, total energy") indicator.IDPPressureTVD && print(io, ", pressure") + indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG) print(io, ")") end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index bd20af2391..0c778275a6 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -200,11 +200,12 @@ function create_cache(indicator::Union{Type{IndicatorIDP}, Type{IndicatorMCL}}, alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) + time_per_timestep = zeros(real(basis), 200) idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] return (; ContainerShockCapturingIndicator, - alpha_max_per_timestep, alpha_mean_per_timestep, + alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, idp_bounds_delta_threaded) end @@ -214,22 +215,27 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator alpha .= 0.0 + if indicator_IDP.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache, elements) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache, elements) # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) @unpack alpha_maxIDP = indicator_IDP if alpha_maxIDP != 1.0 - @threaded for element in eachelement(dg, cache) + @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) end @@ -238,7 +244,7 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(dg, cache) + @threaded for element in elements for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) end @@ -370,7 +376,7 @@ end end end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) +@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator rho_min = var_bounds[1] @@ -379,10 +385,15 @@ end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis - @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] + @threaded for element in elements + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + end for j in eachnode(dg), i in eachnode(dg) + if mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end rho = u_safe[1, i, j, element] # Real Zalesak type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" @@ -390,41 +401,44 @@ end # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - # Calculate P_plus and P_minus + Qp = max(0.0, (rho_max[i, j, element] - rho) / dt) + Qm = min(0.0, (rho_min[i, j, element] - rho) / dt) + + # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] - P_plus = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) - P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - P_plus = dt * inverse_jacobian * P_plus - P_minus = dt * inverse_jacobian * P_minus + Pp = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + + max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) + Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm # Calculate alpha_plus and alpha_minus - if P_plus == 0.0 - frac_plus = 1.0 + if Pp == 0.0 + Qp = 1.0 else - frac_plus = max(0.0, rho_max[i, j, element] - rho) / P_plus + Qp = Qp / Pp end - if P_minus == 0.0 - frac_minus = 1.0 + if Pm == 0.0 + Qm = 1.0 else - frac_minus = min(0.0, rho_min[i, j, element] - rho) / P_minus + Qm = Qm / Pm end # Calculate alpha at nodes - alpha[i, j, element] = 1 - min(1.0, frac_plus, frac_minus) + alpha[i, j, element] = 1 - min(1.0, Qp, Qm) end end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -436,10 +450,15 @@ end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis - @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] + @threaded for element in elements + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + end for j in eachnode(dg), i in eachnode(dg) + if mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) # Real Zalesak type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" @@ -447,7 +466,10 @@ end # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - # Calculate P_plus and P_minus + Qp = max(0.0, (p_max[i, j, element] - p) / dt) + Qm = min(0.0, (p_min[i, j, element] - p) / dt) + + # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. v1 = u_safe[2, i, j, element] / u_safe[1, i, j, element] v2 = u_safe[3, i, j, element] / u_safe[1, i, j, element] @@ -463,34 +485,34 @@ end val_flux2_local_jp1 = gamma_m1 * (antidiffusive_flux2[4, i, j+1, element] + v2s2 * antidiffusive_flux2[1, i, j+1, element] - v1 * antidiffusive_flux2[2, i, j+1, element] - v2 * antidiffusive_flux2[3, i, j+1, element]) - P_plus = max(0.0, inverse_weights[i] * val_flux1_local) + max(0.0, -inverse_weights[i] * val_flux1_local_ip1) + - max(0.0, inverse_weights[j] * val_flux2_local) + max(0.0, -inverse_weights[j] * val_flux2_local_jp1) - P_minus = min(0.0, inverse_weights[i] * val_flux1_local) + min(0.0, -inverse_weights[i] * val_flux1_local_ip1) + - min(0.0, inverse_weights[j] * val_flux2_local) + min(0.0, -inverse_weights[j] * val_flux2_local_jp1) - P_plus = dt * inverse_jacobian * P_plus - P_minus = dt * inverse_jacobian * P_minus + Pp = max(0.0, inverse_weights[i] * val_flux1_local) + max(0.0, -inverse_weights[i] * val_flux1_local_ip1) + + max(0.0, inverse_weights[j] * val_flux2_local) + max(0.0, -inverse_weights[j] * val_flux2_local_jp1) + Pm = min(0.0, inverse_weights[i] * val_flux1_local) + min(0.0, -inverse_weights[i] * val_flux1_local_ip1) + + min(0.0, inverse_weights[j] * val_flux2_local) + min(0.0, -inverse_weights[j] * val_flux2_local_jp1) + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm # Calculate alpha_plus and alpha_minus - if P_plus == 0.0 - frac_plus = 1.0 + if Pp == 0.0 + Qp = 1.0 else - frac_plus = max(0.0, p_max[i, j, element] - p) / P_plus + Qp = Qp / Pp end - if P_minus == 0.0 - frac_minus = 1.0 + if Pm == 0.0 + Qm = 1.0 else - frac_minus = min(0.0, p_min[i, j, element] - p) / P_minus + Qm = Qm / Pm end # Calculate alpha at nodes - alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1.0, frac_plus, frac_minus)) + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1.0, Qp, Qm)) end end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache, elements) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -499,7 +521,7 @@ end calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha - @threaded for element in eachelement(dg, cache) + @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, @@ -515,7 +537,7 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache, elements) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -525,7 +547,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, mesh, equations, dg, cache) # Perform Newton's bisection method to find new alpha - @threaded for element in eachelement(dg, cache) + @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u_safe, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, @@ -541,7 +563,7 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache) +@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP @@ -561,10 +583,14 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto end end - @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] + @threaded for element in elements + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + end for j in eachnode(dg), i in eachnode(dg) - + if mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end ####################### # Correct density ####################### @@ -584,27 +610,27 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - frac_minus = min(0.0, rho_min[i, j, element] - u_safe[1, i, j, element]) + Qm = min(0.0, (rho_min[i, j, element] - u_safe[1, i, j, element]) / dt) - # Calculate P_minus + # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] - P_minus = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + + Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) - P_minus = dt * inverse_jacobian * P_minus + Pm = inverse_jacobian * Pm - if P_minus < 0.0 - frac_minus = min(1.0, frac_minus / P_minus) + if Pm < 0.0 + Qm = min(1.0, Qm / Pm) else - frac_minus = 1.0 + Qm = 1.0 end # Calculate alpha - alpha[i, j, element] = max(alpha[i, j, element], 1 - frac_minus) + alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) ####################### # Correct pressure @@ -642,7 +668,11 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma dt, mesh, equations, dg, cache, indicator_IDP) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - inverse_jacobian = cache.elements.inverse_jacobian[element] + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + else # mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end @unpack IDPgamma = indicator_IDP @@ -716,8 +746,10 @@ end # Check new beta for condition and update bounds as = goal_fct(bound, u_curr, equations) if initialCheck(bound, as, newton_abstol) + # New beta fulfills condition beta_L = beta else + # New beta does not fulfill condition beta_R = beta end else @@ -743,6 +775,10 @@ end if finalCheck(bound, as, newton_abstol) break end + + if iter == indicator_IDP.IDPMaxIter + @warn "Maximum number of iterations for the Newton-bisection algorithm reached." + end end new_alpha = 1.0 - beta @@ -757,17 +793,33 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) -@inline function update_alpha_per_timestep!(alpha_max_per_timestep, alpha_mean_per_timestep, alpha, - timestep, n_stages, semi) - _, equations, solver, cache = mesh_equations_solver_cache(semi) - n_elements = nelements(solver, cache) - n_nodes = nnodes(solver)^ndims(equations) +@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) + _, _, solver, cache = mesh_equations_solver_cache(semi) + @unpack weights = solver.basis + @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) - alpha_mean_per_timestep[timestep] += 1/(n_stages * n_nodes * n_elements) * sum(alpha) + alpha_avg = zero(eltype(alpha)) + total_volume = zero(eltype(alpha)) + for element in eachelement(solver, cache) + jacobian = inv(cache.elements.inverse_jacobian[element]) + for j in eachnode(solver), i in eachnode(solver) + alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + + return nothing +end + +@inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) return nothing end + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index cab7f07da0..cb79263546 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -153,12 +153,7 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) - if indicator isa IndicatorIDP - update_alpha_per_timestep!(indicator.cache.alpha_max_per_timestep, - indicator.cache.alpha_mean_per_timestep, - indicator.cache.ContainerShockCapturingIndicator.alpha, - integrator.iter+1, length(alg.c), integrator.p) - end + @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) # Check that we are within bounds if indicator.IDPCheckBounds @@ -176,12 +171,16 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. + indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t + if integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep new_length = length(indicator.cache.alpha_max_per_timestep) + 200 resize!(indicator.cache.alpha_max_per_timestep, new_length) resize!(indicator.cache.alpha_mean_per_timestep, new_length) + resize!(indicator.cache.time_per_timestep, new_length) indicator.cache.alpha_max_per_timestep[new_length - 199:new_length] .= 0.0 indicator.cache.alpha_mean_per_timestep[new_length - 199:new_length] .= 0.0 + indicator.cache.time_per_timestep[new_length - 199:new_length] .= 0.0 end integrator.iter += 1 @@ -231,6 +230,7 @@ function terminate!(integrator::SimpleIntegratorSSP) resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.time_per_timestep, integrator.iter+1) end # used for AMR diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index 8eae13f1b7..1eb0fa8343 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -69,7 +69,7 @@ function trixi2txt(filename::AbstractString...; center_level_0, length_level_0, leaf_cells, coordinates, levels = read_meshfile(meshfile) # Read data - labels, data, n_elements, n_nodes, element_variables, time = read_datafile(filename) + labels, data, n_elements, n_nodes, element_variables, node_variables, time = read_datafile(filename) # Check if dimensions match if length(leaf_cells) != n_elements @@ -263,7 +263,16 @@ function read_datafile(filename::String) index +=1 end - return labels, data, n_elements, n_nodes, element_variables, time + # Extract node variable arrays + node_variables = Dict{String, Union{Vector{Float64}, Vector{Int}}}() + index = 1 + while haskey(file, "node_variables_$index") + varname = read(attributes(file["node_variables_$index"])["name"]) + node_variables[varname] = read(file["node_variables_$index"]) + index +=1 + end + + return labels, data, n_elements, n_nodes, element_variables, node_variables, time end end From 361263db0ce9fa00bbd176225f5b49d18315e63d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 15 Nov 2022 14:22:11 +0100 Subject: [PATCH 086/423] Update elixirs and speed up `update_alpha_per_timestep` --- .../elixir_euler_free_stream_sc_subcell.jl | 84 ++++++++++++++++ .../elixir_euler_source_terms_sc_subcell.jl | 67 +++++++++++++ .../elixir_euler_blast_wave_sc_subcell.jl | 4 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 96 +++++++++++++++++++ .../elixir_euler_source_terms_sc_subcell.jl | 69 +++++++++++++ src/callbacks_step/stepsize.jl | 2 +- src/solvers/dgsem_structured/indicators_2d.jl | 12 ++- src/solvers/dgsem_tree/dg.jl | 7 +- src/solvers/dgsem_tree/indicators.jl | 55 +++++------ src/solvers/dgsem_tree/indicators_2d.jl | 20 ++-- src/time_integration/methods_SSP.jl | 2 +- 12 files changed, 379 insertions(+), 41 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl create mode 100644 examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl new file mode 100644 index 0000000000..6ea41c0618 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -0,0 +1,84 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_constant + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=false, + IDPPressureTVD=false, + IDPPositivity=false, + indicator_smooth=false) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. +# This particular mesh is unstructured in the yz-plane, but extruded in x-direction. +# Apply the warping mapping in the yz-plane to get a curved 2D mesh that is extruded +# in x-direction to ensure free stream preservation on a non-conforming mesh. +# See https://doi.org/10.1007/s10915-018-00897-9, Section 6. + +# Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D +function mapping(xi_, eta_) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + + y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * + cos(0.5 * pi * (2 * eta - 3)/3)) + + x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * + cos(2 * pi * (2 * y - 3)/3)) + + return SVector(x, y) +end + +cells_per_dimension = (32, 32) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 20000.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=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode; + 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_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl new file mode 100644 index 0000000000..398fbc345c --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -0,0 +1,67 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_convergence_test + +# Get the DG approximation space +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=false, + indicator_smooth=true) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (0.0, 0.0) +coordinates_max = (2.0, 2.0) + +cells_per_dimension = (16, 16) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms=source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 47c418ca7a..c1e34dc076 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -40,8 +40,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=false, - IDPPositivity=false) + IDPPressureTVD=true, + indicator_smooth=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 70505edde9..d5d1543c43 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -67,7 +67,7 @@ save_solution = SaveSolutionCallback(interval=50, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..408e259738 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,96 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_chandrashekar +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=true, + IDPCheckBounds=true, + indicator_smooth=true, + IDPMaxIter=15) +volume_integral = VolumeIntegralShockCapturingSubcell(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# 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) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=500, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl new file mode 100644 index 0000000000..a082b9bf89 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -0,0 +1,69 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_convergence_test + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPressureTVD=true, + IDPPositivity=false, + indicator_smooth=true) +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (0.0, 0.0) +coordinates_max = (2.0, 2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + n_cells_max=10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms=source_terms_convergence_test) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_restart = SaveRestartCallback(interval=100, + save_final_restart=true) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_restart, save_solution, + stepsize_callback) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 113841d5e4..3679f92ddf 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -92,7 +92,7 @@ max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral) = max_ constant_speed, equations, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) return max_dt(u, t, mesh, - constant_speed, equations, dg::DG, cache, volume_integral.indicator) + constant_speed, equations, dg, cache, volume_integral.indicator) end max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator::AbstractIndicator) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index e59baa44fe..3b7a872437 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -69,17 +69,25 @@ end @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(solver, cache) + end + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) - for element in eachelement(solver, cache) + for element in elements for j in eachnode(solver), i in eachnode(solver) jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + if total_volume > 0 + alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + end return nothing end diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 65bd56defa..247f20c007 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -27,7 +27,12 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) - dg_only = isapprox(alpha[element], 0, atol=0.1) + if dg.volume_integral isa VolumeIntegralShockCapturingSubcell + tol = 0.1 + else + tol = 1e-12 + end + dg_only = isapprox(alpha[element], 0, atol=tol) if dg_only push!(element_ids_dg, element) else diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index befd008902..59a0f55535 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -21,32 +21,6 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end -function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) - node_variables[:indicator_shock_capturing] = indicator.cache.ContainerShockCapturingIndicator.alpha - # TODO BB: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. - return nothing -end - -function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) - if !indicator.Plotting - return nothing - end - @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator - variables = varnames(cons2cons, equations) - for v in eachvariable(equations) - s = Symbol("shock_capturing_delta_volume_flux_", variables[v]) - node_variables[s] = volume_flux_difference[v, ntuple(_ -> :, nvariables(equations) + 1)...] - end - - if indicator.IDPPressureTVD - @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - node_variables[:indicator_shock_capturing_pressure] = alpha_pressure - end - - return nothing -end - - """ IndicatorHennemannGassner @@ -257,7 +231,8 @@ function Base.show(io::IO, indicator::IndicatorIDP) else print(io, "limiter=(") IDPDensityTVD && print(io, "IDPDensityTVD, ") - IDPPressureTVD && print(io, "IDPPressureTVD, ") + IDPPressureTVD && print(io, "IDPPressureTVD with positivity correlation factor of ", + indicator.positCorrFactor, ", ") IDPPositivity && print(io, "IDPPositivity, ") IDPSpecEntropy && print(io, "IDPSpecEntropy, ") IDPMathEntropy && print(io, "IDPMathEntropy, ") @@ -267,6 +242,12 @@ function Base.show(io::IO, indicator::IndicatorIDP) print(io, ")") end +function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) + node_variables[:indicator_shock_capturing] = indicator.cache.ContainerShockCapturingIndicator.alpha + # TODO BB: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. + return nothing +end + """ IndicatorMCL @@ -312,6 +293,26 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, ")") end +function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) + if !indicator.Plotting + return nothing + end + @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator + variables = varnames(cons2cons, equations) + for v in eachvariable(equations) + s = Symbol("shock_capturing_delta_volume_flux_", variables[v]) + node_variables[s] = volume_flux_difference[v, ntuple(_ -> :, nvariables(equations) + 1)...] + end + + if indicator.IDPPressureTVD + @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + node_variables[:indicator_shock_capturing_pressure] = alpha_pressure + end + + return nothing +end + + struct IndicatorMax{Variable, Cache<:NamedTuple} <: AbstractIndicator variable::Variable cache::Cache diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 0c778275a6..760f64e35c 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -620,7 +620,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) Pm = inverse_jacobian * Pm if Pm < 0.0 @@ -776,9 +776,9 @@ end break end - if iter == indicator_IDP.IDPMaxIter - @warn "Maximum number of iterations for the Newton-bisection algorithm reached." - end + # if iter == indicator_IDP.IDPMaxIter + # @warn "Maximum number of iterations for the Newton-bisection algorithm reached." + # end end new_alpha = 1.0 - beta @@ -799,17 +799,25 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(solver, cache) + end + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) - for element in eachelement(solver, cache) + for element in elements jacobian = inv(cache.elements.inverse_jacobian[element]) for j in eachnode(solver), i in eachnode(solver) alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + if total_volume > 0 + alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + end return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index cb79263546..b27957d5e8 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -45,7 +45,7 @@ mutable struct SimpleIntegratorSSPOptions{Callback} callback::Callback # callbacks; used in Trixi adaptive::Bool # whether the algorithm is adaptive; ignored dtmax::Float64 # ignored - maxiters::Int # maximal numer of time steps + maxiters::Int # maximal number of time steps tstops::Vector{Float64} # tstops from https://diffeq.sciml.ai/v6.8/basics/common_solver_opts/#Output-Control-1; ignored end From d5dfa6b70c9908299f7cdb98222c0fa13b9d40f2 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 17 Nov 2022 15:13:29 +0100 Subject: [PATCH 087/423] Update elixirs --- .../elixir_euler_shock_upstream_sc_subcell.jl | 136 ++++++++++++++++++ .../elixir_euler_astro_jet_subcell.jl | 12 +- .../elixir_euler_astro_jet_subcell_restart.jl | 13 +- .../elixir_euler_blob_sc_subcell.jl | 6 +- 4 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl new file mode 100644 index 0000000000..4b24b5ffbf --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -0,0 +1,136 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_inviscid_bow(x, t, equations::CompressibleEulerEquations2D) + rho = 1.4 + p = 1.0 + v1 = 4.0 + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_inviscid_bow + +boundary_condition = BoundaryConditionDirichlet(initial_condition) +boundary_conditions = (x_neg=boundary_condition, + x_pos=boundary_condition_slip_wall, + y_neg=boundary_condition, + y_pos=boundary_condition) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 5 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPositivity=true, + IDPMaxIter=20, + IDPSpecEntropy=true, + indicator_smooth=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# domain +# ,, +# , | +# , | f4 of length a-1 +#f1 , | +# , ,` f2 /alpha +# , |_(0,0)___________/_______(3.85,0) +# , | +# , `, +# , `| +# , | f3 +# ,| +# l = circumference of quarter circle / length of egg-shaped form +a = sqrt(5.9^2 - 3.85^2) +alpha = acos(3.85 / 5.9) +l = (pi / 4) / (pi / 2 + 1) +f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)) # left +function f2(s) # right + t = 0.5 * s + 0.5 # in [0,1] + if 0 <= t <= l + beta = t / l # in [0,1] + return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) + elseif l < t <= 1 - l # 0 <= t - l <= 1-2l + beta = (t - l) / (1 - 2 * l) # in [0,1] + return SVector(-0.5, -0.5 + beta) + else # 1 - l < t <= 1 + beta = (t + l - 1) / l # in [0,1] + return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) + end +end +f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom +f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a) # top +faces = (f1, f2, f3, f4) + +# This creates a mapping that transforms [-1, 1]^2 to the domain with the faces defined above. +Trixi.validate_faces(faces) +mapping_bow = Trixi.transfinite_mapping(faces) + +mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi / 4) / (pi / 2 + 1); " * + "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * + "function f2(s); t = 0.5 * s + 0.5; " * + "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * + "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * + "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * + "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * + "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * + "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" + +cells_per_dimension = (24, 36) + +mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string=mapping_as_string, periodicity=false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_conditions) + +############################################################################### +# 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) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=500, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.3) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index f20d3c1cf5..940ab9ec20 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -38,15 +38,19 @@ boundary_conditions = ( ) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_chandrashekar # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=false, - IDPPositivity=true) + IDPPressureTVD=true, + IDPSpecEntropy=true, + IDPPositivity=true, + IDPCheckBounds=true, + IDPMaxIter=25, + indicator_smooth=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -55,7 +59,7 @@ coordinates_min = (-0.5, -0.5) coordinates_max = ( 0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=8, periodicity=(false,true), n_cells_max=100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl index 01c276c332..4bf6fa2258 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl @@ -10,14 +10,7 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_subcell.jl ############################################################################### # adapt the parameters that have changed compared to "elixir_euler_astro_jet_subcell.jl" -restart_filename = joinpath("out", "restart_000001.h5") -# setups: -# - refinement level = 6: -# * Limiter: IDPPressureTVD, IDPPositivity: T_1=2.5e-6 (CFL=0.004, 1 timestep) -# - refinement level = 7: -# * Limiter: IDPPressureTVD, IDPPositivity: T_1=5.0e-6 (CFL=0.004, 260 timesteps) -# - refinement level = 8: -# * Limiter: IDPPressureTVD, IDPPositivity: T_1=2.5e-6 (CFL=0.004, 269 timesteps) +restart_filename = joinpath("out", "restart_000271.h5") mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) @@ -25,12 +18,12 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, tspan = (load_time(restart_filename), 0.001) ode = semidiscretize(semi, tspan, restart_filename); -save_solution = SaveSolutionCallback(interval=100, +save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=false, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl=0.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl index 2ff08a2fb1..5d10a56b99 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl @@ -61,8 +61,8 @@ volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (-32.0, -32.0) -coordinates_max = ( 32.0, 32.0) +coordinates_min = (-20.0, -20.0) +coordinates_max = ( 20.0, 20.0) mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level=6, @@ -74,7 +74,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 16.0) +tspan = (0.0, 8.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() From 6ed3455d00df4bb653a00bd3224f360b91407c1d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 21 Nov 2022 23:38:59 +0100 Subject: [PATCH 088/423] Remove IDPalpha_max, Add smoothness indicator to timestep --- src/callbacks_step/stepsize.jl | 14 +++--- src/callbacks_step/stepsize_dg2d.jl | 62 ++++++++++++++++++++++++- src/solvers/dgsem_tree/containers_2d.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 43 ++++++----------- src/solvers/dgsem_tree/indicators.jl | 10 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 32 ++++++------- 6 files changed, 100 insertions(+), 65 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 3679f92ddf..4401b2f28f 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -86,17 +86,19 @@ end return nothing end -max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) +max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral::AbstractVolumeIntegral) = + max_dt(u, t, mesh, constant_speed, equations, dg, cache) @inline function max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) - - return max_dt(u, t, mesh, - constant_speed, equations, dg, cache, volume_integral.indicator) + @unpack indicator = volume_integral + if indicator isa IndicatorIDP + return max_dt(u, t, mesh, constant_speed, equations, dg, cache) + else + return max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator) + end end -max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator::AbstractIndicator) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) - # Time integration methods from the DiffEq ecosystem without adaptive time stepping on their own # such as `CarpenterKennedy2N54` require passing `dt=...` in `solve(ode, ...)`. Since we don't have diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 424df4cb1c..262df2f70d 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -42,14 +42,24 @@ function max_dt(u, t, mesh::TreeMesh{2}, return 2 / (nnodes(dg) * max_scaled_speed) end -@inline function max_dt(u, t, mesh::TreeMesh{2}, +@inline function max_dt(u, t, mesh::TreeMesh2D, constant_speed::Val{false}, equations, dg::DG, cache, indicator::IndicatorMCL) @unpack inverse_weights = dg.basis @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator maxdt = typemax(eltype(u)) - for element in eachelement(dg, cache) + if indicator.indicator_smooth + @unpack element_ids_dg, element_ids_dgfv = cache + alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, mesh, equations, dg, cache) + pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, dg, cache) + else + element_ids_dg = Int[] + element_ids_dgfv = eachelement(dg, cache) + end + + for idx_element in eachindex(element_ids_dgfv) + element = element_ids_dgfv[idx_element] J = 1 / cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) @@ -59,9 +69,57 @@ end end end + maxdt = min(maxdt, + max_dt_RK(u, t, mesh, constant_speed, equations, dg, cache, indicator, element_ids_dg)) + return maxdt end +@inline function max_dt_RK(u, t, mesh::TreeMesh2D, constant_speed, equations, dg::DG, cache, indicator, element_ids_dg) + max_scaled_speed = nextfloat(zero(t)) + for idx_element in eachindex(element_ids_dg) + element = element_ids_dg[idx_element] + max_λ1 = max_λ2 = zero(max_scaled_speed) + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + λ1, λ2 = max_abs_speeds(u_node, equations) + max_λ1 = max(max_λ1, λ1) + max_λ2 = max(max_λ2, λ2) + end + inv_jacobian = cache.elements.inverse_jacobian[element] + max_scaled_speed = max(max_scaled_speed, inv_jacobian * (max_λ1 + max_λ2)) + end + + return 2 / (nnodes(dg) * max_scaled_speed) +end + +@inline function max_dt_RK(u, t, mesh::StructuredMesh{2}, constant_speed, equations, dg::DG, cache, indicator, element_ids_dg) + @unpack contravariant_vectors, inverse_jacobian = cache.elements + + max_scaled_speed = nextfloat(zero(t)) + for element in element_ids_dg + max_λ1 = max_λ2 = zero(max_scaled_speed) + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + λ1, λ2 = max_abs_speeds(u_node, equations) + + # Local speeds transformed to the reference element + Ja11, Ja12 = get_contravariant_vector(1, contravariant_vectors, i, j, element) + λ1_transformed = abs(Ja11 * λ1 + Ja12 * λ2) + Ja21, Ja22 = get_contravariant_vector(2, contravariant_vectors, i, j, element) + λ2_transformed = abs(Ja21 * λ1 + Ja22 * λ2) + + inv_jacobian = abs(inverse_jacobian[i, j, element]) + + max_λ1 = max(max_λ1, λ1_transformed * inv_jacobian) + max_λ2 = max(max_λ2, λ2_transformed * inv_jacobian) + end + max_scaled_speed = max(max_scaled_speed, max_λ1 + max_λ2) + end + + return 2 / (nnodes(dg) * max_scaled_speed) +end + function max_dt(u, t, mesh::ParallelTreeMesh{2}, constant_speed::Val{false}, equations, dg::DG, cache) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index b85ea3d852..e3fc975f5b 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1308,7 +1308,7 @@ end mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} - alpha::Array{uEltype, 3} # [i, j, element] + alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} var_bounds::Vector{Array{uEltype, 3}} @@ -1337,7 +1337,7 @@ function ContainerShockCapturingIndicatorIDP{uEltype}(capacity::Integer, n_nodes var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) end - return ContainerShockCapturingIndicatorIDP{uEltype}(alpha, alpha1, alpha2, var_bounds, + return ContainerShockCapturingIndicatorIDP{uEltype}(alpha, alpha1, alpha2, var_bounds, _alpha, _alpha1, _alpha2, _var_bounds) end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 873119820f..93b92d5692 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -522,26 +522,14 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache) + @unpack indicator = volume_integral # Calculate maximum wave speeds lambda - # TODO: - # Option one: (Right now) Calculate the lambdas 4 times each time step (before each RK stage and in callback) plus one time to init the callback - # 1 In the stepsize callback to get the right time step - # Remove 1, the first time step cannot be calculated and the others are not accurate (with old lambdas) - # 2 In the volume integral (here). - # Remove 2, the first entropy analysis of the analysis_callback doesn't work. - # And we get different result because otherwise the lambdas are only updated once in a RK step. - # -> 4 times per timestep is actually not that bad. (3 times would be optimal) - # -- With option 1: I don't need to save all lambdas, just use threaded vector of 2 dimensions [i, j] - # (wrong!, because I need the lambdas to calculate the bar states here) - # Option two: Calculate lambdas after each RK stage plus in the init_stepsize_callback. - # Problem: Entropy change at t=0 only works if the stepsize callback is listed before analysis callback (to calculate the lambdas before) - @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, volume_integral.indicator) + @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) # Calculate bar states - @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) # Calculate boundaries - @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, volume_integral.indicator, dg, cache) + @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) - @unpack indicator = volume_integral if indicator.indicator_smooth @unpack element_ids_dg, element_ids_dgfv = cache # Calculate element-wise blending factors α @@ -1215,37 +1203,34 @@ end @threaded for element in eachelement(solver, cache) idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] for j in eachnode(solver), i in eachnode(solver) - counter = 0 + counter = 1 if IDPDensityTVD - counter += 1 # rho_min - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[1][i, j, element] - u[1, i, j, element]) - counter += 1 # rho_max - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], u[1, i, j, element] - var_bounds[2][i, j, element]) + idp_bounds_delta[1] = max(idp_bounds_delta[1], var_bounds[1][i, j, element] - u[1, i, j, element]) + idp_bounds_delta[2] = max(idp_bounds_delta[2], u[1, i, j, element] - var_bounds[2][i, j, element]) + counter += 2 end if IDPPressureTVD p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - counter += 1 # p_min - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) - counter += 1 # p_max - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], p - var_bounds[counter][i, j, element]) + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) + idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], p - var_bounds[counter+1][i, j, element]) + counter += 2 end if IDPPositivity && !IDPDensityTVD - counter += 1 # rho_min idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - u[1, i, j, element]) + counter += 1 end if IDPPositivity && !IDPPressureTVD p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - counter += 1 # p_min idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) + counter += 1 end if IDPSpecEntropy s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) - counter += 1 # s_min idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - s) + counter += 1 end if IDPMathEntropy s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) - counter += 1 # s_max idp_bounds_delta[counter] = max(idp_bounds_delta[counter], s - var_bounds[counter][i, j, element]) end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 59a0f55535..41ae09d3d7 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -169,7 +169,6 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi This is an experimental feature and may change in future releases. """ struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator - alpha_maxIDP::RealT IDPDensityTVD::Bool IDPPressureTVD::Bool IDPPositivity::Bool @@ -188,7 +187,6 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; - alpha_maxIDP=1.0, IDPDensityTVD=false, IDPPressureTVD=false, IDPPositivity=false, @@ -215,10 +213,9 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(alpha_maxIDP), typeof(cache), typeof(IndicatorHG)}(alpha_maxIDP, - IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy, - cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, - indicator_smooth, IndicatorHG) + IndicatorIDP{typeof(positCorrFactor), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, + IDPPositivity, IDPSpecEntropy, IDPMathEntropy, cache, positCorrFactor, IDPMaxIter, + newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -238,7 +235,6 @@ function Base.show(io::IO, indicator::IndicatorIDP) IDPMathEntropy && print(io, "IDPMathEntropy, ") print(io, "), ") end - indicator.alpha_maxIDP != 1.0 && print(io, "alpha_maxIDP=", indicator.alpha_maxIDP) print(io, ")") end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 760f64e35c..75a604ec62 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -191,12 +191,8 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Union{Type{IndicatorIDP}, Type{IndicatorMCL}}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) - if indicator == IndicatorIDP - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), length) - else # indicator == IndicatorMCL - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) - end +function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), length) alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) @@ -204,9 +200,8 @@ function create_cache(indicator::Union{Type{IndicatorIDP}, Type{IndicatorMCL}}, idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] - return (; ContainerShockCapturingIndicator, - alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, - idp_bounds_delta_threaded) + return (; alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, + ContainerShockCapturingIndicator, idp_bounds_delta_threaded) end function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -232,16 +227,6 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab indicator_IDP.IDPMathEntropy && @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache, elements) - # Clip the maximum amount of FV allowed (default: alpha_maxIDP = 1.0) - @unpack alpha_maxIDP = indicator_IDP - if alpha_maxIDP != 1.0 - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - alpha[i, j, element] = min(alpha_maxIDP, alpha[i, j, element]) - end - end - end - # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator @threaded for element in elements @@ -822,6 +807,15 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, return nothing end +# this method is used when the indicator is constructed as for shock-capturing volume integrals +function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) + + idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] + + return (; ContainerShockCapturingIndicator, idp_bounds_delta_threaded) +end + @inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) return nothing From 6c53133520c9aaf7171b301196c12032e9d8a974 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 22 Nov 2022 12:28:56 +0100 Subject: [PATCH 089/423] Fix time step calculation --- src/callbacks_step/stepsize.jl | 9 +++------ src/callbacks_step/stepsize_dg2d.jl | 17 +++++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 4401b2f28f..4593f12814 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -91,14 +91,11 @@ max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral::Abstra @inline function max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) - @unpack indicator = volume_integral - if indicator isa IndicatorIDP - return max_dt(u, t, mesh, constant_speed, equations, dg, cache) - else - return max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator) - end + return max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral.indicator) end +max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator::IndicatorIDP) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) + # Time integration methods from the DiffEq ecosystem without adaptive time stepping on their own # such as `CarpenterKennedy2N54` require passing `dt=...` in `solve(ode, ...)`. Since we don't have diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 262df2f70d..c8cd7441e7 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -42,7 +42,7 @@ function max_dt(u, t, mesh::TreeMesh{2}, return 2 / (nnodes(dg) * max_scaled_speed) end -@inline function max_dt(u, t, mesh::TreeMesh2D, +@inline function max_dt(u, t, mesh::Union{TreeMesh,StructuredMesh}, constant_speed::Val{false}, equations, dg::DG, cache, indicator::IndicatorMCL) @unpack inverse_weights = dg.basis @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) @@ -54,23 +54,28 @@ end alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, mesh, equations, dg, cache) pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, dg, cache) else - element_ids_dg = Int[] element_ids_dgfv = eachelement(dg, cache) end for idx_element in eachindex(element_ids_dgfv) element = element_ids_dgfv[idx_element] - J = 1 / cache.elements.inverse_jacobian[element] - + if mesh isa TreeMesh + J = 1 / cache.elements.inverse_jacobian[element] + end for j in eachnode(dg), i in eachnode(dg) + if mesh isa StructuredMesh{2} + J = 1 / cache.elements.inverse_jacobian[i, j, element] + end denom = inverse_weights[i] * (lambda1[i, j, element] + lambda1[i+1, j, element]) + inverse_weights[j] * (lambda2[i, j, element] + lambda2[i, j+1, element]) maxdt = min(maxdt, J / denom) end end - maxdt = min(maxdt, - max_dt_RK(u, t, mesh, constant_speed, equations, dg, cache, indicator, element_ids_dg)) + if indicator.indicator_smooth && !isempty(element_ids_dg) + maxdt = min(maxdt, + max_dt_RK(u, t, mesh, constant_speed, equations, dg, cache, indicator, element_ids_dg)) + end return maxdt end From 9b0dcb38f587af287b8bb6afb4686d0492d5c9d8 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 22 Nov 2022 13:34:21 +0100 Subject: [PATCH 090/423] Delete weak blast wave elixirs --- .../elixir_euler_shockcapturing_MCL.jl | 63 ------------------ .../elixir_euler_shockcapturing_subcell.jl | 65 ------------------- 2 files changed, 128 deletions(-) delete mode 100644 examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl delete mode 100644 examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl deleted file mode 100644 index a546d1ce94..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_MCL.jl +++ /dev/null @@ -1,63 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -initial_condition = initial_condition_weak_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorMCL(equations, basis; - IDPCheckBounds=true) -volume_integral = VolumeIntegralShockCapturingSubcell(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) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - - -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 = 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=0.8) - -callbacks = CallbackSet(summary_callback, stepsize_callback, - save_solution, - analysis_callback, alive_callback) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl deleted file mode 100644 index 3c16339f6f..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ /dev/null @@ -1,65 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -initial_condition = initial_condition_weak_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPressureTVD=true, - IDPPositivity=false) -volume_integral = VolumeIntegralShockCapturingSubcell(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) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - - -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 = 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=0.5) - -callbacks = CallbackSet(summary_callback, stepsize_callback, - save_solution, - analysis_callback, alive_callback) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary From f6d7cbecbb3789664d2becec41dc463d0f8e54c5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 22 Nov 2022 18:19:58 +0100 Subject: [PATCH 091/423] Adapt KHI-MCL example, remove alphas_per_timestep for MCL implementation --- ...ixir_euler_kelvin_helmholtz_instability_MCL.jl | 6 ++++-- src/solvers/dgsem_tree/indicators.jl | 2 +- src/time_integration/methods_SSP.jl | 15 ++++++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 4895f3c337..3c225acaed 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -38,7 +38,9 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorMCL(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true) + IDPPressureTVD=false, + indicator_smooth=false, + Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -53,7 +55,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 1.0) +tspan = (0.0, 3.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 41ae09d3d7..b49e6574b4 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -265,7 +265,7 @@ end function IndicatorMCL(equations::AbstractEquations, basis; IDPPressureTVD=false, IDPCheckBounds=false, - indicator_smooth=true, + indicator_smooth=false, variable_smooth=density_pressure, Plotting=false) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index b27957d5e8..7bd269eaf1 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -171,9 +171,12 @@ function solve!(integrator::SimpleIntegratorSSP) # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe # solves the differences between the (not-)unrolled for-loop versions. - indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t + if integrator.p.solver.volume_integral.indicator isa IndicatorIDP + indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t + end - if integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep + if integrator.p.solver.volume_integral.indicator isa IndicatorIDP && + integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep new_length = length(indicator.cache.alpha_max_per_timestep) + 200 resize!(indicator.cache.alpha_max_per_timestep, new_length) resize!(indicator.cache.alpha_mean_per_timestep, new_length) @@ -228,9 +231,11 @@ function terminate!(integrator::SimpleIntegratorSSP) integrator.finalstep = true empty!(integrator.opts.tstops) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) - resize!(integrator.p.solver.volume_integral.indicator.cache.time_per_timestep, integrator.iter+1) + if integrator.p.solver.volume_integral.indicator isa IndicatorIDP + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.time_per_timestep, integrator.iter+1) + end end # used for AMR From 6ebf8e15df2aad9bc80ed8304e851027f1cbaf68 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 24 Nov 2022 13:18:23 +0100 Subject: [PATCH 092/423] Add calculation of lambdas and bar states at boundaries --- src/callbacks_step/stepsize.jl | 10 +- src/callbacks_step/stepsize_dg2d.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 274 ++++++++++++++++++++-------- 3 files changed, 205 insertions(+), 83 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 4593f12814..0a1a343165 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -74,7 +74,7 @@ end dt = @trixi_timeit timer() "calculate dt" cfl_number * max_dt(u, t, mesh, have_constant_speed(equations), equations, - solver, cache, solver.volume_integral) + semi, solver, cache, solver.volume_integral) set_proposed_dt!(integrator, dt) integrator.opts.dtmax = dt @@ -86,15 +86,15 @@ end return nothing end -max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral::AbstractVolumeIntegral) = +max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral::AbstractVolumeIntegral) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) @inline function max_dt(u, t, mesh, - constant_speed, equations, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) - return max_dt(u, t, mesh, constant_speed, equations, dg, cache, volume_integral.indicator) + constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) + return max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral.indicator) end -max_dt(u, t, mesh, constant_speed, equations, dg, cache, indicator::IndicatorIDP) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) +max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, indicator::IndicatorIDP) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) # Time integration methods from the DiffEq ecosystem without adaptive time stepping on their own diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index c8cd7441e7..3b3c8dfdd2 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -43,9 +43,9 @@ function max_dt(u, t, mesh::TreeMesh{2}, end @inline function max_dt(u, t, mesh::Union{TreeMesh,StructuredMesh}, - constant_speed::Val{false}, equations, dg::DG, cache, indicator::IndicatorMCL) + constant_speed::Val{false}, equations, semi, dg::DG, cache, indicator::IndicatorMCL) @unpack inverse_weights = dg.basis - @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) + @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, t, mesh, equations, dg, cache, indicator, semi.boundary_conditions) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator maxdt = typemax(eltype(u)) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 93b92d5692..a63a8cde84 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -135,7 +135,7 @@ function rhs!(du, u, t, @trixi_timeit timer() "volume integral" calc_volume_integral!( du, u, mesh, have_nonconservative_terms(equations), equations, - dg.volume_integral, dg, cache) + dg.volume_integral, dg, cache, t, boundary_conditions) # Prolong solution to interfaces @trixi_timeit timer() "prolong2interfaces" prolong2interfaces!( @@ -181,6 +181,19 @@ function rhs!(du, u, t, end +function calc_volume_integral!(du, u, mesh, + nonconservative_terms, equations, + volume_integral::AbstractVolumeIntegral, + dg, cache, t, boundary_conditions) + + calc_volume_integral!(du, u, mesh, + nonconservative_terms, equations, + volume_integral, dg, cache) + + return nothing +end + + function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}}, nonconservative_terms, equations, @@ -521,12 +534,12 @@ function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, volume_integral::VolumeIntegralShockCapturingSubcell, - dg::DGSEM, cache) + dg::DGSEM, cache, t, boundary_conditions) @unpack indicator = volume_integral # Calculate maximum wave speeds lambda - @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, mesh, equations, dg, cache, indicator) + @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, t, mesh, equations, dg, cache, indicator, boundary_conditions) # Calculate bar states - @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) + @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, t, mesh, nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) # Calculate boundaries @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) @@ -765,15 +778,16 @@ end return nothing end -@inline function calc_bar_states!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) +@inline function calc_bar_states!(u, t, mesh, nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) return nothing end -@inline function calc_bar_states!(u, mesh, - nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) +@inline function calc_bar_states!(u, t, mesh::TreeMesh, + nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + # Calc bar states inside elements @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in 2:nnodes(dg) u_node = get_node_vars(u, equations, dg, i, j, element) @@ -800,6 +814,116 @@ end end end + # Calc bar states at interfaces and periodic boundaries + @threaded for interface in eachinterface(dg, cache) + # Get neighboring element ids + left_id = cache.interfaces.neighbor_ids[1, interface] + right_id = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + if orientation == 1 + for j in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) + u_right = get_node_vars(u, equations, dg, 1, j, right_id) + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + + lambda = lambda1[1, j, right_id] + bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda + for v in eachvariable(equations) + bar_states1[v, nnodes(dg)+1, j, left_id] = bar_state[v] + bar_states1[v, 1, j, right_id] = bar_state[v] + end + end + else # orientation == 2 + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) + u_right = get_node_vars(u, equations, dg, i, 1, right_id) + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + + lambda = lambda2[i, 1, right_id] + bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg)+1, left_id] = bar_state[v] + bar_states2[v, i, 1, right_id] = bar_state[v] + end + end + end + end + + # Calc bar states at physical boundaries + @threaded for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # boundary_side == 1 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + + lambda = lambda1[1, j, element] + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda + for v in eachvariable(equations) + bar_states1[v, 1, j, element] = bar_state[v] + end + end + else # boundary_side == 2 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + + lambda = lambda1[nnodes(dg)+1, j, element] + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda + for v in eachvariable(equations) + bar_states1[v, nnodes(dg)+1, j, element] = bar_state[v] + end + end + end + else # orientation == 2 + if neighbor_side == 2 # boundary_side == 1 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + + lambda = lambda2[i, 1, element] + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda + for v in eachvariable(equations) + bar_states2[v, i, 1, element] = bar_state[v] + end + end + else # boundary_side == 2 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + + lambda = lambda2[i, nnodes(dg)+1, element] + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg)+1, element] = bar_state[v] + end + end + end + end + end + return nothing end @@ -817,79 +941,42 @@ end var_max[v, :, :, element] .= typemin(eltype(var_max)) end - for j in eachnode(dg), i in 2:nnodes(dg) + for j in eachnode(dg), i in eachnode(dg) + # - xi direction bar_state_rho = bar_states1[1, i, j, element] - var_min[1, i-1, j, element] = min(var_min[1, i-1, j, element], bar_state_rho) - var_max[1, i-1, j, element] = max(var_max[1, i-1, j, element], bar_state_rho) - var_min[1, i , j, element] = min(var_min[1, i , j, element], bar_state_rho) - var_max[1, i , j, element] = max(var_max[1, i , j, element], bar_state_rho) + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) for v in 2:nvariables(equations) bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho - var_min[v, i-1, j, element] = min(var_min[v, i-1, j, element], bar_state_phi) - var_max[v, i-1, j, element] = max(var_max[v, i-1, j, element], bar_state_phi) - var_min[v, i , j, element] = min(var_min[v, i , j, element], bar_state_phi) - var_max[v, i , j, element] = max(var_max[v, i , j, element], bar_state_phi) + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, 1, j, element], bar_state_phi) end - end - for j in 2:nnodes(dg), i in eachnode(dg) + # + xi direction + bar_state_rho = bar_states1[1, i+1, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i+1, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end + # - eta direction bar_state_rho = bar_states2[1, i, j, element] - var_min[1, i, j-1, element] = min(var_min[1, i, j-1, element], bar_state_rho) - var_max[1, i, j-1, element] = max(var_max[1, i, j-1, element], bar_state_rho) - var_min[1, i, j , element] = min(var_min[1, i, j, element], bar_state_rho) - var_max[1, i, j , element] = max(var_max[1, i, j, element], bar_state_rho) + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) for v in 2:nvariables(equations) bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho - var_min[v, i, j-1, element] = min(var_min[v, i, j-1, element], bar_state_phi) - var_max[v, i, j-1, element] = max(var_max[v, i, j-1, element], bar_state_phi) - var_min[v, i, j , element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j , element] = max(var_max[v, i, j, element], bar_state_phi) + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) end - end - end - - calc_var_bounds_interface!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) - - return nothing -end - -@inline function calc_var_bounds_interface!(u, mesh::TreeMesh2D, nonconservative_terms, equations, indicator, dg, cache) - @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left_id = cache.interfaces.neighbor_ids[1, interface] - right_id = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left_id) - index_right = (1, i, right_id) - lambda = lambda1[1, i, right_id] - else - index_left = (i, nnodes(dg), left_id) - index_right = (i, 1, right_id) - lambda = lambda2[i, 1, right_id] - end - - u_left = get_node_vars(u, equations, dg, index_left...) - u_right = get_node_vars(u, equations, dg, index_right...) - - flux_left = flux(u_left, orientation, equations) - flux_right = flux(u_right, orientation, equations) - - bar_state_rho = 0.5 * (u_left[1] + u_right[1]) - 0.5 * (flux_right[1] - flux_left[1]) / lambda - var_min[1, index_left...] = min(var_min[1, index_left...], bar_state_rho) - var_max[1, index_left...] = max(var_max[1, index_left...], bar_state_rho) - var_min[1, index_right...] = min(var_min[1, index_right...], bar_state_rho) - var_max[1, index_right...] = max(var_max[1, index_right...], bar_state_rho) + # + eta direction + bar_state_rho = bar_states2[1, i, j+1, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) for v in 2:nvariables(equations) - bar_state_phi = 0.5 * (u_left[v] + u_right[v]) - 0.5 * (flux_right[v] - flux_left[v]) / lambda - bar_state_phi = bar_state_phi / bar_state_rho - var_min[v, index_left...] = min(var_min[v, index_left...], bar_state_phi) - var_max[v, index_left...] = max(var_max[v, index_left...], bar_state_phi) - var_min[v, index_right...] = min(var_min[v, index_right...], bar_state_phi) - var_max[v, index_right...] = max(var_max[v, index_right...], bar_state_phi) + bar_state_phi = bar_states2[v, i, j+1, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) end end end @@ -1078,9 +1165,10 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh::TreeMesh2D, equations, dg, cache, indicator::IndicatorMCL) +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::TreeMesh2D, equations, dg, cache, indicator::IndicatorMCL, boundary_conditions) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in 2:nnodes(dg) u_node = get_node_vars(u, equations, dg, i, j, element) @@ -1095,6 +1183,7 @@ end end end + # Calc lambdas at interfaces and periodic boundaries @threaded for interface in eachinterface(dg, cache) left = cache.interfaces.neighbor_ids[1, interface] right = cache.interfaces.neighbor_ids[2, interface] @@ -1122,6 +1211,7 @@ end end end + # Calc lambdas at physical boundaries @threaded for boundary in eachboundary(dg, cache) element = cache.boundaries.neighbor_ids[boundary] orientation = cache.boundaries.orientations[boundary] @@ -1129,15 +1219,35 @@ end if orientation == 1 if neighbor_side == 2 # boundary_side == 1 - lambda1[1, :, element] .= zero(eltype(lambda1)) + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + end else # boundary_side == 2 - lambda1[nnodes(dg)+1, :, element] .= zero(eltype(lambda1)) + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + end end else # orientation == 2 if neighbor_side == 2 # boundary_side == 1 - lambda2[:, 1, element] .= zero(eltype(lambda2)) + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + end else # boundary_side == 2 - lambda2[:, nnodes(dg)+1, element] .= zero(eltype(lambda2)) + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + end end end end @@ -1145,6 +1255,18 @@ end return nothing end +get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, indices...) = u_inner + +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, equations, dg, indices...) + @unpack node_coordinates = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(x, t, equations) + + return u_outer +end + + @inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) From 8d2679389214c97cc64f96557e02bab52ffcac03 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 24 Nov 2022 14:58:40 +0100 Subject: [PATCH 093/423] Fix Astro jet elixir --- .../elixir_euler_astro_jet_MCL.jl | 9 ++-- .../elixir_euler_astro_jet_MCL_restart.jl | 44 ------------------- 2 files changed, 5 insertions(+), 48 deletions(-) delete mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index e8fcbb0af9..f72673332f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -20,7 +20,7 @@ function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations p = 0.4127 # add inflow for t>0 at x=-0.5 # domain size is [-0.5,+0.5]^2 - if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) rho = 5 v1 = 800 # about Mach number Ma = 2000 v2 = 0 @@ -45,7 +45,8 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorMCL(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true) + IDPPressureTVD=true, + Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -54,7 +55,7 @@ coordinates_min = (-0.5, -0.5) coordinates_max = ( 0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=8, periodicity=(false,true), n_cells_max=100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) @@ -62,7 +63,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 2.5e-6) # simulation with end time T=0.001 in the restart file +tspan = (0.0, 0.001) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl deleted file mode 100644 index f554f09914..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL_restart.jl +++ /dev/null @@ -1,44 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# create a restart file - -trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_MCL.jl")) - -############################################################################### -# adapt the parameters that have changed compared to "elixir_euler_astro_jet_MCL.jl" - -restart_filename = joinpath("out", "restart_000001.h5") -# setups: -# - refinement level = 6: -# * Limiter: IDPPressureTVD: T_1=2.5e-6 (CFL=1.0, 1 timestep) -# - refinement level = 7: -# * Limiter: IDPPressureTVD: T_1=2.0e-6 (CFL=0.005, 219 timesteps) -# - refinement level = 8: -# * Limiter: IDPPressureTVD: T_1=1.0e-6 (CFL=0.005, 220 timesteps) -mesh = load_mesh(restart_filename) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - -tspan = (load_time(restart_filename), 0.001) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=false, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=1.0) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) -############################################################################### -# run the simulation -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary From 00dea7620a68b9851ebba37ae27d45ea99bb6a0e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 28 Nov 2022 12:10:56 +0100 Subject: [PATCH 094/423] Add time and boundaries to VolInt, Speed up due to rearranging functions, Add boundary contribution for IDP limiting --- src/solvers/dgsem_structured/dg_2d.jl | 9 +- src/solvers/dgsem_structured/indicators_2d.jl | 74 ++++-- src/solvers/dgsem_tree/dg_2d.jl | 81 ++++--- src/solvers/dgsem_tree/indicators_2d.jl | 227 ++++++++++++++---- src/time_integration/methods_SSP.jl | 3 +- 5 files changed, 290 insertions(+), 104 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index c5269e4708..49ae869ce2 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -16,7 +16,7 @@ function rhs!(du, u, t, @trixi_timeit timer() "volume integral" calc_volume_integral!( du, u, mesh, have_nonconservative_terms(equations), equations, - dg.volume_integral, dg, cache) + dg.volume_integral, dg, cache, t, boundary_conditions) # Calculate interface fluxes @trixi_timeit timer() "interface flux" calc_interface_flux!( @@ -416,8 +416,9 @@ end end -@inline function calc_var_bounds_interface!(u, mesh::StructuredMesh, nonconservative_terms, equations, indicator, dg, cache) - @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator +@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, + nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator @unpack contravariant_vectors = cache.elements for element in eachelement(dg, cache) @@ -487,7 +488,7 @@ end end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh::StructuredMesh, equations, dg, cache, indicator::IndicatorMCL) +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::StructuredMesh, equations, dg, cache, indicator::IndicatorMCL, boundary_conditions) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator @unpack contravariant_vectors = cache.elements diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 3b7a872437..de565a5859 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -28,22 +28,25 @@ function apply_smoothing!(mesh::StructuredMesh{2}, alpha, alpha_tmp, dg, cache) end -function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::StructuredMesh{2}, equations, dg, cache) +function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] lower = cache.elements.left_neighbors[2, element] if left != 0 - for i in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), i, left), equations) - var_element = variable(get_node_vars(u, equations, dg, 1, i, element), equations) + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) + var_element = variable(get_node_vars(u, equations, dg, 1, j, element), equations) - var_min[nnodes(dg), i, left] = min(var_min[nnodes(dg), i, left], var_element) - var_max[nnodes(dg), i, left] = max(var_max[nnodes(dg), i, left], var_element) + var_min[1, j, element] = min(var_min[1, j, element], var_left) + var_max[1, j, element] = max(var_max[1, j, element], var_left) - var_min[1, i, element] = min(var_min[1, i, element], var_left) - var_max[1, i, element] = max(var_max[1, i, element], var_left) + var_min[nnodes(dg), j, left] = min(var_min[nnodes(dg), j, left], var_element) + var_max[nnodes(dg), j, left] = max(var_max[nnodes(dg), j, left], var_element) end end if lower != 0 @@ -51,11 +54,11 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::Stru var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) var_element = variable(get_node_vars(u, equations, dg, i, 1, element), equations) - var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], var_element) - var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], var_element) - var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) + + var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], var_element) + var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], var_element) end end end @@ -92,28 +95,31 @@ end return nothing end -function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::StructuredMesh{2}, equations, dg, cache) +function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] lower = cache.elements.left_neighbors[2, element] if left != 0 - for i in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), i, left), equations) - var_element = variable(get_node_vars(u, equations, dg, 1, i, element), equations) + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) + var_element = variable(get_node_vars(u, equations, dg, 1, j, element), equations) - var_minmax[nnodes(dg), i, left] = minmax(var_minmax[nnodes(dg), i, left], var_element) - var_minmax[1, i, element] = minmax(var_minmax[1, i, element], var_left) + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_left) + var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, left], var_element) end end if lower != 0 for i in eachnode(dg) - var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) + var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) var_element = variable(get_node_vars(u, equations, dg, i, 1, element), equations) + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_lower) var_minmax[i, nnodes(dg), lower] = minmax(var_minmax[i, nnodes(dg), lower], var_element) - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_lower) end end end @@ -122,4 +128,34 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::St end +@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh) + _, _, solver, cache = mesh_equations_solver_cache(semi) + @unpack weights = solver.basis + @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + + if indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(solver, cache) + end + + alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_avg = zero(eltype(alpha)) + total_volume = zero(eltype(alpha)) + for element in elements + for j in eachnode(solver), i in eachnode(solver) + jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) + alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + if total_volume > 0 + alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + end + + return nothing +end + + end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index a63a8cde84..6d28497801 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -536,10 +536,10 @@ function calc_volume_integral!(du, u, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DGSEM, cache, t, boundary_conditions) @unpack indicator = volume_integral - # Calculate maximum wave speeds lambda - @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, t, mesh, equations, dg, cache, indicator, boundary_conditions) - # Calculate bar states - @trixi_timeit timer() "calc_bar_states!" calc_bar_states!(u, t, mesh, nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) + + # Calculate lambdas and bar states + @trixi_timeit timer() "calc_lambdas_bar_states!" calc_lambdas_bar_states!(u, t, mesh, + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) # Calculate boundaries @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) @@ -778,20 +778,22 @@ end return nothing end -@inline function calc_bar_states!(u, t, mesh, nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) +@inline function calc_lambdas_bar_states!(u, t, mesh, + nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache, boundary_conditions) return nothing end -@inline function calc_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) +@inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, + nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator - # Calc bar states inside elements + # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) for j in eachnode(dg), i in 2:nnodes(dg) u_node = get_node_vars(u, equations, dg, i, j, element) u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) flux1 = flux(u_node, 1, equations) flux1_im1 = flux(u_node_im1, 1, equations) @@ -804,6 +806,7 @@ end for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j , element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) flux2 = flux(u_node, 2, equations) flux2_jm1 = flux(u_node_jm1, 2, equations) @@ -814,7 +817,7 @@ end end end - # Calc bar states at interfaces and periodic boundaries + # Calc lambdas and bar states at interfaces and periodic boundaries @threaded for interface in eachinterface(dg, cache) # Get neighboring element ids left_id = cache.interfaces.neighbor_ids[1, interface] @@ -826,11 +829,14 @@ end for j in eachnode(dg) u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) u_right = get_node_vars(u, equations, dg, 1, j, right_id) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda1[nnodes(dg)+1, j, left_id] = lambda + lambda1[1, j, right_id] = lambda flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) - lambda = lambda1[1, j, right_id] bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda for v in eachvariable(equations) bar_states1[v, nnodes(dg)+1, j, left_id] = bar_state[v] @@ -841,11 +847,14 @@ end for i in eachnode(dg) u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) u_right = get_node_vars(u, equations, dg, i, 1, right_id) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda2[i, nnodes(dg)+1, left_id] = lambda + lambda2[i, 1, right_id] = lambda flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) - lambda = lambda2[i, 1, right_id] bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda for v in eachvariable(equations) bar_states2[v, i, nnodes(dg)+1, left_id] = bar_state[v] @@ -855,7 +864,7 @@ end end end - # Calc bar states at physical boundaries + # Calc lambdas and bar states at physical boundaries @threaded for boundary in eachboundary(dg, cache) element = cache.boundaries.neighbor_ids[boundary] orientation = cache.boundaries.orientations[boundary] @@ -867,11 +876,12 @@ end u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - lambda = lambda1[1, j, element] - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda1[1, j, element] for v in eachvariable(equations) bar_states1[v, 1, j, element] = bar_state[v] end @@ -881,11 +891,12 @@ end u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], equations, dg, nnodes(dg), j, element) + lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - lambda = lambda1[nnodes(dg)+1, j, element] - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda1[nnodes(dg)+1, j, element] for v in eachvariable(equations) bar_states1[v, nnodes(dg)+1, j, element] = bar_state[v] end @@ -897,11 +908,12 @@ end u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - lambda = lambda2[i, 1, element] - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda2[i, 1, element] for v in eachvariable(equations) bar_states2[v, i, 1, element] = bar_state[v] end @@ -911,11 +923,12 @@ end u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], equations, dg, i, nnodes(dg), element) + lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - lambda = lambda2[i, nnodes(dg)+1, element] - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda + bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda2[i, nnodes(dg)+1, element] for v in eachvariable(equations) bar_states2[v, i, nnodes(dg)+1, element] = bar_state[v] end @@ -1185,28 +1198,28 @@ end # Calc lambdas at interfaces and periodic boundaries @threaded for interface in eachinterface(dg, cache) - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] + left_id = cache.interfaces.neighbor_ids[1, interface] + right_id = cache.interfaces.neighbor_ids[2, interface] orientation = cache.interfaces.orientations[interface] if orientation == 1 for j in eachnode(dg) - u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left) - u_right = get_node_vars(u, equations, dg, 1, j, right) + u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) + u_right = get_node_vars(u, equations, dg, 1, j, right_id) lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - lambda1[nnodes(dg)+1, j, left] = lambda - lambda1[1, j, right] = lambda + lambda1[nnodes(dg)+1, j, left_id] = lambda + lambda1[1, j, right_id] = lambda end - else + else # orientation == 2 for i in eachnode(dg) - u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left) - u_right = get_node_vars(u, equations, dg, i, 1, right) + u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) + u_right = get_node_vars(u, equations, dg, i, 1, right_id) lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - lambda2[i, nnodes(dg)+1, left] = lambda - lambda2[i, 1, right] = lambda + lambda2[i, nnodes(dg)+1, left_id] = lambda + lambda2[i, 1, right_id] = lambda end end end @@ -1267,13 +1280,13 @@ get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, i end -@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorIDP) +@inline function antidiffusive_stage!(u_ode, u_old_ode, t, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, mesh, equations, solver, dt, cache) + @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, semi, solver, t, dt) perform_IDP_correction(u, dt, mesh, equations, solver, cache) @@ -1311,7 +1324,7 @@ end return nothing end -@inline function antidiffusive_stage!(u_ode, u_old_ode, dt, semi, indicator::IndicatorMCL) +@inline function antidiffusive_stage!(u_ode, u_old_ode, t, dt, semi, indicator::IndicatorMCL) return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 75a604ec62..9fe1fcbe63 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -205,27 +205,26 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation end function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, - mesh, equations, dg::DGSEM, - dt, cache; + semi, dg::DGSEM, t, dt; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator alpha .= 0.0 if indicator_IDP.indicator_smooth - elements = cache.element_ids_dgfv + elements = semi.cache.element_ids_dgfv else - elements = eachelement(dg, cache) + elements = eachelement(dg, semi.cache) end indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, t, dt, semi, elements) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, semi, elements) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache, elements) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, t, dt, semi, elements) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, dt, mesh, equations, dg, cache, elements) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, t, dt, semi, elements) # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -245,8 +244,9 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab return nothing end -@inline function calc_bounds_2sided!(var_min, var_max, variable, u, mesh, equations, dg, cache) - # Values inside each element +@inline function calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements @threaded for element in eachelement(dg, cache) var_min[:, :, element] .= typemax(eltype(var_min)) var_max[:, :, element] .= typemin(eltype(var_max)) @@ -276,10 +276,13 @@ end end # Values at element boundary - calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh, equations, dg, cache) + calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh) end -@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, mesh::TreeMesh2D, equations, dg, cache) +@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] @@ -287,28 +290,91 @@ end orientation = cache.interfaces.orientations[interface] - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) + if orientation == 1 + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) + var_right = variable(get_node_vars(u, equations, dg, 1, j, right), equations) + + var_min[1, j, right] = min(var_min[1, j, right], var_left) + var_max[1, j, right] = max(var_max[1, j, right], var_left) + + var_min[nnodes(dg), j, left] = min(var_min[nnodes(dg), j, left], var_right) + var_max[nnodes(dg), j, left] = max(var_max[nnodes(dg), j, left], var_right) end - var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) - var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) + else # orientation == 2 + for i in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), left), equations) + var_right = variable(get_node_vars(u, equations, dg, i, 1, right), equations) - var_min[index_right...] = min(var_min[index_right...], var_left) - var_max[index_right...] = max(var_max[index_right...], var_left) + var_min[i, 1, right] = min(var_min[i, 1, right], var_left) + var_max[i, 1, right] = max(var_max[i, 1, right], var_left) + + var_min[i, nnodes(dg), left] = min(var_min[i, nnodes(dg), left], var_right) + var_max[i, nnodes(dg), left] = max(var_max[i, nnodes(dg), left], var_right) + end + end + end - var_min[index_left...] = min(var_min[index_left...], var_right) - var_max[index_left...] = max(var_max[index_left...], var_right) + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # boundary_side == 1 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer) + + var_min[1, j, element] = min(var_min[1, j, element], var_outer) + var_max[1, j, element] = max(var_max[1, j, element], var_outer) + end + else # boundary_side == 2 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer) + + var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) + var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) + end + end + else # orientation == 2 + if neighbor_side == 2 # boundary_side == 1 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer) + + var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) + var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) + end + else # boundary_side == 2 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer) + + var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) + var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) + end + end end end + + return nothing end -@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, mesh, equations, dg, cache) - # Values inside each element + +@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, t, semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements @threaded for element in eachelement(dg, cache) var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) @@ -333,10 +399,13 @@ end end # Values at element boundary - calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh, equations, dg, cache) + calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) end -@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, mesh::TreeMesh2D, equations, dg, cache) +@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get neighboring element ids left = cache.interfaces.neighbor_ids[1, interface] @@ -344,24 +413,83 @@ end orientation = cache.interfaces.orientations[interface] - for i in eachnode(dg) - if orientation == 1 - index_left = (nnodes(dg), i, left) - index_right = (1, i, right) - else - index_left = (i, nnodes(dg), left) - index_right = (i, 1, right) + if orientation == 1 + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) + var_right = variable(get_node_vars(u, equations, dg, 1, j, right), equations) + + var_minmax[1, j, right] = minmax(var_minmax[1, j, right], var_left) + var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, left], var_right) + end + else # orientation == 2 + for i in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), left), equations) + var_right = variable(get_node_vars(u, equations, dg, i, 1, right), equations) + + var_minmax[i, 1, right] = minmax(var_minmax[i, 1, right], var_left) + var_minmax[i, nnodes(dg), left] = minmax(var_minmax[i, nnodes(dg), left], var_right) end - var_left = variable(get_node_vars(u, equations, dg, index_left...), equations) - var_right = variable(get_node_vars(u, equations, dg, index_right...), equations) + end + end - var_minmax[index_right...] = minmax(var_minmax[index_right...], var_left) - var_minmax[index_left...] = minmax(var_minmax[index_left...], var_right) + if boundary_conditions isa BoundaryConditionPeriodic + return nothing + end + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # boundary_side == 1 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) + end + else # boundary_side == 2 + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer) + + var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) + end + end + else # orientation == 2 + if neighbor_side == 2 # boundary_side == 1 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) + end + else # boundary_side == 2 + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer) + + var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) + end + end end end + + return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) +@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) + mesh, _, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator rho_min = var_bounds[1] @@ -423,9 +551,11 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator offset = 2 * indicator_IDP.IDPDensityTVD @@ -497,7 +627,9 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache, elements) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, t, dt, semi, elements) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -522,7 +654,9 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, dt, mesh, equations, dg, cache, elements) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, t, dt, semi, elements) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -548,7 +682,8 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, mesh, equations, dg, cache, elements) +@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, semi, elements) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @unpack positCorrFactor = indicator_IDP diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 7bd269eaf1..ba2e95d1b5 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -151,7 +151,8 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, alg.b[stage] * integrator.dt, integrator.p, indicator) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, + integrator.t, alg.b[stage] * integrator.dt, integrator.p, indicator) @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) From e589c515e24cefc627841e2cd5cad0e9eccc58ab Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 28 Nov 2022 12:30:23 +0100 Subject: [PATCH 095/423] Fix variable calculation for IDP; Fix lambdas and bar states at boundaries for MCL --- src/solvers/dgsem_structured/dg_2d.jl | 292 +++++++++++++----- src/solvers/dgsem_structured/indicators_2d.jl | 131 ++++++-- src/solvers/dgsem_tree/indicators_2d.jl | 16 +- 3 files changed, 335 insertions(+), 104 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 49ae869ce2..d5330e05f3 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -419,9 +419,55 @@ end @inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements - for element in eachelement(dg, cache) + # Calc lambdas and bar states inside elements + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg) + normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + for i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + + for m in 1:nnodes(dg) + normal_direction += weights[i-1] * derivative_matrix[i-1, m] * get_contravariant_vector(1, contravariant_vectors, m, j, element) + end + + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) + flux1 = flux(u_node, normal_direction, equations) + flux1_im1 = flux(u_node_im1, normal_direction, equations) + + for v in eachvariable(equations) + bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] + end + end + end + + for i in eachnode(dg) + normal_direction = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + for j in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + + for m in 1:nnodes(dg) + normal_direction += weights[j-1] * derivative_matrix[j-1, m] * get_contravariant_vector(2, contravariant_vectors, i, m, element) + end + + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) + flux2 = flux(u_node, normal_direction, equations) + flux2_jm1 = flux(u_node_jm1, normal_direction, equations) + + for v in eachvariable(equations) + bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] + end + end + end + end + + # Calc lambdas and bar states at interfaces and periodic boundaries + # TODO: Speed this for loop up with mesh.periodicity? + @threaded for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] lower = cache.elements.left_neighbors[2, element] @@ -429,56 +475,118 @@ end if left != 0 for i in eachnode(dg) u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) - u_element = get_node_vars(u, equations, dg, 1, i, element) - - # Ja1_left = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), i, left) - Ja1_element = get_contravariant_vector(1, contravariant_vectors, 1, i, element) - # Ja1_avg = 0.5 * (Ja1_left + Ja1_element) - - flux_left = flux(u_left, Ja1_element, equations) - flux_element = flux(u_element, Ja1_element, equations) - lambda = lambda1[1, i, element] - - bar_state_rho = 0.5 * (u_element[1] + u_left[1]) - 0.5 * (flux_element[1] - flux_left[1]) / lambda - var_min[1, nnodes(dg), i, left] = min(var_min[1, nnodes(dg), i, left], bar_state_rho) - var_max[1, nnodes(dg), i, left] = max(var_max[1, nnodes(dg), i, left], bar_state_rho) - var_min[1, 1, i, element] = min(var_min[1, 1, i, element], bar_state_rho) - var_max[1, 1, i, element] = max(var_max[1, 1, i, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = 0.5 * (u_element[v] + u_left[v]) - 0.5 * (flux_element[v] - flux_left[v]) / lambda - bar_state_phi = bar_state_phi / bar_state_rho - var_min[v, nnodes(dg), i, left] = min(var_min[v, nnodes(dg), i, left], bar_state_phi) - var_max[v, nnodes(dg), i, left] = max(var_max[v, nnodes(dg), i, left], bar_state_phi) - var_min[v, 1, i, element] = min(var_min[v, 1, i, element], bar_state_phi) - var_max[v, 1, i, element] = max(var_max[v, 1, i, element], bar_state_phi) + u_element = get_node_vars(u, equations, dg, 1, i, element) + + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, i, element) + lambda = max_abs_speed_naive(u_left, u_element, Ja1, equations) + + lambda1[nnodes(dg)+1, i, left] = lambda + lambda1[1, i, element] = lambda + flux_left = flux(u_left, Ja1, equations) + flux_element = flux(u_element, Ja1, equations) + + bar_state = 0.5 * (u_element + u_left) - 0.5 * (flux_element - flux_left) / lambda + for v in eachvariable(equations) + bar_states1[v, nnodes(dg)+1, i, left] = bar_state[v] + bar_states1[v, 1, i, element] = bar_state[v] end end end if lower != 0 for i in eachnode(dg) - u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) + u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) u_element = get_node_vars(u, equations, dg, i, 1, element) - # Ja2_lower = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), lower) - Ja2_element = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - # Ja2_avg = 0.5 * (Ja2_lower + Ja2_element) - - flux_lower = flux(u_lower, Ja2_element, equations) - flux_element = flux(u_element, Ja2_element, equations) - lambda = lambda1[i, 1, element] - - bar_state_rho = 0.5 * (u_element[1] + u_lower[1]) - 0.5 * (flux_element[1] - flux_lower[1]) / lambda - var_min[1, i, nnodes(dg), lower] = min(var_min[1, i, nnodes(dg), lower], bar_state_rho) - var_max[1, i, nnodes(dg), lower] = max(var_max[1, i, nnodes(dg), lower], bar_state_rho) - var_min[1, i, 1, element] = min(var_min[1, i, 1, element], bar_state_rho) - var_max[1, i, 1, element] = max(var_max[1, i, 1, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = 0.5 * (u_element[v] + u_lower[v]) - 0.5 * (flux_element[v] - flux_lower[v]) / lambda - bar_state_phi = bar_state_phi / bar_state_rho - var_min[v, i, nnodes(dg), lower] = min(var_min[v, i, nnodes(dg), lower], bar_state_phi) - var_max[v, i, nnodes(dg), lower] = max(var_max[v, i, nnodes(dg), lower], bar_state_phi) - var_min[v, i, 1, element] = min(var_min[v, i, 1, element], bar_state_phi) - var_max[v, i, 1, element] = max(var_max[v, i, 1, element], bar_state_phi) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + lambda = max_abs_speed_naive(u_lower, u_element, Ja2, equations) + + lambda2[i, nnodes(dg)+1, lower] = lambda + lambda2[i, 1, element] = lambda + flux_lower = flux(u_lower, Ja2, equations) + flux_element = flux(u_element, Ja2, equations) + + bar_state = 0.5 * (u_element + u_lower) - 0.5 * (flux_element - flux_lower) / lambda + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg)+1, lower] = bar_state[v] + bar_states2[v, i, 1, element] = bar_state[v] + end + end + end + end + + # Calc lambdas and bar states at physical boundaries + # TODO: Speed this for loop up with mesh.periodicity? + if boundary_conditions isa BoundaryConditionPeriodic + return nothing + end + linear_indices = LinearIndices(size(mesh)) + # x-direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + element_opp = linear_indices[end, cell_y] + left = cache.elements.left_neighbors[1, element] + if left == 0 # element is at boundary + for j in eachnode(dg) + # left side of the domain + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + + flux_inner = flux(u_inner, Ja1, equations) + flux_outer = flux(u_outer, Ja1, equations) + for v in eachvariable(equations) + bar_states1[v, 1, j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda1[1, j, element] + end + + # right side of the domain + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element_opp) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element_opp) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element_opp) + lambda1[nnodes(dg)+1, j, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + + flux_inner = flux(u_inner, Ja1, equations) + flux_outer = flux(u_outer, Ja1, equations) + for v in eachvariable(equations) + # TODO: Or change the order of the fluxes? Right - Left + bar_states1[v, nnodes(dg), j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda1[nnodes(dg)+1, j, element_opp] + end + end + end + end + # y-direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + element_opp = linear_indices[cell_x, end] + lower = cache.elements.left_neighbors[2, element] + if lower == 0 # element is at boundary + for i in eachnode(dg) + # bottom side of the domain + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + + flux_inner = flux(u_inner, Ja2, equations) + flux_outer = flux(u_outer, Ja2, equations) + for v in eachvariable(equations) + bar_states2[v, i, 1, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda2[i, 1, element] + end + + # top side of the domain + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element_opp) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element_opp) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element_opp) + lambda2[i, nnodes(dg)+1, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + + flux_inner = flux(u_inner, Ja2, equations) + flux_outer = flux(u_outer, Ja2, equations) + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg), element] = 0.5 * (u_outer[v] + u_inner[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda2[i, nnodes(dg)+1, element_opp] end end end @@ -490,31 +598,42 @@ end @inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::StructuredMesh, equations, dg, cache, indicator::IndicatorMCL, boundary_conditions) @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements + # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + for j in eachnode(dg) + normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + for i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, element) - Ja1_node_im1 = get_contravariant_vector(1, contravariant_vectors, i-1, j, element) - Ja1_avg = 0.5 * (Ja1_node + Ja1_node_im1) + for m in 1:nnodes(dg) + normal_direction += weights[i-1] * derivative_matrix[i-1, m] * get_contravariant_vector(1, contravariant_vectors, m, j, element) + end - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, Ja1_avg, equations) + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) + end end - for j in 2:nnodes(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, element) - Ja2_node_jm1 = get_contravariant_vector(2, contravariant_vectors, i, j-1, element) - Ja2_avg = 0.5 * (Ja2_node + Ja2_node_jm1) + for i in eachnode(dg) + normal_direction = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + for j in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + + for m in 1:nnodes(dg) + normal_direction += weights[j-1] * derivative_matrix[j-1, m] * get_contravariant_vector(2, contravariant_vectors, i, m, element) + end - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, Ja2_avg, equations) + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) + end end end + # Calc lambdas at interfaces and periodic boundaries + # TODO: Speed this for loop up with mesh.periodicity? @threaded for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] @@ -525,10 +644,8 @@ end u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) u_element = get_node_vars(u, equations, dg, 1, i, element) - # Ja1_left = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), i, left) - Ja1_element = get_contravariant_vector(1, contravariant_vectors, 1, i, element) - # Ja1_avg = 0.5 * (Ja1_left + Ja1_element) - lambda = max_abs_speed_naive(u_left, u_element, Ja1_element, equations) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, i, element) + lambda = max_abs_speed_naive(u_left, u_element, Ja1, equations) lambda1[nnodes(dg)+1, i, left] = lambda lambda1[1, i, element] = lambda @@ -539,10 +656,8 @@ end u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) u_element = get_node_vars(u, equations, dg, i, 1, element) - # Ja2_lower = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), lower) - Ja2_element = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - # Ja2_avg = 0.5 * (Ja2_lower + Ja2_element) - lambda = max_abs_speed_naive(u_lower, u_element, Ja2_element, equations) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + lambda = max_abs_speed_naive(u_lower, u_element, Ja2, equations) lambda2[i, nnodes(dg)+1, lower] = lambda lambda2[i, 1, element] = lambda @@ -550,23 +665,56 @@ end end end + # Calc lambdas at physical boundaries + # TODO: Speed this for loop up with mesh.periodicity? + if boundary_conditions isa BoundaryConditionPeriodic + return nothing + end linear_indices = LinearIndices(size(mesh)) # x-direction for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] + element = linear_indices[begin, cell_y] + element_opp = linear_indices[end, cell_y] left = cache.elements.left_neighbors[1, element] if left == 0 # element is at boundary - lambda1[1, :, element] .= zero(eltype(lambda1)) - lambda1[nnodes(dg)+1, :, linear_indices[end, cell_y]] .= zero(eltype(lambda1)) + for j in eachnode(dg) + # left side of the domain + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + + # right side of the domain + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element_opp) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element_opp) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element_opp) + lambda1[nnodes(dg)+1, j, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + end end end # y-direction for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] + element = linear_indices[cell_x, begin] + element_opp = linear_indices[cell_x, end] lower = cache.elements.left_neighbors[2, element] if lower == 0 # element is at boundary - lambda2[:, 1, element] .= zero(eltype(lambda2)) - lambda2[:, nnodes(dg)+1, linear_indices[cell_x, end]] .= zero(eltype(lambda2)) + for i in eachnode(dg) + # bottom side of the domain + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + + # top side of the domain + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element_opp) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element_opp) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element_opp) + lambda2[i, nnodes(dg)+1, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + end end end diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index de565a5859..488c0a9cb3 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -63,33 +63,62 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m end end - return nothing -end - -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh) - _, _, solver, cache = mesh_equations_solver_cache(semi) - @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - - if indicator.indicator_smooth - elements = cache.element_ids_dgfv - else - elements = eachelement(solver, cache) + # Calc bounds at physical boundaries + if boundary_conditions isa BoundaryConditionPeriodic + return nothing end - - alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) - alpha_avg = zero(eltype(alpha)) - total_volume = zero(eltype(alpha)) - for element in elements - for j in eachnode(solver), i in eachnode(solver) - jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) - alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] - total_volume += jacobian * weights[i] * weights[j] + linear_indices = LinearIndices(size(mesh)) + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer) + + var_min[1, j, element] = min(var_min[1, j, element], var_outer) + var_max[1, j, element] = max(var_max[1, j, element], var_outer) end end - if total_volume > 0 - alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer) + + var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) + var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) + end + end + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer) + + var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) + var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) + end + end + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer) + + var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) + var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) + end end return nothing @@ -124,6 +153,60 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end end + # Calc bounds at physical boundaries + if boundary_conditions isa BoundaryConditionPeriodic + return nothing + end + linear_indices = LinearIndices(size(mesh)) + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer) + + var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) + end + end + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) + end + end + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer) + + var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) + end + end + return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 9fe1fcbe63..43306e59f8 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -327,7 +327,7 @@ end u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[1, j, element] = min(var_min[1, j, element], var_outer) var_max[1, j, element] = max(var_max[1, j, element], var_outer) @@ -337,7 +337,7 @@ end u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) @@ -349,7 +349,7 @@ end u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) @@ -359,7 +359,7 @@ end u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) @@ -447,7 +447,7 @@ end u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) end @@ -456,7 +456,7 @@ end u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) end @@ -467,7 +467,7 @@ end u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) end @@ -476,7 +476,7 @@ end u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) end From a010a539847fad9b7f158ecf386b8e8ec91d6820 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 29 Nov 2022 17:56:24 +0100 Subject: [PATCH 096/423] Adapt IDP elixirs --- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 13 +++++-- .../elixir_euler_astro_jet_subcell.jl | 16 +++----- .../elixir_euler_astro_jet_subcell_restart.jl | 37 ------------------- .../elixir_euler_blob_sc_subcell.jl | 6 ++- ...kelvin_helmholtz_instability_sc_subcell.jl | 11 +++--- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 1 - src/solvers/dgsem_tree/containers_2d.jl | 1 - 8 files changed, 26 insertions(+), 61 deletions(-) delete mode 100644 examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 6ea41c0618..2bbcbcd759 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -52,7 +52,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 20000.0) +tspan = (0.0, 2.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 398fbc345c..1e9c8f9bac 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -8,6 +8,7 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test +source_terms = source_terms_convergence_test # Get the DG approximation space surface_flux = flux_lax_friedrichs @@ -24,14 +25,18 @@ volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (0.0, 0.0) -coordinates_max = (2.0, 2.0) +# Waving flag +f1(s) = SVector(-1.0, s - 1.0) +f2(s) = SVector( 1.0, s + 1.0) +f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +mapping = Trixi.transfinite_mapping((f1, f2, f3, f4)) cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms=source_terms) ############################################################################### # ODE solvers, callbacks etc. diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 940ab9ec20..cf49e4c43a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -20,7 +20,7 @@ function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations p = 0.4127 # add inflow for t>0 at x=-0.5 # domain size is [-0.5,+0.5]^2 - if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) rho = 5 v1 = 800 # about Mach number Ma = 2000 v2 = 0 @@ -50,7 +50,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=true, IDPCheckBounds=true, IDPMaxIter=25, - indicator_smooth=true) + indicator_smooth=true, thr_smooth=0.05) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -67,7 +67,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 2.5e-6) # simulation with end time T=0.001 in the restart file +tspan = (0.0, 0.001) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -77,20 +77,16 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -# The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted -save_restart = SaveRestartCallback(interval=5000, - save_final_restart=true) - save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, - save_final_solution=false, + save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.004) +stepsize_callback = StepsizeCallback(cfl=0.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_restart, save_solution, + save_solution, stepsize_callback) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl deleted file mode 100644 index 4bf6fa2258..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell_restart.jl +++ /dev/null @@ -1,37 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# create a restart file - -trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_astro_jet_subcell.jl")) - -############################################################################### -# adapt the parameters that have changed compared to "elixir_euler_astro_jet_subcell.jl" - -restart_filename = joinpath("out", "restart_000271.h5") -mesh = load_mesh(restart_filename) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - -tspan = (load_time(restart_filename), 0.001) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=false, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.1) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) -############################################################################### -# run the simulation -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl index 5d10a56b99..033dafef72 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl @@ -56,7 +56,9 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true) + IDPPositivity=true, + indicator_smooth=false, + IDPMaxIter=25) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -84,7 +86,7 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=100, +save_solution = SaveSolutionCallback(interval=500, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index d5d1543c43..2cdbcf94a2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,7 +37,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true) + IDPPositivity=true, + indicator_smooth=false) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -52,22 +53,22 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 3.0) +tspan = (0.0, 3.7) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 500 +analysis_interval = 1000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=50, +save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl=0.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 408e259738..db1ecfa550 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -45,7 +45,6 @@ indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, IDPPressureTVD=true, IDPPositivity=true, - IDPCheckBounds=true, indicator_smooth=true, IDPMaxIter=15) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index e3fc975f5b..f135513f08 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1441,7 +1441,6 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) @unpack _var_min, _var_max = container resize!(_var_min, n_variables * n_nodes * n_nodes * capacity) container.var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) - @unpack _var_max, _var_max = container resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) From 86eca48f69880d41cf48c0e52a75fe985418b85c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 29 Nov 2022 17:58:30 +0100 Subject: [PATCH 097/423] Add smoothness indicator threshold to parameter --- src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/indicators.jl | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 247f20c007..a3d06feb1d 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -28,7 +28,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) if dg.volume_integral isa VolumeIntegralShockCapturingSubcell - tol = 0.1 + tol = dg.volume_integral.indicator.thr_smooth else tol = 1e-12 end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b49e6574b4..5791df8301 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -182,6 +182,7 @@ struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator end @@ -196,6 +197,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), IDPCheckBounds=false, indicator_smooth=true, + thr_smooth=0.1, variable_smooth=density_pressure) if IDPMathEntropy && IDPSpecEntropy @@ -215,7 +217,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; end IndicatorIDP{typeof(positCorrFactor), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy, cache, positCorrFactor, IDPMaxIter, - newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, IndicatorHG) + newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -235,6 +237,8 @@ function Base.show(io::IO, indicator::IndicatorIDP) IDPMathEntropy && print(io, "IDPMathEntropy, ") print(io, "), ") end + indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, + " with threshold ", indicator.thr_smooth, "), ") print(io, ")") end @@ -252,11 +256,12 @@ IndicatorMCL !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorMCL{Cache, Indicator} <: AbstractIndicator +struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator cache::Cache IDPPressureTVD::Bool # synchronized pressure limiting IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end @@ -266,6 +271,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; IDPPressureTVD=false, IDPCheckBounds=false, indicator_smooth=false, + thr_smooth=0.1, variable_smooth=density_pressure, Plotting=false) @@ -276,7 +282,8 @@ function IndicatorMCL(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorMCL{typeof(cache), typeof(IndicatorHG)}(cache, IDPPressureTVD, IDPCheckBounds, indicator_smooth, IndicatorHG, Plotting) + IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, IDPPressureTVD, IDPCheckBounds, + indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @@ -285,7 +292,8 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, "IndicatorMCL(") print(io, "density, velocity, total energy") indicator.IDPPressureTVD && print(io, ", pressure") - indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG) + indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, + " with threshold ", indicator.thr_smooth) print(io, ")") end From 6d6abe70871cd82b500682a4e0e62751f10378e7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 29 Nov 2022 18:00:25 +0100 Subject: [PATCH 098/423] Speed up MCL by saving subcell normal directions --- src/solvers/dgsem_structured/dg_2d.jl | 20 +++++------ src/solvers/dgsem_tree/containers_2d.jl | 24 +++++++++++++- src/time_integration/methods_SSP.jl | 44 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index d5330e05f3..eb9506397b 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -422,6 +422,8 @@ end @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements + @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerShockCapturingIndicator + # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) for j in eachnode(dg) @@ -430,9 +432,7 @@ end u_node = get_node_vars(u, equations, dg, i, j, element) u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - for m in 1:nnodes(dg) - normal_direction += weights[i-1] * derivative_matrix[i-1, m] * get_contravariant_vector(1, contravariant_vectors, m, j, element) - end + normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) flux1 = flux(u_node, normal_direction, equations) @@ -450,9 +450,7 @@ end u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - for m in 1:nnodes(dg) - normal_direction += weights[j-1] * derivative_matrix[j-1, m] * get_contravariant_vector(2, contravariant_vectors, i, m, element) - end + normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) flux2 = flux(u_node, normal_direction, equations) @@ -601,6 +599,8 @@ end @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements + @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerShockCapturingIndicator + # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) for j in eachnode(dg) @@ -609,9 +609,7 @@ end u_node = get_node_vars(u, equations, dg, i, j, element) u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - for m in 1:nnodes(dg) - normal_direction += weights[i-1] * derivative_matrix[i-1, m] * get_contravariant_vector(1, contravariant_vectors, m, j, element) - end + normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) end @@ -623,9 +621,7 @@ end u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - for m in 1:nnodes(dg) - normal_direction += weights[j-1] * derivative_matrix[j-1, m] * get_contravariant_vector(2, contravariant_vectors, i, m, element) - end + normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index f135513f08..4340959361 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1377,6 +1377,8 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} alpha_pressure::Array{uEltype, 3} # [i, j, element] lambda1::Array{uEltype, 3} # [i, j, element] lambda2::Array{uEltype, 3} # [i, j, element] + normal_direction_xi::Array{uEltype, 4} # [index, i, j, elements] + normal_direction_eta::Array{uEltype, 4} # [index, i, j, elements] # internal `resize!`able storage _bar_states1::Vector{uEltype} _bar_states2::Vector{uEltype} @@ -1386,6 +1388,8 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} _alpha_pressure::Vector{uEltype} _lambda1::Vector{uEltype} _lambda2::Vector{uEltype} + _normal_direction_xi::Vector{uEltype} + _normal_direction_eta::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real @@ -1414,10 +1418,20 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) + _normal_direction_xi = fill(nan_uEltype, (n_variables - 2) * (n_nodes - 1) * n_nodes * capacity) + normal_direction_xi = unsafe_wrap(Array, pointer(_normal_direction_xi), + (n_variables - 2, n_nodes - 1, n_nodes, capacity)) + + _normal_direction_eta = fill(nan_uEltype, (n_variables - 2) * n_nodes * (n_nodes - 1) * capacity) + normal_direction_eta = unsafe_wrap(Array, pointer(_normal_direction_eta), + (n_variables - 2, n_nodes, n_nodes - 1, capacity)) + return ContainerShockCapturingIndicatorMCL{uEltype}(bar_states1, bar_states2, var_min, var_max, volume_flux_difference, alpha_pressure, lambda1, lambda2, + normal_direction_xi, normal_direction_eta, _bar_states1, _bar_states2, _var_min, _var_max, - _volume_flux_difference, _alpha_pressure, _lambda1, _lambda2) + _volume_flux_difference, _alpha_pressure, _lambda1, _lambda2, + _normal_direction_xi, _normal_direction_eta) end nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) @@ -1458,6 +1472,14 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_lambda2, n_nodes * (n_nodes+1) * capacity) container.lambda2 = unsafe_wrap(Array, pointer(_lambda2), (n_nodes, n_nodes+1, capacity)) + @unpack _normal_direction_xi, _normal_direction_eta = container + resize!(_normal_direction_xi, (n_variables - 2) * (n_nodes - 1) * n_nodes * capacity) + container.normal_direction_xi = unsafe_wrap(Array, pointer(_normal_direction_xi), + (n_variables-2, n_nodes-1, n_nodes, capacity)) + resize!(_normal_direction_eta, (n_variables - 2) * n_nodes * (n_nodes - 1) * capacity) + container.normal_direction_eta = unsafe_wrap(Array, pointer(_normal_direction_eta), + (n_variables-2, n_nodes, n_nodes-1, capacity)) + return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index ba2e95d1b5..1bf76123dd 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -108,6 +108,12 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, # Resize container resize!(integrator.p, nelements(integrator.p.solver, integrator.p.cache)) + # Calc subcell normal directions before StepsizeCallback + @unpack indicator = integrator.p.solver.volume_integral + if indicator isa IndicatorMCL + calc_normal_directions!(indicator.cache.ContainerShockCapturingIndicator, mesh_equations_solver_cache(integrator.p)...) + end + # initialize callbacks if callback isa CallbackSet for cb in callback.continuous_callbacks @@ -258,6 +264,44 @@ function Base.resize!(semi::AbstractSemidiscretization, new_size) resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) end +function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::TreeMesh, dg, cache) + + return nothing +end + +function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::StructuredMesh, equations, dg, cache) + @unpack weights, derivative_matrix = dg.basis + @unpack contravariant_vectors = cache.elements + + @unpack normal_direction_xi, normal_direction_eta = ContainerShockCapturingIndicator + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg) + normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + for i in 2:nnodes(dg) + for m in 1:nnodes(dg) + normal_direction += weights[i-1] * derivative_matrix[i-1, m] * get_contravariant_vector(1, contravariant_vectors, m, j, element) + end + for v in 1:nvariables(equations)-2 + normal_direction_xi[v, i-1, j, element] = normal_direction[v] + end + end + end + for i in eachnode(dg) + normal_direction = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + for j in 2:nnodes(dg) + for m in 1:nnodes(dg) + normal_direction += weights[j-1] * derivative_matrix[j-1, m] * get_contravariant_vector(2, contravariant_vectors, i, m, element) + end + for v in 1:nvariables(equations)-2 + normal_direction_eta[v, i, j-1, element] = normal_direction[v] + end + end + end + end + + return nothing +end + # check deviation from boundaries of IDP indicator @inline function summary_check_bounds(indicator::IndicatorIDP, equations::CompressibleEulerEquations2D) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator From eaefe303ffa6ef52a56b8a95b47b903d1e3580be Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 29 Nov 2022 18:05:10 +0100 Subject: [PATCH 099/423] Calculate normal directions after resized (when amr) --- src/time_integration/methods_SSP.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 1bf76123dd..82b1a48e97 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -262,6 +262,11 @@ function Base.resize!(semi::AbstractSemidiscretization, new_size) # Resize ContainerShockCapturingIndicator resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) + # Calc subcell normal directions before StepsizeCallback + @unpack indicator = semi.solver.volume_integral + if indicator isa IndicatorMCL + calc_normal_directions!(indicator.cache.ContainerShockCapturingIndicator, mesh_equations_solver_cache(semi)...) + end end function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::TreeMesh, dg, cache) From 2cbf157dd0c5ad38a89e6bc11e13a049cbaa50db Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 30 Nov 2022 12:59:47 +0100 Subject: [PATCH 100/423] Fix normal directions changes for TreeMesh --- src/time_integration/methods_SSP.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 82b1a48e97..dbc6457740 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -269,7 +269,7 @@ function Base.resize!(semi::AbstractSemidiscretization, new_size) end end -function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::TreeMesh, dg, cache) +function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::TreeMesh, equations, dg, cache) return nothing end From ae148f6137d2507c855462247522b36d365579f0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 2 Dec 2022 15:59:13 +0100 Subject: [PATCH 101/423] Adapt MCL elixirs; Adapt limited MCL fluxes --- .../elixir_euler_astro_jet_MCL.jl | 10 +-- ..._euler_kelvin_helmholtz_instability_MCL.jl | 5 +- src/solvers/dgsem_tree/dg_2d.jl | 86 ++++++++++--------- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index f72673332f..d35262e114 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -55,7 +55,7 @@ coordinates_min = (-0.5, -0.5) coordinates_max = ( 0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=8, + initial_refinement_level=6, periodicity=(false,true), n_cells_max=100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) @@ -73,20 +73,16 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -# The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted -save_restart = SaveRestartCallback(interval=5000, - save_final_restart=true) - save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, - save_final_solution=false, + save_final_solution=true, solution_variables=cons2prim) stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_restart, save_solution, + save_solution, stepsize_callback) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 3c225acaed..e6130cd0c3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -65,7 +65,7 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=50, +save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) @@ -75,8 +75,7 @@ stepsize_callback = StepsizeCallback(cfl=1.0) callbacks = CallbackSet(summary_callback, stepsize_callback, analysis_callback, alive_callback, - save_solution, - ) + save_solution) ############################################################################### diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 6d28497801..7ce5d55c17 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1005,20 +1005,24 @@ end lambda = lambda1[i, j, element] bar_state_rho = lambda * bar_states1[1, i, j, element] # Limit density - # if antidiffusive_flux1[1, i, j, element] > 0 - # antidiffusive_flux1[1, i, j, element] = min(antidiffusive_flux1[1, i, j, element], - # min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element])) - # else - # antidiffusive_flux1[1, i, j, element] = max(antidiffusive_flux1[1, i, j, element], - # max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i-1, j, element])) - # end + if antidiffusive_flux1[1, i, j, element] > 0 + f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i-1, j, element]) + flux_limited = min(antidiffusive_flux1[1, i, j, element], f_max) + else + f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i-1, j, element]) + flux_limited = max(antidiffusive_flux1[1, i, j, element], f_min) + end # alternative density limiting - f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i-1, j, element]) - f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i-1, j, element]) - antidiffusive_flux1[1, i, j, element] = max(f_min, min(antidiffusive_flux1[1, i, j, element], f_max)) + # f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_max[1, i-1, j, element]) + # f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_min[1, i-1, j, element]) + # flux_limited = max(f_min, min(antidiffusive_flux1[1, i, j, element], f_max)) + + antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy for v in 2:nvariables(equations) @@ -1035,14 +1039,13 @@ end rho_limited_im1 * (phi - var_max[v, i-1, j, element])) g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), rho_limited_im1 * (phi - var_min[v, i-1, j, element])) - # if isapprox(g_min, 0.0, atol=eps()) - # g_min = 0.0 - # end - # if isapprox(g_max, 0.0, atol=eps()) - # g_max = 0.0 - # end - - antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + max(g_min, min(g, g_max)) + if g > 0 + g_limited = min(g_max, max(g, g_min)) + else + g_limited = max(g_min, min(g, g_max)) + end + + antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + g_limited end end @@ -1050,20 +1053,24 @@ end lambda = lambda2[i, j, element] bar_state_rho = lambda * bar_states2[1, i, j, element] # Limit density - # if antidiffusive_flux2[1, i, j, element] > 0 - # antidiffusive_flux2[1, i, j, element] = min(antidiffusive_flux2[1, i, j, element], - # min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element])) - # else - # antidiffusive_flux2[1, i, j, element] = max(antidiffusive_flux2[1, i, j, element], - # max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i, j-1, element])) - # end + if antidiffusive_flux2[1, i, j, element] > 0 + f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i, j-1, element]) + flux_limited = min(antidiffusive_flux2[1, i, j, element], f_max) + else + f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i, j-1, element]) + flux_limited = max(antidiffusive_flux2[1, i, j, element], f_min) + end # alternative density limiting - f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i, j-1, element]) - f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i, j-1, element]) - antidiffusive_flux2[1, i, j, element] = max(f_min, min(antidiffusive_flux2[1, i, j, element], f_max)) + # f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_max[1, i, j-1, element]) + # f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_min[1, i, j-1, element]) + # flux_limited = max(f_min, min(antidiffusive_flux2[1, i, j, element], f_max)) + + antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy for v in 2:nvariables(equations) @@ -1080,14 +1087,13 @@ end rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) - # if isapprox(g_min, 0.0, atol=eps()) - # g_min = 0.0 - # end - # if isapprox(g_max, 0.0, atol=eps()) - # g_max = 0.0 - # end - - antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + max(g_min, min(g, g_max)) + if g > 0 + g_limited = min(g_max, max(g, g_min)) + else + g_limited = max(g_min, min(g, g_max)) + end + + antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + g_limited end end From 8de9fb7534bedc85c56cd27a3b88429e2f42b033 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 5 Dec 2022 13:45:29 +0100 Subject: [PATCH 102/423] Adapt flux limiting for MCL --- src/solvers/dgsem_tree/dg_2d.jl | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 7ce5d55c17..c02100c9b0 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1001,6 +1001,12 @@ end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack var_min, var_max, lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. + # To avoid further calculations with these values, we replace them by 0. + # It can also happen that the limited flux changes its sign (for instance to -1e-13). + # This does not really make sense in the theory and causes problems for the visualization. + # Therefore we make sure that the flux keeps its sign during limiting. + for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = lambda * bar_states1[1, i, j, element] @@ -1008,11 +1014,13 @@ end if antidiffusive_flux1[1, i, j, element] > 0 f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i-1, j, element]) - flux_limited = min(antidiffusive_flux1[1, i, j, element], f_max) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = max(0.0, min(antidiffusive_flux1[1, i, j, element], f_max)) else f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i-1, j, element]) - flux_limited = max(antidiffusive_flux1[1, i, j, element], f_min) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = min(0.0, max(antidiffusive_flux1[1, i, j, element], f_min)) end # alternative density limiting @@ -1039,10 +1047,12 @@ end rho_limited_im1 * (phi - var_max[v, i-1, j, element])) g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), rho_limited_im1 * (phi - var_min[v, i-1, j, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 - g_limited = min(g_max, max(g, g_min)) + g_limited = max(0.0, min(g_max, max(g, g_min))) else - g_limited = max(g_min, min(g, g_max)) + g_limited = min(0.0, max(g_min, min(g, g_max))) end antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + g_limited @@ -1056,11 +1066,13 @@ end if antidiffusive_flux2[1, i, j, element] > 0 f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_min[1, i, j-1, element]) - flux_limited = min(antidiffusive_flux2[1, i, j, element], f_max) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = max(0.0, min(antidiffusive_flux2[1, i, j, element], f_max)) else f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, bar_state_rho - lambda * var_max[1, i, j-1, element]) - flux_limited = max(antidiffusive_flux2[1, i, j, element], f_min) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = min(0.0, max(antidiffusive_flux2[1, i, j, element], f_min)) end # alternative density limiting @@ -1087,10 +1099,12 @@ end rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 - g_limited = min(g_max, max(g, g_min)) + g_limited = max(0.0, min(g_max, max(g, g_min))) else - g_limited = max(g_min, min(g, g_max)) + g_limited = min(0.0, max(g_min, min(g, g_max))) end antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + g_limited From 81d86dbced1e181a561fe72a9d6c7463465fc134 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 5 Dec 2022 14:22:11 +0100 Subject: [PATCH 103/423] Revise MCL Plotting of coefficients --- src/solvers/dgsem_tree/containers_2d.jl | 18 ++++----- src/solvers/dgsem_tree/dg_2d.jl | 51 +++++++++++++++++++------ src/solvers/dgsem_tree/indicators.jl | 4 +- src/time_integration/methods_SSP.jl | 11 ++++++ 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 4340959361..7373257224 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1373,7 +1373,7 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} bar_states2::Array{uEltype, 4} # [variable, i, j, element] var_min::Array{uEltype, 4} # [variable, i, j, element] var_max::Array{uEltype, 4} # [variable, i, j, element] - volume_flux_difference::Array{uEltype, 4} # [variable, i, j, element] + alpha::Array{uEltype, 4} # [variable, i, j, element] alpha_pressure::Array{uEltype, 3} # [i, j, element] lambda1::Array{uEltype, 3} # [i, j, element] lambda2::Array{uEltype, 3} # [i, j, element] @@ -1384,7 +1384,7 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} _bar_states2::Vector{uEltype} _var_min::Vector{uEltype} _var_max::Vector{uEltype} - _volume_flux_difference::Vector{uEltype} + _alpha::Vector{uEltype} _alpha_pressure::Vector{uEltype} _lambda1::Vector{uEltype} _lambda2::Vector{uEltype} @@ -1407,8 +1407,8 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _var_max = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) - _volume_flux_difference = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) - volume_flux_difference = unsafe_wrap(Array, pointer(_volume_flux_difference), (n_variables, n_nodes, n_nodes, capacity)) + _alpha = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) + alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables, n_nodes, n_nodes, capacity)) _alpha_pressure = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) @@ -1427,10 +1427,10 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia (n_variables - 2, n_nodes, n_nodes - 1, capacity)) return ContainerShockCapturingIndicatorMCL{uEltype}(bar_states1, bar_states2, var_min, var_max, - volume_flux_difference, alpha_pressure, lambda1, lambda2, + alpha, alpha_pressure, lambda1, lambda2, normal_direction_xi, normal_direction_eta, _bar_states1, _bar_states2, _var_min, _var_max, - _volume_flux_difference, _alpha_pressure, _lambda1, _lambda2, + _alpha, _alpha_pressure, _lambda1, _lambda2, _normal_direction_xi, _normal_direction_eta) end @@ -1458,9 +1458,9 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) - @unpack _volume_flux_difference = container - resize!(_volume_flux_difference, n_variables * n_nodes * n_nodes * capacity) - container.volume_flux_difference = unsafe_wrap(Array, pointer(_volume_flux_difference), (n_variables, n_nodes, n_nodes, capacity)) + @unpack _alpha = container + resize!(_alpha, n_variables * n_nodes * n_nodes * capacity) + container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables, n_nodes, n_nodes, capacity)) @unpack _alpha_pressure = container resize!(_alpha_pressure, n_nodes * n_nodes * capacity) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c02100c9b0..e941b618f2 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -662,17 +662,6 @@ end end end - if indicator.Plotting - @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator - for j in eachnode(dg), i in eachnode(dg) - for v in eachvariable(equations) - volume_flux_difference[v, i, j, element] = abs(du[v, i, j, element] - - (inverse_weights[i] * (fhat1[v, i+1, j] - fhat1[v, i, j]) + - inverse_weights[j] * (fhat2[v, i, j+1] - fhat2[v, i, j]))) - end - end - end - return nothing end @@ -1004,7 +993,7 @@ end # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. # To avoid further calculations with these values, we replace them by 0. # It can also happen that the limited flux changes its sign (for instance to -1e-13). - # This does not really make sense in the theory and causes problems for the visualization. + # This does not really make sense in theory and causes problems for the visualization. # Therefore we make sure that the flux keeps its sign during limiting. for j in eachnode(dg), i in 2:nnodes(dg) @@ -1030,6 +1019,16 @@ end # bar_state_rho - lambda * var_min[1, i-1, j, element]) # flux_limited = max(f_min, min(antidiffusive_flux1[1, i, j, element], f_max)) + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + end + alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy @@ -1054,6 +1053,15 @@ end else g_limited = min(0.0, max(g_min, min(g, g_max))) end + if indicator.Plotting + if isapprox(g, 0.0, atol=eps()) + coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + else + coefficient = g_limited / g + end + alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + g_limited end @@ -1082,6 +1090,16 @@ end # bar_state_rho - lambda * var_min[1, i, j-1, element]) # flux_limited = max(f_min, min(antidiffusive_flux2[1, i, j, element], f_max)) + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + end + alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy @@ -1106,6 +1124,15 @@ end else g_limited = min(0.0, max(g_min, min(g, g_max))) end + if indicator.Plotting + if isapprox(g, 0.0, atol=eps()) + coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + else + coefficient = g_limited / g + end + alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + g_limited end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 5791df8301..e593d58037 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -301,11 +301,11 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn if !indicator.Plotting return nothing end - @unpack volume_flux_difference = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator variables = varnames(cons2cons, equations) for v in eachvariable(equations) s = Symbol("shock_capturing_delta_volume_flux_", variables[v]) - node_variables[s] = volume_flux_difference[v, ntuple(_ -> :, nvariables(equations) + 1)...] + node_variables[s] = alpha[v, ntuple(_ -> :, nvariables(equations) + 1)...] end if indicator.IDPPressureTVD diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index dbc6457740..acbaa5faaa 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -148,6 +148,17 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end + # Reset alphas for PLotting of MCL + @unpack indicator = integrator.p.solver.volume_integral + if indicator isa IndicatorMCL && indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) + for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) + alpha[:, i, j, element] .= 1.0 + end + end + end + @. integrator.u_safe = integrator.u for stage in eachindex(alg.c) t_stage = integrator.t + integrator.dt * alg.c[stage] From 148c554e2d67df6a5b772ba2349cc8dabc73c6a0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 8 Dec 2022 11:59:08 +0100 Subject: [PATCH 104/423] Save lines by using `reverse()` --- src/solvers/dgsem_tree/indicators.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 92 ++++++++----------------- 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index e593d58037..624c16c7e5 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -273,7 +273,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, - Plotting=false) + Plotting=true) cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)+IDPPressureTVD) if indicator_smooth diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 43306e59f8..f4810ba4fd 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -290,28 +290,21 @@ end orientation = cache.interfaces.orientations[interface] - if orientation == 1 - for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) - var_right = variable(get_node_vars(u, equations, dg, 1, j, right), equations) - - var_min[1, j, right] = min(var_min[1, j, right], var_left) - var_max[1, j, right] = max(var_max[1, j, right], var_left) - - var_min[nnodes(dg), j, left] = min(var_min[nnodes(dg), j, left], var_right) - var_max[nnodes(dg), j, left] = max(var_max[nnodes(dg), j, left], var_right) + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) end - else # orientation == 2 - for i in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), left), equations) - var_right = variable(get_node_vars(u, equations, dg, i, 1, right), equations) + var_left = variable(get_node_vars(u, equations, dg, index_left..., left), equations) + var_right = variable(get_node_vars(u, equations, dg, index_right..., right), equations) - var_min[i, 1, right] = min(var_min[i, 1, right], var_left) - var_max[i, 1, right] = max(var_max[i, 1, right], var_left) + var_min[index_right..., right] = min(var_min[index_right..., right], var_left) + var_max[index_right..., right] = max(var_max[index_right..., right], var_left) - var_min[i, nnodes(dg), left] = min(var_min[i, nnodes(dg), left], var_right) - var_max[i, nnodes(dg), left] = max(var_max[i, nnodes(dg), left], var_right) - end + var_min[index_left..., left] = min(var_min[index_left..., left], var_right) + var_max[index_left..., left] = max(var_max[index_left..., left], var_right) end end @@ -321,50 +314,25 @@ end orientation = cache.boundaries.orientations[boundary] neighbor_side = cache.boundaries.neighbor_sides[boundary] - if orientation == 1 - if neighbor_side == 2 # boundary_side == 1 - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) - - var_min[1, j, element] = min(var_min[1, j, element], var_outer) - var_max[1, j, element] = max(var_max[1, j, element], var_outer) - end - else # boundary_side == 2 - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer, equations) - - var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) - var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) - end + for i in eachnode(dg) + if neighbor_side == 2 # Element is on the right, boundary on the left + index = (1, i) + boundary_index = 1 + else # Element is on the left, boundary on the right + index = (nnodes(dg), i) + boundary_index = 2 end - else # orientation == 2 - if neighbor_side == 2 # boundary_side == 1 - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) - - var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) - var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) - end - else # boundary_side == 2 - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer, equations) - - var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) - var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) - end + if orientation == 2 + index = reverse(index) + boundary_index += 2 end + u_inner = get_node_vars(u, equations, dg, index..., element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[boundary_index], + equations, dg, index..., element) + var_outer = variable(u_outer, equations) + + var_min[index..., element] = min(var_min[index..., element], var_outer) + var_max[index..., element] = max(var_max[index..., element], var_outer) end end @@ -544,7 +512,7 @@ end end # Calculate alpha at nodes - alpha[i, j, element] = 1 - min(1.0, Qp, Qm) + alpha[i, j, element] = 1 - min(1.0, Qp, Qm) end end From c3b23a5afe53f1a4e8adc6ea632f891fd8939a33 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 12 Dec 2022 16:02:50 +0100 Subject: [PATCH 105/423] Revise Bounds Check --- src/solvers/dgsem_structured/indicators_2d.jl | 16 +-- src/solvers/dgsem_tree/dg_2d.jl | 118 +++++++++++------- src/solvers/dgsem_tree/indicators_2d.jl | 12 +- src/time_integration/methods_SSP.jl | 39 ++---- 4 files changed, 95 insertions(+), 90 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 488c0a9cb3..4e70c0a69d 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -75,7 +75,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[1, j, element] = min(var_min[1, j, element], var_outer) var_max[1, j, element] = max(var_max[1, j, element], var_outer) @@ -88,7 +88,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) @@ -101,7 +101,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) @@ -114,7 +114,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) @@ -165,7 +165,7 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) end @@ -177,7 +177,7 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) end @@ -189,7 +189,7 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) end @@ -201,7 +201,7 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer) + var_outer = variable(u_outer, equations) var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e941b618f2..cb9f813b2d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -860,7 +860,7 @@ end neighbor_side = cache.boundaries.neighbor_sides[boundary] if orientation == 1 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], @@ -875,7 +875,7 @@ end bar_states1[v, 1, j, element] = bar_state[v] end end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], @@ -892,7 +892,7 @@ end end end else # orientation == 2 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], @@ -907,7 +907,7 @@ end bar_states2[v, i, 1, element] = bar_state[v] end end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], @@ -1278,14 +1278,14 @@ end neighbor_side = cache.boundaries.neighbor_sides[boundary] if orientation == 1 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], @@ -1294,14 +1294,14 @@ end end end else # orientation == 2 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], @@ -1380,42 +1380,67 @@ end @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache - - @threaded for element in eachelement(solver, cache) - idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] - for j in eachnode(solver), i in eachnode(solver) - counter = 1 - if IDPDensityTVD - idp_bounds_delta[1] = max(idp_bounds_delta[1], var_bounds[1][i, j, element] - u[1, i, j, element]) - idp_bounds_delta[2] = max(idp_bounds_delta[2], u[1, i, j, element] - var_bounds[2][i, j, element]) - counter += 2 - end - if IDPPressureTVD - p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) - idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], p - var_bounds[counter+1][i, j, element]) - counter += 2 - end - if IDPPositivity && !IDPDensityTVD - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - u[1, i, j, element]) - counter += 1 - end - if IDPPositivity && !IDPPressureTVD - p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - p) - counter += 1 - end - if IDPSpecEntropy - s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], var_bounds[counter][i, j, element] - s) - counter += 1 - end - if IDPMathEntropy - s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], s - var_bounds[counter][i, j, element]) - end + @unpack idp_bounds_delta = solver.volume_integral.indicator.cache + + # Save the deviations every x iterations + x = 0 + counter = 1 + if IDPDensityTVD + deviation_min = zero(eltype(u)) + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + deviation_min = max(deviation_min, var_bounds[1][i, j, element] - u[1, i, j, element]) + deviation_max = max(deviation_max, u[1, i, j, element] - var_bounds[2][i, j, element]) + end + idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) + idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) + counter += 2 + end + if IDPPressureTVD + deviation_min = zero(eltype(u)) + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) + deviation_max = max(deviation_max, p - var_bounds[counter+1][i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], deviation_max) + counter += 2 + end + if IDPPositivity && !IDPDensityTVD + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - u[1, i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + counter += 1 + end + if IDPPositivity && !IDPPressureTVD + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + counter += 1 + end + if IDPSpecEntropy + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - s) end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + counter += 1 + end + if IDPMathEntropy + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_max = max(deviation_max, s - var_bounds[counter][i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) end return nothing @@ -1424,14 +1449,11 @@ end # 2d, IndicatorMCL @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL) @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @unpack idp_bounds_delta_threaded = solver.volume_integral.indicator.cache + @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D n_vars = nvariables(equations) - - @threaded for element in eachelement(solver, cache) - idp_bounds_delta = idp_bounds_delta_threaded[Threads.threadid()] - + for element in eachelement(solver, cache) # -x for j in eachnode(solver), i in 2:nnodes(solver) lambda = lambda1[i, j, element] diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index f4810ba4fd..25913978ba 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -198,10 +198,10 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation alpha_mean_per_timestep = zeros(real(basis), 200) time_per_timestep = zeros(real(basis), 200) - idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] + idp_bounds_delta = zeros(real(basis), length) return (; alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, - ContainerShockCapturingIndicator, idp_bounds_delta_threaded) + ContainerShockCapturingIndicator, idp_bounds_delta) end function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -410,7 +410,7 @@ end neighbor_side = cache.boundaries.neighbor_sides[boundary] if orientation == 1 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], @@ -419,7 +419,7 @@ end var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], @@ -430,7 +430,7 @@ end end end else # orientation == 2 - if neighbor_side == 2 # boundary_side == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], @@ -439,7 +439,7 @@ end var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) end - else # boundary_side == 2 + else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index acbaa5faaa..32b4d03d60 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -321,43 +321,34 @@ end # check deviation from boundaries of IDP indicator @inline function summary_check_bounds(indicator::IndicatorIDP, equations::CompressibleEulerEquations2D) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator - @unpack idp_bounds_delta_threaded = indicator.cache - - err_bounds = idp_bounds_delta_threaded[1] - - for i in 2:Threads.nthreads() - for index in 1:length(err_bounds) - err_bounds[index] = max(err_bounds[index], idp_bounds_delta_threaded[i][index]) - end - end + @unpack idp_bounds_delta = indicator.cache println("─"^100) println("Maximum deviation from bounds:") println("─"^100) - counter = 0 + counter = 1 if IDPDensityTVD + println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) counter += 2 - println("rho:\n- lower bound: ", err_bounds[counter-1], "\n- upper bound: ", err_bounds[counter]) end if IDPPressureTVD + println("pressure:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) counter += 2 - println("pressure:\n- lower bound: ", err_bounds[counter-1], "\n- upper bound: ", err_bounds[counter]) end if IDPPositivity && !IDPDensityTVD + println("rho:\n- positivity: ", idp_bounds_delta[counter]) counter += 1 - println("rho:\n- positivity: ", err_bounds[counter]) end if IDPPositivity && !IDPPressureTVD + println("pressure:\n- positivity: ", idp_bounds_delta[counter]) counter += 1 - println("pressure:\n- positivity: ", err_bounds[counter]) end if IDPSpecEntropy + println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) counter += 1 - println("spec. entropy:\n- lower bound: ", err_bounds[counter]) end if IDPMathEntropy - counter += 1 - println("math. entropy:\n- upper bound: ", err_bounds[counter]) + println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) end println("─"^100 * "\n") @@ -366,25 +357,17 @@ end # check deviation from boundaries of IndicatorMCL @inline function summary_check_bounds(indicator::IndicatorMCL, equations::CompressibleEulerEquations2D) - @unpack idp_bounds_delta_threaded = indicator.cache - - err_bounds = idp_bounds_delta_threaded[1] - - for i in 2:Threads.nthreads() - for index in 1:length(err_bounds) - err_bounds[index] = max(err_bounds[index], idp_bounds_delta_threaded[i][index]) - end - end + @unpack idp_bounds_delta = indicator.cache println("─"^100) println("Maximum deviation from bounds:") println("─"^100) variables = varnames(cons2cons, equations) for v in eachvariable(equations) - println(variables[v], ":\n- lower bound: ", err_bounds[2*v-1], "\n- upper bound: ", err_bounds[2*v]) + println(variables[v], ":\n- lower bound: ", idp_bounds_delta[2*v-1], "\n- upper bound: ", idp_bounds_delta[2*v]) end if indicator.IDPPressureTVD - println("pressure:\n- lower bound: ", err_bounds[2*nvariables(equations)+1]) + println("pressure:\n- lower bound: ", idp_bounds_delta[2*nvariables(equations)+1]) end println("─"^100 * "\n") From 4b663184fa50d0ccc0529ca1243f804b9cfef8bb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 12 Dec 2022 16:05:13 +0100 Subject: [PATCH 106/423] Revise computation of blending coefficient (avoiding division by zero) --- src/solvers/dgsem_tree/indicators_2d.jl | 42 ++++++++----------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 25913978ba..b0ee2f5b06 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -499,17 +499,10 @@ end Pp = inverse_jacobian * Pp Pm = inverse_jacobian * Pm - # Calculate alpha_plus and alpha_minus - if Pp == 0.0 - Qp = 1.0 - else - Qp = Qp / Pp - end - if Pm == 0.0 - Qm = 1.0 - else - Qm = Qm / Pm - end + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / (abs(Pp) + eps() * 100 * abs(rho_max[i, j, element])) + Qm = abs(Qm) / (abs(Pm) + eps() * 100 * abs(rho_max[i, j, element])) # Calculate alpha at nodes alpha[i, j, element] = 1 - min(1.0, Qp, Qm) @@ -575,17 +568,10 @@ end Pp = inverse_jacobian * Pp Pm = inverse_jacobian * Pm - # Calculate alpha_plus and alpha_minus - if Pp == 0.0 - Qp = 1.0 - else - Qp = Qp / Pp - end - if Pm == 0.0 - Qm = 1.0 - else - Qm = Qm / Pm - end + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / (abs(Pp) + eps() * 100 * abs(p_max[i, j, element])) + Qm = abs(Qm) / (abs(Pm) + eps() * 100 * abs(p_max[i, j, element])) # Calculate alpha at nodes alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1.0, Qp, Qm)) @@ -711,11 +697,9 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) Pm = inverse_jacobian * Pm - if Pm < 0.0 - Qm = min(1.0, Qm / Pm) - else - Qm = 1.0 - end + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qm = abs(Qm) / (abs(Pm) + eps() * 100) # Calculate alpha alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) @@ -914,9 +898,9 @@ end function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta_threaded = [zeros(real(basis), length) for _ in 1:Threads.nthreads()] + idp_bounds_delta = zeros(real(basis), length) - return (; ContainerShockCapturingIndicator, idp_bounds_delta_threaded) + return (; ContainerShockCapturingIndicator, idp_bounds_delta) end @inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) From 2a9ffb8bca7993608708dbe53f9a58c44c395807 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Dec 2022 23:13:49 +0100 Subject: [PATCH 107/423] Allow BarStates for IDP; Restructure Containers --- src/callbacks_step/stepsize.jl | 9 +- src/callbacks_step/stepsize_dg2d.jl | 4 +- src/solvers/dgsem_structured/dg_2d.jl | 19 ++- src/solvers/dgsem_tree/containers_2d.jl | 107 ++++++++++------- src/solvers/dgsem_tree/dg_2d.jl | 153 +++++++++++++++++++++--- src/solvers/dgsem_tree/indicators.jl | 12 +- src/solvers/dgsem_tree/indicators_2d.jl | 34 ++++-- src/time_integration/methods_SSP.jl | 17 +-- 8 files changed, 260 insertions(+), 95 deletions(-) diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 0a1a343165..c5d47391a6 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -91,11 +91,14 @@ max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral:: @inline function max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) - return max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral.indicator) + @unpack indicator = volume_integral + if indicator isa IndicatorIDP && !indicator.BarStates + return max_dt(u, t, mesh, constant_speed, equations, dg, cache) + else + return max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, indicator) + end end -max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, indicator::IndicatorIDP) = max_dt(u, t, mesh, constant_speed, equations, dg, cache) - # Time integration methods from the DiffEq ecosystem without adaptive time stepping on their own # such as `CarpenterKennedy2N54` require passing `dt=...` in `solve(ode, ...)`. Since we don't have diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 3b3c8dfdd2..23a2ad590f 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -43,10 +43,10 @@ function max_dt(u, t, mesh::TreeMesh{2}, end @inline function max_dt(u, t, mesh::Union{TreeMesh,StructuredMesh}, - constant_speed::Val{false}, equations, semi, dg::DG, cache, indicator::IndicatorMCL) + constant_speed::Val{false}, equations, semi, dg::DG, cache, indicator::Union{IndicatorIDP, IndicatorMCL}) @unpack inverse_weights = dg.basis @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, t, mesh, equations, dg, cache, indicator, semi.boundary_conditions) - @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates maxdt = typemax(eltype(u)) if indicator.indicator_smooth diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index eb9506397b..9292ea845f 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -417,12 +417,16 @@ end @inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, - nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) + + if indicator isa IndicatorIDP && !indicator.BarStates + return nothing + end + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerShockCapturingIndicator + @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) @@ -594,12 +598,15 @@ end end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::StructuredMesh, equations, dg, cache, indicator::IndicatorMCL, boundary_conditions) - @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::StructuredMesh, equations, dg, cache, indicator, boundary_conditions) + if indicator isa IndicatorIDP && !indicator.BarStates + return nothing + end + @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerShockCapturingIndicator + @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 7373257224..69e7730025 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1369,38 +1369,20 @@ function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) end mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} - bar_states1::Array{uEltype, 4} # [variable, i, j, element] - bar_states2::Array{uEltype, 4} # [variable, i, j, element] var_min::Array{uEltype, 4} # [variable, i, j, element] var_max::Array{uEltype, 4} # [variable, i, j, element] alpha::Array{uEltype, 4} # [variable, i, j, element] alpha_pressure::Array{uEltype, 3} # [i, j, element] - lambda1::Array{uEltype, 3} # [i, j, element] - lambda2::Array{uEltype, 3} # [i, j, element] - normal_direction_xi::Array{uEltype, 4} # [index, i, j, elements] - normal_direction_eta::Array{uEltype, 4} # [index, i, j, elements] # internal `resize!`able storage - _bar_states1::Vector{uEltype} - _bar_states2::Vector{uEltype} _var_min::Vector{uEltype} _var_max::Vector{uEltype} _alpha::Vector{uEltype} _alpha_pressure::Vector{uEltype} - _lambda1::Vector{uEltype} - _lambda2::Vector{uEltype} - _normal_direction_xi::Vector{uEltype} - _normal_direction_eta::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) - # Initialize fields with defaults - _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) - bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) - _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) - bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) - _var_min = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) @@ -1413,6 +1395,64 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_pressure = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) + return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, + _var_min, _var_max, _alpha, _alpha_pressure) +end + +nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) +nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 2) + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) + n_variables = nvariables(container) + n_nodes = nnodes(container) + + @unpack _var_min, _var_max = container + resize!(_var_min, n_variables * n_nodes * n_nodes * capacity) + container.var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) + resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) + container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) + + @unpack _alpha = container + resize!(_alpha, n_variables * n_nodes * n_nodes * capacity) + container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables, n_nodes, n_nodes, capacity)) + + @unpack _alpha_pressure = container + resize!(_alpha_pressure, n_nodes * n_nodes * capacity) + container.alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) + + return nothing +end + +mutable struct ContainerBarStates{uEltype<:Real} + bar_states1::Array{uEltype, 4} # [variable, i, j, element] + bar_states2::Array{uEltype, 4} # [variable, i, j, element] + lambda1::Array{uEltype, 3} # [i, j, element] + lambda2::Array{uEltype, 3} + normal_direction_xi::Array{uEltype, 4} # [index, i, j, elements] + normal_direction_eta::Array{uEltype, 4} # [index, i, j, elements] + # internal `resize!`able storage + _bar_states1::Vector{uEltype} + _bar_states2::Vector{uEltype} + _lambda1::Vector{uEltype} + _lambda2::Vector{uEltype} + _normal_direction_xi::Vector{uEltype} + _normal_direction_eta::Vector{uEltype} +end + +function ContainerBarStates{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real + nan_uEltype = convert(uEltype, NaN) + + # Initialize fields with defaults + _bar_states1 = fill(nan_uEltype, n_variables * (n_nodes+1) * n_nodes * capacity) + bar_states1 = unsafe_wrap(Array, pointer(_bar_states1), (n_variables, n_nodes+1, n_nodes, capacity)) + _bar_states2 = fill(nan_uEltype, n_variables * n_nodes * (n_nodes+1) * capacity) + bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) + _lambda1 = fill(nan_uEltype, (n_nodes+1) * n_nodes * capacity) lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) _lambda2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) @@ -1426,23 +1466,21 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia normal_direction_eta = unsafe_wrap(Array, pointer(_normal_direction_eta), (n_variables - 2, n_nodes, n_nodes - 1, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(bar_states1, bar_states2, var_min, var_max, - alpha, alpha_pressure, lambda1, lambda2, - normal_direction_xi, normal_direction_eta, - _bar_states1, _bar_states2, _var_min, _var_max, - _alpha, _alpha_pressure, _lambda1, _lambda2, - _normal_direction_xi, _normal_direction_eta) + return ContainerBarStates{uEltype}(bar_states1, bar_states2, lambda1, lambda2, + normal_direction_xi, normal_direction_eta, + _bar_states1, _bar_states2, _lambda1, _lambda2, + _normal_direction_xi, _normal_direction_eta) end -nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) -nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 2) +nvariables(container::ContainerBarStates) = size(container.bar_states1, 1) +nnodes(container::ContainerBarStates) = size(container.bar_states1, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) +function Base.resize!(container::ContainerBarStates, capacity) n_variables = nvariables(container) n_nodes = nnodes(container) @@ -1452,20 +1490,6 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_bar_states2, n_variables * n_nodes * (n_nodes+1) * capacity) container.bar_states2 = unsafe_wrap(Array, pointer(_bar_states2), (n_variables, n_nodes, n_nodes+1, capacity)) - @unpack _var_min, _var_max = container - resize!(_var_min, n_variables * n_nodes * n_nodes * capacity) - container.var_min = unsafe_wrap(Array, pointer(_var_min), (n_variables, n_nodes, n_nodes, capacity)) - resize!(_var_max, n_variables * n_nodes * n_nodes * capacity) - container.var_max = unsafe_wrap(Array, pointer(_var_max), (n_variables, n_nodes, n_nodes, capacity)) - - @unpack _alpha = container - resize!(_alpha, n_variables * n_nodes * n_nodes * capacity) - container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_variables, n_nodes, n_nodes, capacity)) - - @unpack _alpha_pressure = container - resize!(_alpha_pressure, n_nodes * n_nodes * capacity) - container.alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) - @unpack _lambda1, _lambda2 = container resize!(_lambda1, (n_nodes+1) * n_nodes * capacity) container.lambda1 = unsafe_wrap(Array, pointer(_lambda1), (n_nodes+1, n_nodes, capacity)) @@ -1483,4 +1507,5 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) return nothing end + end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index cb9f813b2d..5fcb131531 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -767,15 +767,13 @@ end return nothing end -@inline function calc_lambdas_bar_states!(u, t, mesh, - nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache, boundary_conditions) - - return nothing -end - @inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache, boundary_conditions) - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) + + if indicator isa IndicatorIDP && !indicator.BarStates + return nothing + end + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) @@ -929,13 +927,130 @@ end return nothing end -@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) +@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) + if !indicator.BarStates + return nothing + end + @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2 = indicator.cache.ContainerBarStates + + counter = 1 + # Density + if indicator.IDPDensityTVD + rho_min = var_bounds[1] + rho_max = var_bounds[2] + @threaded for element in eachelement(dg, cache) + rho_min[:, :, element] .= typemax(eltype(rho_min)) + rho_max[:, :, element] .= typemin(eltype(rho_max)) + for j in eachnode(dg), i in eachnode(dg) + rho_min[i, j, element] = min(rho_min[i, j, element], u[1, i, j, element]) + rho_max[i, j, element] = max(rho_max[i, j, element], u[1, i, j, element]) + # TODO: Add source term! + # - xi direction + rho_min[i, j, element] = min(rho_min[i, j, element], bar_states1[1, i, j, element]) + rho_max[i, j, element] = max(rho_max[i, j, element], bar_states1[1, i, j, element]) + # + xi direction + rho_min[i, j, element] = min(rho_min[i, j, element], bar_states1[1, i+1, j, element]) + rho_max[i, j, element] = max(rho_max[i, j, element], bar_states1[1, i+1, j, element]) + # - eta direction + rho_min[i, j, element] = min(rho_min[i, j, element], bar_states2[1, i, j, element]) + rho_max[i, j, element] = max(rho_max[i, j, element], bar_states2[1, i, j, element]) + # + eta direction + rho_min[i, j, element] = min(rho_min[i, j, element], bar_states2[1, i, j+1, element]) + rho_max[i, j, element] = max(rho_max[i, j, element], bar_states2[1, i, j+1, element]) + end + end + counter += 2 + end + # Pressure + if indicator.IDPPressureTVD + p_min = var_bounds[counter] + p_max = var_bounds[counter+1] + @threaded for element in eachelement(dg, cache) + p_min[:, :, element] .= typemax(eltype(p_min)) + p_max[:, :, element] .= typemin(eltype(p_max)) + for j in eachnode(dg), i in eachnode(dg) + p = pressure(get_node_vars(u, equations, dg, i, j, element), equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) + # - xi direction + p = pressure(get_node_vars(bar_states1, equations, dg, i, j, element), equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) + # + xi direction + p = pressure(get_node_vars(bar_states1, equations, dg, i+1, j, element), equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) + # - eta direction + p = pressure(get_node_vars(bar_states2, equations, dg, i, j, element), equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) + # + eta direction + p = pressure(get_node_vars(bar_states2, equations, dg, i, j+1, element), equations) + p_min[i, j, element] = min(p_min[i, j, element], p) + p_max[i, j, element] = max(p_max[i, j, element], p) + end + end + counter += 2 + end + if indicator.IDPPositivity + counter += !indicator.IDPDensityTVD + !indicator.IDPPressureTVD + end + # Specific Entropy + if indicator.IDPSpecEntropy + s_min = var_bounds[counter] + @threaded for element in eachelement(dg, cache) + s_min[:, :, element] .= typemax(eltype(s_min)) + for j in eachnode(dg), i in eachnode(dg) + s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # TODO: Add source? + # - xi direction + s = entropy_spec(get_node_vars(bar_states1, equations, dg, i, j, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # + xi direction + s = entropy_spec(get_node_vars(bar_states1, equations, dg, i+1, j, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # - eta direction + s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # + eta direction + s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j+1, element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + end + end + counter += 1 + end + # Mathematical entropy + if indicator.IDPMathEntropy + s_max = var_bounds[counter] + @threaded for element in eachelement(dg, cache) + s_max[:, :, element] .= typemin(eltype(s_max)) + for j in eachnode(dg), i in eachnode(dg) + s = entropy_math(get_node_vars(u, equations, dg, i, j, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # - xi direction + s = entropy_math(get_node_vars(bar_states1, equations, dg, i, j, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # + xi direction + s = entropy_math(get_node_vars(bar_states1, equations, dg, i+1, j, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # - eta direction + s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # + eta direction + s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j+1, element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + end + end + end return nothing end @inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) - @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator + @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @threaded for element in eachelement(dg, cache) for v in eachvariable(equations) @@ -988,7 +1103,8 @@ end @inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - @unpack var_min, var_max, lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerShockCapturingIndicator + @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. # To avoid further calculations with these values, we replace them by 0. @@ -1220,13 +1336,11 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, mesh, equations, dg, cache, indicator) - - return nothing -end - -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::TreeMesh2D, equations, dg, cache, indicator::IndicatorMCL, boundary_conditions) - @unpack lambda1, lambda2 = indicator.cache.ContainerShockCapturingIndicator +@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::TreeMesh2D, equations, dg, cache, indicator, boundary_conditions) + if indicator isa IndicatorIDP && !indicator.BarStates + return nothing + end + @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) @@ -1448,7 +1562,8 @@ end # 2d, IndicatorMCL @inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL) - @unpack var_min, var_max, bar_states1, bar_states2, lambda1, lambda2 = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 624c16c7e5..b48786e357 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -174,6 +174,7 @@ struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator IDPPositivity::Bool IDPSpecEntropy::Bool IDPMathEntropy::Bool + BarStates::Bool cache::Cache positCorrFactor::RealT # Correction factor for IDPPositivity IDPMaxIter::Int # Maximal number of iterations for Newton's method @@ -193,6 +194,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPPositivity=false, IDPSpecEntropy=false, IDPMathEntropy=false, + BarStates=false, positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), IDPCheckBounds=false, @@ -207,7 +209,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; length = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) - cache = create_cache(IndicatorIDP, equations, basis, length) + cache = create_cache(IndicatorIDP, equations, basis, length, BarStates) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max=1.0, alpha_smooth=false, @@ -216,7 +218,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; IndicatorHG = nothing end IndicatorIDP{typeof(positCorrFactor), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, - IDPPositivity, IDPSpecEntropy, IDPMathEntropy, cache, positCorrFactor, IDPMaxIter, + IDPPositivity, IDPSpecEntropy, IDPMathEntropy, BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG) end @@ -239,6 +241,12 @@ function Base.show(io::IO, indicator::IndicatorIDP) end indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth, "), ") + print(io, "Local bounds with ") + if indicator.BarStates + print(io, "Bar States") + else + print(io, "FV solution") + end print(io, ")") end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index b0ee2f5b06..e925d69294 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -191,17 +191,23 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) +function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length, BarStates) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), length) + cache = (; ) + if BarStates + ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) + cache = (; cache..., ContainerBarStates) + end + alpha_max_per_timestep = zeros(real(basis), 200) alpha_mean_per_timestep = zeros(real(basis), 200) time_per_timestep = zeros(real(basis), 200) idp_bounds_delta = zeros(real(basis), length) - return (; alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, - ContainerShockCapturingIndicator, idp_bounds_delta) + return (; cache..., alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, + ContainerShockCapturingIndicator, idp_bounds_delta) end function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, @@ -400,9 +406,6 @@ end end end - if boundary_conditions isa BoundaryConditionPeriodic - return nothing - end # Calc bounds at physical boundaries for boundary in eachboundary(dg, cache) element = cache.boundaries.neighbor_ids[boundary] @@ -462,7 +465,9 @@ end rho_min = var_bounds[1] rho_max = var_bounds[2] - calc_bounds_2sided!(rho_min, rho_max, density, u_safe, mesh, equations, dg, cache) + if !indicator_IDP.BarStates + calc_bounds_2sided!(rho_min, rho_max, density, u_safe, t, semi) + end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -522,7 +527,9 @@ end offset = 2 * indicator_IDP.IDPDensityTVD p_min = var_bounds[1 + offset] p_max = var_bounds[2 + offset] - calc_bounds_2sided!(p_min, p_max, pressure, u_safe, mesh, equations, dg, cache) + if !indicator_IDP.BarStates + calc_bounds_2sided!(p_min, p_max, pressure, u_safe, t, semi) + end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -589,7 +596,9 @@ end offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) s_min = var_bounds[offset + 1] - calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, mesh, equations, dg, cache) + if !indicator_IDP.BarStates + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, t, semi) + end # Perform Newton's bisection method to find new alpha @threaded for element in elements @@ -617,7 +626,9 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol offset = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) s_max = var_bounds[offset + 1] - calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, mesh, equations, dg, cache) + if !indicator_IDP.BarStates + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, t, semi) + end # Perform Newton's bisection method to find new alpha @threaded for element in elements @@ -897,10 +908,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) + ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) idp_bounds_delta = zeros(real(basis), length) - return (; ContainerShockCapturingIndicator, idp_bounds_delta) + return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end @inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 32b4d03d60..7d8ca05b91 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -108,12 +108,6 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, # Resize container resize!(integrator.p, nelements(integrator.p.solver, integrator.p.cache)) - # Calc subcell normal directions before StepsizeCallback - @unpack indicator = integrator.p.solver.volume_integral - if indicator isa IndicatorMCL - calc_normal_directions!(indicator.cache.ContainerShockCapturingIndicator, mesh_equations_solver_cache(integrator.p)...) - end - # initialize callbacks if callback isa CallbackSet for cb in callback.continuous_callbacks @@ -275,21 +269,22 @@ function Base.resize!(semi::AbstractSemidiscretization, new_size) resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) # Calc subcell normal directions before StepsizeCallback @unpack indicator = semi.solver.volume_integral - if indicator isa IndicatorMCL - calc_normal_directions!(indicator.cache.ContainerShockCapturingIndicator, mesh_equations_solver_cache(semi)...) + if indicator isa IndicatorMCL || (indicator isa IndicatorIDP && indicator.BarStates) + resize!(semi.solver.volume_integral.indicator.cache.ContainerBarStates, new_size) + calc_normal_directions!(indicator.cache.ContainerBarStates, mesh_equations_solver_cache(semi)...) end end -function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::TreeMesh, equations, dg, cache) +function calc_normal_directions!(ContainerBarStates, mesh::TreeMesh, equations, dg, cache) return nothing end -function calc_normal_directions!(ContainerShockCapturingIndicator, mesh::StructuredMesh, equations, dg, cache) +function calc_normal_directions!(ContainerBarStates, mesh::StructuredMesh, equations, dg, cache) @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = ContainerShockCapturingIndicator + @unpack normal_direction_xi, normal_direction_eta = ContainerBarStates @threaded for element in eachelement(dg, cache) for j in eachnode(dg) normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) From 7fff640c6c319e505ef7f3b66f11f8db5e36dca6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Dec 2022 23:25:37 +0100 Subject: [PATCH 108/423] Speedup simulations with StructuredMesh using mesh.periodicity --- src/solvers/dgsem_structured/dg_2d.jl | 125 ++++++------ src/solvers/dgsem_structured/indicators_2d.jl | 188 +++++++++--------- 2 files changed, 160 insertions(+), 153 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 9292ea845f..4b3dd9234e 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -468,7 +468,6 @@ end end # Calc lambdas and bar states at interfaces and periodic boundaries - # TODO: Speed this for loop up with mesh.periodicity? @threaded for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] @@ -517,22 +516,18 @@ end end # Calc lambdas and bar states at physical boundaries - # TODO: Speed this for loop up with mesh.periodicity? - if boundary_conditions isa BoundaryConditionPeriodic + if all(mesh.periodicity) return nothing end linear_indices = LinearIndices(size(mesh)) - # x-direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - element_opp = linear_indices[end, cell_y] - left = cache.elements.left_neighbors[1, element] - if left == 0 # element is at boundary + if !mesh.periodicity[1] + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] for j in eachnode(dg) - # left side of the domain u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) + equations, dg, 1, j, element) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) @@ -541,34 +536,34 @@ end for v in eachvariable(equations) bar_states1[v, 1, j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda1[1, j, element] end - - # right side of the domain - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element_opp) + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element_opp) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element_opp) - lambda1[nnodes(dg)+1, j, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + equations, dg, nnodes(dg), j, element) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) + lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) for v in eachvariable(equations) - # TODO: Or change the order of the fluxes? Right - Left - bar_states1[v, nnodes(dg), j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda1[nnodes(dg)+1, j, element_opp] + bar_states1[v, nnodes(dg), j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda1[nnodes(dg)+1, j, element] end end end end - # y-direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - element_opp = linear_indices[cell_x, end] - lower = cache.elements.left_neighbors[2, element] - if lower == 0 # element is at boundary + if !mesh.periodicity[2] + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] for i in eachnode(dg) - # bottom side of the domain u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) + equations, dg, i, 1, element) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) @@ -577,18 +572,22 @@ end for v in eachvariable(equations) bar_states2[v, i, 1, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda2[i, 1, element] end - - # top side of the domain - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element_opp) + end + end + # + eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element_opp) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element_opp) - lambda2[i, nnodes(dg)+1, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + equations, dg, i, nnodes(dg), element) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) + lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg), element] = 0.5 * (u_outer[v] + u_inner[v]) - 0.5 * (flux_inner[v] - flux_outer[v]) / lambda2[i, nnodes(dg)+1, element_opp] + bar_states2[v, i, nnodes(dg), element] = 0.5 * (u_outer[v] + u_inner[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda2[i, nnodes(dg)+1, element] end end end @@ -636,7 +635,6 @@ end end # Calc lambdas at interfaces and periodic boundaries - # TODO: Speed this for loop up with mesh.periodicity? @threaded for element in eachelement(dg, cache) # Get neighboring element ids left = cache.elements.left_neighbors[1, element] @@ -669,54 +667,55 @@ end end # Calc lambdas at physical boundaries - # TODO: Speed this for loop up with mesh.periodicity? - if boundary_conditions isa BoundaryConditionPeriodic + if all(mesh.periodicity) return nothing end linear_indices = LinearIndices(size(mesh)) - # x-direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - element_opp = linear_indices[end, cell_y] - left = cache.elements.left_neighbors[1, element] - if left == 0 # element is at boundary + if !mesh.periodicity[1] + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] for j in eachnode(dg) - # left side of the domain u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], equations, dg, 1, j, element) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) - - # right side of the domain - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element_opp) + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element_opp) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element_opp) - lambda1[nnodes(dg)+1, j, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + equations, dg, nnodes(dg), j, element) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) + lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) end end end - # y-direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - element_opp = linear_indices[cell_x, end] - lower = cache.elements.left_neighbors[2, element] - if lower == 0 # element is at boundary + if !mesh.periodicity[2] + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] for i in eachnode(dg) - # bottom side of the domain u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], equations, dg, i, 1, element) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) - - # top side of the domain - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element_opp) + end + end + # + eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element_opp) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element_opp) - lambda2[i, nnodes(dg)+1, element_opp] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + equations, dg, i, nnodes(dg), element) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) + lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) end end end diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 4e70c0a69d..ee2be0324f 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -64,60 +64,64 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m end # Calc bounds at physical boundaries - if boundary_conditions isa BoundaryConditionPeriodic + if all(mesh.periodicity) return nothing end linear_indices = LinearIndices(size(mesh)) - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) - - var_min[1, j, element] = min(var_min[1, j, element], var_outer) - var_max[1, j, element] = max(var_max[1, j, element], var_outer) + if !mesh.periodicity[1] + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer, equations) + + var_min[1, j, element] = min(var_min[1, j, element], var_outer) + var_max[1, j, element] = max(var_max[1, j, element], var_outer) + end end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer, equations) - - var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) - var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer, equations) + + var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) + var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) + end end end - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) - - var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) - var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) + if !mesh.periodicity[2] + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer, equations) + + var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) + var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) + end end - end - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer, equations) - - var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) - var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer, equations) + + var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) + var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) + end end end @@ -154,56 +158,60 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end # Calc bounds at physical boundaries - if boundary_conditions isa BoundaryConditionPeriodic + if all(mesh.periodicity) return nothing end linear_indices = LinearIndices(size(mesh)) - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) - - var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) + if !mesh.periodicity[1] + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + equations, dg, 1, j, element) + var_outer = variable(u_outer, equations) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) + end end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer, equations) - - var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + equations, dg, nnodes(dg), j, element) + var_outer = variable(u_outer, equations) + + var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, element], var_outer) + end end end - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) - - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) + if !mesh.periodicity[2] + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + equations, dg, i, 1, element) + var_outer = variable(u_outer, equations) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) + end end - end - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer, equations) - - var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) + # + eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + equations, dg, i, nnodes(dg), element) + var_outer = variable(u_outer, equations) + + var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), element], var_outer) + end end end From 2213213ed8b60a2a8c51865a1254086191b50dae Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 15 Dec 2022 13:57:02 +0100 Subject: [PATCH 109/423] Remove not needed code for StructuredMesh --- src/solvers/dgsem_structured/dg_2d.jl | 70 +++++++++++---------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 4b3dd9234e..b8809b65a2 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -423,46 +423,39 @@ end return nothing end @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates - @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) - for j in eachnode(dg) - normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - for i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) + normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) - flux1 = flux(u_node, normal_direction, equations) - flux1_im1 = flux(u_node_im1, normal_direction, equations) + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) + flux1 = flux(u_node, normal_direction, equations) + flux1_im1 = flux(u_node_im1, normal_direction, equations) - for v in eachvariable(equations) - bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] - end + for v in eachvariable(equations) + bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] end end - for i in eachnode(dg) - normal_direction = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - for j in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + for i in eachnode(dg), j in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) + normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) - flux2 = flux(u_node, normal_direction, equations) - flux2_jm1 = flux(u_node_jm1, normal_direction, equations) + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) + flux2 = flux(u_node, normal_direction, equations) + flux2_jm1 = flux(u_node_jm1, normal_direction, equations) - for v in eachvariable(equations) - bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] - end + for v in eachvariable(equations) + bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] end end end @@ -602,35 +595,28 @@ end return nothing end @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates - @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates # Calc lambdas inside the elements @threaded for element in eachelement(dg, cache) - for j in eachnode(dg) - normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - for i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) + normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) - end + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) end - for i in eachnode(dg) - normal_direction = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - for j in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) + for i in eachnode(dg), j in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) + normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) - end + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) end end From 791216ef39a1c84ce1354b6dbdb78170fab6155b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 15 Dec 2022 14:12:26 +0100 Subject: [PATCH 110/423] Merge lambda function --- src/callbacks_step/stepsize_dg2d.jl | 4 +- src/solvers/dgsem_structured/dg_2d.jl | 147 ++++---------------------- src/solvers/dgsem_tree/dg_2d.jl | 111 +++---------------- 3 files changed, 41 insertions(+), 221 deletions(-) diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 23a2ad590f..2ee0bfca16 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -45,7 +45,9 @@ end @inline function max_dt(u, t, mesh::Union{TreeMesh,StructuredMesh}, constant_speed::Val{false}, equations, semi, dg::DG, cache, indicator::Union{IndicatorIDP, IndicatorMCL}) @unpack inverse_weights = dg.basis - @trixi_timeit timer() "calc_lambda!" calc_lambda!(u, t, mesh, equations, dg, cache, indicator, semi.boundary_conditions) + @trixi_timeit timer() "calc_lambda!" calc_lambdas_bar_states!(u, t, mesh, have_nonconservative_terms(equations), equations, + indicator, dg, cache, semi.boundary_conditions; + calcBarStates=false) @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates maxdt = typemax(eltype(u)) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index b8809b65a2..c3e981317b 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -417,7 +417,7 @@ end @inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, - nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calcBarStates=true) if indicator isa IndicatorIDP && !indicator.BarStates return nothing @@ -436,9 +436,11 @@ end normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) + + !calcBarStates && continue + flux1 = flux(u_node, normal_direction, equations) flux1_im1 = flux(u_node_im1, normal_direction, equations) - for v in eachvariable(equations) bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] end @@ -451,9 +453,11 @@ end normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) + + !calcBarStates && continue + flux2 = flux(u_node, normal_direction, equations) flux2_jm1 = flux(u_node_jm1, normal_direction, equations) - for v in eachvariable(equations) bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] end @@ -476,9 +480,11 @@ end lambda1[nnodes(dg)+1, i, left] = lambda lambda1[1, i, element] = lambda + + !calcBarStates && continue + flux_left = flux(u_left, Ja1, equations) flux_element = flux(u_element, Ja1, equations) - bar_state = 0.5 * (u_element + u_left) - 0.5 * (flux_element - flux_left) / lambda for v in eachvariable(equations) bar_states1[v, nnodes(dg)+1, i, left] = bar_state[v] @@ -496,9 +502,11 @@ end lambda2[i, nnodes(dg)+1, lower] = lambda lambda2[i, 1, element] = lambda + + !calcBarStates && continue + flux_lower = flux(u_lower, Ja2, equations) flux_element = flux(u_element, Ja2, equations) - bar_state = 0.5 * (u_element + u_lower) - 0.5 * (flux_element - flux_lower) / lambda for v in eachvariable(equations) bar_states2[v, i, nnodes(dg)+1, lower] = bar_state[v] @@ -524,6 +532,8 @@ end Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) for v in eachvariable(equations) @@ -541,6 +551,8 @@ end Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) for v in eachvariable(equations) @@ -560,6 +572,8 @@ end Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) for v in eachvariable(equations) @@ -577,6 +591,8 @@ end Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) for v in eachvariable(equations) @@ -589,127 +605,6 @@ end return nothing end - -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::StructuredMesh, equations, dg, cache, indicator, boundary_conditions) - if indicator isa IndicatorIDP && !indicator.BarStates - return nothing - end - @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates - @unpack contravariant_vectors = cache.elements - - @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates - - # Calc lambdas inside the elements - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - - normal_direction = get_node_coords(normal_direction_xi, equations, dg, i-1, j, element) - - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) - end - - for i in eachnode(dg), j in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - - normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, j-1, element) - - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) - end - end - - # Calc lambdas at interfaces and periodic boundaries - @threaded for element in eachelement(dg, cache) - # Get neighboring element ids - left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] - - if left != 0 - for i in eachnode(dg) - u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) - u_element = get_node_vars(u, equations, dg, 1, i, element) - - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, i, element) - lambda = max_abs_speed_naive(u_left, u_element, Ja1, equations) - - lambda1[nnodes(dg)+1, i, left] = lambda - lambda1[1, i, element] = lambda - end - end - if lower != 0 - for i in eachnode(dg) - u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) - u_element = get_node_vars(u, equations, dg, i, 1, element) - - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - lambda = max_abs_speed_naive(u_lower, u_element, Ja2, equations) - - lambda2[i, nnodes(dg)+1, lower] = lambda - lambda2[i, 1, element] = lambda - end - end - end - - # Calc lambdas at physical boundaries - if all(mesh.periodicity) - return nothing - end - linear_indices = LinearIndices(size(mesh)) - if !mesh.periodicity[1] - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) - end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) - lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) - end - end - end - if !mesh.periodicity[2] - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) - end - end - # + eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) - lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) - end - end - end - - return nothing -end - - @inline function perform_IDP_correction(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5fcb131531..8e20138b48 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -768,7 +768,7 @@ end end @inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calcBarStates=true) if indicator isa IndicatorIDP && !indicator.BarStates return nothing @@ -782,6 +782,8 @@ end u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) + !calcBarStates && continue + flux1 = flux(u_node, 1, equations) flux1_im1 = flux(u_node_im1, 1, equations) @@ -795,6 +797,8 @@ end u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) + !calcBarStates && continue + flux2 = flux(u_node, 2, equations) flux2_jm1 = flux(u_node_jm1, 2, equations) @@ -821,6 +825,8 @@ end lambda1[nnodes(dg)+1, j, left_id] = lambda lambda1[1, j, right_id] = lambda + !calcBarStates && continue + flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) @@ -839,6 +845,8 @@ end lambda2[i, nnodes(dg)+1, left_id] = lambda lambda2[i, 1, right_id] = lambda + !calcBarStates && continue + flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) @@ -865,6 +873,8 @@ end equations, dg, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -880,6 +890,8 @@ end equations, dg, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -897,6 +909,8 @@ end equations, dg, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -912,6 +926,8 @@ end equations, dg, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) + !calcBarStates && continue + flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -1336,99 +1352,6 @@ end return nothing end -@inline function calc_lambda!(u::AbstractArray{<:Any,4}, t, mesh::TreeMesh2D, equations, dg, cache, indicator, boundary_conditions) - if indicator isa IndicatorIDP && !indicator.BarStates - return nothing - end - @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates - - # Calc lambdas inside the elements - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) - end - - for j in 2:nnodes(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) - end - end - - # Calc lambdas at interfaces and periodic boundaries - @threaded for interface in eachinterface(dg, cache) - left_id = cache.interfaces.neighbor_ids[1, interface] - right_id = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - if orientation == 1 - for j in eachnode(dg) - u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) - u_right = get_node_vars(u, equations, dg, 1, j, right_id) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - - lambda1[nnodes(dg)+1, j, left_id] = lambda - lambda1[1, j, right_id] = lambda - end - else # orientation == 2 - for i in eachnode(dg) - u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) - u_right = get_node_vars(u, equations, dg, i, 1, right_id) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - - lambda2[i, nnodes(dg)+1, left_id] = lambda - lambda2[i, 1, right_id] = lambda - end - end - end - - # Calc lambdas at physical boundaries - @threaded for boundary in eachboundary(dg, cache) - element = cache.boundaries.neighbor_ids[boundary] - orientation = cache.boundaries.orientations[boundary] - neighbor_side = cache.boundaries.neighbor_sides[boundary] - - if orientation == 1 - if neighbor_side == 2 # Element is on the right, boundary on the left - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) - lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - end - else # Element is on the left, boundary on the right - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], - equations, dg, nnodes(dg), j, element) - lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - end - end - else # orientation == 2 - if neighbor_side == 2 # Element is on the right, boundary on the left - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) - lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - end - else # Element is on the left, boundary on the right - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) - lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - end - end - end - end - - return nothing -end - get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, indices...) = u_inner @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, equations, dg, indices...) From 69a0271200f688e5fb6764fe84a64a168537494c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 19 Dec 2022 01:38:27 +0100 Subject: [PATCH 111/423] Fix SSPRK method --- src/solvers/dgsem_structured/dg_2d.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 17 ++++------------- src/solvers/dgsem_tree/indicators_2d.jl | 22 ++++++++++------------ src/time_integration/methods_SSP.jl | 16 ++++++++-------- 4 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index c3e981317b..729eda1887 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -446,7 +446,7 @@ end end end - for i in eachnode(dg), j in 2:nnodes(dg) + for j in 2:nnodes(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 8e20138b48..7c4ad72c3c 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -786,7 +786,6 @@ end flux1 = flux(u_node, 1, equations) flux1_im1 = flux(u_node_im1, 1, equations) - for v in eachvariable(equations) bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - 0.5 * (flux1[v] - flux1_im1[v]) / lambda1[i, j, element] end @@ -801,7 +800,6 @@ end flux2 = flux(u_node, 2, equations) flux2_jm1 = flux(u_node_jm1, 2, equations) - for v in eachvariable(equations) bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - 0.5 * (flux2[v] - flux2_jm1[v]) / lambda2[i, j, element] end @@ -829,7 +827,6 @@ end flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) - bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda for v in eachvariable(equations) bar_states1[v, nnodes(dg)+1, j, left_id] = bar_state[v] @@ -849,7 +846,6 @@ end flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) - bar_state = 0.5 * (u_left + u_right) - 0.5 * (flux_right - flux_left) / lambda for v in eachvariable(equations) bar_states2[v, i, nnodes(dg)+1, left_id] = bar_state[v] @@ -877,7 +873,6 @@ end flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda1[1, j, element] for v in eachvariable(equations) bar_states1[v, 1, j, element] = bar_state[v] @@ -894,7 +889,6 @@ end flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda1[nnodes(dg)+1, j, element] for v in eachvariable(equations) bar_states1[v, nnodes(dg)+1, j, element] = bar_state[v] @@ -913,7 +907,6 @@ end flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_inner - flux_outer) / lambda2[i, 1, element] for v in eachvariable(equations) bar_states2[v, i, 1, element] = bar_state[v] @@ -930,7 +923,6 @@ end flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - 0.5 * (flux_outer - flux_inner) / lambda2[i, nnodes(dg)+1, element] for v in eachvariable(equations) bar_states2[v, i, nnodes(dg)+1, element] = bar_state[v] @@ -1364,13 +1356,12 @@ get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, i end -@inline function antidiffusive_stage!(u_ode, u_old_ode, t, dt, semi, indicator::IndicatorIDP) +@inline function antidiffusive_stage!(u_ode, t, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - u_old = wrap_array(u_old_ode, mesh, equations, solver, cache) - u = wrap_array(u_ode, mesh, equations, solver, cache) + u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, u_old, semi, solver, t, dt) + @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) perform_IDP_correction(u, dt, mesh, equations, solver, cache) @@ -1408,7 +1399,7 @@ end return nothing end -@inline function antidiffusive_stage!(u_ode, u_old_ode, t, dt, semi, indicator::IndicatorMCL) +@inline function antidiffusive_stage!(u_ode, t, dt, semi, indicator::IndicatorMCL) return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index e925d69294..ccb6934bff 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -210,9 +210,7 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation ContainerShockCapturingIndicator, idp_bounds_delta) end -function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::AbstractArray{<:Any,4}, - semi, dg::DGSEM, t, dt; - kwargs...) +function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator alpha .= 0.0 if indicator_IDP.indicator_smooth @@ -222,15 +220,15 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, u_old::Ab end indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, t, dt, semi, elements) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, semi, elements) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, semi, elements) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -588,7 +586,7 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, u_old, t, dt, semi, elements) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @@ -597,7 +595,7 @@ end offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) s_min = var_bounds[offset + 1] if !indicator_IDP.BarStates - calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_old, t, semi) + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_safe, t, semi) end # Perform Newton's bisection method to find new alpha @@ -617,7 +615,7 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, u_old, t, dt, semi, elements) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @@ -627,7 +625,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) s_max = var_bounds[offset + 1] if !indicator_IDP.BarStates - calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_old, t, semi) + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_safe, t, semi) end # Perform Newton's bisection method to find new alpha diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 7d8ca05b91..c33492116b 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -24,7 +24,7 @@ struct SimpleSSPRK33 <: SimpleAlgorithmSSP c::SVector{3, Float64} function SimpleSSPRK33() - a = SVector(1.0, 1/4, 2/3) + a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -155,15 +155,13 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u_safe = integrator.u for stage in eachindex(alg.c) - t_stage = integrator.t + integrator.dt * alg.c[stage] - integrator.f(integrator.du, integrator.u_safe, integrator.p, t_stage) - @trixi_timeit timer() "Runge-Kutta stage" begin - @. integrator.u_old = (1.0 - alg.a[stage]) * integrator.u + alg.a[stage] * integrator.u_safe - @. integrator.u_safe = integrator.u_old + alg.b[stage] * integrator.dt * integrator.du + t_stage = integrator.t + integrator.dt * alg.c[stage] + integrator.f(integrator.du, integrator.u_safe, integrator.p, t_stage) + + @. integrator.u_safe = integrator.u_safe + integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, integrator.u_old, - integrator.t, alg.b[stage] * integrator.dt, integrator.p, indicator) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, t_stage, integrator.dt, integrator.p, indicator) @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) @@ -171,6 +169,8 @@ function solve!(integrator::SimpleIntegratorSSP) if indicator.IDPCheckBounds @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) end + + @. integrator.u_safe = alg.a[stage] * integrator.u + alg.b[stage] * integrator.u_safe end @. integrator.u = integrator.u_safe From db9dfed86d829f3d5202146fe2dd382852622f83 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 10 Jan 2023 11:47:28 +0100 Subject: [PATCH 112/423] Fix MCL limitation --- src/solvers/dgsem_tree/dg_2d.jl | 72 ++++++++++++++-------------- src/solvers/dgsem_tree/indicators.jl | 8 +--- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 7c4ad72c3c..8136e45448 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1125,22 +1125,22 @@ end bar_state_rho = lambda * bar_states1[1, i, j, element] # Limit density if antidiffusive_flux1[1, i, j, element] > 0 - f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i-1, j, element]) + f_max = min(lambda * var_max[1, i-1, j, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max - flux_limited = max(0.0, min(antidiffusive_flux1[1, i, j, element], f_max)) + flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i-1, j, element]) + f_min = max(lambda * var_min[1, i-1, j, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min - flux_limited = min(0.0, max(antidiffusive_flux1[1, i, j, element], f_min)) + flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end # alternative density limiting - # f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - # bar_state_rho - lambda * var_max[1, i-1, j, element]) - # f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - # bar_state_rho - lambda * var_min[1, i-1, j, element]) + # f_min = max(lambda * var_min[1, i-1, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_max[1, i, j, element]) + # f_max = min(lambda * var_max[1, i-1, j, element] - bar_state_rho, + # bar_state_rho - lambda * var_min[1, i, j, element]) # flux_limited = max(f_min, min(antidiffusive_flux1[1, i, j, element], f_max)) if indicator.Plotting @@ -1159,17 +1159,17 @@ end for v in 2:nvariables(equations) bar_states_phi = lambda * bar_states1[v, i, j, element] - rho_limited_i = bar_state_rho + antidiffusive_flux1[1, i, j, element] - rho_limited_im1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = bar_state_rho + antidiffusive_flux1[1, i, j, element] + rho_limited_iim1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] phi = bar_states_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] - rho_limited_i * phi + bar_states_phi + g = antidiffusive_flux1[v, i, j, element] - rho_limited_im1i * phi + bar_states_phi - g_min = max(rho_limited_i * (var_min[v, i, j, element] - phi), - rho_limited_im1 * (phi - var_max[v, i-1, j, element])) - g_max = min(rho_limited_i * (var_max[v, i, j, element] - phi), - rho_limited_im1 * (phi - var_min[v, i-1, j, element])) + g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i, j, element])) + g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 @@ -1187,7 +1187,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux1[v, i, j, element] = rho_limited_i * phi - bar_states_phi + g_limited + antidiffusive_flux1[v, i, j, element] = rho_limited_im1i * phi - bar_states_phi + g_limited end end @@ -1196,22 +1196,22 @@ end bar_state_rho = lambda * bar_states2[1, i, j, element] # Limit density if antidiffusive_flux2[1, i, j, element] > 0 - f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i, j-1, element]) + f_max = min(lambda * var_max[1, i, j-1, element] - bar_state_rho, + bar_state_rho - lambda * var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max - flux_limited = max(0.0, min(antidiffusive_flux2[1, i, j, element], f_max)) + flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i, j-1, element]) + f_min = max(lambda * var_min[1, i, j-1, element] - bar_state_rho, + bar_state_rho - lambda * var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min - flux_limited = min(0.0, max(antidiffusive_flux2[1, i, j, element], f_min)) + flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end # alternative density limiting - # f_min = max(lambda * var_min[1, i, j, element] - bar_state_rho, - # bar_state_rho - lambda * var_max[1, i, j-1, element]) - # f_max = min(lambda * var_max[1, i, j, element] - bar_state_rho, - # bar_state_rho - lambda * var_min[1, i, j-1, element]) + # f_min = max(lambda * var_min[1, i, j-1, element] - bar_state_rho, + # bar_state_rho - lambda * var_max[1, i, j, element]) + # f_max = min(lambda * var_max[1, i, j-1, element] - bar_state_rho, + # bar_state_rho - lambda * var_min[1, i, j, element]) # flux_limited = max(f_min, min(antidiffusive_flux2[1, i, j, element], f_max)) if indicator.Plotting @@ -1230,17 +1230,17 @@ end for v in 2:nvariables(equations) bar_state_phi = lambda * bar_states2[v, i, j, element] - rho_limited_j = bar_state_rho + antidiffusive_flux2[1, i, j, element] - rho_limited_jm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = bar_state_rho + antidiffusive_flux2[1, i, j, element] + rho_limited_jjm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] - rho_limited_j * phi + bar_state_phi + g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + bar_state_phi - g_min = max(rho_limited_j * (var_min[v, i, j, element] - phi), - rho_limited_jm1 * (phi - var_max[v, i, j-1, element])) - g_max = min(rho_limited_j * (var_max[v, i, j, element] - phi), - rho_limited_jm1 * (phi - var_min[v, i, j-1, element])) + g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j, element])) + g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 @@ -1258,7 +1258,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux2[v, i, j, element] = rho_limited_j * phi - bar_state_phi + g_limited + antidiffusive_flux2[v, i, j, element] = rho_limited_jm1j * phi - bar_state_phi + g_limited end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b48786e357..60977a7fea 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -198,9 +198,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), IDPCheckBounds=false, - indicator_smooth=true, - thr_smooth=0.1, - variable_smooth=density_pressure) + indicator_smooth=true, thr_smooth=0.1, variable_smooth=density_pressure) if IDPMathEntropy && IDPSpecEntropy error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") @@ -278,9 +276,7 @@ end function IndicatorMCL(equations::AbstractEquations, basis; IDPPressureTVD=false, IDPCheckBounds=false, - indicator_smooth=false, - thr_smooth=0.1, - variable_smooth=density_pressure, + indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)+IDPPressureTVD) From dc85a2c86db01c3df0a1d0f7dc1936cb472f2331 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 10 Jan 2023 13:16:33 +0100 Subject: [PATCH 113/423] Reduce unnecessary calculations --- src/solvers/dgsem_tree/dg_2d.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 8136e45448..312cc3132e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1156,12 +1156,11 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy + rho_limited_im1i = bar_state_rho + antidiffusive_flux1[1, i, j, element] + rho_limited_iim1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] for v in 2:nvariables(equations) bar_states_phi = lambda * bar_states1[v, i, j, element] - rho_limited_im1i = bar_state_rho + antidiffusive_flux1[1, i, j, element] - rho_limited_iim1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] - phi = bar_states_phi / bar_state_rho g = antidiffusive_flux1[v, i, j, element] - rho_limited_im1i * phi + bar_states_phi @@ -1227,12 +1226,11 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy + rho_limited_jm1j = bar_state_rho + antidiffusive_flux2[1, i, j, element] + rho_limited_jjm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] for v in 2:nvariables(equations) bar_state_phi = lambda * bar_states2[v, i, j, element] - rho_limited_jm1j = bar_state_rho + antidiffusive_flux2[1, i, j, element] - rho_limited_jjm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] - phi = bar_state_phi / bar_state_rho g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + bar_state_phi From 0c44f35e3278958b5143056ef8ebab01cb8f600b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 11 Jan 2023 17:05:42 +0100 Subject: [PATCH 114/423] Revise BoundsCheck --- src/solvers/dgsem_tree/dg.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 150 ++++++++++-------------- src/solvers/dgsem_tree/indicators.jl | 26 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 5 +- src/time_integration/methods_SSP.jl | 5 +- 5 files changed, 82 insertions(+), 108 deletions(-) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index a3d06feb1d..af7bb7ec0c 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -44,11 +44,11 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end -@inline function IDP_checkBounds(u_ode, semi) +@inline function IDP_checkBounds(u_ode, semi, iter, laststage) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) - IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator) + IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator, iter, laststage) return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 312cc3132e..1355e98e4d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1261,7 +1261,7 @@ end end # Limit pressure - if indicator.IDPPressureTVD + if indicator.IDPPressure @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator if indicator.Plotting alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) @@ -1403,13 +1403,14 @@ end end # 2d, IndicatorIDP -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP) +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP, iter, laststage) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta = solver.volume_integral.indicator.cache # Save the deviations every x iterations x = 0 + save_errors = laststage && (x > 0) && (iter % x == 0) counter = 1 if IDPDensityTVD deviation_min = zero(eltype(u)) @@ -1420,6 +1421,12 @@ end end idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) + if save_errors + deviation_min_ = deviation_min + deviation_max_ = deviation_max + open("Deviation_rho_min.txt", "a") do f; println(f, deviation_min_); end + open("Deviation_rho_max.txt", "a") do f; println(f, deviation_max_); end + end counter += 2 end if IDPPressureTVD @@ -1432,6 +1439,12 @@ end end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], deviation_max) + if save_errors + deviation_min_ = deviation_min + deviation_max_ = deviation_max + open("Deviation_pre_min.txt", "a") do f; println(f, deviation_min_); end + open("Deviation_pre_max.txt", "a") do f; println(f, deviation_max_); end + end counter += 2 end if IDPPositivity && !IDPDensityTVD @@ -1440,6 +1453,10 @@ end deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - u[1, i, j, element]) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors + deviation_min_ = deviation_min + open("Deviation_rho_min.txt", "a") do f; println(f, deviation_min_); end + end counter += 1 end if IDPPositivity && !IDPPressureTVD @@ -1449,6 +1466,10 @@ end deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors + deviation_min_ = deviation_min + open("Deviation_pre_min.txt", "a") do f; println(f, deviation_min_); end + end counter += 1 end if IDPSpecEntropy @@ -1458,6 +1479,10 @@ end deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - s) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors + deviation_min_ = deviation_min + open("Deviation_specEntr.txt", "a") do f; println(f, deviation_min_); end + end counter += 1 end if IDPMathEntropy @@ -1467,111 +1492,58 @@ end deviation_max = max(deviation_max, s - var_bounds[counter][i, j, element]) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) + if save_errors + deviation_max_ = deviation_max + open("Deviation_mathEntr.txt", "a") do f; println(f, deviation_max_); end + end end return nothing end # 2d, IndicatorMCL -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL) +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL, iter, laststage) @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D n_vars = nvariables(equations) + + deviation_min = zeros(eltype(u), n_vars + indicator.IDPPressure) + deviation_max = zeros(eltype(u), n_vars) + + # Save the deviations every x iterations + x = 1 + save_errors = laststage && (x > 0) && (iter % x == 0) for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 2:nnodes(solver) - lambda = lambda1[i, j, element] - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda - idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) - idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - if indicator.IDPPressureTVD - error_pressure = zero(eltype(idp_bounds_delta)) - var_limited = zero(eltype(idp_bounds_delta)) - end - for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda - idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) - idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) - if indicator.IDPPressureTVD - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressureTVD - error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited - idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) - end - end - # +x - for j in eachnode(solver), i in 1:nnodes(solver)-1 - lambda = lambda1[i+1, j, element] - rho_limited = bar_states1[1, i+1, j, element] - antidiffusive_flux1[1, i+1, j, element] / lambda - idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) - idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - if indicator.IDPPressureTVD - error_pressure = zero(eltype(idp_bounds_delta)) - var_limited = zero(eltype(idp_bounds_delta)) - end + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) for v in 2:n_vars - var_limited = bar_states1[v, i+1, j, element] - antidiffusive_flux1[v, i+1, j, element] / lambda - idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) - idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) - if indicator.IDPPressureTVD - error_pressure += 0.5 * var_limited^2 - end + var_limited = u[v, i, j, element] / u[1, i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) end - if indicator.IDPPressureTVD - error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited - idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) + if indicator.IDPPressure + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end end - # -y - for j in 2:nnodes(solver), i in eachnode(solver) - lambda = lambda2[i, j, element] - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda - idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) - idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - if indicator.IDPPressureTVD - error_pressure = zero(eltype(idp_bounds_delta)) - var_limited = zero(eltype(idp_bounds_delta)) - end - for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda - idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) - idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) - if indicator.IDPPressureTVD - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressureTVD - error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited - idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) - end + end + vars = varnames(cons2cons, equations) + for v in eachvariable(equations) + idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) + idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) + if save_errors + open(string("Deviation_", vars[v], "_min.txt"), "a") do f; println(f, deviation_min[v]); end + open(string("Deviation_", vars[v], "_max.txt"), "a") do f; println(f, deviation_max[v]); end end - # +y - for j in 1:nnodes(solver)-1, i in eachnode(solver) - lambda = lambda2[i, j+1, element] - rho_limited = bar_states2[1, i, j+1, element] - antidiffusive_flux2[1, i, j+1, element] / lambda - idp_bounds_delta[1] = max(idp_bounds_delta[1], var_min[1, i, j, element] - rho_limited) - idp_bounds_delta[2] = max(idp_bounds_delta[2], rho_limited - var_max[1, i, j, element]) - if indicator.IDPPressureTVD - error_pressure = zero(eltype(idp_bounds_delta)) - var_limited = zero(eltype(idp_bounds_delta)) - end - for v in 2:n_vars - var_limited = bar_states2[v, i, j+1, element] - antidiffusive_flux2[v, i, j+1, element] / lambda - idp_bounds_delta[2*v-1] = max(idp_bounds_delta[2*v-1], rho_limited * var_min[v, i, j, element] - var_limited) - idp_bounds_delta[2*v ] = max(idp_bounds_delta[2*v ], var_limited - rho_limited * var_max[v, i, j, element]) - if indicator.IDPPressureTVD - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressureTVD - error_pressure -= 0.5 * var_limited^2 + var_limited * rho_limited - idp_bounds_delta[2*n_vars+1] = max(idp_bounds_delta[2*n_vars+1], error_pressure) - end + end + if indicator.IDPPressure + idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) + if save_errors + open("Deviation_pressure.txt", "a") do f; println(f, deviation_min[n_vars+1]); end end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 60977a7fea..830a74991a 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -264,39 +264,39 @@ IndicatorMCL """ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator cache::Cache - IDPPressureTVD::Bool # synchronized pressure limiting + IDPPressure::Bool # synchronized pressure limiting IDPCheckBounds::Bool - indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner - thr_smooth::RealT # threshold for smoothness indicator + indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorMCL(equations::AbstractEquations, basis; - IDPPressureTVD=false, + IDPPressure=false, IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) - cache = create_cache(IndicatorMCL, equations, basis, 2*nvariables(equations)+IDPPressureTVD) + cache = create_cache(IndicatorMCL, equations, basis, IDPPressure) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, variable=variable_smooth) else IndicatorHG = nothing end - IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, IDPPressureTVD, IDPCheckBounds, - indicator_smooth, thr_smooth, IndicatorHG, Plotting) + IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, IDPPressure, + IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @nospecialize indicator # reduce precompilation time print(io, "IndicatorMCL(") - print(io, "density, velocity, total energy") - indicator.IDPPressureTVD && print(io, ", pressure") - indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, + print(io, "Limiting of density, velocity and total energy") + indicator.IDPPressure && print(io, "; pressure limiting") + indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) print(io, ")") end @@ -308,13 +308,13 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn @unpack alpha = indicator.cache.ContainerShockCapturingIndicator variables = varnames(cons2cons, equations) for v in eachvariable(equations) - s = Symbol("shock_capturing_delta_volume_flux_", variables[v]) + s = Symbol("shock_capturing_alpha_", variables[v]) node_variables[s] = alpha[v, ntuple(_ -> :, nvariables(equations) + 1)...] end - if indicator.IDPPressureTVD + if indicator.IDPPressure @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - node_variables[:indicator_shock_capturing_pressure] = alpha_pressure + node_variables[:shock_capturing_alpha_pressure] = alpha_pressure end return nothing diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ccb6934bff..746c3f0c03 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -904,11 +904,12 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length) +function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, + basis::LobattoLegendreBasis, IDPPressure) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), length) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index c33492116b..172fd73eb4 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -167,7 +167,8 @@ function solve!(integrator::SimpleIntegratorSSP) # Check that we are within bounds if indicator.IDPCheckBounds - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p) + laststage = (stage == length(alg.c)) + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p, integrator.iter, laststage) end @. integrator.u_safe = alg.a[stage] * integrator.u + alg.b[stage] * integrator.u_safe @@ -361,7 +362,7 @@ end for v in eachvariable(equations) println(variables[v], ":\n- lower bound: ", idp_bounds_delta[2*v-1], "\n- upper bound: ", idp_bounds_delta[2*v]) end - if indicator.IDPPressureTVD + if indicator.IDPPressure println("pressure:\n- lower bound: ", idp_bounds_delta[2*nvariables(equations)+1]) end println("─"^100 * "\n") From 4fe13acc75033ea8c65a85754b5b45e0fe4a6d96 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 11 Jan 2023 17:31:27 +0100 Subject: [PATCH 115/423] Add previous solution to calculation of Bounds --- src/solvers/dgsem_tree/dg_2d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 1355e98e4d..e98d4a656d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1067,6 +1067,14 @@ end end for j in eachnode(dg), i in eachnode(dg) + # Previous solution + var_min[1, i, j, element] = min(var_min[1, i, j, element], u[1, i, j, element]) + var_max[1, i, j, element] = max(var_max[1, i, j, element], u[1, i, j, element]) + for v in 2:nvariables(equations) + phi = u[v, i, j, element] / u[1, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], phi) + end # - xi direction bar_state_rho = bar_states1[1, i, j, element] var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) From 9090c069f93cb79b28f3168cd52ad47fd795cf4d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 11 Jan 2023 19:00:42 +0100 Subject: [PATCH 116/423] Remove not-needed text; Rename in elixirs --- examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 4 +++- .../elixir_euler_kelvin_helmholtz_instability_MCL.jl | 2 +- src/time_integration/methods_SSP.jl | 9 --------- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index d35262e114..c57e51df1d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -45,7 +45,7 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorMCL(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=true, + IDPPressure=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index e732597b06..73fde7b6dd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,7 +39,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorMCL(equations, basis; - IDPPressureTVD=true) + IDPCheckBounds=true, + IDPPressure=false, + Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index e6130cd0c3..e543bbd732 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -38,7 +38,7 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorMCL(equations, basis; IDPCheckBounds=true, - IDPPressureTVD=false, + IDPPressure=false, indicator_smooth=false, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 172fd73eb4..52ffa52826 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -175,15 +175,6 @@ function solve!(integrator::SimpleIntegratorSSP) end @. integrator.u = integrator.u_safe - # Note: - # @. integrator.u_old = (1.0 - alg.a[i]) * integrator.u + alg.a[i] * integrator.u_safe - # The combination of the macro muladd with the operator @. changes the order of operations knowingly, which - # results in changed solutions. - # Moreover, unrolling the for-loop changes the order unexpectedly. Using a cache variable like - # @. u_tmp = (1.0 - alg.a[i]) * integrator.u - # @. integrator.u_old = u_tmp + alg.a[i] * integrator.u_safe - # solves the differences between the (not-)unrolled for-loop versions. - if integrator.p.solver.volume_integral.indicator isa IndicatorIDP indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t end From 4c7f73c256aeba84abb59e2b0209d82c755896d1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 11 Jan 2023 20:59:18 +0100 Subject: [PATCH 117/423] Rename u_safe; Remove u_old --- src/solvers/dgsem_tree/indicators_2d.jl | 76 ++++++++++++------------- src/time_integration/methods_SSP.jl | 26 ++++----- 2 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 746c3f0c03..3123313ef6 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -210,7 +210,7 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation ContainerShockCapturingIndicator, idp_bounds_delta) end -function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) +function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator alpha .= 0.0 if indicator_IDP.indicator_smooth @@ -220,15 +220,15 @@ function (indicator_IDP::IndicatorIDP)(u_safe::AbstractArray{<:Any,4}, semi, dg: end indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u_safe, dt, semi, elements) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements) indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) + @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -456,7 +456,7 @@ end return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) +@inline function IDP_densityTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, _, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -464,7 +464,7 @@ end rho_min = var_bounds[1] rho_max = var_bounds[2] if !indicator_IDP.BarStates - calc_bounds_2sided!(rho_min, rho_max, density, u_safe, t, semi) + calc_bounds_2sided!(rho_min, rho_max, density, u, t, semi) end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @@ -478,7 +478,7 @@ end if mesh isa StructuredMesh inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - rho = u_safe[1, i, j, element] + rho = u[1, i, j, element] # Real Zalesak type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @@ -515,7 +515,7 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) +@inline function IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) # IDP limiter for pressure based on # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @@ -526,7 +526,7 @@ end p_min = var_bounds[1 + offset] p_max = var_bounds[2 + offset] if !indicator_IDP.BarStates - calc_bounds_2sided!(p_min, p_max, pressure, u_safe, t, semi) + calc_bounds_2sided!(p_min, p_max, pressure, u, t, semi) end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @@ -540,7 +540,7 @@ end if mesh isa StructuredMesh inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - p = pressure(get_node_vars(u_safe, equations, dg, i, j, element), equations) + p = pressure(get_node_vars(u, equations, dg, i, j, element), equations) # Real Zalesak type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" @@ -552,8 +552,8 @@ end # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - v1 = u_safe[2, i, j, element] / u_safe[1, i, j, element] - v2 = u_safe[3, i, j, element] / u_safe[1, i, j, element] + v1 = u[2, i, j, element] / u[1, i, j, element] + v2 = u[3, i, j, element] / u[1, i, j, element] v2s2 = 0.5 * (v1^2 + v2^2) gamma_m1 = equations.gamma - 1.0 @@ -586,7 +586,7 @@ end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) +@inline function IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @@ -595,13 +595,13 @@ end offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) s_min = var_bounds[offset + 1] if !indicator_IDP.BarStates - calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u_safe, t, semi) + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u_safe, equations, dg, i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, dt, mesh, equations, dg, cache, indicator_IDP) @@ -615,7 +615,7 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u_safe, t, dt, semi, elements) +@inline function IDP_mathEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @@ -625,13 +625,13 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) s_max = var_bounds[offset + 1] if !indicator_IDP.BarStates - calc_bounds_1sided!(s_max, max, typemin, entropy_math, u_safe, t, semi) + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u_safe, equations, dg, i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, dt, mesh, equations, dg, cache, indicator_IDP) @@ -645,7 +645,7 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u_safe, dt, semi, elements) +@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -677,15 +677,15 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto ####################### # Correct density ####################### - if u_safe[1, i, j, element] < 0.0 - println("Error: safe density is not safe. element=$element, node: $i $j, density=$(u_safe[1, i, j, element])") + if u[1, i, j, element] < 0.0 + println("Error: safe density is not safe. element=$element, node: $i $j, density=$(u[1, i, j, element])") end # Compute bound if indicator_IDP.IDPDensityTVD - rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * u_safe[1, i, j, element]) + rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * u[1, i, j, element]) else - rho_min[i, j, element] = positCorrFactor * u_safe[1, i, j, element] + rho_min[i, j, element] = positCorrFactor * u[1, i, j, element] end # Real one-sided Zalesak-type limiter @@ -693,7 +693,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qm = min(0.0, (rho_min[i, j, element] - u_safe[1, i, j, element]) / dt) + Qm = min(0.0, (rho_min[i, j, element] - u[1, i, j, element]) / dt) # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -718,7 +718,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto ####################### # Compute bound - u_local = get_node_vars(u_safe, equations, dg, i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) p_safe = pressure(u_local, equations) if p_safe < 0.0 println("Error: safe pressure is not safe. element=$element, node: $i $j, pressure=$p_safe") @@ -744,7 +744,7 @@ pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(dpdu(u, equati pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0.0 pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) -@inline function newton_loops_alpha!(alpha, bound, u_safe, i, j, element, +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, dt, mesh, equations, dg, cache, indicator_IDP) @unpack inverse_weights = dg.basis @@ -759,24 +759,24 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma # negative xi direction antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # positive xi direction antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # negative eta direction antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) # positive eta direction antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - newton_loop!(alpha, bound, u_safe, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u_safe, i, j, element, +@inline function newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) newton_reltol, newton_abstol = indicator_IDP.newton_tol @@ -786,7 +786,7 @@ end beta_L = 0.0 # alpha = 1 beta_R = beta # No higher beta (lower alpha) than the current one - u_curr = u_safe + beta * dt * antidiffusive_flux + u_curr = u + beta * dt * antidiffusive_flux # If state is valid, perform initial check and return if correction is not needed if isValidState(u_curr, equations) @@ -816,7 +816,7 @@ end # Out of bounds, do a bisection step beta = 0.5 * (beta_L + beta_R) # Get new u - u_curr = u_safe + beta * dt * antidiffusive_flux + u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, finish bisection step without checking tolerance and iterate further if !isValidState(u_curr, equations) @@ -835,7 +835,7 @@ end end else # Get new u - u_curr = u_safe + beta * dt * antidiffusive_flux + u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, redefine right bound without checking tolerance and iterate further if !isValidState(u_curr, equations) @@ -905,11 +905,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, IDPPressure) + basis::LobattoLegendreBasis, IDPPressure, IDPSemiDiscEntropy) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure + IDPSemiDiscEntropy) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 52ffa52826..1f724e835e 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -61,8 +61,7 @@ end mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, F, Alg, SimpleIntegratorSSPOptions} u::uType du::uType - u_safe::uType - u_old::uType + r0::uType t::RealT dt::RealT # current time step dtcache::RealT # ignored @@ -97,11 +96,10 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, dt, callback=nothing, kwargs...) u = copy(ode.u0) du = similar(u) - u_safe = similar(u) - u_old = similar(u) + r0 = similar(u) t = first(ode.tspan) iter = 0 - integrator = SimpleIntegratorSSP(u, du, u_safe, u_old, t, dt, zero(dt), iter, ode.p, + integrator = SimpleIntegratorSSP(u, du, r0, t, dt, zero(dt), iter, ode.p, (prob=ode,), ode.f, alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) @@ -153,27 +151,26 @@ function solve!(integrator::SimpleIntegratorSSP) end end - @. integrator.u_safe = integrator.u + @. integrator.r0 = integrator.u for stage in eachindex(alg.c) @trixi_timeit timer() "Runge-Kutta stage" begin t_stage = integrator.t + integrator.dt * alg.c[stage] - integrator.f(integrator.du, integrator.u_safe, integrator.p, t_stage) + integrator.f(integrator.du, integrator.u, integrator.p, t_stage) - @. integrator.u_safe = integrator.u_safe + integrator.dt * integrator.du + @. integrator.u = integrator.u + integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u_safe, t_stage, integrator.dt, integrator.p, indicator) + @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) # Check that we are within bounds if indicator.IDPCheckBounds laststage = (stage == length(alg.c)) - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u_safe, integrator.p, integrator.iter, laststage) + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u, integrator.p, integrator.iter, laststage) end - @. integrator.u_safe = alg.a[stage] * integrator.u + alg.b[stage] * integrator.u_safe + @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end - @. integrator.u = integrator.u_safe if integrator.p.solver.volume_integral.indicator isa IndicatorIDP indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t @@ -220,7 +217,7 @@ end # get a cache where the RHS can be stored get_du(integrator::SimpleIntegratorSSP) = integrator.du -get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.u_safe, integrator.u_old) +get_tmp_cache(integrator::SimpleIntegratorSSP) = (integrator.r0,) # some algorithms from DiffEq like FSAL-ones need to be informed when a callback has modified u u_modified!(integrator::SimpleIntegratorSSP, ::Bool) = false @@ -246,8 +243,7 @@ end function Base.resize!(integrator::SimpleIntegratorSSP, new_size) resize!(integrator.u, new_size) resize!(integrator.du, new_size) - resize!(integrator.u_safe, new_size) - resize!(integrator.u_old, new_size) + resize!(integrator.r0, new_size) # Resize container resize!(integrator.p, new_size) From b08244095e0a4a9e54b1de159b2ed71e19fd6e41 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 11 Jan 2023 21:25:16 +0100 Subject: [PATCH 118/423] Add explanations --- src/time_integration/methods_SSP.jl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 1f724e835e..cc09f92741 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -103,7 +103,7 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, (prob=ode,), ode.f, alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), false) - # Resize container + # resize container resize!(integrator.p, nelements(integrator.p.solver, integrator.p.cache)) # initialize callbacks @@ -140,7 +140,7 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - # Reset alphas for PLotting of MCL + # reset alphas for Plotting of MCL @unpack indicator = integrator.p.solver.volume_integral if indicator isa IndicatorMCL && indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator @@ -155,20 +155,23 @@ function solve!(integrator::SimpleIntegratorSSP) for stage in eachindex(alg.c) @trixi_timeit timer() "Runge-Kutta stage" begin t_stage = integrator.t + integrator.dt * alg.c[stage] + # compute du integrator.f(integrator.du, integrator.u, integrator.p, t_stage) + # perfom forward Euler step @. integrator.u = integrator.u + integrator.dt * integrator.du end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) - # Check that we are within bounds + # check that we are within bounds if indicator.IDPCheckBounds laststage = (stage == length(alg.c)) @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u, integrator.p, integrator.iter, laststage) end + # perform convex combination @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end @@ -233,7 +236,7 @@ function terminate!(integrator::SimpleIntegratorSSP) empty!(integrator.opts.tstops) if integrator.p.solver.volume_integral.indicator isa IndicatorIDP - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) + resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) resize!(integrator.p.solver.volume_integral.indicator.cache.time_per_timestep, integrator.iter+1) end @@ -347,10 +350,10 @@ end println("─"^100) variables = varnames(cons2cons, equations) for v in eachvariable(equations) - println(variables[v], ":\n- lower bound: ", idp_bounds_delta[2*v-1], "\n- upper bound: ", idp_bounds_delta[2*v]) + println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) end if indicator.IDPPressure - println("pressure:\n- lower bound: ", idp_bounds_delta[2*nvariables(equations)+1]) + println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(equations)+1]) end println("─"^100 * "\n") From d413073167935314f620f9aa01605e6f7ed08cb3 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 12 Jan 2023 15:43:27 +0100 Subject: [PATCH 119/423] Fix create_cache --- src/solvers/dgsem_tree/indicators_2d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 3123313ef6..24edbe4297 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -905,11 +905,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, IDPPressure, IDPSemiDiscEntropy) + basis::LobattoLegendreBasis, IDPPressure) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure + IDPSemiDiscEntropy) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end From 4c87a696d969cfec306eb52e779d724032c7e548 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 16 Jan 2023 13:20:07 +0100 Subject: [PATCH 120/423] Revise BoundsCheck --- src/solvers/dgsem_tree/dg_2d.jl | 89 ++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e98d4a656d..9c21612677 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1524,18 +1524,93 @@ end # Save the deviations every x iterations x = 1 save_errors = laststage && (x > 0) && (iter % x == 0) + + var_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} + # - velocities and energy (phi): + # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v_1}^{Lim}|^2 / 2 for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) - deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + # -x + for j in eachnode(solver), i in 2:nnodes(solver)+1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +x + for j in eachnode(solver), i in 1:nnodes(solver) + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) for v in 2:n_vars - var_limited = u[v, i, j, element] / u[1, i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # -y + for j in 2:nnodes(solver)+1, i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +y + for j in 1:nnodes(solver), i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end end if indicator.IDPPressure - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) end end end From 434ac2fb184b8fb0713cd2ad78ee0102163855b6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 16 Jan 2023 13:21:17 +0100 Subject: [PATCH 121/423] Rescale variable --- src/solvers/dgsem_tree/dg_2d.jl | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 9c21612677..35650ee115 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1130,16 +1130,16 @@ end for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] - bar_state_rho = lambda * bar_states1[1, i, j, element] + bar_state_rho = bar_states1[1, i, j, element] # Limit density if antidiffusive_flux1[1, i, j, element] > 0 - f_max = min(lambda * var_max[1, i-1, j, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i, j, element]) + f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - f_min = max(lambda * var_min[1, i-1, j, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i, j, element]) + f_min = lambda * max(var_min[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end @@ -1164,14 +1164,14 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_im1i = bar_state_rho + antidiffusive_flux1[1, i, j, element] - rho_limited_iim1 = bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] + rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] for v in 2:nvariables(equations) - bar_states_phi = lambda * bar_states1[v, i, j, element] + bar_states_phi = bar_states1[v, i, j, element] phi = bar_states_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] - rho_limited_im1i * phi + bar_states_phi + g = antidiffusive_flux1[v, i, j, element] - (rho_limited_im1i * phi - lambda * bar_states_phi) g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), rho_limited_iim1 * (phi - var_max[v, i, j, element])) @@ -1194,22 +1194,22 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux1[v, i, j, element] = rho_limited_im1i * phi - bar_states_phi + g_limited + antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited end end for j in 2:nnodes(dg), i in eachnode(dg) lambda = lambda2[i, j, element] - bar_state_rho = lambda * bar_states2[1, i, j, element] + bar_state_rho = bar_states2[1, i, j, element] # Limit density if antidiffusive_flux2[1, i, j, element] > 0 - f_max = min(lambda * var_max[1, i, j-1, element] - bar_state_rho, - bar_state_rho - lambda * var_min[1, i, j, element]) + f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - f_min = max(lambda * var_min[1, i, j-1, element] - bar_state_rho, - bar_state_rho - lambda * var_max[1, i, j, element]) + f_min = lambda * max(var_min[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end @@ -1234,14 +1234,14 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_jm1j = bar_state_rho + antidiffusive_flux2[1, i, j, element] - rho_limited_jjm1 = bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] + rho_limited_jjm1 = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] for v in 2:nvariables(equations) - bar_state_phi = lambda * bar_states2[v, i, j, element] + bar_state_phi = bar_states2[v, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + bar_state_phi + g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + lambda * bar_state_phi g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), rho_limited_jjm1 * (phi - var_max[v, i, j, element])) @@ -1264,7 +1264,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux2[v, i, j, element] = rho_limited_jm1j * phi - bar_state_phi + g_limited + antidiffusive_flux2[v, i, j, element] = rho_limited_jm1j * phi - lambda * bar_state_phi + g_limited end end From 9bf83d27544f3c40054350f63e816ffeecd43914 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 Jan 2023 11:06:25 +0100 Subject: [PATCH 122/423] Add alternative BoundsCheck --- src/solvers/dgsem_tree/dg_2d.jl | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 35650ee115..bbb807fa5e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1525,8 +1525,23 @@ end x = 1 save_errors = laststage && (x > 0) && (iter % x == 0) - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + for v in 2:n_vars + var_limited = u[v, i, j, element] / u[1, i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + end + if indicator.IDPPressure + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ # Checking the bounds for... @@ -1536,6 +1551,8 @@ end # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v_1}^{Lim}|^2 / 2 + var_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) # -x for j in eachnode(solver), i in 2:nnodes(solver)+1 @@ -1614,6 +1631,7 @@ end end end end + vars = varnames(cons2cons, equations) for v in eachvariable(equations) idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) From 9216765a8a2833bbb44d037770376c0829528a96 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 Jan 2023 11:07:33 +0100 Subject: [PATCH 123/423] Add BoundsCheck as comment --- src/solvers/dgsem_tree/dg_2d.jl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index bbb807fa5e..45d5ebc9d2 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1526,21 +1526,21 @@ end save_errors = laststage && (x > 0) && (iter % x == 0) # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) - deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) - for v in 2:n_vars - var_limited = u[v, i, j, element] / u[1, i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - end - if indicator.IDPPressure - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - end - end - end + # for element in eachelement(solver, cache) + # for j in eachnode(solver), i in eachnode(solver) + # deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + # deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + # for v in 2:n_vars + # var_limited = u[v, i, j, element] / u[1, i, j, element] + # deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + # deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + # end + # if indicator.IDPPressure + # error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + # deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # end + # end + # end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ From c3c1e444eaab8df070746fbe101055ff83adad2f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 Jan 2023 20:11:46 +0100 Subject: [PATCH 124/423] Fix index error --- src/solvers/dgsem_tree/dg_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 45d5ebc9d2..f13298de77 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1082,7 +1082,7 @@ end for v in 2:nvariables(equations) bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, 1, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) end # + xi direction bar_state_rho = bar_states1[1, i+1, j, element] From 3d308394ed82973249ef952b7735a4d5c245148c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 17 Jan 2023 20:21:34 +0100 Subject: [PATCH 125/423] Revise limiting of g --- src/solvers/dgsem_tree/dg_2d.jl | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index f13298de77..19f0cc04bf 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1172,17 +1172,16 @@ end phi = bar_states_phi / bar_state_rho g = antidiffusive_flux1[v, i, j, element] - (rho_limited_im1i * phi - lambda * bar_states_phi) - - g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i, j, element])) - g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min - g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 - g_limited = max(0.0, min(g_max, max(g, g_min))) + g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) else - g_limited = min(0.0, max(g_min, min(g, g_max))) + g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_limited = max(g_min, min(g_min, 0.0)) end if indicator.Plotting if isapprox(g, 0.0, atol=eps()) @@ -1242,17 +1241,16 @@ end phi = bar_state_phi / bar_state_rho g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + lambda * bar_state_phi - - g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j, element])) - g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min - g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 - g_limited = max(0.0, min(g_max, max(g, g_min))) + g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) else - g_limited = min(0.0, max(g_min, min(g, g_max))) + g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting if isapprox(g, 0.0, atol=eps()) From 93b2e59c0ec38440ada57b587af159c0c474fdb1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 18 Jan 2023 00:47:24 +0100 Subject: [PATCH 126/423] Correct indices in limitation --- src/solvers/dgsem_tree/dg_2d.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index f13298de77..4129a09eef 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1133,13 +1133,13 @@ end bar_state_rho = bar_states1[1, i, j, element] # Limit density if antidiffusive_flux1[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) + f_max = lambda * min(var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i-1, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[1, i-1, j, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) + f_min = lambda * max(var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i-1, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end @@ -1173,10 +1173,10 @@ end g = antidiffusive_flux1[v, i, j, element] - (rho_limited_im1i * phi - lambda * bar_states_phi) - g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i, j, element])) - g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i, j, element])) + g_min = max(rho_limited_im1i * (var_min[v, i, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i-1, j, element])) + g_max = min(rho_limited_im1i * (var_max[v, i, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i-1, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 @@ -1203,13 +1203,13 @@ end bar_state_rho = bar_states2[1, i, j, element] # Limit density if antidiffusive_flux2[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) + f_max = lambda * min(var_max[1, i, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j-1, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[1, i, j-1, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) + f_min = lambda * max(var_min[1, i, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j-1, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end @@ -1243,10 +1243,10 @@ end g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + lambda * bar_state_phi - g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j, element])) - g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j, element])) + g_min = max(rho_limited_jm1j * (var_min[v, i, j, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j-1, element])) + g_max = min(rho_limited_jm1j * (var_max[v, i, j, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j-1, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max if g > 0 From 8b51138b62656eb0ae42a5f24891279f1aa199c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 18 Jan 2023 14:19:27 +0100 Subject: [PATCH 127/423] Fixed BoundCheck for limited bar states and specified type for `start_time` when calling `AnalysisCallback` -> We now check that the solution AND the limited bar states are within bounds --- src/callbacks_step/analysis.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 70 ++++++++++++++++----------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index 59b2d2e911..523e938404 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -101,7 +101,7 @@ function AnalysisCallback(mesh, equations::AbstractEquations, solver, cache; analyzer = SolutionAnalyzer(solver; kwargs...) cache_analysis = create_cache_analysis(analyzer, mesh, equations, solver, cache, RealT, uEltype) - analysis_callback = AnalysisCallback(0.0, interval, save_analysis, output_directory, analysis_filename, + analysis_callback = AnalysisCallback(Float64(0.0), interval, save_analysis, output_directory, analysis_filename, analyzer, analysis_errors, Tuple(analysis_integrals), SVector(ntuple(_ -> zero(uEltype), Val(nvariables(equations)))), diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ef0d708d49..5d81cdbffc 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1512,21 +1512,21 @@ end save_errors = laststage && (x > 0) && (iter % x == 0) # New solution u^{n+1} - # for element in eachelement(solver, cache) - # for j in eachnode(solver), i in eachnode(solver) - # deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) - # deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) - # for v in 2:n_vars - # var_limited = u[v, i, j, element] / u[1, i, j, element] - # deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - # deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - # end - # if indicator.IDPPressure - # error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - # deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - # end - # end - # end + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + for v in 2:n_vars + var_limited = u[v, i, j, element] / u[1, i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + end + if indicator.IDPPressure + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ @@ -1541,14 +1541,14 @@ end error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) # -x - for j in eachnode(solver), i in 2:nnodes(solver)+1 + for j in eachnode(solver), i in 1:nnodes(solver) rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) for v in 2:n_vars var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1560,14 +1560,14 @@ end end end # +x - for j in eachnode(solver), i in 1:nnodes(solver) + for j in eachnode(solver), i in 2:nnodes(solver)+1 rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1579,14 +1579,14 @@ end end end # -y - for j in 2:nnodes(solver)+1, i in eachnode(solver) + for j in 1:nnodes(solver), i in eachnode(solver) rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) for v in 2:n_vars var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1598,14 +1598,14 @@ end end end # +y - for j in 1:nnodes(solver), i in eachnode(solver) + for j in 2:nnodes(solver)+1, i in eachnode(solver) rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end From a11fc4bf5967336c628d09c63273c47244579f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 18 Jan 2023 14:25:57 +0100 Subject: [PATCH 128/423] Fixed indexing for the new computation of the limited fluxes for velocity and energy --- src/solvers/dgsem_tree/dg_2d.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5d81cdbffc..3d031ac963 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1167,13 +1167,13 @@ end g = antidiffusive_flux1[v, i, j, element] - (rho_limited_im1i * phi - lambda * bar_states_phi) if g > 0 - g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i, j, element])) + g_max = min(rho_limited_im1i * (var_max[v, i, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i-1, j, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i, j, element])) + g_min = max(rho_limited_im1i * (var_min[v, i, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i-1, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end @@ -1230,13 +1230,13 @@ end g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + lambda * bar_state_phi if g > 0 - g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j, element])) + g_max = min(rho_limited_jm1j * (var_max[v, i, j, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j-1, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j, element])) + g_min = max(rho_limited_jm1j * (var_min[v, i, j, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j-1, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end From 13da00c4a334ad816b90753eaf3cc7cdad36b9d0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 19 Jan 2023 15:35:39 +0100 Subject: [PATCH 129/423] Correct variable names; Add ( ) in g limitation --- src/solvers/dgsem_tree/dg_2d.jl | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 3d031ac963..f91da404cb 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1157,23 +1157,23 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] - rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_iim1 = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] for v in 2:nvariables(equations) bar_states_phi = bar_states1[v, i, j, element] phi = bar_states_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] - (rho_limited_im1i * phi - lambda * bar_states_phi) + g = antidiffusive_flux1[v, i, j, element] - (rho_limited_iim1 * phi - lambda * bar_states_phi) if g > 0 - g_max = min(rho_limited_im1i * (var_max[v, i, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i-1, j, element])) + g_max = min(rho_limited_iim1 * (var_max[v, i, j, element] - phi), + rho_limited_im1i * (phi - var_min[v, i-1, j, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_im1i * (var_min[v, i, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i-1, j, element])) + g_min = max(rho_limited_iim1 * (var_min[v, i, j, element] - phi), + rho_limited_im1i * (phi - var_max[v, i-1, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end @@ -1187,7 +1187,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited + antidiffusive_flux1[v, i, j, element] = (rho_limited_iim1 * phi - lambda * bar_states_phi) + g_limited end end @@ -1220,23 +1220,23 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_jm1j = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] - rho_limited_jjm1 = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jjm1 = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] for v in 2:nvariables(equations) bar_state_phi = bar_states2[v, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] - rho_limited_jm1j * phi + lambda * bar_state_phi + g = antidiffusive_flux2[v, i, j, element] - (rho_limited_jjm1 * phi - lambda * bar_state_phi) if g > 0 - g_max = min(rho_limited_jm1j * (var_max[v, i, j, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j-1, element])) + g_max = min(rho_limited_jjm1 * (var_max[v, i, j, element] - phi), + rho_limited_jm1j * (phi - var_min[v, i, j-1, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_jm1j * (var_min[v, i, j, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j-1, element])) + g_min = max(rho_limited_jjm1 * (var_min[v, i, j, element] - phi), + rho_limited_jm1j * (phi - var_max[v, i, j-1, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end @@ -1250,7 +1250,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux2[v, i, j, element] = rho_limited_jm1j * phi - lambda * bar_state_phi + g_limited + antidiffusive_flux2[v, i, j, element] = (rho_limited_jjm1 * phi - lambda * bar_state_phi) + g_limited end end @@ -1536,7 +1536,7 @@ end # - velocities and energy (phi): # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v_1}^{Lim}|^2 / 2 + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 var_limited = zero(eltype(idp_bounds_delta)) error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) From 01fc24bf52209c6d01127927bb5267e255422b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 27 Jan 2023 16:35:27 +0100 Subject: [PATCH 130/423] Modified calcflux_antidiffusive_limited! to match my notes --- src/solvers/dgsem_tree/dg_2d.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 8984086f88..ab35fffa62 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1164,7 +1164,7 @@ end phi = bar_states_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] - (rho_limited_iim1 * phi - lambda * bar_states_phi) + g = antidiffusive_flux1[v, i, j, element] + (rho_limited_im1i * phi - lambda * bar_states_phi) if g > 0 g_max = min(rho_limited_iim1 * (var_max[v, i, j, element] - phi), @@ -1186,8 +1186,7 @@ end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - - antidiffusive_flux1[v, i, j, element] = (rho_limited_iim1 * phi - lambda * bar_states_phi) + g_limited + antidiffusive_flux1[v, i, j, element] = (lambda * bar_states_phi - rho_limited_im1i * phi) + g_limited end end @@ -1227,7 +1226,7 @@ end phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] - (rho_limited_jjm1 * phi - lambda * bar_state_phi) + g = antidiffusive_flux2[v, i, j, element] + (rho_limited_jm1j * phi - lambda * bar_state_phi) if g > 0 g_max = min(rho_limited_jjm1 * (var_max[v, i, j, element] - phi), @@ -1250,7 +1249,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux2[v, i, j, element] = (rho_limited_jjm1 * phi - lambda * bar_state_phi) + g_limited + antidiffusive_flux2[v, i, j, element] = (lambda * bar_state_phi - rho_limited_jm1j * phi) + g_limited end end From fefca4fc9552a30cd385a5736bb19d24a7c5cead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 30 Jan 2023 08:54:54 +0100 Subject: [PATCH 131/423] Swapped antidiffusive fluxes, such that they match Kuzmin's & Hajduk's (and adjusted the limiting procedure) -> TODO: Fluxes should be switched only for MCL, not IDP --- src/solvers/dgsem_tree/dg_2d.jl | 72 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ab35fffa62..3ddfc89d58 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -657,8 +657,8 @@ end du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + inverse_weights[j] * (fstar2_L[v, i, j+1] - fstar2_R[v, i, j]) - du[v, i, j, element] += inverse_weights[i] * (antidiffusive_flux1[v, i+1, j, element] - antidiffusive_flux1[v, i, j, element]) + - inverse_weights[j] * (antidiffusive_flux2[v, i, j+1, element] - antidiffusive_flux2[v, i, j, element]) + du[v, i, j, element] += inverse_weights[i] * (-antidiffusive_flux1[v, i+1, j, element] + antidiffusive_flux1[v, i, j, element]) + + inverse_weights[j] * (-antidiffusive_flux2[v, i, j+1, element] + antidiffusive_flux2[v, i, j, element]) end end @@ -749,12 +749,12 @@ end for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + antidiffusive_flux1[v, i, j, element] = -(fhat1[v, i, j] - fstar1[v, i, j]) end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] + antidiffusive_flux2[v, i, j, element] = -(fhat2[v, i, j] - fstar2[v, i, j]) end end @@ -1133,13 +1133,13 @@ end bar_state_rho = bar_states1[1, i, j, element] # Limit density if antidiffusive_flux1[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - var_min[1, i-1, j, element]) + f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - var_max[1, i-1, j, element]) + f_min = lambda * max(var_min[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end @@ -1157,23 +1157,23 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_iim1 = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] - rho_limited_im1i = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] for v in 2:nvariables(equations) bar_states_phi = bar_states1[v, i, j, element] phi = bar_states_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] + (rho_limited_im1i * phi - lambda * bar_states_phi) + g = antidiffusive_flux1[v, i, j, element] + (lambda * bar_states_phi - rho_limited_im1i * phi) if g > 0 - g_max = min(rho_limited_iim1 * (var_max[v, i, j, element] - phi), - rho_limited_im1i * (phi - var_min[v, i-1, j, element])) + g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i, j, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_iim1 * (var_min[v, i, j, element] - phi), - rho_limited_im1i * (phi - var_max[v, i-1, j, element])) + g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end @@ -1186,7 +1186,7 @@ end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux1[v, i, j, element] = (lambda * bar_states_phi - rho_limited_im1i * phi) + g_limited + antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited end end @@ -1195,13 +1195,13 @@ end bar_state_rho = bar_states2[1, i, j, element] # Limit density if antidiffusive_flux2[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i, j, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j-1, element]) + f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[1, i, j, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j-1, element]) + f_min = lambda * max(var_min[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end @@ -1219,23 +1219,23 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited # Limit velocity and total energy - rho_limited_jjm1 = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] - rho_limited_jm1j = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jjm1 = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] for v in 2:nvariables(equations) bar_state_phi = bar_states2[v, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] + (rho_limited_jm1j * phi - lambda * bar_state_phi) + g = antidiffusive_flux2[v, i, j, element] + (lambda * bar_state_phi - rho_limited_jm1j * phi) if g > 0 - g_max = min(rho_limited_jjm1 * (var_max[v, i, j, element] - phi), - rho_limited_jm1j * (phi - var_min[v, i, j-1, element])) + g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j, element])) g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max g_limited = min(g, max(g_max, 0.0)) else - g_min = max(rho_limited_jjm1 * (var_min[v, i, j, element] - phi), - rho_limited_jm1j * (phi - var_max[v, i, j-1, element])) + g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j, element])) g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end @@ -1249,7 +1249,7 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux2[v, i, j, element] = (lambda * bar_state_phi - rho_limited_jm1j * phi) + g_limited + antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - lambda * bar_state_phi) + g_limited end end @@ -1541,11 +1541,11 @@ end for element in eachelement(solver, cache) # -x for j in eachnode(solver), i in 1:nnodes(solver) - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) @@ -1560,11 +1560,11 @@ end end # +x for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) @@ -1579,11 +1579,11 @@ end end # -y for j in 1:nnodes(solver), i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) @@ -1598,11 +1598,11 @@ end end # +y for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) if indicator.IDPPressure && (v == 2 || v == 3) From 11f1aca52c520318952ee1f135f0959dde345cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 1 Feb 2023 10:11:25 +0100 Subject: [PATCH 132/423] Added new MCL limiters -> The new MCL limiters with their default value and a short explanation are: * DensityLimiter=true - Impose local maximum/minimum for cons(1) based on bar states * DensityAlphaForAll=false - Use the cons(1) blending coefficient for all quantities * SequentialLimiter=true - Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states * ConservativeLimiter=false - Impose local maximum/minimum for conservative variables 2:nvariables based on bar states * DensityPositivityLimiter=false - Impose positivity for cons(1) (the default quantities lead to the standard MCL sequential approach) -> Only one of SequentialLimiter or ConservativeLimiter can be selected simultaneously -> TODO: These limiters are equation specific (Euler equations) -> TODO: The bounds check for IDPPressure is only done when SequentialLimiter||trueConservativeLimiter=true --- src/solvers/dgsem_tree/dg_2d.jl | 852 +++++++++++++++++++-------- src/solvers/dgsem_tree/indicators.jl | 26 +- 2 files changed, 637 insertions(+), 241 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 3ddfc89d58..949d66bac5 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1066,50 +1066,98 @@ end var_max[v, :, :, element] .= typemin(eltype(var_max)) end - for j in eachnode(dg), i in eachnode(dg) - # Previous solution - var_min[1, i, j, element] = min(var_min[1, i, j, element], u[1, i, j, element]) - var_max[1, i, j, element] = max(var_max[1, i, j, element], u[1, i, j, element]) - for v in 2:nvariables(equations) - phi = u[v, i, j, element] / u[1, i, j, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], phi) + if indicator.DensityLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + var_min[1, i, j, element] = min(var_min[1, i, j, element], u[1, i, j, element]) + var_max[1, i, j, element] = max(var_max[1, i, j, element], u[1, i, j, element]) + # - xi direction + bar_state_rho = bar_states1[1, i, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) + # + xi direction + bar_state_rho = bar_states1[1, i+1, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) + # - eta direction + bar_state_rho = bar_states2[1, i, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) + # + eta direction + bar_state_rho = bar_states2[1, i, j+1, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) end - # - xi direction - bar_state_rho = bar_states1[1, i, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) - end - # + xi direction - bar_state_rho = bar_states1[1, i+1, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i+1, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end #indicator.DensityLimiter + + if indicator.SequentialLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + for v in 2:nvariables(equations) + phi = u[v, i, j, element] / u[1, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], phi) + end + # - xi direction + bar_state_rho = bar_states1[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end + # + xi direction + bar_state_rho = bar_states1[1, i+1, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i+1, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end + # - eta direction + bar_state_rho = bar_states2[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end + # + eta direction + bar_state_rho = bar_states2[1, i, j+1, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j+1, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + end end - # - eta direction - bar_state_rho = bar_states2[1, i, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) - end - # + eta direction - bar_state_rho = bar_states2[1, i, j+1, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j+1, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_phi) + elseif indicator.ConservativeLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + for v in 2:nvariables(equations) + var_min[v, i, j, element] = min(var_min[v, i, j, element], u[v, i, j, element]) + var_max[v, i, j, element] = max(var_max[v, i, j, element], u[v, i, j, element]) + end + # - xi direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states1[v, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_rho) + end + # + xi direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states1[v, i+1, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_rho) + end + # - eta direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states2[v, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_rho) + end + # + eta direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states2[v, i, j+1, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], bar_state_rho) + end end end end @@ -1127,131 +1175,299 @@ end # It can also happen that the limited flux changes its sign (for instance to -1e-13). # This does not really make sense in theory and causes problems for the visualization. # Therefore we make sure that the flux keeps its sign during limiting. + + # Density limiter + if indicator.DensityLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] + + # Limit density + if antidiffusive_flux1[1, i, j, element] > 0 + f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) + else + f_min = lambda * max(var_min[1, i-1, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) + end - for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - bar_state_rho = bar_states1[1, i, j, element] - # Limit density - if antidiffusive_flux1[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) - f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) - else - f_min = lambda * max(var_min[1, i-1, j, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) - f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) + if indicator.Plotting || indicator.DensityAlphaForAll + if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + end + + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end + end + antidiffusive_flux1[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if indicator.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, element] + if indicator.Plotting + alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + end + end end - if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] + + # Limit density + if antidiffusive_flux2[1, i, j, element] > 0 + f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + f_min = lambda * max(var_min[1, i, j-1, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) + end + + if indicator.Plotting || indicator.DensityAlphaForAll + if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + end + + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end + end + antidiffusive_flux2[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if indicator.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, element] + if indicator.Plotting + alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) + alpha[v, i, j , element] = min(alpha[v, i, j , element], coefficient) + end + end end - alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) end - antidiffusive_flux1[1, i, j, element] = flux_limited + end # if indicator.DensityLimiter - # Limit velocity and total energy - rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] - rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] - for v in 2:nvariables(equations) - bar_states_phi = bar_states1[v, i, j, element] + # Sequential limiter + if indicator.SequentialLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] - phi = bar_states_phi / bar_state_rho + # Limit velocity and total energy + rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] + for v in 2:nvariables(equations) + bar_states_phi = bar_states1[v, i, j, element] - g = antidiffusive_flux1[v, i, j, element] + (lambda * bar_states_phi - rho_limited_im1i * phi) + phi = bar_states_phi / bar_state_rho - if g > 0 - g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i, j, element])) - g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max - g_limited = min(g, max(g_max, 0.0)) - else - g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min - g_limited = max(g, min(g_min, 0.0)) - end - if indicator.Plotting - if isapprox(g, 0.0, atol=eps()) - coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + g = antidiffusive_flux1[v, i, j, element] + (lambda * bar_states_phi - rho_limited_im1i * phi) + + if g > 0 + g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) else - coefficient = g_limited / g + g_min = max(rho_limited_im1i * (var_min[v, i-1, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_limited = max(g, min(g_min, 0.0)) end - alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(g, 0.0, atol=eps()) + coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + else + coefficient = g_limited / g + end + alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited end - antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited end - end - for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - bar_state_rho = bar_states2[1, i, j, element] - # Limit density - if antidiffusive_flux2[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) - f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) - else - f_min = lambda * max(var_min[1, i, j-1, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) - f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) - end + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] - if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + # Limit velocity and total energy + rho_limited_jjm1 = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] + + phi = bar_state_phi / bar_state_rho + + g = antidiffusive_flux2[v, i, j, element] + (lambda * bar_state_phi - rho_limited_jm1j * phi) + + if g > 0 + g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) + else + g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min + g_limited = max(g, min(g_min, 0.0)) + end + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(g, 0.0, atol=eps()) + coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + else + coefficient = g_limited / g + end + alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + + antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - lambda * bar_state_phi) + g_limited end - alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) end - antidiffusive_flux2[1, i, j, element] = flux_limited + # Conservative limiter + elseif indicator.ConservativeLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + for v in 2:nvariables(equations) + bar_state_rho = bar_states1[v, i, j, element] + # Limit density + if antidiffusive_flux1[v, i, j, element] > 0 + f_max = lambda * min(var_max[v, i-1, j, element] - bar_state_rho, + bar_state_rho - var_min[v, i, j, element]) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[v, i, j, element], max(f_max, 0.0)) + else + f_min = lambda * max(var_min[v, i-1, j, element] - bar_state_rho, + bar_state_rho - var_max[v, i, j, element]) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[v, i, j, element], min(f_min, 0.0)) + end - # Limit velocity and total energy - rho_limited_jjm1 = lambda * bar_state_rho - antidiffusive_flux2[1, i, j, element] - rho_limited_jm1j = lambda * bar_state_rho + antidiffusive_flux2[1, i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j, element] + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux1[v, i, j, element] + end + alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + antidiffusive_flux1[v, i, j, element] = flux_limited + end + end - phi = bar_state_phi / bar_state_rho + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + for v in 2:nvariables(equations) + bar_state_rho = bar_states2[v, i, j, element] + # Limit density + if antidiffusive_flux2[v, i, j, element] > 0 + f_max = lambda * min(var_max[v, i, j-1, element] - bar_state_rho, + bar_state_rho - var_min[v, i, j, element]) + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[v, i, j, element], max(f_max, 0.0)) + else + f_min = lambda * max(var_min[v, i, j-1, element] - bar_state_rho, + bar_state_rho - var_max[v, i, j, element]) + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[v, i, j, element], min(f_min, 0.0)) + end - g = antidiffusive_flux2[v, i, j, element] + (lambda * bar_state_phi - rho_limited_jm1j * phi) + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux2[v, i, j, element] + end + alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + antidiffusive_flux2[v, i, j, element] = flux_limited + end + end + end # indicator.SequentialLimiter and indicator.ConservativeLimiter - if g > 0 - g_max = min(rho_limited_jm1j * (var_max[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j, element])) - g_max = isapprox(g_max, 0.0, atol=eps()) ? 0.0 : g_max - g_limited = min(g, max(g_max, 0.0)) + # Density positivity limiter + if indicator.DensityPositivityLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] + # Limit density + if antidiffusive_flux1[1, i, j, element] > 0 + f_max = lambda * bar_state_rho + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - g_min = max(rho_limited_jm1j * (var_min[v, i, j-1, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol=eps()) ? 0.0 : g_min - g_limited = max(g, min(g_min, 0.0)) + f_min = -lambda * bar_state_rho + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end + if indicator.Plotting - if isapprox(g, 0.0, atol=eps()) - coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well else - coefficient = g_limited / g + coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] end - alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) end + antidiffusive_flux1[1, i, j, element] = flux_limited + end - antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - lambda * bar_state_phi) + g_limited + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] + # Limit density + if antidiffusive_flux2[1, i, j, element] > 0 + f_max = lambda * bar_state_rho + f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) + else + f_min = -lambda * bar_state_rho + f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) + end + + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + end + alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end + antidiffusive_flux2[1, i, j, element] = flux_limited end - end + end #if indicator.DensityPositivityLimiter # Limit pressure if indicator.IDPPressure @@ -1510,112 +1726,276 @@ end x = 1 save_errors = laststage && (x > 0) && (iter % x == 0) - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) - deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) - for v in 2:n_vars - var_limited = u[v, i, j, element] / u[1, i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.DensityLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} + for element in eachelement(solver, cache) + # -x + for j in eachnode(solver), i in 1:nnodes(solver) + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + end + # +x + for j in eachnode(solver), i in 2:nnodes(solver)+1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) end - if indicator.IDPPressure - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # -y + for j in 1:nnodes(solver), i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + end + # +y + for j in 2:nnodes(solver)+1, i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) end end - end + end # indicator.DensityLimiter - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - density (rho): - # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} - # - velocities and energy (phi): - # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) - for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 1:nnodes(solver) - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressure - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - end - # +x - for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) - for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressure - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - end - # -y - for j in 1:nnodes(solver), i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressure - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - end - # +y - for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) - for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) - if indicator.IDPPressure && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.IDPPressure - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + # TODO: Pressure bounds are only checked if sequential or conservative limiters are active + if indicator.SequentialLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + for v in 2:n_vars + var_limited = u[v, i, j, element] / u[1, i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + end + if indicator.IDPPressure + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end end end - end + + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - velocities and energy (phi): + # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) + for element in eachelement(solver, cache) + # -x + for j in eachnode(solver), i in 1:nnodes(solver) + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +x + for j in eachnode(solver), i in 2:nnodes(solver)+1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # -y + for j in 1:nnodes(solver), i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +y + for j in 2:nnodes(solver)+1, i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + end + elseif indicator.ConservativeLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + for v in 2:n_vars + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - u[v, i, j, element]) + deviation_max[v] = max(deviation_max[v], u[v, i, j, element] - var_max[v, i, j, element]) + end + if indicator.IDPPressure + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end + + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - conservative variables (phi): + # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(idp_bounds_delta)) + rho_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) + for element in eachelement(solver, cache) + # -x + for j in eachnode(solver), i in 1:nnodes(solver) + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +x + for j in eachnode(solver), i in 2:nnodes(solver)+1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i-1, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # -y + for j in 1:nnodes(solver), i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + # +y + for j in 2:nnodes(solver)+1, i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j-1, element]) + if indicator.IDPPressure && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.IDPPressure + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + end + end # indicator.ConservativeLimiter + + if indicator.DensityPositivityLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], - u[1, i, j, element]) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # 0 <= \bar{rho}^{Lim} + for element in eachelement(solver, cache) + # -x + for j in eachnode(solver), i in 1:nnodes(solver) + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + end + # +x + for j in eachnode(solver), i in 2:nnodes(solver)+1 + rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + end + # -y + for j in 1:nnodes(solver), i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + end + # +y + for j in 2:nnodes(solver)+1, i in eachnode(solver) + rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + end + end + end # indicator.DensityPositivityLimiter vars = varnames(cons2cons, equations) for v in eachvariable(equations) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index d5e466b86d..b51b19efa6 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -293,7 +293,12 @@ TODO: docstring """ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator cache::Cache + DensityLimiter::Bool + DensityAlphaForAll::Bool + SequentialLimiter::Bool + ConservativeLimiter::Bool IDPPressure::Bool # synchronized pressure limiting + DensityPositivityLimiter::Bool IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner thr_smooth::RealT # threshold for smoothness indicator @@ -303,11 +308,18 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorMCL(equations::AbstractEquations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, IDPPressure=false, + DensityPositivityLimiter=false, IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) - + if SequentialLimiter && ConservativeLimiter + error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") + end cache = create_cache(IndicatorMCL, equations, basis, IDPPressure) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, @@ -315,16 +327,20 @@ function IndicatorMCL(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, IDPPressure, - IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) + IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, + IDPPressure, DensityPositivityLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @nospecialize indicator # reduce precompilation time print(io, "IndicatorMCL(") - print(io, "Limiting of density, velocity and total energy") - indicator.IDPPressure && print(io, "; pressure limiting") + indicator.DensityLimiter && print(io, "; dens") + indicator.DensityAlphaForAll && print(io, "; dens alpha ∀") + indicator.SequentialLimiter && print(io, "; seq") + indicator.ConservativeLimiter && print(io, "; cons") + indicator.IDPPressure && print(io, "; pres") + indicator.DensityPositivityLimiter && print(io, "; dens pos") indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) print(io, ")") From edca2316e289725c02478ff95d4d3ade6cca272c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 3 Feb 2023 16:48:58 +0100 Subject: [PATCH 133/423] Implemented a characteristics based BC for Euler 2D --- src/Trixi.jl | 1 + src/equations/compressible_euler_2d.jl | 51 ++++++++++++++++++++++++++ src/equations/equations.jl | 34 +++++++++++++++++ src/solvers/dgsem_tree/dg_2d.jl | 21 ++++++++--- 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index 07ae056f97..a07314d54e 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -167,6 +167,7 @@ export initial_condition_constant, export boundary_condition_do_nothing, boundary_condition_periodic, BoundaryConditionDirichlet, + BoundaryConditionCharacteristic, BoundaryConditionNeumann, boundary_condition_noslip_wall, boundary_condition_slip_wall, diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 6b47f21176..37e51e3130 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -367,6 +367,57 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end +@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner,orientation, direction, x,t,equations) + + # Get inverse of density + srho = 1 / u_inner[1] + + # Get normal velocity + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + factor = 1 + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + factor = -1 + end + if orientation==1 + vn = factor * u_inner[2] * srho + else + vn = factor * u_inner[3] * srho + end + + # get pressure and Mach from state + pres = pressure(u_inner, equations) + a = sqrt(equations.gamma * pres * srho) + normalMachNo = abs(vn/a) + + if (vn < 0) # inflow + if (normalMachNo<1.0) + # subsonic inflow: All variables from outside but pressure + cons = outer_boundary_value_function(x, t, equations) + + prim = cons2prim(cons, equations) + #prim[4] = pres + prim2 = SVector(prim[1:3]..., pres) + cons = prim2cons(prim2, equations) + else + # supersonic inflow: All variables from outside + cons = outer_boundary_value_function(x, t, equations) + end + else # outflow + if (normalMachNo<1.0) + # subsonic outflow: All variables from inside but pressure + cons = outer_boundary_value_function(x, t, equations) + + prim = cons2prim(u_inner, equations) + prim2 = SVector(prim[1:3]..., pressure(cons, equations)) + cons = prim2cons(prim2, equations) + else + # supersonic outflow: All variables from inside + cons = u_inner + end + end + + return cons +end # Calculate 2D flux for a single point @inline function flux(u, orientation::Integer, equations::CompressibleEulerEquations2D) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 68612347d3..ea1a172db3 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -181,6 +181,40 @@ end return flux end +""" + BoundaryConditionCharacteristic(boundary_value_function) + +""" +struct BoundaryConditionCharacteristic{B,C} + outer_boundary_value_function::B + boundary_value_function::C +end + +function BoundaryConditionCharacteristic(outer_boundary_value_function) + BoundaryConditionCharacteristic{typeof(outer_boundary_value_function), typeof(characteristic_boundary_value_function)}(outer_boundary_value_function, characteristic_boundary_value_function) +end + + +# Dirichlet-type boundary condition for use with TreeMesh or StructuredMesh +@inline function (boundary_condition::BoundaryConditionCharacteristic)(u_inner, orientation_or_normal, + direction, + x, t, + surface_flux_function, equations) + u_boundary = characteristic_boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, orientation_or_normal, direction, x , t, equations) + + # 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_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 + + + # operator types used for dispatch on parabolic boundary fluxes struct Gradient end struct Divergence end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 949d66bac5..eac080df39 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -865,7 +865,7 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], orientation, 1, equations, dg, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -881,7 +881,7 @@ end else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], orientation, 2, equations, dg, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -899,7 +899,7 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], orientation, 3, equations, dg, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -915,7 +915,7 @@ end else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], orientation, 4, equations, dg, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -1551,9 +1551,9 @@ end return nothing end -get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, indices...) = u_inner +get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation, direction, equations, dg, indices...) = u_inner -@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, equations, dg, indices...) +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, orientation, direction, equations, dg, indices...) @unpack node_coordinates = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1562,6 +1562,15 @@ get_boundary_outer_state(u_inner, cache, t, boundary_condition, equations, dg, i return u_outer end +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionCharacteristic, orientation, direction, equations, dg, indices...) + @unpack node_coordinates = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, u_inner, orientation, direction, x, t, equations) + + return u_outer +end + @inline function antidiffusive_stage!(u_ode, t, dt, semi, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) From 0d4fef469e3a535855f87583f763415e9d0de92d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 5 Feb 2023 12:44:56 +0100 Subject: [PATCH 134/423] Speed up `BoundaryConditionCharacteristic` --- .../elixir_euler_astro_jet_MCL.jl | 4 +- src/equations/compressible_euler_2d.jl | 38 +++++++++---------- src/equations/equations.jl | 18 +++++---- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index c57e51df1d..2e74008008 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -31,8 +31,8 @@ end initial_condition = initial_condition_astro_jet boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), - x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), + x_neg=BoundaryConditionCharacteristic(initial_condition_astro_jet), + x_pos=BoundaryConditionCharacteristic(initial_condition_astro_jet), y_neg=boundary_condition_periodic, y_pos=boundary_condition_periodic, ) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 37e51e3130..07452ca8ee 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -367,49 +367,47 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end -@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner,orientation, direction, x,t,equations) - +@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, orientation, direction, x, t, equations) # Get inverse of density srho = 1 / u_inner[1] - + # Get normal velocity - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary factor = 1 else # u_boundary is "left" of boundary, u_inner is "right" of boundary factor = -1 end - if orientation==1 + if orientation == 1 vn = factor * u_inner[2] * srho else vn = factor * u_inner[3] * srho end - + # get pressure and Mach from state - pres = pressure(u_inner, equations) - a = sqrt(equations.gamma * pres * srho) - normalMachNo = abs(vn/a) - - if (vn < 0) # inflow - if (normalMachNo<1.0) + p = pressure(u_inner, equations) + a = sqrt(equations.gamma * p * srho) + normalMachNo = abs(vn / a) + + if vn < 0 # inflow + if normalMachNo < 1.0 # subsonic inflow: All variables from outside but pressure cons = outer_boundary_value_function(x, t, equations) prim = cons2prim(cons, equations) - #prim[4] = pres - prim2 = SVector(prim[1:3]..., pres) - cons = prim2cons(prim2, equations) - else + prim = SVector(view(prim, 1:3)..., p) + cons = prim2cons(prim, equations) + else # supersonic inflow: All variables from outside cons = outer_boundary_value_function(x, t, equations) end else # outflow - if (normalMachNo<1.0) + if normalMachNo < 1.0 # subsonic outflow: All variables from inside but pressure cons = outer_boundary_value_function(x, t, equations) - + prim = cons2prim(u_inner, equations) - prim2 = SVector(prim[1:3]..., pressure(cons, equations)) - cons = prim2cons(prim2, equations) + prim = SVector(view(prim, 1:3)..., pressure(cons, equations)) + cons = prim2cons(prim, equations) else # supersonic outflow: All variables from inside cons = u_inner diff --git a/src/equations/equations.jl b/src/equations/equations.jl index ea1a172db3..ce2d540080 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -181,8 +181,9 @@ end return flux end + """ - BoundaryConditionCharacteristic(boundary_value_function) + BoundaryConditionCharacteristic(outer_boundary_value_function) """ struct BoundaryConditionCharacteristic{B,C} @@ -191,16 +192,17 @@ struct BoundaryConditionCharacteristic{B,C} end function BoundaryConditionCharacteristic(outer_boundary_value_function) - BoundaryConditionCharacteristic{typeof(outer_boundary_value_function), typeof(characteristic_boundary_value_function)}(outer_boundary_value_function, characteristic_boundary_value_function) + BoundaryConditionCharacteristic{typeof(outer_boundary_value_function), typeof(characteristic_boundary_value_function)}( + outer_boundary_value_function, characteristic_boundary_value_function) end # Dirichlet-type boundary condition for use with TreeMesh or StructuredMesh @inline function (boundary_condition::BoundaryConditionCharacteristic)(u_inner, orientation_or_normal, - direction, - x, t, - surface_flux_function, equations) - u_boundary = characteristic_boundary_value_function(boundary_condition.outer_boundary_value_function, + direction, + x, t, + surface_flux_function, equations) + u_boundary = characteristic_boundary_value_function(boundary_condition.outer_boundary_value_function, u_inner, orientation_or_normal, direction, x , t, equations) # Calculate boundary flux @@ -360,7 +362,7 @@ include("compressible_euler_multicomponent_2d.jl") eachcomponent(equations::AbstractCompressibleEulerMulticomponentEquations) Return an iterator over the indices that specify the location in relevant data structures -for the components in `AbstractCompressibleEulerMulticomponentEquations`. +for the components in `AbstractCompressibleEulerMulticomponentEquations`. In particular, not the components themselves are returned. """ @inline eachcomponent(equations::AbstractCompressibleEulerMulticomponentEquations) = Base.OneTo(ncomponents(equations)) @@ -382,7 +384,7 @@ include("ideal_glm_mhd_multicomponent_2d.jl") eachcomponent(equations::AbstractIdealGlmMhdMulticomponentEquations) Return an iterator over the indices that specify the location in relevant data structures -for the components in `AbstractIdealGlmMhdMulticomponentEquations`. +for the components in `AbstractIdealGlmMhdMulticomponentEquations`. In particular, not the components themselves are returned. """ @inline eachcomponent(equations::AbstractIdealGlmMhdMulticomponentEquations) = Base.OneTo(ncomponents(equations)) From 9425e3173840db2d57cd9a2b1484a4074e851c34 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 6 Feb 2023 15:35:39 +0100 Subject: [PATCH 135/423] Restructure `for` loops in BoundsCheck --- src/solvers/dgsem_tree/dg_2d.jl | 128 +++++++++++++------------------- 1 file changed, 52 insertions(+), 76 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index eac080df39..490f03e06e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1175,13 +1175,13 @@ end # It can also happen that the limited flux changes its sign (for instance to -1e-13). # This does not really make sense in theory and causes problems for the visualization. # Therefore we make sure that the flux keeps its sign during limiting. - + # Density limiter if indicator.DensityLimiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] - + # Limit density if antidiffusive_flux1[1, i, j, element] > 0 f_max = lambda * min(var_max[1, i-1, j, element] - bar_state_rho, @@ -1225,7 +1225,7 @@ end for j in 2:nnodes(dg), i in eachnode(dg) lambda = lambda2[i, j, element] bar_state_rho = bar_states2[1, i, j, element] - + # Limit density if antidiffusive_flux2[1, i, j, element] > 0 f_max = lambda * min(var_max[1, i, j-1, element] - bar_state_rho, @@ -1245,7 +1245,7 @@ end else coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] end - + if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) @@ -1408,9 +1408,9 @@ end alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end antidiffusive_flux2[v, i, j, element] = flux_limited - end + end end - end # indicator.SequentialLimiter and indicator.ConservativeLimiter + end # indicator.SequentialLimiter and indicator.ConservativeLimiter # Density positivity limiter if indicator.DensityPositivityLimiter @@ -1749,29 +1749,23 @@ end # - density (rho): # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 1:nnodes(solver) + for j in eachnode(solver), i in eachnode(solver) + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - end - # +x - for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i-1, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i-1, j, element]) - end - # -y - for j in 1:nnodes(solver), i in eachnode(solver) + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - end - # +y - for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j-1, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j-1, element]) + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) end end end # indicator.DensityLimiter @@ -1804,8 +1798,8 @@ end var_limited = zero(eltype(idp_bounds_delta)) error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 1:nnodes(solver) + for j in eachnode(solver), i in eachnode(solver) + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] @@ -1820,14 +1814,12 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # +x - for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i-1, j, element]) + var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1837,9 +1829,7 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # -y - for j in 1:nnodes(solver), i in eachnode(solver) + # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] @@ -1854,14 +1844,12 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # +y - for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j-1, element]) + var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1874,7 +1862,7 @@ end end end elseif indicator.ConservativeLimiter - # New solution u^{n+1} + # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) for v in 2:n_vars @@ -1899,8 +1887,8 @@ end rho_limited = zero(eltype(idp_bounds_delta)) error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 1:nnodes(solver) + for j in eachnode(solver), i in eachnode(solver) + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] @@ -1915,14 +1903,12 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # +x - for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] + antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i-1, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i-1, j, element]) + var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1932,9 +1918,7 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # -y - for j in 1:nnodes(solver), i in eachnode(solver) + # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] @@ -1949,14 +1933,12 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end - end - # +y - for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] + antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j-1, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j-1, element]) + var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) if indicator.IDPPressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end @@ -1974,7 +1956,7 @@ end # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], - u[1, i, j, element]) + deviation_min[1] = max(deviation_min[1], -u[1, i, j, element]) end end @@ -1983,24 +1965,18 @@ end # - density (rho): # 0 <= \bar{rho}^{Lim} for element in eachelement(solver, cache) - # -x - for j in eachnode(solver), i in 1:nnodes(solver) + for j in eachnode(solver), i in eachnode(solver) + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) - end - # +x - for j in eachnode(solver), i in 2:nnodes(solver)+1 - rho_limited = bar_states1[1, i, j, element] + antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) - end - # -y - for j in 1:nnodes(solver), i in eachnode(solver) + # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) - end - # +y - for j in 2:nnodes(solver)+1, i in eachnode(solver) - rho_limited = bar_states2[1, i, j, element] + antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] deviation_min[1] = max(deviation_min[1], -rho_limited) end end From f8cde1b3af2bc8c91728c7f72201c2a88a4c195c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 7 Feb 2023 23:50:53 +0100 Subject: [PATCH 136/423] Fix bug in bar state calculation for StrucuturedMesh --- src/solvers/dgsem_structured/dg_2d.jl | 10 +++++----- src/solvers/dgsem_structured/indicators_2d.jl | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index b355cc4690..d948a7e575 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -517,11 +517,11 @@ end end # Calc lambdas and bar states at physical boundaries - if all(mesh.periodicity) + if isperiodic(mesh) return nothing end linear_indices = LinearIndices(size(mesh)) - if !mesh.periodicity[1] + if !isperiodic(mesh, 1) # - xi direction for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] @@ -556,12 +556,12 @@ end flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) for v in eachvariable(equations) - bar_states1[v, nnodes(dg), j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda1[nnodes(dg)+1, j, element] + bar_states1[v, nnodes(dg)+1, j, element] = 0.5 * (u_inner[v] + u_outer[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda1[nnodes(dg)+1, j, element] end end end end - if !mesh.periodicity[2] + if !isperiodic(mesh, 2) # - eta direction for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] @@ -596,7 +596,7 @@ end flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg), element] = 0.5 * (u_outer[v] + u_inner[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda2[i, nnodes(dg)+1, element] + bar_states2[v, i, nnodes(dg)+1, element] = 0.5 * (u_outer[v] + u_inner[v]) - 0.5 * (flux_outer[v] - flux_inner[v]) / lambda2[i, nnodes(dg)+1, element] end end end diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index ee2be0324f..2050a7b08f 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -64,11 +64,11 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m end # Calc bounds at physical boundaries - if all(mesh.periodicity) + if isperiodic(mesh) return nothing end linear_indices = LinearIndices(size(mesh)) - if !mesh.periodicity[1] + if !isperiodic(mesh, 1) # - xi direction for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] @@ -96,7 +96,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m end end end - if !mesh.periodicity[2] + if !isperiodic(mesh, 2) # - eta direction for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] @@ -158,11 +158,11 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end # Calc bounds at physical boundaries - if all(mesh.periodicity) + if isperiodic(mesh) return nothing end linear_indices = LinearIndices(size(mesh)) - if !mesh.periodicity[1] + if !isperiodic(mesh, 1) # - xi direction for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] @@ -188,7 +188,7 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end end end - if !mesh.periodicity[2] + if !isperiodic(mesh, 2) # - eta direction for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] From 10460e2224a2de4867d72498f1af77aa31086066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 8 Feb 2023 09:27:16 +0100 Subject: [PATCH 137/423] Added a new pressure positivity limiter (less dissipative than Kuzmin's) --- src/solvers/dgsem_tree/dg_2d.jl | 151 +++++++++++++++++++++++---- src/solvers/dgsem_tree/indicators.jl | 28 +++-- 2 files changed, 146 insertions(+), 33 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 490f03e06e..aaefaa4c52 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1469,8 +1469,8 @@ end end end #if indicator.DensityPositivityLimiter - # Limit pressure - if indicator.IDPPressure + # Limit pressure à la Kuzmin + if indicator.PressurePositivityLimiterKuzmin @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator if indicator.Plotting alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) @@ -1546,6 +1546,113 @@ end end end end + # New pressure limiter! + elseif indicator.PressurePositivityLimiter + @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting + alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) + end + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 + flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 + + Q = - lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - + 0.5 * bar_state_velocity) + P_1 = 0.5 * flux_velocity - antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element] + P_2 = lambda1[i, j, element] * (bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + + bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] + - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] + - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + + # Solve the quadratic formula + aux_var = P_2^2 - 4*P_1*Q + if aux_var >= 0.0 + # Only solve for real solutions + aux_var = sqrt(aux_var) + alpha1 = 0.5 * (-P_2 + aux_var) / (P_1) + alpha2 = 0.5 * (-P_2 - aux_var) / (P_1) + alpha3 = 0.5 * ( P_2 + aux_var) / (P_1) + alpha4 = 0.5 * ( P_2 - aux_var) / (P_1) + + # If the solutions are negative, we can take the maximum antidiffusive flux + if alpha1 < 0.0 + alpha1 = 1.0 + end + if alpha2 < 0.0 + alpha2 = 1.0 + end + if alpha3 < 0.0 + alpha3 = 1.0 + end + if alpha4 < 0.0 + alpha4 = 1.0 + end + # Get the most restrictive alpha + alpha = min(alpha1,alpha2,alpha3,alpha4,1.0) + else + # If the solutions are complex, we can take the maximum antidiffusive flux + alpha = 1.0 + end + + if indicator.Plotting + alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + end + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] *= alpha + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state_velocity = bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 + flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + antidiffusive_flux2[3, i, j, element]^2 + + Q = -lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - + 0.5 * bar_state_velocity) + + P_1 = 0.5 * flux_velocity - antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element] + P_2 = lambda2[i, j, element] * (bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + + bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] + - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] + - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + # Solve the quadratic formula + aux_var = P_2^2 - 4*P_1*Q + if P_2^2 - 4*P_1*Q >= 0.0 + # Only solve for real solutions + aux_var = sqrt(aux_var) + alpha1 = 0.5 * (-P_2 + aux_var) / (P_1) + alpha2 = 0.5 * (-P_2 - aux_var) / (P_1) + alpha3 = 0.5 * ( P_2 + aux_var) / (P_1) + alpha4 = 0.5 * ( P_2 - aux_var) / (P_1) + + # If the solutions are negative, we can take the maximum antidiffusive flux + if alpha1 < 0.0 + alpha1 = 1.0 + end + if alpha2 < 0.0 + alpha2 = 1.0 + end + if alpha3 < 0.0 + alpha3 = 1.0 + end + if alpha4 < 0.0 + alpha4 = 1.0 + end + # Get the most restrictive alpha + alpha = min(alpha1,alpha2,alpha3,alpha4,1.0) + else + # If the solutions are complex, we can take the maximum antidiffusive flux + alpha = 1.0 + end + + if indicator.Plotting + alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + end + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] *= alpha + end + end end return nothing @@ -1728,7 +1835,7 @@ end n_vars = nvariables(equations) - deviation_min = zeros(eltype(u), n_vars + indicator.IDPPressure) + deviation_min = zeros(eltype(u), n_vars + (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter)) deviation_max = zeros(eltype(u), n_vars) # Save the deviations every x iterations @@ -1781,7 +1888,7 @@ end deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end @@ -1805,11 +1912,11 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1820,11 +1927,11 @@ end var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1835,11 +1942,11 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1850,11 +1957,11 @@ end var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1869,7 +1976,7 @@ end deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - u[v, i, j, element]) deviation_max[v] = max(deviation_max[v], u[v, i, j, element] - var_max[v, i, j, element]) end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end @@ -1894,11 +2001,11 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1909,11 +2016,11 @@ end var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1924,11 +2031,11 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1939,11 +2046,11 @@ end var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.IDPPressure && (v == 2 || v == 3) + if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -1991,7 +2098,7 @@ end open(string("Deviation_", vars[v], "_max.txt"), "a") do f; println(f, deviation_max[v]); end end end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) if save_errors open("Deviation_pressure.txt", "a") do f; println(f, deviation_min[n_vars+1]); end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b51b19efa6..03bc8f2a8d 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -297,7 +297,8 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator DensityAlphaForAll::Bool SequentialLimiter::Bool ConservativeLimiter::Bool - IDPPressure::Bool # synchronized pressure limiting + PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin + PressurePositivityLimiter::Bool # synchronized pressure limiting DensityPositivityLimiter::Bool IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner @@ -308,19 +309,23 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorMCL(equations::AbstractEquations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - IDPPressure=false, - DensityPositivityLimiter=false, + DensityLimiter=true, # Impose local maximum/minimum for cons(1) based on bar states + DensityAlphaForAll=false, # Use the cons(1) blending coefficient for all quantities + SequentialLimiter=true, # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states + ConservativeLimiter=false, # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states + PressurePositivityLimiterKuzmin=false,# Impose positivity for pressure â la Kuzmin + PressurePositivityLimiter=false, # Impose positivity for pressure + DensityPositivityLimiter=false, # Impose positivity for cons(1) IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) if SequentialLimiter && ConservativeLimiter error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") end - cache = create_cache(IndicatorMCL, equations, basis, IDPPressure) + if PressurePositivityLimiterKuzmin && PressurePositivityLimiter + error("Only one of the two can be selected: PressurePositivityLimiterKuzmin/PressurePositivityLimiter") + end + cache = create_cache(IndicatorMCL, equations, basis, PressurePositivityLimiterKuzmin || PressurePositivityLimiter) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, variable=variable_smooth) @@ -328,7 +333,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; IndicatorHG = nothing end IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - IDPPressure, DensityPositivityLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) + PressurePositivityLimiterKuzmin, PressurePositivityLimiter, DensityPositivityLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @@ -339,7 +344,8 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.DensityAlphaForAll && print(io, "; dens alpha ∀") indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") - indicator.IDPPressure && print(io, "; pres") + indicator.PressurePositivityLimiterKuzmin && print(io, "; pres (Kuzmin)") + indicator.PressurePositivityLimiter && print(io, "; pres") indicator.DensityPositivityLimiter && print(io, "; dens pos") indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) @@ -357,7 +363,7 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[s] = alpha[v, ntuple(_ -> :, nvariables(equations) + 1)...] end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator node_variables[:shock_capturing_alpha_pressure] = alpha_pressure end From 3d16f098c33434d8b76b16935771bf2d76ae989f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 8 Feb 2023 10:44:11 +0100 Subject: [PATCH 138/423] Revert antidiffusive flux for IDP --- src/solvers/dgsem_tree/dg_2d.jl | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index aaefaa4c52..9fc5b5a839 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -606,7 +606,7 @@ end # antidiffusive flux calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, dg, element, cache) + nonconservative_terms, equations, indicator, dg, element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -646,7 +646,7 @@ end # antidiffusive flux calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, dg, element, cache) + u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) # limit antidiffusive flux calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) @@ -744,7 +744,31 @@ end end @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, dg, element, cache) + nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] + end + end + + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg)+1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg)+1, element] .= zero(eltype(antidiffusive_flux2)) + + return nothing +end + +@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, indicator::IndicatorMCL, dg, element, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D for j in eachnode(dg), i in 2:nnodes(dg) From 1eab85e24eb3d2ffcaed59327601afee3de35ceb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 8 Feb 2023 12:23:30 +0100 Subject: [PATCH 139/423] Add `BoundaryConditionCharacteristic` for StructuredMesh --- .../elixir_euler_shock_upstream_sc_subcell.jl | 11 ++--- .../elixir_euler_astro_jet_subcell.jl | 4 +- src/equations/compressible_euler_2d.jl | 48 ++++++++++++++++++- src/solvers/dgsem_structured/dg_2d.jl | 18 +++---- src/solvers/dgsem_structured/indicators_2d.jl | 30 ++++++++---- src/solvers/dgsem_tree/dg_2d.jl | 8 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 10 ++-- 7 files changed, 92 insertions(+), 37 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 4b24b5ffbf..d0b740d422 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -25,7 +25,7 @@ function initial_condition_inviscid_bow(x, t, equations::CompressibleEulerEquati end initial_condition = initial_condition_inviscid_bow -boundary_condition = BoundaryConditionDirichlet(initial_condition) +boundary_condition = BoundaryConditionCharacteristic(initial_condition) boundary_conditions = (x_neg=boundary_condition, x_pos=boundary_condition_slip_wall, y_neg=boundary_condition, @@ -38,9 +38,8 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPositivity=true, - IDPMaxIter=20, - IDPSpecEntropy=true, + IDPSpecEntropy=true, IDPMaxIter=100, + BarStates=true, indicator_smooth=false) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -114,12 +113,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=500, +save_solution = SaveSolutionCallback(interval=5000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.3) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index cf49e4c43a..9cc2020855 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -31,8 +31,8 @@ end initial_condition = initial_condition_astro_jet boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), - x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), + x_neg=BoundaryConditionCharacteristic(initial_condition_astro_jet), + x_pos=BoundaryConditionCharacteristic(initial_condition_astro_jet), y_neg=boundary_condition_periodic, y_pos=boundary_condition_periodic, ) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 07452ca8ee..ad1e73b275 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -367,7 +367,7 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end -@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, orientation, direction, x, t, equations) +@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, orientation::Integer, direction, x, t, equations) # Get inverse of density srho = 1 / u_inner[1] @@ -417,6 +417,52 @@ end return cons end +@inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, normal_direction::AbstractVector, direction, x, t, equations) + # Get inverse of density + srho = 1 / u_inner[1] + + # Get normal velocity + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + factor = 1 + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + factor = -1 + end + vn = factor * (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) / norm(normal_direction) + + # get pressure and Mach from state + p = pressure(u_inner, equations) + a = sqrt(equations.gamma * p * srho) + normalMachNo = abs(vn / a) + + if vn < 0 # inflow + if normalMachNo < 1.0 + # subsonic inflow: All variables from outside but pressure + cons = outer_boundary_value_function(x, t, equations) + + prim = cons2prim(cons, equations) + prim = SVector(view(prim, 1:3)..., p) + cons = prim2cons(prim, equations) + else + # supersonic inflow: All variables from outside + cons = outer_boundary_value_function(x, t, equations) + end + else # outflow + if normalMachNo < 1.0 + # subsonic outflow: All variables from inside but pressure + cons = outer_boundary_value_function(x, t, equations) + + prim = cons2prim(u_inner, equations) + prim = SVector(view(prim, 1:3)..., pressure(cons, equations)) + cons = prim2cons(prim, equations) + else + # supersonic outflow: All variables from inside + cons = u_inner + end + end + + return cons +end + # Calculate 2D flux for a single point @inline function flux(u, orientation::Integer, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index d948a7e575..2ebbaa9c40 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -526,10 +526,10 @@ end for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, equations, dg, 1, j, element) - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) !calcBarStates && continue @@ -545,10 +545,10 @@ end for cell_y in axes(mesh, 2) element = linear_indices[end, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, equations, dg, nnodes(dg), j, element) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) !calcBarStates && continue @@ -566,10 +566,10 @@ end for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, equations, dg, i, 1, element) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) !calcBarStates && continue @@ -585,10 +585,10 @@ end for cell_x in axes(mesh, 1) element = linear_indices[cell_x, end] for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], - equations, dg, i, nnodes(dg), element) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, + equations, dg, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) !calcBarStates && continue diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 2050a7b08f..74ce40d0a8 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -31,6 +31,7 @@ end function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh::StructuredMesh{2}) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi + @unpack contravariant_vectors = cache.elements # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids @@ -73,9 +74,10 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], - equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, + equations, dg, 1, j, element) var_outer = variable(u_outer, equations) var_min[1, j, element] = min(var_min[1, j, element], var_outer) @@ -86,8 +88,9 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m for cell_y in axes(mesh, 2) element = linear_indices[end, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, equations, dg, nnodes(dg), j, element) var_outer = variable(u_outer, equations) @@ -101,9 +104,10 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], - equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, + equations, dg, i, 1, element) var_outer = variable(u_outer, equations) var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) @@ -114,8 +118,9 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m for cell_x in axes(mesh, 1) element = linear_indices[cell_x, end] for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, equations, dg, i, nnodes(dg), element) var_outer = variable(u_outer, equations) @@ -131,6 +136,7 @@ end function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh::StructuredMesh{2}) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi + @unpack contravariant_vectors = cache.elements # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids @@ -167,8 +173,9 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, for cell_y in axes(mesh, 2) element = linear_indices[begin, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, equations, dg, 1, j, element) var_outer = variable(u_outer, equations) @@ -179,8 +186,9 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, for cell_y in axes(mesh, 2) element = linear_indices[end, cell_y] for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, equations, dg, nnodes(dg), j, element) var_outer = variable(u_outer, equations) @@ -193,8 +201,9 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, for cell_x in axes(mesh, 1) element = linear_indices[cell_x, begin] for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, equations, dg, i, 1, element) var_outer = variable(u_outer, equations) @@ -205,8 +214,9 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, for cell_x in axes(mesh, 1) element = linear_indices[cell_x, end] for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, equations, dg, i, nnodes(dg), element) var_outer = variable(u_outer, equations) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 9fc5b5a839..f55fff54d4 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1682,9 +1682,9 @@ end return nothing end -get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation, direction, equations, dg, indices...) = u_inner +get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation_or_normal, direction, equations, dg, indices...) = u_inner -@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, orientation, direction, equations, dg, indices...) +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, orientation_or_normal, direction, equations, dg, indices...) @unpack node_coordinates = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1693,11 +1693,11 @@ get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation, dir return u_outer end -@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionCharacteristic, orientation, direction, equations, dg, indices...) +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionCharacteristic, orientation_or_normal, direction, equations, dg, indices...) @unpack node_coordinates = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) - u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, u_inner, orientation, direction, x, t, equations) + u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, u_inner, orientation_or_normal, direction, x, t, equations) return u_outer end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 24edbe4297..c38fe62bec 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -331,7 +331,7 @@ end boundary_index += 2 end u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[boundary_index], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[boundary_index], orientation, boundary_index, equations, dg, index..., element) var_outer = variable(u_outer, equations) @@ -414,7 +414,7 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], orientation, 1, equations, dg, 1, j, element) var_outer = variable(u_outer, equations) @@ -423,7 +423,7 @@ end else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], orientation, 2, equations, dg, nnodes(dg), j, element) var_outer = variable(u_outer, equations) @@ -434,7 +434,7 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], orientation, 3, equations, dg, i, 1, element) var_outer = variable(u_outer, equations) @@ -443,7 +443,7 @@ end else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], + u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], orientation, 4, equations, dg, i, nnodes(dg), element) var_outer = variable(u_outer, equations) From 094868893484ef5a9119e6cec33f8396d1d3886f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 8 Feb 2023 14:41:29 +0100 Subject: [PATCH 140/423] Add semidiscrete entropy fix for Cartesian Meshes --- src/solvers/dgsem_tree/containers_2d.jl | 13 +- src/solvers/dgsem_tree/dg_2d.jl | 153 ++++++++++++++++++------ src/solvers/dgsem_tree/indicators.jl | 15 ++- src/solvers/dgsem_tree/indicators_2d.jl | 4 +- 4 files changed, 144 insertions(+), 41 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 758fe0648b..4b80b0bd0c 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1380,11 +1380,13 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} var_max::Array{uEltype, 4} # [variable, i, j, element] alpha::Array{uEltype, 4} # [variable, i, j, element] alpha_pressure::Array{uEltype, 3} # [i, j, element] + alpha_entropy::Array{uEltype, 3} # [i, j, element] # internal `resize!`able storage _var_min::Vector{uEltype} _var_max::Vector{uEltype} _alpha::Vector{uEltype} _alpha_pressure::Vector{uEltype} + _alpha_entropy::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real @@ -1402,8 +1404,11 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_pressure = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, - _var_min, _var_max, _alpha, _alpha_pressure) + _alpha_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) + alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) + + return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, + _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy) end nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) @@ -1432,6 +1437,10 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_alpha_pressure, n_nodes * n_nodes * capacity) container.alpha_pressure = unsafe_wrap(Array, pointer(_alpha_pressure), (n_nodes, n_nodes, capacity)) + @unpack _alpha_entropy = container + resize!(_alpha_entropy, n_nodes * n_nodes * capacity) + container.alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) + return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index f55fff54d4..2cfdc31204 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -649,7 +649,8 @@ end u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) # limit antidiffusive flux - calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) + calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache, + fstar1_L, fstar2_L) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D for j in eachnode(dg), i in eachnode(dg) @@ -1189,7 +1190,8 @@ end return nothing end -@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache) +@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache, + fstar1, fstar2) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @@ -1581,38 +1583,38 @@ end flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 Q = - lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - - 0.5 * bar_state_velocity) + 0.5 * bar_state_velocity) P_1 = 0.5 * flux_velocity - antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element] - P_2 = lambda1[i, j, element] * (bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + - bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) - + P_2 = lambda1[i, j, element] * (bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + + bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - + bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - + bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + # Solve the quadratic formula - aux_var = P_2^2 - 4*P_1*Q + aux_var = P_2^2 - 4 * P_1 * Q if aux_var >= 0.0 # Only solve for real solutions aux_var = sqrt(aux_var) - alpha1 = 0.5 * (-P_2 + aux_var) / (P_1) - alpha2 = 0.5 * (-P_2 - aux_var) / (P_1) - alpha3 = 0.5 * ( P_2 + aux_var) / (P_1) - alpha4 = 0.5 * ( P_2 - aux_var) / (P_1) - + alpha1 = 0.5 * (-P_2 + aux_var) / P_1 + alpha2 = 0.5 * (-P_2 - aux_var) / P_1 + alpha3 = 0.5 * ( P_2 + aux_var) / P_1 + alpha4 = 0.5 * ( P_2 - aux_var) / P_1 + # If the solutions are negative, we can take the maximum antidiffusive flux - if alpha1 < 0.0 + if alpha1 < 0.0 alpha1 = 1.0 end - if alpha2 < 0.0 + if alpha2 < 0.0 alpha2 = 1.0 end - if alpha3 < 0.0 + if alpha3 < 0.0 alpha3 = 1.0 end - if alpha4 < 0.0 + if alpha4 < 0.0 alpha4 = 1.0 end # Get the most restrictive alpha - alpha = min(alpha1,alpha2,alpha3,alpha4,1.0) + alpha = min(alpha1, alpha2, alpha3, alpha4, 1.0) else # If the solutions are complex, we can take the maximum antidiffusive flux alpha = 1.0 @@ -1636,39 +1638,39 @@ end P_1 = 0.5 * flux_velocity - antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element] P_2 = lambda2[i, j, element] * (bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + - bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - + bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - + bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) # Solve the quadratic formula - aux_var = P_2^2 - 4*P_1*Q - if P_2^2 - 4*P_1*Q >= 0.0 + aux_var = P_2^2 - 4 * P_1 * Q + if aux_var >= 0.0 # Only solve for real solutions aux_var = sqrt(aux_var) - alpha1 = 0.5 * (-P_2 + aux_var) / (P_1) - alpha2 = 0.5 * (-P_2 - aux_var) / (P_1) - alpha3 = 0.5 * ( P_2 + aux_var) / (P_1) - alpha4 = 0.5 * ( P_2 - aux_var) / (P_1) - + alpha1 = 0.5 * (-P_2 + aux_var) / P_1 + alpha2 = 0.5 * (-P_2 - aux_var) / P_1 + alpha3 = 0.5 * ( P_2 + aux_var) / P_1 + alpha4 = 0.5 * ( P_2 - aux_var) / P_1 + # If the solutions are negative, we can take the maximum antidiffusive flux - if alpha1 < 0.0 + if alpha1 < 0.0 alpha1 = 1.0 end - if alpha2 < 0.0 + if alpha2 < 0.0 alpha2 = 1.0 end - if alpha3 < 0.0 + if alpha3 < 0.0 alpha3 = 1.0 end - if alpha4 < 0.0 + if alpha4 < 0.0 alpha4 = 1.0 end # Get the most restrictive alpha - alpha = min(alpha1,alpha2,alpha3,alpha4,1.0) + alpha = min(alpha1, alpha2, alpha3, alpha4, 1.0) else # If the solutions are complex, we can take the maximum antidiffusive flux alpha = 1.0 end - + if indicator.Plotting alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) @@ -1679,6 +1681,87 @@ end end end + # Limit entropy + # TODO: This is a very inefficient function. We compute the entropy four times at each node. + # TODO: For now, this only works for Cartesian meshes. + if indicator.SemiDiscEntropyLimiter + @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting + alpha_entropy[:, :, element] .= one(eltype(alpha_entropy)) + end + for j in eachnode(dg), i in 2:nnodes(dg) + antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) + u_local_m1 = get_node_vars(u, equations, dg, i-1, j, element) + + # Using mathematic entropy + v_local = cons2entropy(u_local, equations) + v_local_m1 = cons2entropy(u_local_m1, equations) + + q_local = u_local[2] / u_local[1] * entropy(u_local, equations) + q_local_m1 = u_local_m1[2] / u_local_m1[1] * entropy(u_local_m1, equations) + + f_local = flux(u_local, 1, equations) + f_local_m1 = flux(u_local_m1, 1, equations) + + psi_local = dot(v_local, f_local) - q_local + psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 + + delta_v = v_local - v_local_m1 + delta_psi = psi_local - psi_local_m1 + + entProd_FV = dot(delta_v, fstar1[:, i, j]) - delta_psi + delta_entProd = dot(delta_v, antidiffusive_flux_local) + + if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) + alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) + if indicator.Plotting + alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + end + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] = alpha * antidiffusive_flux1[v, i, j, element] + end + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + antidiffusive_flux_local = get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) + u_local_m1 = get_node_vars(u, equations, dg, i, j-1, element) + + # Using mathematic entropy + v_local = cons2entropy(u_local, equations) + v_local_m1 = cons2entropy(u_local_m1, equations) + + q_local = u_local[3] / u_local[1] * entropy(u_local, equations) + q_local_m1 = u_local_m1[3] / u_local_m1[1] * entropy(u_local_m1, equations) + + f_local = flux(u_local, 2, equations) + f_local_m1 = flux(u_local_m1, 2, equations) + + psi_local = dot(v_local, f_local) - q_local + psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 + + delta_v = v_local - v_local_m1 + delta_psi = psi_local - psi_local_m1 + + entProd_FV = dot(delta_v, fstar2[:, i, j]) - delta_psi + delta_entProd = dot(delta_v, antidiffusive_flux_local) + + if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) + alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) + if indicator.Plotting + alpha_entropy[i, j-1, element] = min(alpha_entropy[i, j-1, element], alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + end + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] = alpha * antidiffusive_flux2[v, i, j, element] + end + end + end + end + return nothing end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 03bc8f2a8d..45a44d30ed 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -300,6 +300,7 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin PressurePositivityLimiter::Bool # synchronized pressure limiting DensityPositivityLimiter::Bool + SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner thr_smooth::RealT # threshold for smoothness indicator @@ -316,6 +317,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; PressurePositivityLimiterKuzmin=false,# Impose positivity for pressure â la Kuzmin PressurePositivityLimiter=false, # Impose positivity for pressure DensityPositivityLimiter=false, # Impose positivity for cons(1) + SemiDiscEntropyLimiter=false, IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) @@ -332,8 +334,11 @@ function IndicatorMCL(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, PressurePositivityLimiter, DensityPositivityLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) + IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, + DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzmin, PressurePositivityLimiter, + DensityPositivityLimiter, SemiDiscEntropyLimiter, + IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @@ -347,6 +352,7 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.PressurePositivityLimiterKuzmin && print(io, "; pres (Kuzmin)") indicator.PressurePositivityLimiter && print(io, "; pres") indicator.DensityPositivityLimiter && print(io, "; dens pos") + indicator.SemiDiscEntropyLimiter && print(io, "; semidiscrete entropy fix") indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) print(io, ")") @@ -368,6 +374,11 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[:shock_capturing_alpha_pressure] = alpha_pressure end + if indicator.SemiDiscEntropyLimiter + @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator + node_variables[:shock_capturing_alpha_entropy] = alpha_entropy + end + return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index c38fe62bec..8efe9ea03d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -905,11 +905,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, IDPPressure) + basis::LobattoLegendreBasis, PressureLimiter) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + IDPPressure) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressureLimiter) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end From ecba7468741c9c9d7cd724396ed76e16199244a7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 10:32:57 +0100 Subject: [PATCH 141/423] Fix `summary_bounds_check` after renaming PressureLimiters --- src/time_integration/methods_SSP.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index cc09f92741..16e9aacbd8 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -352,7 +352,7 @@ end for v in eachvariable(equations) println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) end - if indicator.IDPPressure + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(equations)+1]) end println("─"^100 * "\n") From 838cc0e6dcc81ff0574481f9a1110a358eed5d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 9 Feb 2023 11:15:19 +0100 Subject: [PATCH 142/423] MCL: DensityAlphaForAll can be used in combination with DensityPositivityLimiter --- src/solvers/dgsem_tree/dg_2d.jl | 44 +++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 2cfdc31204..1f824ee13b 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1454,17 +1454,31 @@ end flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end - if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting || indicator.DensityAlphaForAll if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] end - alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end end antidiffusive_flux1[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if indicator.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, element] + if indicator.Plotting + alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + end + end + end end for j in 2:nnodes(dg), i in eachnode(dg) @@ -1481,17 +1495,31 @@ end flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end - if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting || indicator.DensityAlphaForAll if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] end - alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + + if indicator.Plotting + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + end end antidiffusive_flux2[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if indicator.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, element] + if indicator.Plotting + alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) + alpha[v, i, j , element] = min(alpha[v, i, j , element], coefficient) + end + end + end end end #if indicator.DensityPositivityLimiter From f17f84522ad5e1f2394020e044e454239f57b88e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 12:18:39 +0100 Subject: [PATCH 143/423] Check bounds for pressure without `SequentialLimiter` and `ConservativeLimiter` --- src/solvers/dgsem_tree/dg_2d.jl | 45 ++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 1f824ee13b..ec2c8e369e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -2013,7 +2013,6 @@ end end # indicator.DensityLimiter - # TODO: Pressure bounds are only checked if sequential or conservative limiters are active if indicator.SequentialLimiter # New solution u^{n+1} for element in eachelement(solver, cache) @@ -2126,7 +2125,6 @@ end # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 var_limited = zero(eltype(idp_bounds_delta)) - rho_limited = zero(eltype(idp_bounds_delta)) error_pressure = zero(eltype(idp_bounds_delta)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -2192,7 +2190,48 @@ end end end end - end # indicator.ConservativeLimiter + elseif indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + error_pressure = 0.5 * (bar_states1[2, i, j, element] - antidiffusive_flux1[2, i, j, element] / lambda1[i, j, element])^2 + + 0.5 * (bar_states1[3, i, j, element] - antidiffusive_flux1[3, i, j, element] / lambda1[i, j, element])^2 - + (bar_states1[4, i, j, element] - antidiffusive_flux1[4, i, j, element] / lambda1[i, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + error_pressure = 0.5 * (bar_states1[2, i+1, j, element] + antidiffusive_flux1[2, i+1, j, element] / lambda1[i+1, j, element])^2 + + 0.5 * (bar_states1[3, i+1, j, element] + antidiffusive_flux1[3, i+1, j, element] / lambda1[i+1, j, element])^2 - + (bar_states1[4, i+1, j, element] + antidiffusive_flux1[4, i+1, j, element] / lambda1[i+1, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # -y + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + error_pressure = 0.5 * (bar_states2[2, i, j, element] - antidiffusive_flux2[2, i, j, element] / lambda2[i, j, element])^2 + + 0.5 * (bar_states2[3, i, j, element] - antidiffusive_flux2[3, i, j, element] / lambda2[i, j, element])^2 - + (bar_states2[4, i, j, element] - antidiffusive_flux2[4, i, j, element] / lambda2[i, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + error_pressure = 0.5 * (bar_states2[2, i, j+1, element] + antidiffusive_flux2[2, i, j+1, element] / lambda2[i, j+1, element])^2 + + 0.5 * (bar_states2[3, i, j+1, element] + antidiffusive_flux2[3, i, j+1, element] / lambda2[i, j+1, element])^2 - + (bar_states2[4, i, j+1, element] + antidiffusive_flux2[4, i, j+1, element] / lambda2[i, j+1, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end # indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter if indicator.DensityPositivityLimiter # New solution u^{n+1} From 88dbf5cf3716c2e97bf5c42c9e4e54d7f3ecb524 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 13:52:00 +0100 Subject: [PATCH 144/423] Saving the course of the minimal alpha over time --- src/solvers/dgsem_tree/dg_2d.jl | 8 +----- src/solvers/dgsem_tree/indicators_2d.jl | 37 +++++++++++++++++++++++++ src/time_integration/methods_SSP.jl | 7 +++-- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ec2c8e369e..8445932416 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1501,7 +1501,7 @@ end else coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] end - + if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) @@ -1526,9 +1526,6 @@ end # Limit pressure à la Kuzmin if indicator.PressurePositivityLimiterKuzmin @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - if indicator.Plotting - alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) - end for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 @@ -1603,9 +1600,6 @@ end # New pressure limiter! elseif indicator.PressurePositivityLimiter @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - if indicator.Plotting - alpha_pressure[:, :, element] .= one(eltype(alpha_pressure)) - end for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 8efe9ea03d..5a54aa6a7b 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -903,6 +903,17 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, return nothing end +@inline function save_alpha_per_timestep!(indicator::IndicatorIDP, iter, semi, mesh) + _, equations, solver, cache = mesh_equations_solver_cache(semi) + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + + # TODO: For IndicatorIDP + + # TODO: volume-weighted alpha + + return nothing +end + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressureLimiter) @@ -919,6 +930,32 @@ end return nothing end +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + + # TODO: volume-weighted average of alpha + # and then StructuredMesh + + n_vars = nvariables(equations) + vars = varnames(cons2cons, equations) + + # Save the alphas every x iterations + x = 1 + if x == 0 || iter % x != 0 + return nothing + end + + for v in eachvariable(equations) + open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end + end + + return nothing +end + # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 16e9aacbd8..cbb240efde 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -143,10 +143,11 @@ function solve!(integrator::SimpleIntegratorSSP) # reset alphas for Plotting of MCL @unpack indicator = integrator.p.solver.volume_integral if indicator isa IndicatorMCL && indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) - alpha[:, i, j, element] .= 1.0 + alpha[:, i, j, element] .= one(eltype(alpha)) + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end end end @@ -175,6 +176,8 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end + @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.iter+1, integrator.p, integrator.p.mesh) + if integrator.p.solver.volume_integral.indicator isa IndicatorIDP indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t end From 3621eed22baf1abbf14230093ee135de743cab91 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 14:06:17 +0100 Subject: [PATCH 145/423] Add average alpha for MCL and TreeMesh2D --- src/solvers/dgsem_tree/indicators_2d.jl | 72 +++++++++++++++++++------ 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 5a54aa6a7b..0a6d5871b5 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -930,28 +930,66 @@ end return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - # TODO: volume-weighted average of alpha - # and then StructuredMesh + error("TODO: volume-weighted average of alpha") - n_vars = nvariables(equations) - vars = varnames(cons2cons, equations) + # Save the alphas every x iterations + x = 1 + if x == 0 || iter % x != 0 + return nothing + end - # Save the alphas every x iterations - x = 1 - if x == 0 || iter % x != 0 - return nothing - end + n_vars = nvariables(equations) + vars = varnames(cons2cons, equations) - for v in eachvariable(equations) - open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end - end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end + for v in eachvariable(equations) + open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end + end + + return nothing +end + +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack weights = dg.basis + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + + # Save the alphas every x iterations + x = 1 + if x == 0 || iter % x != 0 + return nothing + end + + n_vars = nvariables(equations) + vars = varnames(cons2cons, equations) + + alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) + total_volume = zero(eltype(alpha)) + for element in eachelement(dg, cache) + jacobian = inv(cache.elements.inverse_jacobian[element]) + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + end + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + total_volume += jacobian * weights[i] * weights[j] end + end + + for v in eachvariable(equations) + open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end + open(string("Alpha_avg_", vars[v], ".txt"), "a") do f; println(f, alpha_avg[v] / total_volume); end + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end + open("Alpha_avg_pressure.txt", "a") do f; println(f, alpha_avg[n_vars + 1] / total_volume); end + end return nothing end From 05b1f581b73321d1a965d80a8d45a177d490b049 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 14:32:10 +0100 Subject: [PATCH 146/423] Complete saving alphas --- src/solvers/dgsem_structured/indicators_2d.jl | 49 +++++++++++++++--- src/solvers/dgsem_tree/indicators_2d.jl | 51 +++++-------------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 74ce40d0a8..b0a7d54d4f 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -229,22 +229,16 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh) +@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - if indicator.indicator_smooth - elements = cache.element_ids_dgfv - else - elements = eachelement(solver, cache) - end - alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) - for element in elements + for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] @@ -258,5 +252,44 @@ end return nothing end +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack weights = dg.basis + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + + # Save the alphas every x iterations + x = 1 + if x == 0 || iter % x != 0 + return nothing + end + + n_vars = nvariables(equations) + vars = varnames(cons2cons, equations) + + alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) + total_volume = zero(eltype(alpha)) + for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) + for v in eachvariable(equations) + alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + end + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + + for v in eachvariable(equations) + open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end + open(string("Alpha_avg_", vars[v], ".txt"), "a") do f; println(f, alpha_avg[v] / total_volume); end + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end + open("Alpha_avg_pressure.txt", "a") do f; println(f, alpha_avg[n_vars + 1] / total_volume); end + end + + return nothing +end + end # @muladd diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 0a6d5871b5..2bc080fe2a 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -880,16 +880,10 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - if indicator.indicator_smooth - elements = cache.element_ids_dgfv - else - elements = eachelement(solver, cache) - end - alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) - for element in elements + for element in eachelement(solver, cache) jacobian = inv(cache.elements.inverse_jacobian[element]) for j in eachnode(solver), i in eachnode(solver) alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] @@ -904,23 +898,29 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, end @inline function save_alpha_per_timestep!(indicator::IndicatorIDP, iter, semi, mesh) - _, equations, solver, cache = mesh_equations_solver_cache(semi) - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache + # The maximum and average values were calculated in `update_alpha_per_timestep!` in each RK stage. + # This is necessary if we want the average of the alphas over all stages (discussable). - # TODO: For IndicatorIDP + # Save the alphas every x iterations + x = 1 + if x == 0 || iter % x != 0 + return nothing + end - # TODO: volume-weighted alpha + open(string("Alpha_max.txt"), "a") do f; println(f, alpha_max_per_timestep[iter]); end + open(string("Alpha_avg.txt"), "a") do f; println(f, alpha_mean_per_timestep[iter]); end return nothing end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, PressureLimiter) + basis::LobattoLegendreBasis, PressurePositivityLimiter) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressureLimiter) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiter) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end @@ -930,31 +930,6 @@ end return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::StructuredMesh{2}) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - - error("TODO: volume-weighted average of alpha") - - # Save the alphas every x iterations - x = 1 - if x == 0 || iter % x != 0 - return nothing - end - - n_vars = nvariables(equations) - vars = varnames(cons2cons, equations) - - for v in eachvariable(equations) - open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end - end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end - end - - return nothing -end - @inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis From 420836832049b670f941dbe4f8a7e447f9e6067e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 17:08:23 +0100 Subject: [PATCH 147/423] Revise saving of deviations and alphas --- src/solvers/dgsem_structured/indicators_2d.jl | 38 ++++-- src/solvers/dgsem_tree/dg.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 111 ++++++++++++++---- src/solvers/dgsem_tree/indicators_2d.jl | 54 +++++++-- src/time_integration/methods_SSP.jl | 11 +- 5 files changed, 168 insertions(+), 50 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index b0a7d54d4f..f5861f922d 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -252,20 +252,36 @@ end return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::StructuredMesh{2}) +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 - if x == 0 || iter % x != 0 + if x == 0 return nothing end n_vars = nvariables(equations) vars = varnames(cons2cons, equations) + # Headline + if iter == 1 && x > 0 + open("$output_directory/alphas.txt", "a") do f; + print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + print(f, ", alpha_min_pressure, alpha_avg_pressure\n") + else + print(f, "\n") + end + end + end + + if iter % x != 0 + return nothing + end + alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -279,13 +295,17 @@ end end end - for v in eachvariable(equations) - open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end - open(string("Alpha_avg_", vars[v], ".txt"), "a") do f; println(f, alpha_avg[v] / total_volume); end - end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end - open("Alpha_avg_pressure.txt", "a") do f; println(f, alpha_avg[n_vars + 1] / total_volume); end + open("$output_directory/alphas.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); + print(f, ", ", alpha_avg[v] / total_volume); + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + println(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) + else + print(f, "\n") + end end return nothing diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index af7bb7ec0c..c74024c26f 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -44,11 +44,11 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end -@inline function IDP_checkBounds(u_ode, semi, iter, laststage) +@inline function IDP_checkBounds(u_ode, semi, time, iter, laststage, output_directory) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) - IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator, iter, laststage) + IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator, time, iter, laststage, output_directory) return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 8445932416..e001d52ccc 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1857,15 +1857,47 @@ end end # 2d, IndicatorIDP -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP, iter, laststage) +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP, time, iter, laststage, output_directory) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta = solver.volume_integral.indicator.cache # Save the deviations every x iterations - x = 0 - save_errors = laststage && (x > 0) && (iter % x == 0) + x = 1 + + # Headline + if laststage && x > 0 && iter == 1 + open("$output_directory/deviations.txt", "a") do f; + print(f, "# iter, simu_time") + if IDPDensityTVD + print(f, ", rho_min, rho_max"); + end + if IDPPressureTVD + print(f, ", p_min, p_max"); + end + if IDPPositivity && !IDPDensityTVD + print(f, ", rho_min"); + end + if IDPPositivity && !IDPPressureTVD + print(f, ", p_min"); + end + if IDPSpecEntropy + print(f, ", specEntr_min"); + end + if IDPMathEntropy + print(f, ", mathEntr_max"); + end + print(f, "\n") + end + end + + save_errors = laststage && x > 0 && (iter % x == 0) counter = 1 + if save_errors + open("$output_directory/deviations.txt", "a") do f; + print(f, iter, ", ", time); + end + end if IDPDensityTVD deviation_min = zero(eltype(u)) deviation_max = zero(eltype(u)) @@ -1878,8 +1910,9 @@ end if save_errors deviation_min_ = deviation_min deviation_max_ = deviation_max - open("Deviation_rho_min.txt", "a") do f; println(f, deviation_min_); end - open("Deviation_rho_max.txt", "a") do f; println(f, deviation_max_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_, ", ", deviation_max_); + end end counter += 2 end @@ -1896,8 +1929,9 @@ end if save_errors deviation_min_ = deviation_min deviation_max_ = deviation_max - open("Deviation_pre_min.txt", "a") do f; println(f, deviation_min_); end - open("Deviation_pre_max.txt", "a") do f; println(f, deviation_max_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_, ", ", deviation_max_); + end end counter += 2 end @@ -1909,7 +1943,9 @@ end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors deviation_min_ = deviation_min - open("Deviation_rho_min.txt", "a") do f; println(f, deviation_min_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end end counter += 1 end @@ -1922,7 +1958,9 @@ end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors deviation_min_ = deviation_min - open("Deviation_pre_min.txt", "a") do f; println(f, deviation_min_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end end counter += 1 end @@ -1935,7 +1973,9 @@ end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors deviation_min_ = deviation_min - open("Deviation_specEntr.txt", "a") do f; println(f, deviation_min_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end end counter += 1 end @@ -1948,28 +1988,45 @@ end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) if save_errors deviation_max_ = deviation_max - open("Deviation_mathEntr.txt", "a") do f; println(f, deviation_max_); end + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_max_); + end end end + if save_errors + open("$output_directory/deviations.txt", "a") do f; print(f, "\n"); end; + end return nothing end # 2d, IndicatorMCL -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL, iter, laststage) +@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL, time, iter, laststage, output_directory) @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D n_vars = nvariables(equations) - - deviation_min = zeros(eltype(u), n_vars + (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter)) - deviation_max = zeros(eltype(u), n_vars) + vars = varnames(cons2cons, equations) # Save the deviations every x iterations x = 1 - save_errors = laststage && (x > 0) && (iter % x == 0) + + # Headline + if laststage && x > 0 && iter == 1 + open("$output_directory/deviations.txt", "a") do f; + print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in vars)); + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + print(f, ", pressure_min\n") + else + print(f, "\n") + end + end + end + + deviation_min = zeros(eltype(u), n_vars + (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter)) + deviation_max = zeros(eltype(u), n_vars) if indicator.DensityLimiter # New solution u^{n+1} @@ -2006,7 +2063,6 @@ end end end # indicator.DensityLimiter - if indicator.SequentialLimiter # New solution u^{n+1} for element in eachelement(solver, cache) @@ -2257,19 +2313,26 @@ end end end # indicator.DensityPositivityLimiter - vars = varnames(cons2cons, equations) for v in eachvariable(equations) idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) - if save_errors - open(string("Deviation_", vars[v], "_min.txt"), "a") do f; println(f, deviation_min[v]); end - open(string("Deviation_", vars[v], "_max.txt"), "a") do f; println(f, deviation_max[v]); end - end end if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) - if save_errors - open("Deviation_pressure.txt", "a") do f; println(f, deviation_min[n_vars+1]); end + end + + if !laststage || x == 0 || iter % x != 0 + return nothing + end + open("$output_directory/deviations.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", deviation_min[v], ", ", deviation_max[v]); + end + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + println(f, ", ", deviation_min[n_vars+1]); + else + print(f, "\n"); end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 2bc080fe2a..b655f7a45e 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -897,19 +897,27 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorIDP, iter, semi, mesh) +@inline function save_alpha_per_timestep!(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache # The maximum and average values were calculated in `update_alpha_per_timestep!` in each RK stage. # This is necessary if we want the average of the alphas over all stages (discussable). # Save the alphas every x iterations x = 1 + + # Headline + if x > 0 && iter == 1 + open("$output_directory/alphas.txt", "a") do f; + println(f, "# iter, simu_time, alpha_min, alpha_avg"); + end + end + if x == 0 || iter % x != 0 return nothing end - - open(string("Alpha_max.txt"), "a") do f; println(f, alpha_max_per_timestep[iter]); end - open(string("Alpha_avg.txt"), "a") do f; println(f, alpha_mean_per_timestep[iter]); end + open("$output_directory/alphas.txt", "a") do f; + println(f, iter, ", ", time, ", ", alpha_max_per_timestep[iter], ", ", alpha_mean_per_timestep[iter]); + end return nothing end @@ -930,20 +938,36 @@ end return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, iter, semi, mesh::TreeMesh2D) +@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 - if x == 0 || iter % x != 0 + if x == 0 return nothing end n_vars = nvariables(equations) vars = varnames(cons2cons, equations) + # Headline + if iter == 1 + open("$output_directory/alphas.txt", "a") do f; + print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + println(f, ", alpha_min_pressure, alpha_avg_pressure") + else + print(f, "\n") + end + end + end + + if iter % x != 0 + return nothing + end + alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -957,13 +981,17 @@ end end end - for v in eachvariable(equations) - open(string("Alpha_min_", vars[v], ".txt"), "a") do f; println(f, minimum((view(alpha, v, ntuple(_ -> :, n_vars)...)))); end - open(string("Alpha_avg_", vars[v], ".txt"), "a") do f; println(f, alpha_avg[v] / total_volume); end - end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - open("Alpha_min_pressure.txt", "a") do f; println(f, minimum(alpha_pressure)); end - open("Alpha_avg_pressure.txt", "a") do f; println(f, alpha_avg[n_vars + 1] / total_volume); end + open("$output_directory/alphas.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); + print(f, ", ", alpha_avg[v] / total_volume); + end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + println(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) + else + print(f, "\n") + end end return nothing diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index cbb240efde..15497eecd3 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -128,6 +128,13 @@ function solve!(integrator::SimpleIntegratorSSP) t_end = last(prob.tspan) callbacks = integrator.opts.callback + # WARNING: Only works if the last callback got a variable `output_directory`. + if callbacks.discrete_callbacks[end].condition isa SaveSolutionCallback + output_directory = callbacks.discrete_callbacks[end].condition.output_directory + else + output_directory = "out" + end + integrator.finalstep = false @trixi_timeit timer() "main loop" while !integrator.finalstep if isnan(integrator.dt) @@ -169,14 +176,14 @@ function solve!(integrator::SimpleIntegratorSSP) # check that we are within bounds if indicator.IDPCheckBounds laststage = (stage == length(alg.c)) - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u, integrator.p, integrator.iter, laststage) + @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage, output_directory) end # perform convex combination @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end - @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.iter+1, integrator.p, integrator.p.mesh) + @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) if integrator.p.solver.volume_integral.indicator isa IndicatorIDP indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t From 0f665b0a2f846cd95ecb9fde8c231d93b896c1bd Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 9 Feb 2023 17:16:37 +0100 Subject: [PATCH 148/423] Remove Vectors for alpha_mean and alpha_max --- src/solvers/dgsem_structured/indicators_2d.jl | 4 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 17 +++++++-------- src/time_integration/methods_SSP.jl | 21 ------------------- 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index f5861f922d..6d55f69645 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -235,7 +235,7 @@ end @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) @@ -246,7 +246,7 @@ end end end if total_volume > 0 - alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg end return nothing diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index b655f7a45e..7566959584 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -200,13 +200,12 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation cache = (; cache..., ContainerBarStates) end - alpha_max_per_timestep = zeros(real(basis), 200) - alpha_mean_per_timestep = zeros(real(basis), 200) - time_per_timestep = zeros(real(basis), 200) + alpha_max_per_timestep = zero(real(basis)) + alpha_mean_per_timestep = zero(real(basis)) idp_bounds_delta = zeros(real(basis), length) - return (; cache..., alpha_max_per_timestep, alpha_mean_per_timestep, time_per_timestep, + return (; cache..., alpha_max_per_timestep, alpha_mean_per_timestep, ContainerShockCapturingIndicator, idp_bounds_delta) end @@ -877,10 +876,10 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, @inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache + @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep[timestep] = max(alpha_max_per_timestep[timestep], maximum(alpha)) + alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) @@ -891,14 +890,14 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, end end if total_volume > 0 - alpha_mean_per_timestep[timestep] += 1/(n_stages * total_volume) * alpha_avg + alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg end return nothing end @inline function save_alpha_per_timestep!(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) - @unpack alpha_mean_per_timestep, alpha_max_per_timestep, time_per_timestep = indicator.cache + @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache # The maximum and average values were calculated in `update_alpha_per_timestep!` in each RK stage. # This is necessary if we want the average of the alphas over all stages (discussable). @@ -916,7 +915,7 @@ end return nothing end open("$output_directory/alphas.txt", "a") do f; - println(f, iter, ", ", time, ", ", alpha_max_per_timestep[iter], ", ", alpha_mean_per_timestep[iter]); + println(f, iter, ", ", time, ", ", alpha_max_per_timestep, ", ", alpha_mean_per_timestep); end return nothing diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 15497eecd3..d7a4d1d161 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -185,21 +185,6 @@ function solve!(integrator::SimpleIntegratorSSP) @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) - if integrator.p.solver.volume_integral.indicator isa IndicatorIDP - indicator.cache.time_per_timestep[integrator.iter+1] = integrator.t - end - - if integrator.p.solver.volume_integral.indicator isa IndicatorIDP && - integrator.iter+1 == length(indicator.cache.alpha_max_per_timestep) && !integrator.finalstep - new_length = length(indicator.cache.alpha_max_per_timestep) + 200 - resize!(indicator.cache.alpha_max_per_timestep, new_length) - resize!(indicator.cache.alpha_mean_per_timestep, new_length) - resize!(indicator.cache.time_per_timestep, new_length) - indicator.cache.alpha_max_per_timestep[new_length - 199:new_length] .= 0.0 - indicator.cache.alpha_mean_per_timestep[new_length - 199:new_length] .= 0.0 - indicator.cache.time_per_timestep[new_length - 199:new_length] .= 0.0 - end - integrator.iter += 1 integrator.t += integrator.dt @@ -244,12 +229,6 @@ end function terminate!(integrator::SimpleIntegratorSSP) integrator.finalstep = true empty!(integrator.opts.tstops) - - if integrator.p.solver.volume_integral.indicator isa IndicatorIDP - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_max_per_timestep, integrator.iter+1) - resize!(integrator.p.solver.volume_integral.indicator.cache.alpha_mean_per_timestep, integrator.iter+1) - resize!(integrator.p.solver.volume_integral.indicator.cache.time_per_timestep, integrator.iter+1) - end end # used for AMR From f4a64148ec8e3d0b02f63c41b2096c484f5695e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 9 Feb 2023 22:47:10 +0100 Subject: [PATCH 149/423] Fix bug in new pressure positivity limiter --- src/solvers/dgsem_tree/dg_2d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e001d52ccc..e7b884df51 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1610,7 +1610,7 @@ end P_2 = lambda1[i, j, element] * (bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) # Solve the quadratic formula aux_var = P_2^2 - 4 * P_1 * Q @@ -1662,7 +1662,7 @@ end P_2 = lambda2[i, j, element] * (bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) # Solve the quadratic formula aux_var = P_2^2 - 4 * P_1 * Q if aux_var >= 0.0 From 22e9b17a0e38044c8f85a3fff9692ffc5ead5517 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 11:55:57 +0100 Subject: [PATCH 150/423] Fix alpha_max for IDP; Rename variables and functions --- src/solvers/dgsem_structured/indicators_2d.jl | 30 ++++++------ src/solvers/dgsem_tree/dg_2d.jl | 10 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 48 +++++++++---------- src/time_integration/methods_SSP.jl | 11 +++-- 4 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 6d55f69645..b6b322fb6d 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -229,30 +229,28 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) +@inline function update_alpha!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache + @unpack alpha_avg, alpha_max = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) - alpha_avg = zero(eltype(alpha)) + alpha_max = max(alpha_max, maximum(alpha)) + alpha_avg_ = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) - alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] + alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - if total_volume > 0 - alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg - end + alpha_avg += 1/(n_stages * total_volume) * alpha_avg_ return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) +@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator @@ -271,10 +269,9 @@ end open("$output_directory/alphas.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - print(f, ", alpha_min_pressure, alpha_avg_pressure\n") - else - print(f, "\n") + print(f, ", alpha_min_pressure, alpha_avg_pressure") end + println(f) end end @@ -290,7 +287,9 @@ end for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] end - alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + end total_volume += jacobian * weights[i] * weights[j] end end @@ -302,10 +301,9 @@ end print(f, ", ", alpha_avg[v] / total_volume); end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - println(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - else - print(f, "\n") + print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end + println(f) end return nothing diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e001d52ccc..5813675215 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -2018,10 +2018,9 @@ end open("$output_directory/deviations.txt", "a") do f; print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in vars)); if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - print(f, ", pressure_min\n") - else - print(f, "\n") + print(f, ", pressure_min") end + println(f) end end @@ -2330,10 +2329,9 @@ end print(f, ", ", deviation_min[v], ", ", deviation_max[v]); end if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter - println(f, ", ", deviation_min[n_vars+1]); - else - print(f, "\n"); + print(f, ", ", deviation_min[n_vars+1]); end + println(f); end return nothing diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 7566959584..12e7a95a7e 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -200,12 +200,12 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation cache = (; cache..., ContainerBarStates) end - alpha_max_per_timestep = zero(real(basis)) - alpha_mean_per_timestep = zero(real(basis)) + alpha_max = zero(real(basis)) + alpha_avg = zero(real(basis)) idp_bounds_delta = zeros(real(basis), length) - return (; cache..., alpha_max_per_timestep, alpha_mean_per_timestep, + return (; cache..., alpha_max, alpha_avg, ContainerShockCapturingIndicator, idp_bounds_delta) end @@ -873,32 +873,30 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) +@inline function update_alpha!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache + @unpack alpha_avg, alpha_max = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) - alpha_avg = zero(eltype(alpha)) + alpha_max = max(alpha_max, maximum(alpha)) + alpha_avg_ = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) jacobian = inv(cache.elements.inverse_jacobian[element]) for j in eachnode(solver), i in eachnode(solver) - alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] + alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - if total_volume > 0 - alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg - end + alpha_avg += 1/(n_stages * total_volume) * alpha_avg_ return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) - @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache - # The maximum and average values were calculated in `update_alpha_per_timestep!` in each RK stage. +@inline function save_alpha(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) + @unpack alpha_avg, alpha_max = indicator.cache + # The maximum and average values were calculated in `update_alpha!` in each RK stage. # This is necessary if we want the average of the alphas over all stages (discussable). # Save the alphas every x iterations @@ -907,7 +905,7 @@ end # Headline if x > 0 && iter == 1 open("$output_directory/alphas.txt", "a") do f; - println(f, "# iter, simu_time, alpha_min, alpha_avg"); + println(f, "# iter, simu_time, alpha_max, alpha_avg"); end end @@ -915,7 +913,7 @@ end return nothing end open("$output_directory/alphas.txt", "a") do f; - println(f, iter, ", ", time, ", ", alpha_max_per_timestep, ", ", alpha_mean_per_timestep); + println(f, iter, ", ", time, ", ", alpha_max, ", ", alpha_avg); end return nothing @@ -932,12 +930,12 @@ function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquation return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end -@inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) +@inline function update_alpha!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) +@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator @@ -956,10 +954,9 @@ end open("$output_directory/alphas.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - println(f, ", alpha_min_pressure, alpha_avg_pressure") - else - print(f, "\n") + print(f, ", alpha_min_pressure, alpha_avg_pressure") end + println(f) end end @@ -975,7 +972,9 @@ end for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] end - alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + end total_volume += jacobian * weights[i] * weights[j] end end @@ -987,10 +986,9 @@ end print(f, ", ", alpha_avg[v] / total_volume); end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - println(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - else - print(f, "\n") + print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end + println(f) end return nothing diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index d7a4d1d161..4d22a5c4b1 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -154,9 +154,14 @@ function solve!(integrator::SimpleIntegratorSSP) @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) alpha[:, i, j, element] .= one(eltype(alpha)) - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end end end + elseif indicator isa IndicatorIDP + indicator.cache.alpha_max = zero(indicator.cache.alpha_max) + indicator.cache.alpha_avg = zero(indicator.cache.alpha_avg) end @. integrator.r0 = integrator.u @@ -171,7 +176,7 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) - @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) + @trixi_timeit timer() "update_alpha!" update_alpha!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) # check that we are within bounds if indicator.IDPCheckBounds @@ -183,7 +188,7 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end - @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) + @trixi_timeit timer() "save_alpha" save_alpha(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) integrator.iter += 1 integrator.t += integrator.dt From 28d68c3470a2fda34354707ceee3fe9b2e169b6e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 13:27:36 +0100 Subject: [PATCH 151/423] Fix last commit --- src/time_integration/methods_SSP.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 4d22a5c4b1..0c6d018938 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -160,8 +160,8 @@ function solve!(integrator::SimpleIntegratorSSP) end end elseif indicator isa IndicatorIDP - indicator.cache.alpha_max = zero(indicator.cache.alpha_max) - indicator.cache.alpha_avg = zero(indicator.cache.alpha_avg) + indicator.cache.alpha_max = zero(eltype(indicator.cache.alpha_max)) + indicator.cache.alpha_avg = zero(eltype(indicator.cache.alpha_avg)) end @. integrator.r0 = integrator.u From 199c8ab796e90927b4f49fd239d41b904055bbe1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 13:36:13 +0100 Subject: [PATCH 152/423] Reset alpha_max, alpha_mean every time step (IDP) --- src/time_integration/methods_SSP.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 0c6d018938..c20e2c2dad 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -160,8 +160,9 @@ function solve!(integrator::SimpleIntegratorSSP) end end elseif indicator isa IndicatorIDP - indicator.cache.alpha_max = zero(eltype(indicator.cache.alpha_max)) - indicator.cache.alpha_avg = zero(eltype(indicator.cache.alpha_avg)) + @unpack alpha_avg, alpha_max = indicator.cache + alpha_max = zero(eltype(alpha_max)) + alpha_avg = zero(eltype(alpha_avg)) end @. integrator.r0 = integrator.u From d32051c80f52b4f0059775c4e872a06e1c869790 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 14:21:29 +0100 Subject: [PATCH 153/423] Fix output of alphas for IDP; Rename functions --- src/solvers/dgsem_structured/indicators_2d.jl | 12 ++++---- src/solvers/dgsem_tree/indicators_2d.jl | 28 ++++++++----------- src/time_integration/methods_SSP.jl | 4 +-- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 6d55f69645..40fa94b20f 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -229,13 +229,13 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) +@inline function update_alpha_max_avg!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep= indicator.cache + @unpack alpha_max_avg = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) + alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) @@ -245,14 +245,12 @@ end total_volume += jacobian * weights[i] * weights[j] end end - if total_volume > 0 - alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg - end + alpha_max_avg[2] += 1/(n_stages * total_volume) * alpha_avg return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) +@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 7566959584..014b290f39 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -200,13 +200,11 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation cache = (; cache..., ContainerBarStates) end - alpha_max_per_timestep = zero(real(basis)) - alpha_mean_per_timestep = zero(real(basis)) + alpha_max_avg = zeros(real(basis), 2) idp_bounds_delta = zeros(real(basis), length) - return (; cache..., alpha_max_per_timestep, alpha_mean_per_timestep, - ContainerShockCapturingIndicator, idp_bounds_delta) + return (; cache..., alpha_max_avg, ContainerShockCapturingIndicator, idp_bounds_delta) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) @@ -873,13 +871,13 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) -@inline function update_alpha_per_timestep!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) +@inline function update_alpha_max_avg!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis - @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache + @unpack alpha_max_avg = indicator.cache @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - alpha_max_per_timestep = max(alpha_max_per_timestep, maximum(alpha)) + alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(solver, cache) @@ -889,15 +887,13 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, total_volume += jacobian * weights[i] * weights[j] end end - if total_volume > 0 - alpha_mean_per_timestep += 1/(n_stages * total_volume) * alpha_avg - end + alpha_max_avg[2] += 1/(n_stages * total_volume) * alpha_avg return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) - @unpack alpha_mean_per_timestep, alpha_max_per_timestep = indicator.cache +@inline function save_alpha(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) + @unpack alpha_max_avg = indicator.cache # The maximum and average values were calculated in `update_alpha_per_timestep!` in each RK stage. # This is necessary if we want the average of the alphas over all stages (discussable). @@ -907,7 +903,7 @@ end # Headline if x > 0 && iter == 1 open("$output_directory/alphas.txt", "a") do f; - println(f, "# iter, simu_time, alpha_min, alpha_avg"); + println(f, "# iter, simu_time, alpha_max, alpha_avg"); end end @@ -915,7 +911,7 @@ end return nothing end open("$output_directory/alphas.txt", "a") do f; - println(f, iter, ", ", time, ", ", alpha_max_per_timestep, ", ", alpha_mean_per_timestep); + println(f, iter, ", ", time, ", ", alpha_max_avg[1], ", ", alpha_max_avg[2]); end return nothing @@ -932,12 +928,12 @@ function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquation return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end -@inline function update_alpha_per_timestep!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) +@inline function update_alpha_max_avg!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) return nothing end -@inline function save_alpha_per_timestep!(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) +@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index d7a4d1d161..c257089645 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -171,7 +171,7 @@ function solve!(integrator::SimpleIntegratorSSP) end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) - @trixi_timeit timer() "update_alpha_per_timestep!" update_alpha_per_timestep!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) + @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) # check that we are within bounds if indicator.IDPCheckBounds @@ -183,7 +183,7 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end - @trixi_timeit timer() "save_alpha_per_timestep!" save_alpha_per_timestep!(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) + @trixi_timeit timer() "save_alpha" save_alpha(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) integrator.iter += 1 integrator.t += integrator.dt From 8f4e8aa4d4e1bd1a862fa72860d9270a1d32b1e1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 14:22:20 +0100 Subject: [PATCH 154/423] Reset alpha_max_avg --- src/time_integration/methods_SSP.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index c257089645..a836f8d1e5 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -157,6 +157,8 @@ function solve!(integrator::SimpleIntegratorSSP) alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end end + elseif indicator isa IndicatorIDP + indicator.cache.alpha_max_avg .= zero(eltype(indicator.cache.alpha_max_avg)) end @. integrator.r0 = integrator.u From 8dddbcd8f374fd9c8ff74f718068158c5b811547 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 12 Feb 2023 14:54:58 +0100 Subject: [PATCH 155/423] Move reset of alphas --- src/solvers/dgsem_structured/indicators_2d.jl | 12 +++++++++++- src/solvers/dgsem_tree/dg_2d.jl | 4 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 15 ++++++++++++++- src/time_integration/methods_SSP.jl | 16 ---------------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 7ffd63d40a..d2061591a7 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -257,7 +257,7 @@ end # Save the alphas every x iterations x = 1 - if x == 0 + if x == 0 || !indicator.Plotting return nothing end @@ -306,6 +306,16 @@ end println(f) end + # Reset alphas + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + alpha[:, i, j, element] .= one(eltype(alpha)) + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end + end + end + return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ce44ded979..df1fb221c4 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1887,7 +1887,7 @@ end if IDPMathEntropy print(f, ", mathEntr_max"); end - print(f, "\n") + println(f) end end @@ -1994,7 +1994,7 @@ end end end if save_errors - open("$output_directory/deviations.txt", "a") do f; print(f, "\n"); end; + open("$output_directory/deviations.txt", "a") do f; println(f); end; end return nothing diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index fce0d2bb13..cc9f693299 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -914,6 +914,9 @@ end println(f, iter, ", ", time, ", ", alpha_max_avg[1], ", ", alpha_max_avg[2]); end + # Reset alpha_max_avg + indicator.cache.alpha_max_avg .= zero(eltype(indicator.cache.alpha_max_avg)) + return nothing end @@ -940,7 +943,7 @@ end # Save the alphas every x iterations x = 1 - if x == 0 + if x == 0 || !indicator.Plotting return nothing end @@ -989,6 +992,16 @@ end println(f) end + # Reset alphas + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + alpha[:, i, j, element] .= one(eltype(alpha)) + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end + end + end + return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 5961c06ed8..48a960858b 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -147,22 +147,6 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - # reset alphas for Plotting of MCL - @unpack indicator = integrator.p.solver.volume_integral - if indicator isa IndicatorMCL && indicator.Plotting - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) - for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) - alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) - end - end - end - elseif indicator isa IndicatorIDP - indicator.cache.alpha_max_avg .= zero(eltype(indicator.cache.alpha_max_avg)) - end - @. integrator.r0 = integrator.u for stage in eachindex(alg.c) @trixi_timeit timer() "Runge-Kutta stage" begin From c4ec2fa517d398ae8fdd12089351e964a2398095 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 14 Feb 2023 10:34:42 +0100 Subject: [PATCH 156/423] Fix alphas for first time step (MCL) --- src/solvers/dgsem_structured/indicators_2d.jl | 10 ---------- src/solvers/dgsem_tree/indicators_2d.jl | 10 ---------- src/time_integration/methods_SSP.jl | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index d2061591a7..4adf32dde8 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -306,16 +306,6 @@ end println(f) end - # Reset alphas - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) - end - end - end - return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index cc9f693299..f4428c529c 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -992,16 +992,6 @@ end println(f) end - # Reset alphas - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) - end - end - end - return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 48a960858b..ca092cea37 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -147,6 +147,20 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end + # Reset alphas for MCL + @unpack indicator = integrator.p.solver.volume_integral + if indicator isa IndicatorMCL && indicator.Plotting + @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + alpha[:, i, j, element] .= one(eltype(alpha)) + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end + end + end + end + @. integrator.r0 = integrator.u for stage in eachindex(alg.c) @trixi_timeit timer() "Runge-Kutta stage" begin From 8ff31e725c5c0314709fa8e22a16872acb5d958f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 14 Feb 2023 10:39:47 +0100 Subject: [PATCH 157/423] Fix last commit --- src/time_integration/methods_SSP.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index ca092cea37..c4b0ebb290 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -151,8 +151,8 @@ function solve!(integrator::SimpleIntegratorSSP) @unpack indicator = integrator.p.solver.volume_integral if indicator isa IndicatorMCL && indicator.Plotting @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) + @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) + for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) alpha[:, i, j, element] .= one(eltype(alpha)) if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) From 5ac90f9f76671bee0c7223fc83ba6eacfbf88d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 14 Feb 2023 15:15:52 +0100 Subject: [PATCH 158/423] Added possibility to use the exact or simplified version of Kuzmin's pressure positivity limiter --- src/solvers/dgsem_tree/dg_2d.jl | 69 +++++++++++++++------------- src/solvers/dgsem_tree/indicators.jl | 14 ++++-- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index df1fb221c4..e83ce8f049 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1533,23 +1533,24 @@ end Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) - # exact calculation of max(R_ij, R_ji) - # R_max = lambda1[i, j, element] * - # abs(bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + - # bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - - # bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - - # bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) - # R_max += max(0, 0.5 * flux_velocity - - # antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) - - # approximation R_max - R_max = lambda1[i, j, element] * - (sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + - abs(bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element])) - R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) - + if indicator.PressurePositivityLimiterKuzminExact + # exact calculation of max(R_ij, R_ji) + R_max = lambda1[i, j, element] * + abs(bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + + bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - + bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - + bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) + else + # approximation R_max + R_max = lambda1[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element]) + + abs(bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element])) + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) + end if R_max > Q alpha = Q / R_max if indicator.Plotting @@ -1569,22 +1570,24 @@ end Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) - # exact calculation of max(R_ij, R_ji) - # R_max = lambda2[i, j, element] * - # abs(bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + - # bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - - # bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - - # bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) - # R_max += max(0, 0.5 * flux_velocity - - # antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) - - # approximation R_max - R_max = lambda2[i, j, element] * - (sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + - abs(bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element])) - R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + if indicator.PressurePositivityLimiterKuzminExact + # exact calculation of max(R_ij, R_ji) + R_max = lambda2[i, j, element] * + abs(bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + + bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - + bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - + bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + else + # approximation R_max + R_max = lambda2[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element]) + + abs(bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element])) + R_max += max(0, 0.5 * flux_velocity - + antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) + end if R_max > Q alpha = Q / R_max diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 45a44d30ed..149f737a7d 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -298,6 +298,7 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator SequentialLimiter::Bool ConservativeLimiter::Bool PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin + PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha PressurePositivityLimiter::Bool # synchronized pressure limiting DensityPositivityLimiter::Bool SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix @@ -315,6 +316,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; SequentialLimiter=true, # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states ConservativeLimiter=false, # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states PressurePositivityLimiterKuzmin=false,# Impose positivity for pressure â la Kuzmin + PressurePositivityLimiterKuzminExact=true,# Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha PressurePositivityLimiter=false, # Impose positivity for pressure DensityPositivityLimiter=false, # Impose positivity for cons(1) SemiDiscEntropyLimiter=false, @@ -336,7 +338,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; end IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, PressurePositivityLimiter, + PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, PressurePositivityLimiter, DensityPositivityLimiter, SemiDiscEntropyLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end @@ -349,10 +351,16 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.DensityAlphaForAll && print(io, "; dens alpha ∀") indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") - indicator.PressurePositivityLimiterKuzmin && print(io, "; pres (Kuzmin)") + if indicator.PressurePositivityLimiterKuzmin + if indicator. PressurePositivityLimiterKuzminExact + print(io, "; pres (Kuzmin ex)") + else + print(io, "; pres (Kuzmin)") + end + end indicator.PressurePositivityLimiter && print(io, "; pres") indicator.DensityPositivityLimiter && print(io, "; dens pos") - indicator.SemiDiscEntropyLimiter && print(io, "; semidiscrete entropy fix") + indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) print(io, ")") From eb2fd5955d1c08390219b8726d5041f48dee2efb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Feb 2023 16:51:36 +0100 Subject: [PATCH 159/423] Fix variable names --- src/solvers/dgsem_tree/dg_2d.jl | 33 +++++++++++++--------------- src/solvers/dgsem_tree/indicators.jl | 12 +++++----- src/time_integration/methods_SSP.jl | 5 ++++- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e83ce8f049..c4ccce13ce 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1303,11 +1303,11 @@ end rho_limited_iim1 = lambda * bar_state_rho - antidiffusive_flux1[1, i, j, element] rho_limited_im1i = lambda * bar_state_rho + antidiffusive_flux1[1, i, j, element] for v in 2:nvariables(equations) - bar_states_phi = bar_states1[v, i, j, element] + bar_state_phi = bar_states1[v, i, j, element] - phi = bar_states_phi / bar_state_rho + phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] + (lambda * bar_states_phi - rho_limited_im1i * phi) + g = antidiffusive_flux1[v, i, j, element] + (lambda * bar_state_phi - rho_limited_im1i * phi) if g > 0 g_max = min(rho_limited_im1i * (var_max[v, i-1, j, element] - phi), @@ -1330,7 +1330,7 @@ end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) end - antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_states_phi) + g_limited + antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_state_phi) + g_limited end end @@ -1378,16 +1378,16 @@ end for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] for v in 2:nvariables(equations) - bar_state_rho = bar_states1[v, i, j, element] + bar_state_phi = bar_states1[v, i, j, element] # Limit density if antidiffusive_flux1[v, i, j, element] > 0 - f_max = lambda * min(var_max[v, i-1, j, element] - bar_state_rho, - bar_state_rho - var_min[v, i, j, element]) + f_max = lambda * min(var_max[v, i-1, j, element] - bar_state_phi, + bar_state_phi - var_min[v, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux1[v, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[v, i-1, j, element] - bar_state_rho, - bar_state_rho - var_max[v, i, j, element]) + f_min = lambda * max(var_min[v, i-1, j, element] - bar_state_phi, + bar_state_phi - var_max[v, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux1[v, i, j, element], min(f_min, 0.0)) end @@ -1409,16 +1409,16 @@ end for j in 2:nnodes(dg), i in eachnode(dg) lambda = lambda2[i, j, element] for v in 2:nvariables(equations) - bar_state_rho = bar_states2[v, i, j, element] + bar_state_phi = bar_states2[v, i, j, element] # Limit density if antidiffusive_flux2[v, i, j, element] > 0 - f_max = lambda * min(var_max[v, i, j-1, element] - bar_state_rho, - bar_state_rho - var_min[v, i, j, element]) + f_max = lambda * min(var_max[v, i, j-1, element] - bar_state_phi, + bar_state_phi - var_min[v, i, j, element]) f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux2[v, i, j, element], max(f_max, 0.0)) else - f_min = lambda * max(var_min[v, i, j-1, element] - bar_state_rho, - bar_state_rho - var_max[v, i, j, element]) + f_min = lambda * max(var_min[v, i, j-1, element] - bar_state_phi, + bar_state_phi - var_max[v, i, j, element]) f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux2[v, i, j, element], min(f_min, 0.0)) end @@ -1710,10 +1710,6 @@ end # TODO: This is a very inefficient function. We compute the entropy four times at each node. # TODO: For now, this only works for Cartesian meshes. if indicator.SemiDiscEntropyLimiter - @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator - if indicator.Plotting - alpha_entropy[:, :, element] .= one(eltype(alpha_entropy)) - end for j in eachnode(dg), i in 2:nnodes(dg) antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) u_local = get_node_vars(u, equations, dg, i, j, element) @@ -1741,6 +1737,7 @@ end if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) if indicator.Plotting + @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 149f737a7d..52788a97aa 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -351,8 +351,8 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.DensityAlphaForAll && print(io, "; dens alpha ∀") indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") - if indicator.PressurePositivityLimiterKuzmin - if indicator. PressurePositivityLimiterKuzminExact + if indicator.PressurePositivityLimiterKuzmin + if indicator. PressurePositivityLimiterKuzminExact print(io, "; pres (Kuzmin ex)") else print(io, "; pres (Kuzmin)") @@ -373,18 +373,18 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn @unpack alpha = indicator.cache.ContainerShockCapturingIndicator variables = varnames(cons2cons, equations) for v in eachvariable(equations) - s = Symbol("shock_capturing_alpha_", variables[v]) - node_variables[s] = alpha[v, ntuple(_ -> :, nvariables(equations) + 1)...] + s = Symbol("alpha_", variables[v]) + node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] end if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - node_variables[:shock_capturing_alpha_pressure] = alpha_pressure + node_variables[:alpha_pressure] = alpha_pressure end if indicator.SemiDiscEntropyLimiter @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator - node_variables[:shock_capturing_alpha_entropy] = alpha_entropy + node_variables[:alpha_entropy] = alpha_entropy end return nothing diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index c4b0ebb290..3c994d356e 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -150,13 +150,16 @@ function solve!(integrator::SimpleIntegratorSSP) # Reset alphas for MCL @unpack indicator = integrator.p.solver.volume_integral if indicator isa IndicatorMCL && indicator.Plotting - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) alpha[:, i, j, element] .= one(eltype(alpha)) if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end + if indicator.SemiDiscEntropyLimiter + alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) + end end end end From d9c9cd7a0ce9af37057278dce782426e42afeb3a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Feb 2023 19:05:17 +0100 Subject: [PATCH 160/423] Revise calculation of our blending coefficient --- src/solvers/dgsem_tree/dg_2d.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c4ccce13ce..41538edb89 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1223,9 +1223,9 @@ end if indicator.Plotting || indicator.DensityAlphaForAll if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well + coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux1[1, i, j, element] + sign(flux_limited) * eps())) end if indicator.Plotting @@ -1267,9 +1267,9 @@ end if indicator.Plotting || indicator.DensityAlphaForAll if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well + coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux2[1, i, j, element] + sign(flux_limited) * eps())) end if indicator.Plotting @@ -1323,9 +1323,9 @@ end if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator if isapprox(g, 0.0, atol=eps()) - coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + coefficient = 1.0 # g_limited is zero as well else - coefficient = g_limited / g + coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1362,9 +1362,9 @@ end if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator if isapprox(g, 0.0, atol=eps()) - coefficient = isapprox(g_limited, 0.0, atol=eps()) ? 1.0 : 0.0 + coefficient = 1.0 # g_limited is zero as well else - coefficient = g_limited / g + coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1395,9 +1395,9 @@ end if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well + coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux1[v, i, j, element] + coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux1[v, i, j, element] + sign(flux_limited) * eps())) end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1426,9 +1426,9 @@ end if indicator.Plotting @unpack alpha = indicator.cache.ContainerShockCapturingIndicator if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol=eps()) - coefficient = 1.0 # flux_limited is zero as well + coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux2[v, i, j, element] + coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux2[v, i, j, element] + sign(flux_limited) * eps())) end alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) From d7dfb223504fd496648bd5b3a2ecdb5a2d5921d1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 23 Feb 2023 19:17:30 +0100 Subject: [PATCH 161/423] Add average calculation of alpha and Kuzmins coefficient --- src/solvers/dgsem_tree/containers_2d.jl | 24 ++++- src/solvers/dgsem_tree/dg_2d.jl | 122 ++++++++++++++++++++++-- src/solvers/dgsem_tree/indicators.jl | 12 +++ src/solvers/dgsem_tree/indicators_2d.jl | 30 +++++- 4 files changed, 177 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 4b80b0bd0c..10e639c92c 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -78,7 +78,7 @@ end eachelement(elements::ElementContainer2D) Return an iterator over the indices that specify the location in relevant data structures -for the elements in `elements`. +for the elements in `elements`. In particular, not the elements themselves are returned. """ @inline eachelement(elements::ElementContainer2D) = Base.OneTo(nelements(elements)) @@ -1381,12 +1381,16 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} alpha::Array{uEltype, 4} # [variable, i, j, element] alpha_pressure::Array{uEltype, 3} # [i, j, element] alpha_entropy::Array{uEltype, 3} # [i, j, element] + alpha_eff::Array{uEltype, 4} # [variable, i, j, element] + alpha_mean::Array{uEltype, 4} # [variable, i, j, element] # internal `resize!`able storage _var_min::Vector{uEltype} _var_max::Vector{uEltype} _alpha::Vector{uEltype} _alpha_pressure::Vector{uEltype} _alpha_entropy::Vector{uEltype} + _alpha_eff::Vector{uEltype} + _alpha_mean::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real @@ -1407,8 +1411,14 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, - _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy) + _alpha_eff = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) + alpha_eff = unsafe_wrap(Array, pointer(_alpha_eff), (n_variables, n_nodes, n_nodes, capacity)) + + _alpha_mean = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) + alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) + + return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean, + _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_eff, _alpha_mean) end nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) @@ -1441,6 +1451,14 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_alpha_entropy, n_nodes * n_nodes * capacity) container.alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) + @unpack _alpha_eff = container + resize!(_alpha_eff, n_variables * n_nodes * n_nodes * capacity) + container.alpha_eff = unsafe_wrap(Array, pointer(_alpha_eff), (n_variables, n_nodes, n_nodes, capacity)) + + @unpack _alpha_mean = container + resize!(_alpha_mean, n_variables * n_nodes * n_nodes * capacity) + container.alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) + return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 41538edb89..871594a29b 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1202,6 +1202,17 @@ end # This does not really make sense in theory and causes problems for the visualization. # Therefore we make sure that the flux keeps its sign during limiting. + # TODO: Allocations!!! + P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) + Q = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) + + @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + if indicator.Plotting + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) + end + end + # Density limiter if indicator.DensityLimiter for j in eachnode(dg), i in 2:nnodes(dg) @@ -1222,6 +1233,14 @@ end end if indicator.Plotting || indicator.DensityAlphaForAll + # left node + aux = abs(lambda * (bar_state_rho - u[1, i-1, j, element])) + P[1, i-1, j] += aux + abs(flux_limited) + Q[1, i-1, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) + # right node + aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) + P[1, i, j] += aux + abs(flux_limited) + Q[1, i, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1229,9 +1248,11 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + alpha_mean[1, i-1, j, element] += coefficient + alpha_mean[1, i , j, element] += coefficient end end antidiffusive_flux1[1, i, j, element] = flux_limited @@ -1266,6 +1287,14 @@ end end if indicator.Plotting || indicator.DensityAlphaForAll + # left node + aux = abs(lambda * (bar_state_rho - u[1, i, j-1, element])) + P[1, i, j-1] += aux + abs(flux_limited) + Q[1, i, j-1] += aux + abs(antidiffusive_flux2[1, i, j, element]) + # right node + aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) + P[1, i, j] += aux + abs(flux_limited) + Q[1, i, j] += aux + abs(antidiffusive_flux2[1, i, j, element]) if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1273,9 +1302,11 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + alpha_mean[1, i, j-1, element] += coefficient + alpha_mean[1, i, j, element] += coefficient end end antidiffusive_flux2[1, i, j, element] = flux_limited @@ -1321,7 +1352,15 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # left node + aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) + P[v, i-1, j] += aux + abs(g_limited) + Q[v, i-1, j] += aux + abs(g) + # right node + aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) + P[v, i, j] += aux + abs(g_limited) + Q[v, i, j] += aux + abs(g) if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1329,6 +1368,8 @@ end end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i-1, j, element] += coefficient + alpha_mean[v, i , j, element] += coefficient end antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - lambda * bar_state_phi) + g_limited end @@ -1360,7 +1401,15 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # left node + aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) + P[v, i, j-1] += aux + abs(g_limited) + Q[v, i, j-1] += aux + abs(g) + # right node + aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) + P[v, i, j] += aux + abs(g_limited) + Q[v, i, j] += aux + abs(g) if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1368,6 +1417,8 @@ end end alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i, j-1, element] += coefficient + alpha_mean[v, i, j, element] += coefficient end antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - lambda * bar_state_phi) + g_limited @@ -1393,7 +1444,15 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # left node + aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) + P[v, i-1, j] += aux + abs(flux_limited) + Q[v, i-1, j] += aux + abs(antidiffusive_flux1[v, i, j, element]) + # right node + aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) + P[v, i, j] += aux + abs(flux_limited) + Q[v, i, j] += aux + abs(antidiffusive_flux1[v, i, j, element]) if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1401,6 +1460,8 @@ end end alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i-1, j, element] += coefficient + alpha_mean[v, i, j, element] += coefficient end antidiffusive_flux1[v, i, j, element] = flux_limited end @@ -1424,7 +1485,15 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # left node + aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) + P[v, i, j-1] += aux + abs(flux_limited) + Q[v, i, j-1] += aux + abs(antidiffusive_flux2[v, i, j, element]) + # right node + aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) + P[v, i, j] += aux + abs(flux_limited) + Q[v, i, j] += aux + abs(antidiffusive_flux2[v, i, j, element]) if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1432,12 +1501,53 @@ end end alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i, j-1, element] += coefficient + alpha_mean[v, i, j, element] += coefficient end antidiffusive_flux2[v, i, j, element] = flux_limited end end end # indicator.SequentialLimiter and indicator.ConservativeLimiter + # Compute "effective" alpha using P and Q + if indicator.Plotting + @unpack alpha_eff = indicator.cache.ContainerShockCapturingIndicator + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + alpha_eff[v, i, j, element] = P[v, i, j] / (Q[v, i, j] + eps()) + end + end + end + + if indicator.Plotting + @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # Interfaces don't contribute + # for j in 2:nnodes(dg)-1, i in 2:nnodes(dg)-1 + # alpha_mean[:, i, j, element] ./= 4 + # end + # for i in 2:nnodes(dg)-1 + # alpha_mean[:, i, 1, element] ./= 3.0 + # alpha_mean[:, i, nnodes(dg), element] ./= 3.0 + # alpha_mean[:, 1, i, element] ./= 3.0 + # alpha_mean[:, nnodes(dg), i, element] ./= 3.0 + # end + # alpha_mean[:, 1, 1, element] ./= 2.0 + # alpha_mean[:, nnodes(dg), nnodes(dg), element] ./= 2.0 + # alpha_mean[:, 1, nnodes(dg), element] ./= 2.0 + # alpha_mean[:, nnodes(dg), 1, element] ./= 2.0 + + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean[:, i, 1, element] .+= 1.0 + alpha_mean[:, i, nnodes(dg), element] .+= 1.0 + alpha_mean[:, 1, i, element] .+= 1.0 + alpha_mean[:, nnodes(dg), i, element] .+= 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[:, i, j, element] ./= 4 + end + end + # Density positivity limiter if indicator.DensityPositivityLimiter for j in eachnode(dg), i in 2:nnodes(dg) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 52788a97aa..0a85ec0328 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -387,6 +387,18 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[:alpha_entropy] = alpha_entropy end + @unpack alpha_eff = indicator.cache.ContainerShockCapturingIndicator + for v in eachvariable(equations) + s = Symbol("alpha_effective_", variables[v]) + node_variables[s] = alpha_eff[v, ntuple(_ -> :, size(alpha, 2) + 1)...] + end + + @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + for v in eachvariable(equations) + s = Symbol("alpha_mean_", variables[v]) + node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) + end + return nothing end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index f4428c529c..d99e356bc5 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -939,7 +939,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 @@ -959,6 +959,12 @@ end end println(f) end + open("$output_directory/alphas_mean.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end + open("$output_directory/alphas_eff.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end end if iter % x != 0 @@ -966,12 +972,16 @@ end end alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) + alpha_mean_avg = zeros(eltype(alpha), n_vars) + alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) jacobian = inv(cache.elements.inverse_jacobian[element]) for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] + alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] @@ -983,7 +993,7 @@ end open("$output_directory/alphas.txt", "a") do f; print(f, iter, ", ", time) for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); + print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_avg[v] / total_volume); end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin @@ -991,6 +1001,22 @@ end end println(f) end + open("$output_directory/alphas_mean.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_mean_avg[v] / total_volume); + end + println(f) + end + open("$output_directory/alphas_eff.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha_eff, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_eff_avg[v] / total_volume); + end + println(f) + end return nothing end From a0ba5314155d2d10a3a1326d802e849ad46f7455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 24 Feb 2023 12:29:10 +0100 Subject: [PATCH 162/423] Added computation of alpha_mean for pressure and entropy limiters, and removed the plotting of alpha_rho for other quantities when indicator.DensityAlphaForAll==true --- src/solvers/dgsem_tree/containers_2d.jl | 22 ++++++++- src/solvers/dgsem_tree/dg_2d.jl | 59 +++++++++++++++++-------- src/solvers/dgsem_tree/indicators.jl | 12 +++++ 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 10e639c92c..1e0ffd1b5d 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1383,6 +1383,8 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} alpha_entropy::Array{uEltype, 3} # [i, j, element] alpha_eff::Array{uEltype, 4} # [variable, i, j, element] alpha_mean::Array{uEltype, 4} # [variable, i, j, element] + alpha_mean_pressure::Array{uEltype, 3} # [variable, i, j, element] + alpha_mean_entropy::Array{uEltype, 3} # [variable, i, j, element] # internal `resize!`able storage _var_min::Vector{uEltype} _var_max::Vector{uEltype} @@ -1391,6 +1393,8 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} _alpha_entropy::Vector{uEltype} _alpha_eff::Vector{uEltype} _alpha_mean::Vector{uEltype} + _alpha_mean_pressure::Vector{uEltype} + _alpha_mean_entropy::Vector{uEltype} end function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real @@ -1417,8 +1421,14 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_mean = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean, - _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_eff, _alpha_mean) + _alpha_mean_pressure = fill(nan_uEltype, n_nodes * n_nodes * capacity) + alpha_mean_pressure = unsafe_wrap(Array, pointer(_alpha_mean_pressure), (n_nodes, n_nodes, capacity)) + + _alpha_mean_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) + alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) + + return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, + _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_eff, _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) end nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) @@ -1459,6 +1469,14 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_alpha_mean, n_variables * n_nodes * n_nodes * capacity) container.alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) + @unpack _alpha_mean_pressure = container + resize!(_alpha_mean_pressure, n_nodes * n_nodes * capacity) + container.alpha_mean_pressure = unsafe_wrap(Array, pointer(_alpha_mean_pressure), (n_nodes, n_nodes, capacity)) + + @unpack _alpha_mean_entropy = container + resize!(_alpha_mean_entropy, n_nodes * n_nodes * capacity) + container.alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) + return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 871594a29b..9158dcf839 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1206,10 +1206,12 @@ end P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) Q = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) - @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator if indicator.Plotting for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) + alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) + alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) end end @@ -1261,10 +1263,6 @@ end if indicator.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, element] - if indicator.Plotting - alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - end end end end @@ -1315,10 +1313,6 @@ end if indicator.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, element] - if indicator.Plotting - alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) - alpha[v, i, j , element] = min(alpha[v, i, j , element], coefficient) - end end end end @@ -1583,10 +1577,6 @@ end if indicator.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, element] - if indicator.Plotting - alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - end end end end @@ -1624,10 +1614,6 @@ end if indicator.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, element] - if indicator.Plotting - alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) - alpha[v, i, j , element] = min(alpha[v, i, j , element], coefficient) - end end end end @@ -1635,7 +1621,7 @@ end # Limit pressure à la Kuzmin if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_pressure, alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 @@ -1666,6 +1652,8 @@ end if indicator.Plotting alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + alpha_mean_pressure[i-1, j, element] += alpha + alpha_mean_pressure[i, j, element] += alpha end for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] *= alpha @@ -1704,12 +1692,27 @@ end if indicator.Plotting alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + alpha_mean_pressure[i, j-1, element] += alpha + alpha_mean_pressure[i, j, element] += alpha end for v in eachvariable(equations) antidiffusive_flux2[v, i, j, element] *= alpha end end end + if indicator.Plotting + @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean_pressure[i, 1, element] += 1.0 + alpha_mean_pressure[i, nnodes(dg), element] += 1.0 + alpha_mean_pressure[1, i, element] += 1.0 + alpha_mean_pressure[nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean_pressure[i, j, element] /= 4 + end + end # New pressure limiter! elseif indicator.PressurePositivityLimiter @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator @@ -1847,9 +1850,11 @@ end if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) if indicator.Plotting - @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i-1, j, element] += alpha + alpha_mean_entropy[i, j, element] += alpha end for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] = alpha * antidiffusive_flux1[v, i, j, element] @@ -1884,14 +1889,30 @@ end if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) if indicator.Plotting + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator alpha_entropy[i, j-1, element] = min(alpha_entropy[i, j-1, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i, j-1, element] += alpha + alpha_mean_entropy[i, j, element] += alpha end for v in eachvariable(equations) antidiffusive_flux2[v, i, j, element] = alpha * antidiffusive_flux2[v, i, j, element] end end end + if indicator.Plotting + @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean_entropy[i, 1, element] += 1.0 + alpha_mean_entropy[i, nnodes(dg), element] += 1.0 + alpha_mean_entropy[1, i, element] += 1.0 + alpha_mean_entropy[nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean_entropy[i, j, element] /= 4 + end + end end return nothing diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 0a85ec0328..2d5f0a3ce8 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -399,6 +399,18 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) end + @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + node_variables[:alpha_mean_pressure] = alpha_mean_pressure + end + + @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + if indicator.SemiDiscEntropyLimiter + @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + node_variables[:alpha_mean_entropy] = alpha_mean_entropy + end + return nothing end From 43e544e5bdd8461694f1e901a6a0e0c39c4ff754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 24 Feb 2023 14:08:33 +0100 Subject: [PATCH 163/423] Fixed computation of alpha_mean for pressure and entropy --- src/solvers/dgsem_tree/dg_2d.jl | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 9158dcf839..b0f716d2b8 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1647,18 +1647,19 @@ end R_max += max(0, 0.5 * flux_velocity - antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) end + alpha = 1 # Initialize alpha for plotting if R_max > Q alpha = Q / R_max - if indicator.Plotting - alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) - alpha_mean_pressure[i-1, j, element] += alpha - alpha_mean_pressure[i, j, element] += alpha - end for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] *= alpha end end + if indicator.Plotting + alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + alpha_mean_pressure[i-1, j, element] += alpha + alpha_mean_pressure[i, j, element] += alpha + end end for j in 2:nnodes(dg), i in eachnode(dg) @@ -1686,19 +1687,19 @@ end R_max += max(0, 0.5 * flux_velocity - antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) end - + alpha = 1 # Initialize alpha for plotting if R_max > Q alpha = Q / R_max - if indicator.Plotting - alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) - alpha_mean_pressure[i, j-1, element] += alpha - alpha_mean_pressure[i, j, element] += alpha - end for v in eachvariable(equations) antidiffusive_flux2[v, i, j, element] *= alpha end end + if indicator.Plotting + alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) + alpha_mean_pressure[i, j-1, element] += alpha + alpha_mean_pressure[i, j, element] += alpha + end end if indicator.Plotting @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator @@ -1847,19 +1848,20 @@ end entProd_FV = dot(delta_v, fstar1[:, i, j]) - delta_psi delta_entProd = dot(delta_v, antidiffusive_flux_local) + alpha = 1 # Initialize alpha for plotting if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) - if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator - alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) - alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) - alpha_mean_entropy[i-1, j, element] += alpha - alpha_mean_entropy[i, j, element] += alpha - end for v in eachvariable(equations) antidiffusive_flux1[v, i, j, element] = alpha * antidiffusive_flux1[v, i, j, element] end end + if indicator.Plotting + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i-1, j, element] += alpha + alpha_mean_entropy[i, j, element] += alpha + end end for j in 2:nnodes(dg), i in eachnode(dg) @@ -1886,19 +1888,20 @@ end entProd_FV = dot(delta_v, fstar2[:, i, j]) - delta_psi delta_entProd = dot(delta_v, antidiffusive_flux_local) + alpha = 1 # Initialize alpha for plotting if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) alpha = min(1.0, (abs(entProd_FV)+eps()) / (abs(delta_entProd)+eps())) - if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator - alpha_entropy[i, j-1, element] = min(alpha_entropy[i, j-1, element], alpha) - alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) - alpha_mean_entropy[i, j-1, element] += alpha - alpha_mean_entropy[i, j, element] += alpha - end for v in eachvariable(equations) antidiffusive_flux2[v, i, j, element] = alpha * antidiffusive_flux2[v, i, j, element] end end + if indicator.Plotting + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + alpha_entropy[i, j-1, element] = min(alpha_entropy[i, j-1, element], alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i, j-1, element] += alpha + alpha_mean_entropy[i, j, element] += alpha + end end if indicator.Plotting @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator From 9393a5720b32e863c49be01111a0e270aa23f43c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 24 Feb 2023 18:43:21 +0100 Subject: [PATCH 164/423] Revise structure in dg_2d.jl --- src/solvers/dgsem_tree/dg_2d.jl | 112 ++++++++++++++++---------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b0f716d2b8..b60920d666 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1202,12 +1202,12 @@ end # This does not really make sense in theory and causes problems for the visualization. # Therefore we make sure that the flux keeps its sign during limiting. - # TODO: Allocations!!! - P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) - Q = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) - - @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator if indicator.Plotting + # TODO: Allocations!!! + P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) + Q = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) + + @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) @@ -1235,14 +1235,6 @@ end end if indicator.Plotting || indicator.DensityAlphaForAll - # left node - aux = abs(lambda * (bar_state_rho - u[1, i-1, j, element])) - P[1, i-1, j] += aux + abs(flux_limited) - Q[1, i-1, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) - # right node - aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) - P[1, i, j] += aux + abs(flux_limited) - Q[1, i, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1250,6 +1242,15 @@ end end if indicator.Plotting + # left node + aux = abs(lambda * (bar_state_rho - u[1, i-1, j, element])) + P[1, i-1, j] += aux + abs(flux_limited) + Q[1, i-1, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) + # right node + aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) + P[1, i, j] += aux + abs(flux_limited) + Q[1, i, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1285,14 +1286,6 @@ end end if indicator.Plotting || indicator.DensityAlphaForAll - # left node - aux = abs(lambda * (bar_state_rho - u[1, i, j-1, element])) - P[1, i, j-1] += aux + abs(flux_limited) - Q[1, i, j-1] += aux + abs(antidiffusive_flux2[1, i, j, element]) - # right node - aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) - P[1, i, j] += aux + abs(flux_limited) - Q[1, i, j] += aux + abs(antidiffusive_flux2[1, i, j, element]) if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1300,6 +1293,15 @@ end end if indicator.Plotting + # left node + aux = abs(lambda * (bar_state_rho - u[1, i, j-1, element])) + P[1, i, j-1] += aux + abs(flux_limited) + Q[1, i, j-1] += aux + abs(antidiffusive_flux2[1, i, j, element]) + # right node + aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) + P[1, i, j] += aux + abs(flux_limited) + Q[1, i, j] += aux + abs(antidiffusive_flux2[1, i, j, element]) + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1346,7 +1348,6 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # left node aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) P[v, i-1, j] += aux + abs(g_limited) @@ -1355,11 +1356,13 @@ end aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) P[v, i, j] += aux + abs(g_limited) Q[v, i, j] += aux + abs(g) + if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i-1, j, element] += coefficient @@ -1395,7 +1398,6 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # left node aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) P[v, i, j-1] += aux + abs(g_limited) @@ -1404,11 +1406,13 @@ end aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) P[v, i, j] += aux + abs(g_limited) Q[v, i, j] += aux + abs(g) + if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i, j-1, element] += coefficient @@ -1438,7 +1442,6 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # left node aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) P[v, i-1, j] += aux + abs(flux_limited) @@ -1447,11 +1450,13 @@ end aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) P[v, i, j] += aux + abs(flux_limited) Q[v, i, j] += aux + abs(antidiffusive_flux1[v, i, j, element]) + if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux1[v, i, j, element] + sign(flux_limited) * eps())) end + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i-1, j, element] += coefficient @@ -1479,7 +1484,6 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # left node aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) P[v, i, j-1] += aux + abs(flux_limited) @@ -1488,11 +1492,13 @@ end aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) P[v, i, j] += aux + abs(flux_limited) Q[v, i, j] += aux + abs(antidiffusive_flux2[v, i, j, element]) + if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux2[v, i, j, element] + sign(flux_limited) * eps())) end + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i, j-1, element] += coefficient @@ -1513,35 +1519,6 @@ end end end - if indicator.Plotting - @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator - # Interfaces don't contribute - # for j in 2:nnodes(dg)-1, i in 2:nnodes(dg)-1 - # alpha_mean[:, i, j, element] ./= 4 - # end - # for i in 2:nnodes(dg)-1 - # alpha_mean[:, i, 1, element] ./= 3.0 - # alpha_mean[:, i, nnodes(dg), element] ./= 3.0 - # alpha_mean[:, 1, i, element] ./= 3.0 - # alpha_mean[:, nnodes(dg), i, element] ./= 3.0 - # end - # alpha_mean[:, 1, 1, element] ./= 2.0 - # alpha_mean[:, nnodes(dg), nnodes(dg), element] ./= 2.0 - # alpha_mean[:, 1, nnodes(dg), element] ./= 2.0 - # alpha_mean[:, nnodes(dg), 1, element] ./= 2.0 - - # Interfaces contribute with 1.0 - for i in eachnode(dg) - alpha_mean[:, i, 1, element] .+= 1.0 - alpha_mean[:, i, nnodes(dg), element] .+= 1.0 - alpha_mean[:, 1, i, element] .+= 1.0 - alpha_mean[:, nnodes(dg), i, element] .+= 1.0 - end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean[:, i, j, element] ./= 4 - end - end - # Density positivity limiter if indicator.DensityPositivityLimiter for j in eachnode(dg), i in 2:nnodes(dg) @@ -1566,9 +1543,13 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + if !indicator.DensityLimiter + alpha_mean[1, i-1, j, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end end end antidiffusive_flux1[1, i, j, element] = flux_limited @@ -1603,9 +1584,13 @@ end end if indicator.Plotting - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + if !indicator.DensityLimiter + alpha_mean[1, i, j-1, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end end end antidiffusive_flux2[1, i, j, element] = flux_limited @@ -1619,6 +1604,21 @@ end end end #if indicator.DensityPositivityLimiter + # Divide alpha_mean by number of additions + if indicator.Plotting + @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean[:, i, 1, element] .+= 1.0 + alpha_mean[:, i, nnodes(dg), element] .+= 1.0 + alpha_mean[:, 1, i, element] .+= 1.0 + alpha_mean[:, nnodes(dg), i, element] .+= 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[:, i, j, element] ./= 4 + end + end + # Limit pressure à la Kuzmin if indicator.PressurePositivityLimiterKuzmin @unpack alpha_pressure, alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator From b1b1c039b32e19eda6d05065aabda0b7d6879adb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 24 Feb 2023 18:56:09 +0100 Subject: [PATCH 165/423] Add txt output for alpha_entropy; Plus output for alpha_mean and alpha_eff for StructuredMesh --- src/solvers/dgsem_structured/indicators_2d.jl | 43 ++++++++++++++++++- src/solvers/dgsem_tree/indicators_2d.jl | 17 +++++++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 4adf32dde8..7e482917f0 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -253,7 +253,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 @@ -271,25 +271,44 @@ end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") end + if indicator.SemiDiscEntropyLimiter + print(f, ", alpha_min_entropy, alpha_avg_entropy") + end println(f) end + open("$output_directory/alphas_mean.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end + open("$output_directory/alphas_eff.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end end if iter % x != 0 return nothing end - alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) + alpha_avg = zeros(eltype(alpha), n_vars + + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + + indicator.SemiDiscEntropyLimiter) + alpha_mean_avg = zeros(eltype(alpha), n_vars) + alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] + alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] + end total_volume += jacobian * weights[i] * weights[j] end end @@ -303,6 +322,26 @@ end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) + end + println(f) + end + open("$output_directory/alphas_mean.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_mean_avg[v] / total_volume); + end + println(f) + end + open("$output_directory/alphas_eff.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha_eff, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_eff_avg[v] / total_volume); + end println(f) end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index d99e356bc5..3637597971 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -939,7 +939,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 @@ -957,6 +957,9 @@ end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") end + if indicator.SemiDiscEntropyLimiter + print(f, ", alpha_min_entropy, alpha_avg_entropy") + end println(f) end open("$output_directory/alphas_mean.txt", "a") do f; @@ -971,7 +974,9 @@ end return nothing end - alpha_avg = zeros(eltype(alpha), n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin)) + alpha_avg = zeros(eltype(alpha), n_vars + + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + + indicator.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), n_vars) alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) @@ -986,6 +991,10 @@ end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] + end total_volume += jacobian * weights[i] * weights[j] end end @@ -999,6 +1008,10 @@ end if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) + end println(f) end open("$output_directory/alphas_mean.txt", "a") do f; From 6e9637f304819626c8d6baec6f85f2603aa77de8 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 26 Feb 2023 20:25:42 +0100 Subject: [PATCH 166/423] Add simple reflecting Euler wall as outer boundary state for slip wall boundary --- src/solvers/dgsem_tree/dg_2d.jl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b60920d666..b6fe38c751 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1921,7 +1921,22 @@ end return nothing end -get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation_or_normal, direction, equations, dg, indices...) = u_inner +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation_or_normal, direction, equations, dg, indices...) + if boundary_condition == boundary_condition_slip_wall #boundary_condition_reflecting_euler_wall + if orientation_or_normal isa AbstractArray + u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + else # orientation_or_normal isa Integer + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) + end + end + + return u_inner +end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, orientation_or_normal, direction, equations, dg, indices...) @unpack node_coordinates = cache.elements From 09f4dd77bb8d9cf797a6f9bcd71733f7cda5d64a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 27 Feb 2023 12:26:51 +0100 Subject: [PATCH 167/423] Update FCT/IDP and MCL elixirs --- .../elixir_euler_free_stream_sc_subcell.jl | 13 +- .../elixir_euler_shock_upstream_MCL.jl | 140 ++++++++++++++++++ .../elixir_euler_shock_upstream_sc_subcell.jl | 10 +- .../elixir_euler_astro_jet_MCL.jl | 17 ++- .../elixir_euler_astro_jet_subcell.jl | 16 +- .../elixir_euler_blob_sc_subcell.jl | 108 -------------- ..._euler_kelvin_helmholtz_instability_MCL.jl | 24 ++- ...er_kelvin_helmholtz_instability_restart.jl | 32 ++++ ...kelvin_helmholtz_instability_sc_subcell.jl | 14 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 98 ++++++++++++ ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 17 ++- .../elixir_euler_source_terms_sc_subcell.jl | 11 +- src/solvers/dgsem_tree/indicators.jl | 4 +- 13 files changed, 343 insertions(+), 161 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl delete mode 100644 examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 2bbcbcd759..ca1a07df34 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -17,7 +17,10 @@ indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=false, IDPPressureTVD=false, IDPPositivity=false, - indicator_smooth=false) + IDPSpecEntropy=false, + indicator_smooth=false, + BarStates=true, + IDPCheckBounds=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -62,17 +65,17 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=100000, +save_solution = SaveSolutionCallback(interval=10000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl new file mode 100644 index 0000000000..45acebe004 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -0,0 +1,140 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_inviscid_bow(x, t, equations::CompressibleEulerEquations2D) + rho = 1.4 + p = 1.0 + v1 = 4.0 + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_inviscid_bow + +boundary_condition = BoundaryConditionCharacteristic(initial_condition) +boundary_conditions = (x_neg=boundary_condition, + x_pos=boundary_condition_slip_wall, + y_neg=boundary_condition, + y_pos=boundary_condition) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 5 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=false, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, + IDPCheckBounds=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# domain +# ,, +# , | +# , | f4 of length a-1 +#f1 , | +# , ,` f2 /alpha +# , |_(0,0)___________/_______(3.85,0) +# , | +# , `, +# , `| +# , | f3 +# ,| +# l = circumference of quarter circle / length of egg-shaped form +a = sqrt(5.9^2 - 3.85^2) +alpha = acos(3.85 / 5.9) +l = (pi / 4) / (pi / 2 + 1) +f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)) # left +function f2(s) # right + t = 0.5 * s + 0.5 # in [0,1] + if 0 <= t <= l + beta = t / l # in [0,1] + return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) + elseif l < t <= 1 - l # 0 <= t - l <= 1-2l + beta = (t - l) / (1 - 2 * l) # in [0,1] + return SVector(-0.5, -0.5 + beta) + else # 1 - l < t <= 1 + beta = (t + l - 1) / l # in [0,1] + return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) + end +end +f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom +f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a) # top +faces = (f1, f2, f3, f4) + +# This creates a mapping that transforms [-1, 1]^2 to the domain with the faces defined above. +Trixi.validate_faces(faces) +mapping_bow = Trixi.transfinite_mapping(faces) + +mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi / 4) / (pi / 2 + 1); " * + "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * + "function f2(s); t = 0.5 * s + 0.5; " * + "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * + "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * + "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * + "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * + "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * + "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" + +cells_per_dimension = (24, 36) + +mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string=mapping_as_string, periodicity=false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_conditions) + +############################################################################### +# 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) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=2000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index d0b740d422..d27255d53a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -38,9 +38,11 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPSpecEntropy=true, IDPMaxIter=100, + IDPPositivity=false, + IDPSpecEntropy=true, + IDPMaxIter=100, BarStates=true, - indicator_smooth=false) + IDPCheckBounds=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -122,8 +124,8 @@ stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 2e74008008..46fb754b17 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -38,14 +38,19 @@ boundary_conditions = ( ) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_chandrashekar # works with Ranocha flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + PressurePositivityLimiterKuzmin=false, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, IDPCheckBounds=true, - IDPPressure=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -55,7 +60,7 @@ coordinates_min = (-0.5, -0.5) coordinates_max = ( 0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=8, periodicity=(false,true), n_cells_max=100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) @@ -78,12 +83,12 @@ save_solution = SaveSolutionCallback(interval=5000, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 9cc2020855..7e319cb6a5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -38,19 +38,17 @@ boundary_conditions = ( ) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_chandrashekar # works with Chandrashekar flux as well +volume_flux = flux_chandrashekar # works with Ranocha flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, IDPSpecEntropy=true, - IDPPositivity=true, IDPCheckBounds=true, - IDPMaxIter=25, - indicator_smooth=true, thr_smooth=0.05) + BarStates=true, + IDPMaxIter=25) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -77,17 +75,17 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, +save_solution = SaveSolutionCallback(interval=1000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.1) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl deleted file mode 100644 index 033dafef72..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_blob_sc_subcell.jl +++ /dev/null @@ -1,108 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 5/3 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - -The blob test case taken from -- Agertz et al. (2006) - Fundamental differences between SPH and grid methods - [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) -""" -function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^2, 256^2 - # domain size is [-20.0,20.0]^2 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - dens0 = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh/1.6 # crushing time - # determine background velocity - velx0 = 2*R*sqrt(Chi)/tau_cr - vely0 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = velx0/Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p0 = c*c*dens0/equations.gamma - # initial center of the blob - inicenter = [-15,0] - x_rel = x-inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - # velocity blob is zero - velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - return prim2cons(SVector(dens, velx, vely0, p0), equations) -end -initial_condition = initial_condition_blob - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) - -indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true, - indicator_smooth=false, - IDPMaxIter=25) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-20.0, -20.0) -coordinates_max = ( 20.0, 20.0) - -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000,) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 8.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=500, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.7) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index e543bbd732..1ee01f9b7d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -37,9 +37,14 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, IDPCheckBounds=true, - IDPPressure=false, - indicator_smooth=false, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -55,12 +60,12 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 3.0) +tspan = (0.0, 3.7) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 100 +analysis_interval = 1000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) @@ -70,12 +75,15 @@ save_solution = SaveSolutionCallback(interval=5000, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +save_restart = SaveRestartCallback(interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, - stepsize_callback, analysis_callback, alive_callback, - save_solution) + stepsize_callback, + save_restart, save_solution) ############################################################################### @@ -83,5 +91,5 @@ callbacks = CallbackSet(summary_callback, sol = Trixi.solve(ode, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); + maxiters=1e7, callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl new file mode 100644 index 0000000000..e31a0476a4 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl @@ -0,0 +1,32 @@ +using OrdinaryDiffEq +using Trixi + +path = "out" + +restart_file = "restart_063585.h5" +restart_filename = joinpath(path, restart_file) + +new_path = path + +tspan = (load_time(restart_filename), 6.7) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory=path, + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory=path, + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_restart, save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 2cdbcf94a2..6a79570770 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -38,7 +38,10 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=true, - indicator_smooth=false) + IDPDensityTVD=false, + IDPSpecEntropy=false, + BarStates=true, + IDPCheckBounds=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -68,12 +71,15 @@ save_solution = SaveSolutionCallback(interval=5000, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.3) +save_restart = SaveRestartCallback(interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_restart, save_solution) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl new file mode 100644 index 0000000000..c4951d804b --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -0,0 +1,98 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_chandrashekar +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + DensityPositivityLimiter=false, + PressurePositivityLimiterKuzmin=true, + SemiDiscEntropyLimiter=true, + IDPCheckBounds=true, + Plotting=true) +volume_integral = VolumeIntegralShockCapturingSubcell(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +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, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index db1ecfa550..df3da9655f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -43,10 +43,11 @@ volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, - IDPPositivity=true, + IDPPositivity=false, + IDPSpecEntropy=true, indicator_smooth=true, - IDPMaxIter=15) + BarStates=true, + IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -70,22 +71,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 100 +analysis_interval = 1000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=500, +save_solution = SaveSolutionCallback(interval=1000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index a082b9bf89..dc4fd7733e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,8 +15,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, IDPPositivity=false, + BarStates=true, indicator_smooth=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, @@ -46,20 +46,17 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) - save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_restart, save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### # run the simulation diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 2d5f0a3ce8..406f18f788 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -222,11 +222,11 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPPositivity=false, IDPSpecEntropy=false, IDPMathEntropy=false, - BarStates=false, + BarStates=true, positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), IDPCheckBounds=false, - indicator_smooth=true, thr_smooth=0.1, variable_smooth=density_pressure) + indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure) if IDPMathEntropy && IDPSpecEntropy error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") From a2561911a58e7eebcca95aec22c9e785d4e37fde Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 28 Mar 2023 16:04:52 +0200 Subject: [PATCH 168/423] Add correlation factor beta to MCL positivity limiter --- src/solvers/dgsem_tree/dg_2d.jl | 9 +++++---- src/solvers/dgsem_tree/indicators.jl | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b6fe38c751..b85cb0e099 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1521,16 +1521,17 @@ end # Density positivity limiter if indicator.DensityPositivityLimiter + beta = indicator.DensityPositivityCorrelationFactor for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] # Limit density if antidiffusive_flux1[1, i, j, element] > 0 - f_max = lambda * bar_state_rho + f_max = (1 - beta) * lambda * bar_state_rho f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux1[1, i, j, element], max(f_max, 0.0)) else - f_min = -lambda * bar_state_rho + f_min = - (1 - beta) * lambda * bar_state_rho f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux1[1, i, j, element], min(f_min, 0.0)) end @@ -1567,11 +1568,11 @@ end bar_state_rho = bar_states2[1, i, j, element] # Limit density if antidiffusive_flux2[1, i, j, element] > 0 - f_max = lambda * bar_state_rho + f_max = (1 - beta) * lambda * bar_state_rho f_max = isapprox(f_max, 0.0, atol=eps()) ? 0.0 : f_max flux_limited = min(antidiffusive_flux2[1, i, j, element], max(f_max, 0.0)) else - f_min = -lambda * bar_state_rho + f_min = - (1 - beta) * lambda * bar_state_rho f_min = isapprox(f_min, 0.0, atol=eps()) ? 0.0 : f_min flux_limited = max(antidiffusive_flux2[1, i, j, element], min(f_min, 0.0)) end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 406f18f788..b29b58c6cf 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -301,6 +301,7 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha PressurePositivityLimiter::Bool # synchronized pressure limiting DensityPositivityLimiter::Bool + DensityPositivityCorrelationFactor::RealT SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner @@ -319,6 +320,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; PressurePositivityLimiterKuzminExact=true,# Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha PressurePositivityLimiter=false, # Impose positivity for pressure DensityPositivityLimiter=false, # Impose positivity for cons(1) + DensityPositivityCorrelationFactor=0.0,# Correlation Factor for DensityPositivityLimiter in [0,1) SemiDiscEntropyLimiter=false, IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, @@ -339,7 +341,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, PressurePositivityLimiter, - DensityPositivityLimiter, SemiDiscEntropyLimiter, + DensityPositivityLimiter, DensityPositivityCorrelationFactor, SemiDiscEntropyLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end @@ -360,6 +362,7 @@ function Base.show(io::IO, indicator::IndicatorMCL) end indicator.PressurePositivityLimiter && print(io, "; pres") indicator.DensityPositivityLimiter && print(io, "; dens pos") + (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth) From f2f7d64a8b7a540b10d10b7d1427377657dca7fe Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 28 Mar 2023 19:07:19 +0200 Subject: [PATCH 169/423] Add correlation factor to BoundsCheck --- src/solvers/dgsem_tree/dg_2d.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b85cb0e099..0687f09dd6 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -2441,22 +2441,23 @@ end end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + beta = indicator.DensityPositivityCorrelationFactor # Checking the bounds for... # - density (rho): - # 0 <= \bar{rho}^{Lim} + # beta * \bar{rho} <= \bar{rho}^{Lim} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) # -x - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # +x - rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + rho_limited = (1 - beta) * bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # -y - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + rho_limited = (1 - beta) * bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # +y - rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + rho_limited = (1 - beta) * bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] deviation_min[1] = max(deviation_min[1], -rho_limited) end end From 90eb54a4e042ce306e9129e7bbb5c2b64c41e4ee Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 28 Mar 2023 19:09:07 +0200 Subject: [PATCH 170/423] Remove interfaces contribution to alpha_mean if not required --- src/solvers/dgsem_tree/dg_2d.jl | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 0687f09dd6..5c1031cf42 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1609,14 +1609,29 @@ end if indicator.Plotting @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Interfaces contribute with 1.0 - for i in eachnode(dg) - alpha_mean[:, i, 1, element] .+= 1.0 - alpha_mean[:, i, nnodes(dg), element] .+= 1.0 - alpha_mean[:, 1, i, element] .+= 1.0 - alpha_mean[:, nnodes(dg), i, element] .+= 1.0 + if indicator.DensityLimiter || indicator.DensityPositivityLimiter + for i in eachnode(dg) + alpha_mean[1, i, 1, element] += 1.0 + alpha_mean[1, i, nnodes(dg), element] += 1.0 + alpha_mean[1, 1, i, element] += 1.0 + alpha_mean[1, nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[1, i, j, element] /= 4 + end end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean[:, i, j, element] ./= 4 + if indicator.SequentialLimiter || indicator.ConservativeLimiter + for v in 2:nvariables(equations) + for i in eachnode(dg) + alpha_mean[v, i, 1, element] += 1.0 + alpha_mean[v, i, nnodes(dg), element] += 1.0 + alpha_mean[v, 1, i, element] += 1.0 + alpha_mean[v, nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[v, i, j, element] /= 4 + end + end end end From afa05fc22d74b9850b4134024be848d20ca0f533 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 4 Apr 2023 13:19:35 +0200 Subject: [PATCH 171/423] Update elixirs --- ...elixir_euler_convergence_wavingflag_IDP.jl | 75 +++++++++ ...elixir_euler_convergence_wavingflag_MCL.jl | 75 +++++++++ .../elixir_euler_double_mach.jl | 147 +++++++++++++++++ .../elixir_euler_double_mach_MCL.jl | 150 ++++++++++++++++++ .../elixir_euler_free_stream_MCL.jl | 91 +++++++++++ .../elixir_euler_free_stream_sc_subcell.jl | 7 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 4 +- .../elixir_euler_astro_jet_MCL.jl | 6 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_colliding_flow_sc_subcell.jl | 107 ------------- .../elixir_euler_convergence_IDP.jl | 70 ++++++++ .../elixir_euler_convergence_MCL.jl | 70 ++++++++ ..._euler_kelvin_helmholtz_instability_MCL.jl | 8 +- .../elixir_euler_positivity_sc_subcell.jl | 93 ----------- .../elixir_euler_sedov_blast_wave_MCL.jl | 9 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 4 +- .../idp_density_entropy_cfl0.9_t10.jl | 30 ++++ .../idp_density_entropy_cfl0.9_t3.7.jl | 94 +++++++++++ .../idp_density_entropy_cfl0.9_t6.7.jl | 30 ++++ ..._positivity_density_pressure_cfl0.9_t10.jl | 30 ++++ ...positivity_density_pressure_cfl0.9_t3.7.jl | 94 +++++++++++ ...positivity_density_pressure_cfl0.9_t6.7.jl | 30 ++++ ...ivity_density_pressure_sharp_cfl0.9_t10.jl | 31 ++++ ...vity_density_pressure_sharp_cfl0.9_t3.7.jl | 97 +++++++++++ ...vity_density_pressure_sharp_cfl0.9_t6.7.jl | 31 ++++ .../mcl_sequential_cfl0.9_t10.jl | 30 ++++ .../mcl_sequential_cfl0.9_t3.7.jl | 97 +++++++++++ .../mcl_sequential_cfl0.9_t6.7.jl | 30 ++++ src/Trixi.jl | 1 + src/equations/compressible_euler_2d.jl | 58 +++++++ src/solvers/dgsem_structured/indicators_2d.jl | 22 +-- src/solvers/dgsem_tree/dg_2d.jl | 19 +++ src/solvers/dgsem_tree/indicators_2d.jl | 24 +-- 33 files changed, 1425 insertions(+), 241 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl create mode 100644 examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl create mode 100644 examples/structured_2d_dgsem/elixir_euler_double_mach.jl create mode 100644 examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl create mode 100644 examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl delete mode 100644 examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl create mode 100644 examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl delete mode 100644 examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl create mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl create mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl create mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl create mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl create mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl create mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl create mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl create mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl create mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl create mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl create mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl new file mode 100644 index 0000000000..0a926f439d --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -0,0 +1,75 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_density_wave_highdensity + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=false, + IDPPositivity=true, + IDPSpecEntropy=false, + positCorrFactor=0.1, IDPMaxIter=10, + newton_tol=(1.0e-12, 1.0e-14), + BarStates=true, + IDPCheckBounds=true, + indicator_smooth=false) + +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Deformed rectangle that looks like a waving flag, +# lower and upper faces are sinus curves, left and right are vertical lines. +f1(s) = SVector(-1.0, s - 1.0) +f2(s) = SVector( 1.0, s + 1.0) +f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) + +cells_per_dimension = (4, 4) + +mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl new file mode 100644 index 0000000000..c307a2b166 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -0,0 +1,75 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_density_wave_highdensity + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + IDPCheckBounds=true, + Plotting=true) + +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Deformed rectangle that looks like a waving flag, +# lower and upper faces are sinus curves, left and right are vertical lines. +f1(s) = SVector(-1.0, s - 1.0) +f2(s) = SVector( 1.0, s + 1.0) +f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) + +cells_per_dimension = (4, 4) + +mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl new file mode 100644 index 0000000000..917077e1ea --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -0,0 +1,147 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +# @inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +# if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) +# phi = pi / 6 +# sin_phi, cos_phi = sincos(phi) + +# rho = 8 +# v1 = 8.25 * cos_phi +# v2 = -8.25 * sin_phi +# p = 116.5 +# else +# rho = 1.4 +# v1 = 0 +# v2 = 0 +# p = 1 +# end + +# prim = SVector(rho, v1, v2, p) +# return prim2cons(prim, equations) +# end +initial_condition = Trixi.initial_condition_double_mach_reflection + + +# boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) +boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + + +# Supersonic outflow boundary condition. Solution is taken entirely from the internal state. +# See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. +# @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, direction, x, t, +# surface_flux_function, equations::CompressibleEulerEquations2D) +# # NOTE: Only for the supersonic outflow is this strategy valid +# # Calculate the boundary flux entirely from the internal solution state +# return flux(u_inner, normal_direction, equations) +# end + +# Special mixed boundary condition type for the :Bottom of the domain. +# It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 +# @inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, +# x, t, surface_flux_function, +# equations::CompressibleEulerEquations2D) +# if x[1] < 1 / 6 +# # # From the BoundaryConditionDirichlet +# # # get the external value of the solution +# # u_boundary = initial_condition_double_mach_reflection(x, t, equations) +# # # Calculate boundary flux +# # flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + +# # From the BoundaryConditionCharacteristic +# # get the external state of the solution +# u_boundary = Trixi.characteristic_boundary_value_function(initial_condition, +# u_inner, normal_direction, direction, x, t, equations) +# # Calculate boundary flux +# flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) +# else # x[1] >= 1 / 6 +# # Use the free slip wall BC otherwise +# flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, surface_flux_function, equations) +# end + +# return flux +# end + +boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, + y_pos=boundary_condition_inflow_outflow, + x_pos=boundary_condition_inflow_outflow, + x_neg=boundary_condition_inflow_outflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 4 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=true, + IDPPositivity=false, + IDPSpecEntropy=true, + positCorrFactor=0.1, IDPMaxIter=100, + BarStates=true, + IDPCheckBounds=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +initial_refinement_level = 6 +cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) +coordinates_min = (0.0, 0.0) +coordinates_max = (4.0, 1.0) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=false) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(entropy,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=1000, + output_directory="../../scratch/doublemach/IDP_density_entropy_cfl0_9_new/out", + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl new file mode 100644 index 0000000000..ba4e29d0bc --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -0,0 +1,150 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +# @inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +# if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) +# phi = pi / 6 +# sin_phi, cos_phi = sincos(phi) + +# rho = 8 +# v1 = 8.25 * cos_phi +# v2 = -8.25 * sin_phi +# p = 116.5 +# else +# rho = 1.4 +# v1 = 0 +# v2 = 0 +# p = 1 +# end + +# prim = SVector(rho, v1, v2, p) +# return prim2cons(prim, equations) +# end +initial_condition = Trixi.initial_condition_double_mach_reflection + + +# boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) +boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + + +# Supersonic outflow boundary condition. Solution is taken entirely from the internal state. +# See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. +# @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, direction, x, t, +# surface_flux_function, equations::CompressibleEulerEquations2D) +# # NOTE: Only for the supersonic outflow is this strategy valid +# # Calculate the boundary flux entirely from the internal solution state +# return flux(u_inner, normal_direction, equations) +# end + +# Special mixed boundary condition type for the :Bottom of the domain. +# It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 +# @inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, +# x, t, surface_flux_function, +# equations::CompressibleEulerEquations2D) +# if x[1] < 1 / 6 +# # # From the BoundaryConditionDirichlet +# # # get the external value of the solution +# # u_boundary = initial_condition_double_mach_reflection(x, t, equations) +# # # Calculate boundary flux +# # flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + +# # From the BoundaryConditionCharacteristic +# # get the external state of the solution +# u_boundary = Trixi.characteristic_boundary_value_function(initial_condition, +# u_inner, normal_direction, direction, x, t, equations) +# # Calculate boundary flux +# flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) +# else # x[1] >= 1 / 6 +# # Use the free slip wall BC otherwise +# flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, surface_flux_function, equations) +# end + +# return flux +# end + +boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, + y_pos=boundary_condition_inflow_outflow, + x_pos=boundary_condition_inflow_outflow, + x_neg=boundary_condition_inflow_outflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 4 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + DensityPositivityLimiter=false, + PressurePositivityLimiterKuzmin=false, + SemiDiscEntropyLimiter=false, + IDPCheckBounds=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +initial_refinement_level = 6 +cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) +coordinates_min = (0.0, 0.0) +coordinates_max = (4.0, 1.0) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=false) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(entropy,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=1000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl new file mode 100644 index 0000000000..2be073b558 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -0,0 +1,91 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_constant + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=true, + SemiDiscEntropyLimiter=false, + indicator_smooth=false, + IDPCheckBounds=true, + Plotting=true) + +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. +# This particular mesh is unstructured in the yz-plane, but extruded in x-direction. +# Apply the warping mapping in the yz-plane to get a curved 2D mesh that is extruded +# in x-direction to ensure free stream preservation on a non-conforming mesh. +# See https://doi.org/10.1007/s10915-018-00897-9, Section 6. + +# Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D +function mapping(xi_, eta_) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + + y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * + cos(0.5 * pi * (2 * eta - 3)/3)) + + x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * + cos(2 * pi * (2 * y - 3)/3)) + + return SVector(x, y) +end + +cells_per_dimension = (32, 32) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=10000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode; + 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index ca1a07df34..75ae9ef2c1 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -16,11 +16,14 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=false, IDPPressureTVD=false, - IDPPositivity=false, + IDPPositivity=true, IDPSpecEntropy=false, indicator_smooth=false, BarStates=true, - IDPCheckBounds=false) + positCorrFactor=0.1, IDPMaxIter=10, + newton_tol=(1.0e-12, 1.0e-14), + IDPCheckBounds=true) + volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index d27255d53a..6529bb715a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -115,12 +115,12 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, +save_solution = SaveSolutionCallback(interval=2000, save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 46fb754b17..2a98547ec6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -45,9 +45,9 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorMCL(equations, basis; DensityLimiter=true, - DensityAlphaForAll=false, + DensityAlphaForAll=true, SequentialLimiter=true, - PressurePositivityLimiterKuzmin=false, + PressurePositivityLimiterKuzmin=true, DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, IDPCheckBounds=true, @@ -93,6 +93,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 7e319cb6a5..8b6e9d76cc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -90,6 +90,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl deleted file mode 100644 index 40e80bda06..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_sc_subcell.jl +++ /dev/null @@ -1,107 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.001 # almost isothermal when gamma reaches 1 -equations = CompressibleEulerEquations2D(gamma) - -# This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both -# sides, with relative low temperature, such that pressure keeps relatively small -# Computed with gamma close to 1, to simulate isothermal gas -function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) - # domain size is [-64,+64]^2 - @unpack gamma = equations - # the quantities are chosen such, that they are as close as possible to the astro examples - # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) - rho = 0.0247 - c = 0.2 - p = c^2 / gamma * rho - vel = 13.907432274789372 - slope = 1.0 - v1 = -vel*tanh(slope * x[1]) - # add small initial disturbance to the field, but only close to the interface - if abs(x[1]) < 10 - v1 = v1 * (1 + 0.01 * sin(pi * x[2])) - end - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_colliding_flow_astro - - -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) - - - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 3 -basis = LobattoLegendreBasis(polydeg) - -# shock capturing necessary for this tough example -indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPressureTVD=false, - IDPPositivity=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-64.0, -64.0) -coordinates_max = ( 64.0, 64.0) - -# only refinment in a patch. Needs x=-17/+17 to trigger refinment due to coarse base mesh -refinement_patches = ( - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores -) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - refinement_patches=refinement_patches, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 25.0) -ode = semidiscretize(semi, tspan) - -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, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.35) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - stepsize_callback, - save_solution) - -############################################################################### -# run the simulation -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl new file mode 100644 index 0000000000..0c251edfe2 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -0,0 +1,70 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_density_wave_highdensity + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorIDP(equations, basis; + IDPDensityTVD=false, + IDPPositivity=true, + IDPSpecEntropy=false, + positCorrFactor=0.1, IDPMaxIter=10, + newton_tol=(1.0e-12, 1.0e-14), + BarStates=true, + IDPCheckBounds=true, + indicator_smooth=false) + +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +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) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl new file mode 100644 index 0000000000..62babc4c0f --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -0,0 +1,70 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_density_wave_highdensity + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + IDPCheckBounds=true, + Plotting=true) + +volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +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) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + 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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 1ee01f9b7d..7cdc86483a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -37,12 +37,12 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, + DensityLimiter=false, DensityAlphaForAll=false, - SequentialLimiter=true, + SequentialLimiter=false, ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=false, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, IDPCheckBounds=true, Plotting=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl deleted file mode 100644 index f7b638a447..0000000000 --- a/examples/tree_2d_dgsem/elixir_euler_positivity_sc_subcell.jl +++ /dev/null @@ -1,93 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - -The Sedov blast wave setup based on Flash -- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 -""" -function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_sedov_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=true) -volume_integral = VolumeIntegralShockCapturingSubcell(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) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 4.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=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.5) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index c4951d804b..87f6285e95 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -47,9 +47,10 @@ indicator_sc = IndicatorMCL(equations, basis; SequentialLimiter=true, ConservativeLimiter=false, DensityPositivityLimiter=false, - PressurePositivityLimiterKuzmin=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, SemiDiscEntropyLimiter=true, IDPCheckBounds=true, + indicator_smooth=false, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, @@ -59,7 +60,7 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) coordinates_max = ( 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=3, n_cells_max=100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -87,8 +88,8 @@ stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - save_solution, - stepsize_callback) + stepsize_callback, + save_solution) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index df3da9655f..635084a42b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -45,7 +45,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, IDPPositivity=false, IDPSpecEntropy=true, - indicator_smooth=true, + indicator_smooth=false, BarStates=true, IDPCheckBounds=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -56,7 +56,7 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) coordinates_max = ( 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=3, n_cells_max=100_000) diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl new file mode 100644 index 0000000000..2ff438084c --- /dev/null +++ b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("idp_density_entropy_cfl0.9_t6.7.jl") + +restart_filename = "out_t6_7/restart_050302.h5" + +tspan = (load_time(restart_filename), 10.0) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t10/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t10/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl new file mode 100644 index 0000000000..31e9b958a2 --- /dev/null +++ b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl @@ -0,0 +1,94 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 7 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorIDP(equations, basis; + IDPPositivity=false, + IDPDensityTVD=true, + IDPSpecEntropy=true, + BarStates=true, + IDPCheckBounds=true, + indicator_smooth=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.7) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(output_directory="out_t3_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t3_7/", + interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_restart, save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl new file mode 100644 index 0000000000..d3234ef486 --- /dev/null +++ b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("idp_density_entropy_cfl0.9_t3.7.jl") + +restart_filename = "out_t3_7/restart_062276.h5" + +tspan = (load_time(restart_filename), 6.7) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t6_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t6_7/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl new file mode 100644 index 0000000000..1822b46f10 --- /dev/null +++ b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("idp_positivity_density_pressure_cfl0.9_t6.7.jl") + +restart_filename = "out_t6_7/restart_084955.h5" + +tspan = (load_time(restart_filename), 10.0) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t10/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t10/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl new file mode 100644 index 0000000000..d2a4fb5361 --- /dev/null +++ b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl @@ -0,0 +1,94 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 7 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorIDP(equations, basis; + IDPPositivity=true, + IDPDensityTVD=false, + IDPSpecEntropy=false, + BarStates=true, + IDPCheckBounds=true, + indicator_smooth=false) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.7) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(output_directory="out_t3_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t3_7/", + interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_restart, save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl new file mode 100644 index 0000000000..f9206ea81f --- /dev/null +++ b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("idp_positivity_density_pressure_cfl0.9_t3.7.jl") + +restart_filename = "out_t3_7/restart_063585.h5" + +tspan = (load_time(restart_filename), 6.7) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t6_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t6_7/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl new file mode 100644 index 0000000000..743f47bb70 --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl @@ -0,0 +1,31 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl") + +restart_filename = "out_t6_7/restart_3119274.h5" + + +tspan = (load_time(restart_filename), 10.0) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t10/", + interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t10/", + interval=1000000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + maxiters=1e7, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl new file mode 100644 index 0000000000..7bc0f4d332 --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl @@ -0,0 +1,97 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 7 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=true, + DensityPositivityLimiter=true, #DensityPositivityCorrelationFactor=0.0, + SemiDiscEntropyLimiter=false, + indicator_smooth=false, + IDPCheckBounds=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.7) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(output_directory="out_t3_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t3_7/", + interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + maxiters=1_000_000, callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl new file mode 100644 index 0000000000..b0a01b1a91 --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl @@ -0,0 +1,31 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl") + +restart_filename = "out_t3_7/restart_063921.h5.h5" + + +tspan = (load_time(restart_filename), 6.7) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t6_7/", + interval=100000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t6_7", + interval=500000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + maxiters=1e7, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl new file mode 100644 index 0000000000..704012325b --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("mcl_sequential_cfl0.9_t6.7.jl") + +restart_filename = "out_t6_7/restart_051050.h5" + +tspan = (load_time(restart_filename), 10.0) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t10/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t10/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl new file mode 100644 index 0000000000..0f6e5e955d --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl @@ -0,0 +1,97 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 7 +basis = LobattoLegendreBasis(polydeg) + +indicator_sc = IndicatorMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, + indicator_smooth=false, + IDPCheckBounds=true, + Plotting=true) +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = ( 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.7) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(output_directory="out_t3_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t3_7/", + interval=50000, + save_final_restart=true) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, save_solution) + + +############################################################################### +# run the simulation + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + maxiters=1_000_000, callback=callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl new file mode 100644 index 0000000000..725f8ed551 --- /dev/null +++ b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl @@ -0,0 +1,30 @@ +using OrdinaryDiffEq +using Trixi + +trixi_include("mcl_sequential_cfl0.9_t3.7.jl") + +restart_filename = "out_t3_7/restart_061891.h5" + +tspan = (load_time(restart_filename), 6.7) +ode = semidiscretize(semi, tspan, restart_filename); + +save_solution = SaveSolutionCallback(output_directory="out_t6_7/", + interval=5000, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +save_restart = SaveRestartCallback(output_directory="out_t6_7/", + interval=50000, + save_final_restart=true) + +callbacks = CallbackSet(summary_callback, + stepsize_callback, + analysis_callback, alive_callback, + save_restart, + save_solution) + +sol = Trixi.solve(ode, + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback=callbacks); +summary_callback() # print the timer summary \ No newline at end of file diff --git a/src/Trixi.jl b/src/Trixi.jl index a07314d54e..36f7357a0f 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -162,6 +162,7 @@ export splitting_steger_warming, splitting_vanleer_haenel, export initial_condition_constant, initial_condition_gauss, initial_condition_density_wave, + initial_condition_density_wave_highdensity, initial_condition_weak_blast_wave export boundary_condition_do_nothing, diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index ad1e73b275..7857148340 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -149,6 +149,25 @@ function initial_condition_density_wave(x, t, equations::CompressibleEulerEquati end +""" + initial_condition_density_wave_highdensity(x, t, equations::CompressibleEulerEquations2D) + +A sine wave in the density with constant velocity and pressure; reduces the +compressible Euler equations to the linear advection equations. +High density version of [`initial_condition_density_wave`](@ref). +""" +function initial_condition_density_wave_highdensity(x, t, equations::CompressibleEulerEquations2D) + v1 = 0.1 + v2 = 0.2 + rho = 2.0 + 0.98 * sinpi(2 * (x[1] + x[2] - t * (v1 + v2))) + rho_v1 = rho * v1 + rho_v2 = rho * v2 + p = 20 + rho_e = p / (equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2) + return SVector(rho, rho_v1, rho_v2, rho_e) +end + + """ initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations2D) @@ -463,6 +482,45 @@ end return cons end +@inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0 + v2 = 0 + p = 1 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) +end + +@inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + # From the BoundaryConditionCharacteristic + # get the external state of the solution + u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, normal_direction, direction, x, t, equations) + # Calculate boundary flux + flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, surface_flux_function, equations) + end + + return flux +end + # Calculate 2D flux for a single point @inline function flux(u, orientation::Integer, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 7e482917f0..a4a8f30036 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -266,7 +266,10 @@ end # Headline if iter == 1 && x > 0 - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end + open("$output_directory/alphas_mean.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") @@ -276,9 +279,6 @@ end end println(f) end - open("$output_directory/alphas_mean.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end open("$output_directory/alphas_eff.txt", "a") do f; println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); end @@ -319,13 +319,6 @@ end print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); print(f, ", ", alpha_avg[v] / total_volume); end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 - print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) - end println(f) end open("$output_directory/alphas_mean.txt", "a") do f; @@ -334,6 +327,13 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_mean_avg[v] / total_volume); end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) + end println(f) end open("$output_directory/alphas_eff.txt", "a") do f; diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5c1031cf42..2462f43cc3 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1949,6 +1949,25 @@ end else # orientation_or_normal isa Integer return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) end + elseif boundary_condition == boundary_condition_mixed_dirichlet_wall + x = get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, orientation_or_normal, direction, x, t, equations) + + return u_outer + else # x[1] >= 1 / 6 # boundary_condition_slip_wall + if orientation_or_normal isa AbstractArray + u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + else # orientation_or_normal isa Integer + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) + end + end end return u_inner diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 3637597971..d4e8726b18 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -952,7 +952,10 @@ end # Headline if iter == 1 - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; + println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + end + open("$output_directory/alphas_mean.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") @@ -962,9 +965,6 @@ end end println(f) end - open("$output_directory/alphas_mean.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end open("$output_directory/alphas_eff.txt", "a") do f; println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); end @@ -999,19 +999,12 @@ end end end - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; print(f, iter, ", ", time) for v in eachvariable(equations) print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_avg[v] / total_volume); end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin - print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 - print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) - end println(f) end open("$output_directory/alphas_mean.txt", "a") do f; @@ -1020,6 +1013,13 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_mean_avg[v] / total_volume); end + if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) + end println(f) end open("$output_directory/alphas_eff.txt", "a") do f; From ca10fce76cb0f5a58ac2fe07a7db5a29b4d80863 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 4 Apr 2023 13:29:56 +0200 Subject: [PATCH 172/423] Rename alpha_min txt file --- src/solvers/dgsem_structured/indicators_2d.jl | 2 +- src/solvers/dgsem_tree/indicators_2d.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index a4a8f30036..0fe1c365b9 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -313,7 +313,7 @@ end end end - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; print(f, iter, ", ", time) for v in eachvariable(equations) print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index d4e8726b18..a33500cb62 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -902,7 +902,7 @@ end # Headline if x > 0 && iter == 1 - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; println(f, "# iter, simu_time, alpha_max, alpha_avg"); end end @@ -910,7 +910,7 @@ end if x == 0 || iter % x != 0 return nothing end - open("$output_directory/alphas.txt", "a") do f; + open("$output_directory/alphas_min.txt", "a") do f; println(f, iter, ", ", time, ", ", alpha_max_avg[1], ", ", alpha_max_avg[2]); end From 111e5d1176ffba9a7b69e81ad5b64cd1080b9318 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 9 May 2023 11:39:01 +0200 Subject: [PATCH 173/423] Use name change --- src/time_integration/methods_SSP.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 3c994d356e..e4bb198975 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -74,9 +74,9 @@ mutable struct SimpleIntegratorSSP{RealT<:Real, uType, Params, Sol, F, Alg, Simp finalstep::Bool # added for convenience end -# Forward integrator.destats.naccept to integrator.iter (see GitHub PR#771) +# Forward integrator.stats.naccept to integrator.iter (see GitHub PR#771) function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) - if field === :destats + if field === :stats return (naccept = getfield(integrator, :iter),) end # general fallback From 64ede2a916c9de899acbdaa007e5127eb03fe6fb Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 12 May 2023 14:25:11 +0200 Subject: [PATCH 174/423] Remove PressurePositivityLimiter --- src/solvers/dgsem_structured/indicators_2d.jl | 14 +- src/solvers/dgsem_tree/dg_2d.jl | 152 +++--------------- src/solvers/dgsem_tree/indicators.jl | 24 ++- src/solvers/dgsem_tree/indicators_2d.jl | 18 +-- src/time_integration/methods_SSP.jl | 4 +- 5 files changed, 49 insertions(+), 163 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 0fe1c365b9..8da3184230 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -271,7 +271,7 @@ end end open("$output_directory/alphas_mean.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") end if indicator.SemiDiscEntropyLimiter @@ -288,9 +288,7 @@ end return nothing end - alpha_avg = zeros(eltype(alpha), n_vars + - (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + - indicator.SemiDiscEntropyLimiter) + alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), n_vars) alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) @@ -302,11 +300,11 @@ end alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] end if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] end total_volume += jacobian * weights[i] * weights[j] @@ -327,11 +325,11 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_mean_avg[v] / total_volume); end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) end println(f) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 462e469349..a21dbfca7a 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1730,110 +1730,6 @@ end alpha_mean_pressure[i, j, element] /= 4 end end - # New pressure limiter! - elseif indicator.PressurePositivityLimiter - @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator - for j in eachnode(dg), i in 2:nnodes(dg) - bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 - flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 - - Q = - lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - - 0.5 * bar_state_velocity) - P_1 = 0.5 * flux_velocity - antidiffusive_flux1[4, i, j, element] * antidiffusive_flux1[1, i, j, element] - P_2 = lambda1[i, j, element] * (bar_states1[2, i, j, element] * antidiffusive_flux1[2, i, j, element] + - bar_states1[3, i, j, element] * antidiffusive_flux1[3, i, j, element] - - bar_states1[1, i, j, element] * antidiffusive_flux1[4, i, j, element] - - bar_states1[4, i, j, element] * antidiffusive_flux1[1, i, j, element]) - - # Solve the quadratic formula - aux_var = P_2^2 - 4 * P_1 * Q - if aux_var >= 0.0 - # Only solve for real solutions - aux_var = sqrt(aux_var) - alpha1 = 0.5 * (-P_2 + aux_var) / P_1 - alpha2 = 0.5 * (-P_2 - aux_var) / P_1 - alpha3 = 0.5 * ( P_2 + aux_var) / P_1 - alpha4 = 0.5 * ( P_2 - aux_var) / P_1 - - # If the solutions are negative, we can take the maximum antidiffusive flux - if alpha1 < 0.0 - alpha1 = 1.0 - end - if alpha2 < 0.0 - alpha2 = 1.0 - end - if alpha3 < 0.0 - alpha3 = 1.0 - end - if alpha4 < 0.0 - alpha4 = 1.0 - end - # Get the most restrictive alpha - alpha = min(alpha1, alpha2, alpha3, alpha4, 1.0) - else - # If the solutions are complex, we can take the maximum antidiffusive flux - alpha = 1.0 - end - - if indicator.Plotting - alpha_pressure[i-1, j, element] = min(alpha_pressure[i-1, j, element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) - end - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] *= alpha - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - bar_state_velocity = bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 - flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + antidiffusive_flux2[3, i, j, element]^2 - - Q = -lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - - 0.5 * bar_state_velocity) - - P_1 = 0.5 * flux_velocity - antidiffusive_flux2[4, i, j, element] * antidiffusive_flux2[1, i, j, element] - P_2 = lambda2[i, j, element] * (bar_states2[2, i, j, element] * antidiffusive_flux2[2, i, j, element] + - bar_states2[3, i, j, element] * antidiffusive_flux2[3, i, j, element] - - bar_states2[1, i, j, element] * antidiffusive_flux2[4, i, j, element] - - bar_states2[4, i, j, element] * antidiffusive_flux2[1, i, j, element]) - # Solve the quadratic formula - aux_var = P_2^2 - 4 * P_1 * Q - if aux_var >= 0.0 - # Only solve for real solutions - aux_var = sqrt(aux_var) - alpha1 = 0.5 * (-P_2 + aux_var) / P_1 - alpha2 = 0.5 * (-P_2 - aux_var) / P_1 - alpha3 = 0.5 * ( P_2 + aux_var) / P_1 - alpha4 = 0.5 * ( P_2 - aux_var) / P_1 - - # If the solutions are negative, we can take the maximum antidiffusive flux - if alpha1 < 0.0 - alpha1 = 1.0 - end - if alpha2 < 0.0 - alpha2 = 1.0 - end - if alpha3 < 0.0 - alpha3 = 1.0 - end - if alpha4 < 0.0 - alpha4 = 1.0 - end - # Get the most restrictive alpha - alpha = min(alpha1, alpha2, alpha3, alpha4, 1.0) - else - # If the solutions are complex, we can take the maximum antidiffusive flux - alpha = 1.0 - end - - if indicator.Plotting - alpha_pressure[i, j-1, element] = min(alpha_pressure[i, j-1, element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], alpha) - end - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] *= alpha - end - end end # Limit entropy @@ -2201,14 +2097,14 @@ end if laststage && x > 0 && iter == 1 open("$output_directory/deviations.txt", "a") do f; print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in vars)); - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin print(f, ", pressure_min") end println(f) end end - deviation_min = zeros(eltype(u), n_vars + (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter)) + deviation_min = zeros(eltype(u), n_vars + indicator.PressurePositivityLimiterKuzmin) deviation_max = zeros(eltype(u), n_vars) if indicator.DensityLimiter @@ -2255,7 +2151,7 @@ end deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end @@ -2279,11 +2175,11 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2294,11 +2190,11 @@ end var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2309,11 +2205,11 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2324,11 +2220,11 @@ end var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2343,7 +2239,7 @@ end deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - u[v, i, j, element]) deviation_max[v] = max(deviation_max[v], u[v, i, j, element] - var_max[v, i, j, element]) end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end @@ -2367,11 +2263,11 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2382,11 +2278,11 @@ end var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2397,11 +2293,11 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) @@ -2412,18 +2308,18 @@ end var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if (indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter) && (v == 2 || v == 3) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) error_pressure = zero(eltype(idp_bounds_delta)) end end end - elseif indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + elseif indicator.PressurePositivityLimiterKuzmin # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -2464,7 +2360,7 @@ end deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) end end - end # indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + end # indicator.PressurePositivityLimiterKuzmin if indicator.DensityPositivityLimiter # New solution u^{n+1} @@ -2501,7 +2397,7 @@ end idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) end @@ -2513,7 +2409,7 @@ end for v in eachvariable(equations) print(f, ", ", deviation_min[v], ", ", deviation_max[v]); end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin print(f, ", ", deviation_min[n_vars+1]); end println(f); diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b29b58c6cf..afefc53466 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -297,15 +297,14 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator DensityAlphaForAll::Bool SequentialLimiter::Bool ConservativeLimiter::Bool - PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin + PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - PressurePositivityLimiter::Bool # synchronized pressure limiting DensityPositivityLimiter::Bool DensityPositivityCorrelationFactor::RealT - SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix + SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix IDPCheckBounds::Bool - indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner - thr_smooth::RealT # threshold for smoothness indicator + indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner + thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end @@ -318,7 +317,6 @@ function IndicatorMCL(equations::AbstractEquations, basis; ConservativeLimiter=false, # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states PressurePositivityLimiterKuzmin=false,# Impose positivity for pressure â la Kuzmin PressurePositivityLimiterKuzminExact=true,# Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - PressurePositivityLimiter=false, # Impose positivity for pressure DensityPositivityLimiter=false, # Impose positivity for cons(1) DensityPositivityCorrelationFactor=0.0,# Correlation Factor for DensityPositivityLimiter in [0,1) SemiDiscEntropyLimiter=false, @@ -328,10 +326,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; if SequentialLimiter && ConservativeLimiter error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") end - if PressurePositivityLimiterKuzmin && PressurePositivityLimiter - error("Only one of the two can be selected: PressurePositivityLimiterKuzmin/PressurePositivityLimiter") - end - cache = create_cache(IndicatorMCL, equations, basis, PressurePositivityLimiterKuzmin || PressurePositivityLimiter) + cache = create_cache(IndicatorMCL, equations, basis, PressurePositivityLimiterKuzmin) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, variable=variable_smooth) @@ -340,7 +335,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; end IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, PressurePositivityLimiter, + PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, DensityPositivityCorrelationFactor, SemiDiscEntropyLimiter, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) end @@ -354,13 +349,12 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") if indicator.PressurePositivityLimiterKuzmin - if indicator. PressurePositivityLimiterKuzminExact + if indicator.PressurePositivityLimiterKuzminExact print(io, "; pres (Kuzmin ex)") else print(io, "; pres (Kuzmin)") end end - indicator.PressurePositivityLimiter && print(io, "; pres") indicator.DensityPositivityLimiter && print(io, "; dens pos") (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") @@ -380,7 +374,7 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator node_variables[:alpha_pressure] = alpha_pressure end @@ -403,7 +397,7 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn end @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator node_variables[:alpha_mean_pressure] = alpha_mean_pressure end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 01431640e7..775e3cfa32 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -931,11 +931,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, PressurePositivityLimiter) + basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiter) + idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiterKuzmin) return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end @@ -966,7 +966,7 @@ end end open("$output_directory/alphas_mean.txt", "a") do f; print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") end if indicator.SemiDiscEntropyLimiter @@ -983,9 +983,7 @@ end return nothing end - alpha_avg = zeros(eltype(alpha), n_vars + - (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + - indicator.SemiDiscEntropyLimiter) + alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), n_vars) alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) @@ -997,11 +995,11 @@ end alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] end if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] end total_volume += jacobian * weights[i] * weights[j] @@ -1022,11 +1020,11 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); print(f, ", ", alpha_mean_avg[v] / total_volume); end - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) end if indicator.SemiDiscEntropyLimiter - k = n_vars + (indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin) + 1 + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) end println(f) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index e4bb198975..dac598792a 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -154,7 +154,7 @@ function solve!(integrator::SimpleIntegratorSSP) @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiter || indicator.PressurePositivityLimiterKuzmin + if indicator.PressurePositivityLimiterKuzmin alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end if indicator.SemiDiscEntropyLimiter @@ -346,7 +346,7 @@ end for v in eachvariable(equations) println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) end - if indicator.PressurePositivityLimiterKuzmin || indicator.PressurePositivityLimiter + if indicator.PressurePositivityLimiterKuzmin println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(equations)+1]) end println("─"^100 * "\n") From f41327e654e0b9cf243daf88cf9f87d77de2ec7d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 15 May 2023 10:32:31 +0200 Subject: [PATCH 175/423] First step generalizing IDP_positivity! --- src/solvers/dgsem_tree/indicators_2d.jl | 83 +++++++++++++++++-------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 775e3cfa32..3c681536a6 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -230,7 +230,9 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSE indicator_IDP.IDPPressureTVD && @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements; + variables_cons=(Trixi.density,), + variables_nonlinear=(pressure,)) indicator_IDP.IDPSpecEntropy && @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPMathEntropy && @@ -651,7 +653,22 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements) +@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements; variables_cons::Tuple{Any}, variables_nonlinear::Tuple{Any}) + + # Conservative variables + for variable in variables_cons + IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable) + end + + # Nonlinear variables + for variable in variables_nonlinear + IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable) + end + + return nothing +end + +@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -661,14 +678,11 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto if indicator_IDP.IDPDensityTVD rho_min = var_bounds[1] - p_min = var_bounds[3] else if indicator_IDP.IDPPressureTVD rho_min = var_bounds[3] - p_min = var_bounds[1] else rho_min = var_bounds[1] - p_min = var_bounds[2] end end @@ -680,18 +694,17 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto if mesh isa StructuredMesh inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - ####################### - # Correct density - ####################### - if u[1, i, j, element] < 0.0 - println("Error: safe density is not safe. element=$element, node: $i $j, density=$(u[1, i, j, element])") + + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + if var < 0.0 + println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") end # Compute bound if indicator_IDP.IDPDensityTVD - rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * u[1, i, j, element]) + rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * var) else - rho_min[i, j, element] = positCorrFactor * u[1, i, j, element] + rho_min[i, j, element] = positCorrFactor * var end # Real one-sided Zalesak-type limiter @@ -699,14 +712,14 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qm = min(0.0, (rho_min[i, j, element] - u[1, i, j, element]) / dt) + Qm = min(0.0, (rho_min[i, j, element] - var) / dt) # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] - val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] + val_flux1_local = inverse_weights[i] * variable(get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) + val_flux1_local_ip1 = -inverse_weights[i] * variable(get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) + val_flux2_local = inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) + val_flux2_local_jp1 = -inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) @@ -718,21 +731,41 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Calculate alpha alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) + end + end - ####################### - # Correct pressure - ####################### + return nothing +end + + +@inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack positCorrFactor = indicator_IDP + + @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + + if indicator_IDP.IDPDensityTVD + p_min = var_bounds[3] + else + if indicator_IDP.IDPPressureTVD + p_min = var_bounds[1] + else + p_min = var_bounds[2] + end + end + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) # Compute bound u_local = get_node_vars(u, equations, dg, i, j, element) - p_safe = pressure(u_local, equations) - if p_safe < 0.0 - println("Error: safe pressure is not safe. element=$element, node: $i $j, pressure=$p_safe") + var = variable(u_local, equations) + if var < 0.0 + println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") end if indicator_IDP.IDPPressureTVD - p_min[i, j, element] = max(p_min[i, j, element], positCorrFactor * p_safe) + p_min[i, j, element] = max(p_min[i, j, element], positCorrFactor * var) else - p_min[i, j, element] = positCorrFactor * p_safe + p_min[i, j, element] = positCorrFactor * var end # Perform Newton's bisection method to find new alpha From fd02b387dbf68c40c1520d31b7a4722f5e42afe9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 15 May 2023 16:44:24 +0200 Subject: [PATCH 176/423] Fix typos --- src/solvers/dgsem_tree/dg_2d.jl | 2 +- src/time_integration/methods_SSP.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index a21dbfca7a..4f8325a54e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -702,7 +702,7 @@ end # All diagonal entries of `derivative_split` are zero. Thus, we can skip # the computation of the diagonal terms. In addition, we use the symmetry - # of the `volume_flux` to save half of the possible two-poitn flux + # of the `volume_flux` to save half of the possible two-point flux # computations. for ii in (i+1):nnodes(dg) u_node_ii = get_node_vars(u, equations, dg, ii, j, element) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index dac598792a..074bd1a67d 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -171,7 +171,7 @@ function solve!(integrator::SimpleIntegratorSSP) # compute du integrator.f(integrator.du, integrator.u, integrator.p, t_stage) - # perfom forward Euler step + # perform forward Euler step @. integrator.u = integrator.u + integrator.dt * integrator.du end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) From 1438f4e235fc87007fff3e17f171a506c7a24efd Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 15 May 2023 17:53:29 +0200 Subject: [PATCH 177/423] Continue generalization --- src/solvers/dgsem_tree/indicators.jl | 18 ++++++++++++------ src/solvers/dgsem_tree/indicators_2d.jl | 24 +++++++++++------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index afefc53466..871aa9bc02 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -200,6 +200,8 @@ struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator IDPDensityTVD::Bool IDPPressureTVD::Bool IDPPositivity::Bool + variables_cons::Tuple{Any} # Positivity of conservative variables + variables_nonlinear::Tuple{Any} # Positivity of nonlinear variables IDPSpecEntropy::Bool IDPMathEntropy::Bool BarStates::Bool @@ -220,6 +222,8 @@ function IndicatorIDP(equations::AbstractEquations, basis; IDPDensityTVD=false, IDPPressureTVD=false, IDPPositivity=false, + variables_cons=(first,), + variables_nonlinear=(), IDPSpecEntropy=false, IDPMathEntropy=false, BarStates=true, @@ -232,10 +236,10 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") end - length = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) + number_bounds = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + IDPPositivity * (length(variables_cons) + length(variables_nonlinear)) - cache = create_cache(IndicatorIDP, equations, basis, length, BarStates) + cache = create_cache(IndicatorIDP, equations, basis, number_bounds, BarStates) if indicator_smooth IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max=1.0, alpha_smooth=false, @@ -244,8 +248,9 @@ function IndicatorIDP(equations::AbstractEquations, basis; IndicatorHG = nothing end IndicatorIDP{typeof(positCorrFactor), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, - IDPPositivity, IDPSpecEntropy, IDPMathEntropy, BarStates, cache, positCorrFactor, IDPMaxIter, - newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG) + IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, BarStates, + cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, + indicator_smooth, thr_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -260,7 +265,8 @@ function Base.show(io::IO, indicator::IndicatorIDP) IDPDensityTVD && print(io, "IDPDensityTVD, ") IDPPressureTVD && print(io, "IDPPressureTVD with positivity correlation factor of ", indicator.positCorrFactor, ", ") - IDPPositivity && print(io, "IDPPositivity, ") + IDPPositivity && print(io, "IDPPositivity with variables $(indicator.variables_cons) and + $(indicator.variables_nonlinear), ") IDPSpecEntropy && print(io, "IDPSpecEntropy, ") IDPMathEntropy && print(io, "IDPMathEntropy, ") print(io, "), ") diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 3c681536a6..aef3d3168f 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -200,8 +200,8 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, length, BarStates) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), length) +function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, BarStates) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), number_bounds) cache = (; ) if BarStates @@ -211,7 +211,7 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation alpha_max_avg = zeros(real(basis), 2) - idp_bounds_delta = zeros(real(basis), length) + idp_bounds_delta = zeros(real(basis), number_bounds) return (; cache..., alpha_max_avg, ContainerShockCapturingIndicator, idp_bounds_delta) end @@ -230,9 +230,7 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSE indicator_IDP.IDPPressureTVD && @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements; - variables_cons=(Trixi.density,), - variables_nonlinear=(pressure,)) + @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements) indicator_IDP.IDPSpecEntropy && @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPMathEntropy && @@ -653,22 +651,22 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements; variables_cons::Tuple{Any}, variables_nonlinear::Tuple{Any}) +@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements) # Conservative variables - for variable in variables_cons - IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable) + for (index, variable) in enumerate(indicator_IDP.variables_cons) + IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) end # Nonlinear variables - for variable in variables_nonlinear - IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable) + for (index, variable) in enumerate(indicator_IDP.variables_nonlinear) + IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, length(indicator_IDP.variables_cons) + index) end return nothing end -@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable) +@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis @@ -738,7 +736,7 @@ end end -@inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable) +@inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack positCorrFactor = indicator_IDP From 3b0e2f6e479ab69184169e17c1ae1206d64bb6de Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 22 May 2023 15:27:20 +0200 Subject: [PATCH 178/423] merge branch 'main' into ma-bolm-2022 --- Project.toml | 2 +- .../src/files/scalar_linear_advection_1d.jl | 2 +- .../elixir_advection_extended.jl | 56 +++++++++++++++++++ src/auxiliary/mpi.jl | 12 ---- src/solvers/dg.jl | 32 ++++++++--- src/solvers/dgsem_p4est/dg_3d_parallel.jl | 4 +- src/solvers/dgsem_structured/dg_1d.jl | 4 +- src/solvers/dgsem_structured/dg_2d.jl | 4 +- src/solvers/dgsem_structured/dg_3d.jl | 4 +- src/solvers/dgsem_tree/dg_1d.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 4 +- src/solvers/dgsem_tree/dg_2d_parallel.jl | 4 +- src/solvers/dgsem_tree/dg_3d.jl | 4 +- src/solvers/dgsem_unstructured/dg_2d.jl | 4 +- test/test_tree_1d_fdsbp.jl | 18 ++++++ test/test_tree_2d_fdsbp.jl | 18 ++++++ test/test_tree_3d_fdsbp.jl | 24 ++++++++ 17 files changed, 161 insertions(+), 39 deletions(-) create mode 100644 examples/tree_3d_fdsbp/elixir_advection_extended.jl diff --git a/Project.toml b/Project.toml index 5ee043b323..cb27c828cf 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.5.24-pre" +version = "0.5.25-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" diff --git a/docs/literate/src/files/scalar_linear_advection_1d.jl b/docs/literate/src/files/scalar_linear_advection_1d.jl index 8a8a1b1996..42c831c98b 100644 --- a/docs/literate/src/files/scalar_linear_advection_1d.jl +++ b/docs/literate/src/files/scalar_linear_advection_1d.jl @@ -48,7 +48,7 @@ dx = (coordinates_max - coordinates_min) / n_elements # length of one element # ```math # \frac{dx}{2} u_t^{Q_l} + u_\xi^{Q_l} = 0 \text{, for }t\in\mathbb{R}^+,\; \xi\in[-1, 1] # ``` -# $u_t^{Q_l}$ and $u_\xi^{Q_l}$ denote the time and spatial derivatives of the solution on the element $Q_l$. +# Here, $u_t^{Q_l}$ and $u_\xi^{Q_l}$ denote the time and spatial derivatives of the solution on the element $Q_l$. # ### ii. Polynomial approach diff --git a/examples/tree_3d_fdsbp/elixir_advection_extended.jl b/examples/tree_3d_fdsbp/elixir_advection_extended.jl new file mode 100644 index 0000000000..241e069864 --- /dev/null +++ b/examples/tree_3d_fdsbp/elixir_advection_extended.jl @@ -0,0 +1,56 @@ +# !!! warning "Experimental implementation (upwind SBP)" +# This is an experimental feature and may change in future releases. + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection equation + +advection_velocity = (0.2, -0.7, 0.5) +equations = LinearScalarAdvectionEquation3D(advection_velocity) + +initial_condition = initial_condition_convergence_test + +D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order=1, accuracy_order=4, + xmin=0.0, xmax=1.0, N=10) +solver = FDSBP(D_SBP, + surface_integral=SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral=VolumeIntegralStrongForm()) + +coordinates_min = (-1.0, -1.0, -1.0) +coordinates_max = ( 1.0, 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=1, + n_cells_max=30_000, + periodicity=true) + +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 = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(energy_total,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + + +############################################################################### +# run the simulation + +sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-9, reltol=1.0e-9, + ode_default_options()..., callback=callbacks) +summary_callback() diff --git a/src/auxiliary/mpi.jl b/src/auxiliary/mpi.jl index 3816b42c33..ab1b13d49d 100644 --- a/src/auxiliary/mpi.jl +++ b/src/auxiliary/mpi.jl @@ -45,18 +45,6 @@ const MPI_IS_ROOT = Ref(true) @inline mpi_isparallel() = MPI_IS_PARALLEL[] -# This is not type-stable but that's okay since we want to get rid of it anyway -# and it's not used in performance-critical parts. The alternative we used before, -# calling something like `eval(:(mpi_parallel() = True()))` in `init_mpi()`, -# causes invalidations and slows down the first call to Trixi.jl. -function mpi_parallel() - if mpi_isparallel() - return True() - else - return False() - end -end - @inline mpi_isroot() = MPI_IS_ROOT[] @inline mpi_root() = 0 diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 5e7b4dbea4..cbeae1b62e 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -582,6 +582,12 @@ AdaptorAMR(mesh, dg::DG) = AdaptorL2(dg.basis) # DGSEM (discontinuous Galerkin spectral element method) include("dgsem/dgsem.jl") +# Finite difference methods using summation by parts (SBP) operators +# These methods are very similar to DG methods since they also impose interface +# and boundary conditions weakly. Thus, these methods can re-use a lot of +# functionality implemented for DGSEM. +include("fdsbp_tree/fdsbp.jl") + function allocate_coefficients(mesh::AbstractMesh, equations, dg::DG, cache) @@ -631,6 +637,25 @@ end end end +# Finite difference summation by parts (FDSBP) methods +@inline function wrap_array(u_ode::AbstractVector, mesh::AbstractMesh, equations, dg::FDSBP, cache) + @boundscheck begin + @assert length(u_ode) == nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache) + end + # See comments on the DGSEM version above + if LoopVectorization.check_args(u_ode) + # Here, we do not specialize on the number of nodes using `StaticInt` since + # - it will not be type stable (SBP operators just store it as a runtime value) + # - FD methods tend to use high node counts + PtrArray(pointer(u_ode), + (StaticInt(nvariables(equations)), ntuple(_ -> nnodes(dg), ndims(mesh))..., nelements(dg, cache))) + else + # The following version is reasonably fast and allows us to `resize!(u_ode, ...)`. + unsafe_wrap(Array{eltype(u_ode), ndims(mesh)+2}, pointer(u_ode), + (nvariables(equations), ntuple(_ -> nnodes(dg), ndims(mesh))..., nelements(dg, cache))) + end +end + # General fallback @inline function wrap_array(u_ode::AbstractVector, mesh::AbstractMesh, equations, dg::DG, cache) wrap_array_native(u_ode, mesh, equations, dg, cache) @@ -696,11 +721,4 @@ include("dgsem_unstructured/dg.jl") include("dgsem_p4est/dg.jl") -# Finite difference methods using summation by parts (SBP) operators -# These methods are very similar to DG methods since they also impose interface -# and boundary conditions weakly. Thus, these methods can re-use a lot of -# functionality implemented for DGSEM. -include("fdsbp_tree/fdsbp.jl") - - end # @muladd diff --git a/src/solvers/dgsem_p4est/dg_3d_parallel.jl b/src/solvers/dgsem_p4est/dg_3d_parallel.jl index e0e7268d8e..5c77247ac6 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parallel.jl @@ -7,8 +7,8 @@ function rhs!(du, u, t, mesh::ParallelP4estMesh{3}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Start to receive MPI data @trixi_timeit timer() "start MPI receive" start_mpi_receive!(cache.mpi_cache) diff --git a/src/solvers/dgsem_structured/dg_1d.jl b/src/solvers/dgsem_structured/dg_1d.jl index 504bbe3925..e33328a820 100644 --- a/src/solvers/dgsem_structured/dg_1d.jl +++ b/src/solvers/dgsem_structured/dg_1d.jl @@ -7,8 +7,8 @@ function rhs!(du, u, t, mesh::StructuredMesh{1}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 2ebbaa9c40..5f1aa57d17 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -7,8 +7,8 @@ function rhs!(du, u, t, mesh::StructuredMesh{2}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_structured/dg_3d.jl b/src/solvers/dgsem_structured/dg_3d.jl index 2c823042c7..6c27e20632 100644 --- a/src/solvers/dgsem_structured/dg_3d.jl +++ b/src/solvers/dgsem_structured/dg_3d.jl @@ -7,8 +7,8 @@ function rhs!(du, u, t, mesh::StructuredMesh{3}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_tree/dg_1d.jl b/src/solvers/dgsem_tree/dg_1d.jl index df882befab..a3346a4f15 100644 --- a/src/solvers/dgsem_tree/dg_1d.jl +++ b/src/solvers/dgsem_tree/dg_1d.jl @@ -71,8 +71,8 @@ end function rhs!(du, u, t, mesh::TreeMesh{1}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 246165290e..67a1be8ded 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -126,8 +126,8 @@ end function rhs!(du, u, t, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_tree/dg_2d_parallel.jl b/src/solvers/dgsem_tree/dg_2d_parallel.jl index d605a848aa..a7c6a8b474 100644 --- a/src/solvers/dgsem_tree/dg_2d_parallel.jl +++ b/src/solvers/dgsem_tree/dg_2d_parallel.jl @@ -429,8 +429,8 @@ end function rhs!(du, u, t, mesh::Union{ParallelTreeMesh{2}, ParallelP4estMesh{2}}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Start to receive MPI data @trixi_timeit timer() "start MPI receive" start_mpi_receive!(cache.mpi_cache) diff --git a/src/solvers/dgsem_tree/dg_3d.jl b/src/solvers/dgsem_tree/dg_3d.jl index fd8f76d168..aef86e3de7 100644 --- a/src/solvers/dgsem_tree/dg_3d.jl +++ b/src/solvers/dgsem_tree/dg_3d.jl @@ -122,8 +122,8 @@ end function rhs!(du, u, t, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/src/solvers/dgsem_unstructured/dg_2d.jl b/src/solvers/dgsem_unstructured/dg_2d.jl index acb89bc452..283f8bdc74 100644 --- a/src/solvers/dgsem_unstructured/dg_2d.jl +++ b/src/solvers/dgsem_unstructured/dg_2d.jl @@ -34,8 +34,8 @@ end function rhs!(du, u, t, mesh::UnstructuredMesh2D, equations, - initial_condition, boundary_conditions, source_terms, - dg::DG, cache) + initial_condition, boundary_conditions, source_terms::Source, + dg::DG, cache) where {Source} # Reset du @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) diff --git a/test/test_tree_1d_fdsbp.jl b/test/test_tree_1d_fdsbp.jl index 44be443815..a966b3836f 100644 --- a/test/test_tree_1d_fdsbp.jl +++ b/test/test_tree_1d_fdsbp.jl @@ -13,6 +13,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_fdsbp") l2 = [8.316190308678742e-7], linf = [7.1087263324720595e-6], tspan = (0.0, 0.5)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end # same tolerances as above since the methods should be identical (up to @@ -39,6 +48,15 @@ end l2 = [4.1370344463620254e-6, 4.297052451817826e-6, 9.857382045003056e-6], linf = [1.675305070092392e-5, 1.3448113863834266e-5, 3.8185336878271414e-5], tspan = (0.0, 0.5)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_euler_convergence.jl with splitting_vanleer_haenel" begin diff --git a/test/test_tree_2d_fdsbp.jl b/test/test_tree_2d_fdsbp.jl index f75fedcf2a..7c58ef89a6 100644 --- a/test/test_tree_2d_fdsbp.jl +++ b/test/test_tree_2d_fdsbp.jl @@ -13,6 +13,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_fdsbp") l2 = [2.898644263922225e-6], linf = [8.491517930142578e-6], rtol = 1.0e-7) # These results change a little bit and depend on the CI system + + # 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 @@ -22,6 +31,15 @@ end l2 = [1.7088389997042244e-6, 1.7437997855125774e-6, 1.7437997855350776e-6, 5.457223460127621e-6], linf = [9.796504903736292e-6, 9.614745892783105e-6, 9.614745892783105e-6, 4.026107182575345e-5], tspan = (0.0, 0.1)) + + # 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_euler_convergence.jl with Lax-Friedrichs splitting" begin diff --git a/test/test_tree_3d_fdsbp.jl b/test/test_tree_3d_fdsbp.jl index 22d45abc76..9dceab3803 100644 --- a/test/test_tree_3d_fdsbp.jl +++ b/test/test_tree_3d_fdsbp.jl @@ -8,11 +8,35 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_fdsbp") @testset "Compressible Euler" begin + @trixi_testset "elixir_advection_extended.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2 = [0.005355755365412444], + linf = [0.01856044696350767]) + + # 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_euler_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), l2 = [2.247522803543667e-5, 2.2499169224681058e-5, 2.24991692246826e-5, 2.2499169224684707e-5, 5.814121361417382e-5], linf = [9.579357410749445e-5, 9.544871933409027e-5, 9.54487193367548e-5, 9.544871933453436e-5, 0.0004192294529472562], 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_euler_convergence.jl with VolumeIntegralStrongForm" begin From 86be8d459b30082e6436b68ee909a94ab70fcc83 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 22 May 2023 15:27:50 +0200 Subject: [PATCH 179/423] Adjust and fix tests --- .../elixir_euler_blast_wave_sc_subcell.jl | 2 + test/test_tree_2d_euler.jl | 59 ++++++------------- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index c1e34dc076..58423b5501 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -41,6 +41,8 @@ basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, IDPPressureTVD=true, + IDPMathEntropy=true, + BarStates=false, indicator_smooth=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index e4b37de13a..fb9afeb25d 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -63,12 +63,6 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) end - @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - l2 = [0.05279387793678434, 0.04598968102076476, 0.04598873940396531, 0.19301779222816706], - linf = [0.1866584355939257, 0.2319290947473017, 0.23237647269183395, 0.6911745732545076]) - end - @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), l2 = [0.14170569763947993, 0.11647068900798814, 0.11647072556898294, 0.3391989213659599], @@ -131,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.3518553249794659, 0.19310220470973063, 0.1930955995353822, 0.619265328729751], - linf = [1.6781299814634756, 1.3624305216971244, 1.3621049685174218, 2.4493280170024123], + l2 = [0.29207274278608286, 0.17319844122225747, 0.1732464339957263, 0.6147098214272999], + linf = [1.2344701003292178, 1.017987009333722, 1.0181605576133113, 2.42683176792753], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) @@ -146,6 +140,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2 = [0.47651273561515994, 0.16605194156429376, 0.16605194156447747, 0.6184646142923547], + linf = [2.559717182592356, 1.3594817545576394, 1.3594817545666105, 6.451896959781657], + tspan = (0.0, 1.0), + initial_refinement_level=4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), l2 = [0.0845430093623868, 0.09271459184623232, 0.09271459184623232, 0.4377291875101709], @@ -162,15 +165,6 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=3,)) end - @trixi_testset "elixir_euler_positivity_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity_sc_subcell.jl"), - l2 = [0.49170711532017397, 0.16545207388505218, 0.16545210945870265, 0.6347169459573236], - linf = [2.525440391740859, 1.167550417094284, 1.1675492773007656, 6.468729876521227], - tspan = (0.0, 1.0), - initial_refinement_level=5, - coverage_override = (maxiters=3,)) - end - @trixi_testset "elixir_euler_blob_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_mortar.jl"), l2 = [0.22271619518391986, 0.6284824759323494, 0.24864213447943648, 2.9591811489995474], @@ -187,14 +181,6 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=10^5,)) end - @trixi_testset "elixir_euler_blob_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_sc_subcell.jl"), - l2 = [0.22952600868491232, 0.6598694971331289, 0.2375222572511259, 3.0485750678229198], - linf = [7.661392002055745, 19.336398494293007, 9.378519483511768, 79.18768909325449], - tspan = (0.0, 0.5), - initial_refinement_level=5) - end - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl"), l2 = [0.1057230211245312, 0.10621112311257341, 0.07260957505339989, 0.11178239111065721], @@ -219,8 +205,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.05570314908537475, 0.03298722583361271, 0.052244709734327016, 0.08011559032847568], - linf = [0.24091015067867505, 0.166018978319328, 0.12356154832726032, 0.26951669929779953], + l2 = [0.055703165296633834, 0.032987233605927, 0.05224472051711956, 0.08011565264331237], + linf = [0.24091018397460595, 0.1660190071332282, 0.12356154893467916, 0.2695167937393226], tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=2,)) @@ -252,14 +238,6 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=2,)) end - @trixi_testset "elixir_euler_colliding_flow_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_sc_subcell.jl"), - l2 = [0.006577159539817667, 0.04554740746415583, 1.4554079130334693e-6, 0.6258024941421835], - linf = [0.14555535078246196, 0.5306125024728012, 8.590620121863414e-5, 12.092753540073211], - tspan = (0.0, 0.1), - coverage_override = (maxiters=2,)) - end - @trixi_testset "elixir_euler_astro_jet_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_amr.jl"), l2 = [0.011338365293662804, 10.09743543555765, 0.00392429463200361, 4031.7811487690506], @@ -268,11 +246,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end - @trixi_testset "elixir_euler_astro_jet_subcell_restart.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell_restart.jl"), - l2 = [0.4399267169815457, 352.321452114897, 14.089381141646252, 138648.81629357373], - linf = [7.532813790308049, 5594.80343019963, 626.966037014211, 2.154789660969525e6], - tspan = (2.5e-6, 1.0e-4), + @trixi_testset "elixir_euler_astro_jet_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell.jl"), + l2 = [0.4186473232186195, 341.42386623555944, 12.913743102619245, 135260.31735534978], + linf = [6.594617349637199, 5225.251243383396, 417.4788228266706, 2.0263599311276933e6], + initial_refinement_level=5, + tspan = (0.0, 1.0e-4), coverage_override = (maxiters=6,)) end From 3bf24198c7d0ead102452b91787eaab75b1db97f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 23 May 2023 13:04:18 +0200 Subject: [PATCH 180/423] Fix test --- test/test_tree_2d_euler.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index fb9afeb25d..9a57ced219 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.29207274278608286, 0.17319844122225747, 0.1732464339957263, 0.6147098214272999], - linf = [1.2344701003292178, 1.017987009333722, 1.0181605576133113, 2.42683176792753], + l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], + linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From 1f8d402686aea3f103af039a0c65bfe53a421937 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 24 May 2023 10:51:58 +0200 Subject: [PATCH 181/423] Start adding general positivity limiting --- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 91 +++++++++++-------- src/solvers/dgsem_tree/indicators.jl | 20 ++-- src/solvers/dgsem_tree/indicators_2d.jl | 60 ++++++------ src/time_integration/methods_SSP.jl | 25 +++-- test/test_tree_2d_euler.jl | 4 +- 6 files changed, 118 insertions(+), 84 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 6a79570770..37ae523a4b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,7 +37,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true, + IDPPositivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), IDPDensityTVD=false, IDPSpecEntropy=false, BarStates=true, diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index ddd9cab288..855246b205 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1026,9 +1026,6 @@ end end counter += 2 end - if indicator.IDPPositivity - counter += !indicator.IDPDensityTVD + !indicator.IDPPressureTVD - end # Specific Entropy if indicator.IDPSpecEntropy s_min = var_bounds[counter] @@ -1955,18 +1952,26 @@ end if IDPPressureTVD print(f, ", p_min, p_max"); end - if IDPPositivity && !IDPDensityTVD - print(f, ", rho_min"); - end - if IDPPositivity && !IDPPressureTVD - print(f, ", p_min"); - end if IDPSpecEntropy print(f, ", specEntr_min"); end if IDPMathEntropy print(f, ", mathEntr_max"); end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + print(f, ", $(variable)_min"); + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + print(f, ", $(variable)_min"); + end + end println(f) end end @@ -2015,35 +2020,6 @@ end end counter += 2 end - if IDPPositivity && !IDPDensityTVD - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - u[1, i, j, element]) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_); - end - end - counter += 1 - end - if IDPPositivity && !IDPPressureTVD - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_); - end - end - counter += 1 - end if IDPSpecEntropy deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -2072,6 +2048,45 @@ end print(f, ", ", deviation_max_); end end + counter += 1 + end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + var = variable(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors + deviation_min_ = deviation_min + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end + end + counter += 1 + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + var = variable(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors + deviation_min_ = deviation_min + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end + end + counter += 1 + end end if save_errors open("$output_directory/deviations.txt", "a") do f; println(f); end; diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 2c54560558..ca88d9bd31 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -230,12 +230,12 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT<:Real, Cache, Indicator} <: AbstractIndicator +struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator IDPDensityTVD::Bool IDPPressureTVD::Bool IDPPositivity::Bool - variables_cons::Tuple{Any} # Positivity of conservative variables - variables_nonlinear::Tuple{Any} # Positivity of nonlinear variables + variables_cons::Union{Tuple{}, Tuple{LimitingVariablesCons}} # Positivity of conservative variables + variables_nonlinear::Union{Tuple{}, Tuple{LimitingVariablesNonlinear}} # Positivity of nonlinear variables IDPSpecEntropy::Bool IDPMathEntropy::Bool BarStates::Bool @@ -270,8 +270,16 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") end - number_bounds = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - IDPPositivity * (length(variables_cons) + length(variables_nonlinear)) + number_bounds = IDPPositivity * (length(variables_cons) + length(variables_nonlinear)) + + IDPSpecEntropy + IDPMathEntropy + if equations isa AbstractCompressibleEulerEquations + if IDPDensityTVD + number_bounds += 2 - IDPPositivity * (Trixi.density in variables_cons) + end + if IDPPressureTVD + number_bounds += 2 - IDPPositivity * (pressure in variables_nonlinear) + end + end cache = create_cache(IndicatorIDP, equations, basis, number_bounds, BarStates) @@ -281,7 +289,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positCorrFactor), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, + IndicatorIDP{typeof(positCorrFactor), eltype(variables_cons), eltype(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 62707c695a..776de603fd 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -514,9 +514,8 @@ end @unpack boundary_conditions = semi @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - offset = 2 * indicator_IDP.IDPDensityTVD - p_min = var_bounds[1 + offset] - p_max = var_bounds[2 + offset] + p_min = var_bounds[2 * indicator_IDP.IDPDensityTVD + 1] + p_max = var_bounds[2 * indicator_IDP.IDPDensityTVD + 2] if !indicator_IDP.BarStates calc_bounds_2sided!(p_min, p_max, pressure, u, t, semi) end @@ -584,8 +583,7 @@ end @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - offset = 2 * (IDPDensityTVD + IDPPressureTVD) + min(IDPPositivity, !IDPDensityTVD) + min(IDPPositivity, !IDPPressureTVD) - s_min = var_bounds[offset + 1] + s_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + 1] if !indicator_IDP.BarStates calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -613,9 +611,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - offset = 2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + - min(IDPPositivity, !IDPDensityTVD)+ min(IDPPositivity, !IDPPressureTVD) - s_max = var_bounds[offset + 1] + s_max = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + 1] if !indicator_IDP.BarStates calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -646,7 +642,7 @@ mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_absto # Nonlinear variables for (index, variable) in enumerate(indicator_IDP.variables_nonlinear) - IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, length(indicator_IDP.variables_cons) + index) + IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) end return nothing @@ -656,18 +652,20 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis - @unpack positCorrFactor = indicator_IDP + @unpack IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - if indicator_IDP.IDPDensityTVD - rho_min = var_bounds[1] - else - if indicator_IDP.IDPPressureTVD - rho_min = var_bounds[3] + if Trixi.density in variables_cons && IDPDensityTVD + if Trixi.density == variables_cons[index] + var_min = var_bounds[1] else - rho_min = var_bounds[1] + var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + index - 1] end + else + var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + index] end @threaded for element in elements @@ -686,9 +684,9 @@ end # Compute bound if indicator_IDP.IDPDensityTVD - rho_min[i, j, element] = max(rho_min[i, j, element], positCorrFactor * var) + var_min[i, j, element] = max(var_min[i, j, element], positCorrFactor * var) else - rho_min[i, j, element] = positCorrFactor * var + var_min[i, j, element] = positCorrFactor * var end # Real one-sided Zalesak-type limiter @@ -696,7 +694,7 @@ end # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qm = min(0.0, (rho_min[i, j, element] - var) / dt) + Qm = min(0.0, (var_min[i, j, element] - var) / dt) # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -724,18 +722,22 @@ end @inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack positCorrFactor = indicator_IDP + @unpack IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons, variables_nonlinear = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - if indicator_IDP.IDPDensityTVD - p_min = var_bounds[3] - else - if indicator_IDP.IDPPressureTVD - p_min = var_bounds[1] + if pressure in variables_nonlinear && IDPPressureTVD + if pressure == variables_nonlinear[index] + var_min = var_bounds[2 * IDPDensityTVD + 1] else - p_min = var_bounds[2] + var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + + index - 1] end + else + var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + + length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + + index] end @threaded for element in elements @@ -747,13 +749,13 @@ end println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") end if indicator_IDP.IDPPressureTVD - p_min[i, j, element] = max(p_min[i, j, element], positCorrFactor * var) + var_min[i, j, element] = max(var_min[i, j, element], positCorrFactor * var) else - p_min[i, j, element] = positCorrFactor * var + var_min[i, j, element] = positCorrFactor * var end # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, p_min[i, j, element], u_local, i, j, element, + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, dt, mesh, equations, dg, cache, indicator_IDP) end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 074bd1a67d..138bfebd43 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -315,20 +315,29 @@ end println("pressure:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) counter += 2 end - if IDPPositivity && !IDPDensityTVD - println("rho:\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 - end - if IDPPositivity && !IDPPressureTVD - println("pressure:\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 - end if IDPSpecEntropy println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) counter += 1 end if IDPMathEntropy println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) + counter += 1 + end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + counter += 1 + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + counter += 1 + end end println("─"^100 * "\n") diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index fb9afeb25d..9a57ced219 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.29207274278608286, 0.17319844122225747, 0.1732464339957263, 0.6147098214272999], - linf = [1.2344701003292178, 1.017987009333722, 1.0181605576133113, 2.42683176792753], + l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], + linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From f69e03878085e9f893d15bdb360c0ea0683d7f5d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 24 May 2023 12:22:42 +0200 Subject: [PATCH 182/423] Adjust output of summy callback --- src/solvers/dg.jl | 14 +++++----- src/solvers/dgsem_tree/indicators.jl | 40 +++++++++++++++++++++------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index cbeae1b62e..1b3bb229ef 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -201,18 +201,18 @@ function VolumeIntegralShockCapturingSubcell(indicator; volume_flux_dg, volume_flux_dg, volume_flux_fv, indicator) end -function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) +function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) @nospecialize integral # reduce precompilation time if get(io, :compact, false) show(io, integral) else - setup = [ - "volume flux dg" => integral.volume_flux_dg, - "volume flux fv" => integral.volume_flux_fv, - "indicator" => integral.indicator - ] - summary_box(io, "VolumeIntegralShockCapturingSubcell", setup) + summary_header(io, "VolumeIntegralShockCapturingSubcell") + summary_line(io, "volume flux DG", integral.volume_flux_dg) + summary_line(io, "volume flux FV", integral.volume_flux_fv) + summary_line(io, "indicator", integral.indicator |> typeof |> nameof) + show(increment_indent(io), mime, integral.indicator) + summary_footer(io) end end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index ca88d9bd31..43cfbc3dc8 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -305,23 +305,45 @@ function Base.show(io::IO, indicator::IndicatorIDP) else print(io, "limiter=(") IDPDensityTVD && print(io, "IDPDensityTVD, ") - IDPPressureTVD && print(io, "IDPPressureTVD with positivity correlation factor of ", - indicator.positCorrFactor, ", ") - IDPPositivity && print(io, "IDPPositivity with variables $(indicator.variables_cons) and - $(indicator.variables_nonlinear), ") + IDPPressureTVD && print(io, "IDPPressureTVD, ") + IDPPositivity && print(io, "IDPPositivity, ") IDPSpecEntropy && print(io, "IDPSpecEntropy, ") IDPMathEntropy && print(io, "IDPMathEntropy, ") print(io, "), ") end indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth, "), ") - print(io, "Local bounds with ") - if indicator.BarStates - print(io, "Bar States") + print(io, "Local bounds with $(indicator.BarStates ? "Bar States" : "FV solution")") + print(io, ")") +end + +function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) + @nospecialize indicator # reduce precompilation time + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + + if get(io, :compact, false) + show(io, indicator) else - print(io, "FV solution") + if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + setup = ["limiter" => "No limiter selected => pure DG method"] + else + setup = ["limiter" => ""] + IDPDensityTVD && (setup = [setup..., "" => "IDPDensityTVD"]) + IDPPressureTVD && (setup = [setup..., "" => "IDPPressureTVD"]) + if IDPPositivity + string = "IDPPositivity with variables $(vcat(indicator.variables_cons..., indicator.variables_nonlinear...))" + setup = [setup..., "" => string] + setup = [setup..., "" => " "^14 * "and positivity correlation factor $(indicator.positCorrFactor)"] + end + IDPSpecEntropy && (setup = [setup..., "" => "IDPSpecEntropy"]) + IDPMathEntropy && (setup = [setup..., "" => "IDPMathEntropy"]) + setup = [setup..., "Local bounds" => (indicator.BarStates ? "Bar States" : "FV solution")] + if indicator.indicator_smooth + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + end + end + summary_box(io, "IndicatorIDP", setup) end - print(io, ")") end function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) From f30966236f05937253a5c7dafb99cfa55e522ec5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 24 May 2023 12:47:29 +0200 Subject: [PATCH 183/423] Adjust output of summary callback for MCL --- src/solvers/dgsem_tree/indicators.jl | 37 ++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 43cfbc3dc8..e059aa6e34 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -419,11 +419,7 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") if indicator.PressurePositivityLimiterKuzmin - if indicator.PressurePositivityLimiterKuzminExact - print(io, "; pres (Kuzmin ex)") - else - print(io, "; pres (Kuzmin)") - end + print(io, "; $(indicator.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") end indicator.DensityPositivityLimiter && print(io, "; dens pos") (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") @@ -433,6 +429,37 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, ")") end +function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) + @nospecialize indicator # reduce precompilation time + @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = indicator + + if get(io, :compact, false) + show(io, indicator) + else + setup = ["limiter" => ""] + DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) + DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) + SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) + ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) + if indicator.PressurePositivityLimiterKuzmin + setup = [setup..., "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")"] + end + if DensityPositivityLimiter + if indicator.DensityPositivityCorrelationFactor != 0.0 + setup = [setup..., "" => "DensityPositivityLimiter with correlation factor $(indicator.DensityPositivityCorrelationFactor)"] + else + setup = [setup..., "" => "DensityPositivityLimiter"] + end + end + SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) + if indicator.indicator_smooth + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + end + summary_box(io, "IndicatorMCL", setup) + end +end + function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) if !indicator.Plotting return nothing From a56aab2a608b01e41029e72b3798c7a9dd59a97f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 24 May 2023 12:54:18 +0200 Subject: [PATCH 184/423] Adjust output of summary callback --- src/solvers/dgsem_tree/indicators.jl | 70 +++++++++++++++++++++++----- src/time_integration/methods_SSP.jl | 2 +- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 761ae97d1b..4b5878fecf 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -292,8 +292,7 @@ function Base.show(io::IO, indicator::IndicatorIDP) else print(io, "limiter=(") IDPDensityTVD && print(io, "IDPDensityTVD, ") - IDPPressureTVD && print(io, "IDPPressureTVD with positivity correlation factor of ", - indicator.positCorrFactor, ", ") + IDPPressureTVD && print(io, "IDPPressureTVD, ") IDPPositivity && print(io, "IDPPositivity, ") IDPSpecEntropy && print(io, "IDPSpecEntropy, ") IDPMathEntropy && print(io, "IDPMathEntropy, ") @@ -301,13 +300,33 @@ function Base.show(io::IO, indicator::IndicatorIDP) end indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.thr_smooth, "), ") - print(io, "Local bounds with ") - if indicator.BarStates - print(io, "Bar States") + print(io, "Local bounds with $(indicator.BarStates ? "Bar States" : "FV solution")") + print(io, ")") +end + +function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) + @nospecialize indicator # reduce precompilation time + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + + if get(io, :compact, false) + show(io, indicator) else - print(io, "FV solution") + if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + setup = ["limiter" => "No limiter selected => pure DG method"] + else + setup = ["limiter" => ""] + IDPDensityTVD && (setup = [setup..., "" => "IDPDensityTVD"]) + IDPPressureTVD && (setup = [setup..., "" => "IDPPressureTVD"]) + IDPPositivity && (setup = [setup..., "" => "IDPPositivity with positivity correlation factor $(indicator.positCorrFactor)"]) + IDPSpecEntropy && (setup = [setup..., "" => "IDPSpecEntropy"]) + IDPMathEntropy && (setup = [setup..., "" => "IDPMathEntropy"]) + setup = [setup..., "Local bounds" => (indicator.BarStates ? "Bar States" : "FV solution")] + if indicator.indicator_smooth + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + end + end + summary_box(io, "IndicatorIDP", setup) end - print(io, ")") end function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) @@ -383,11 +402,7 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.SequentialLimiter && print(io, "; seq") indicator.ConservativeLimiter && print(io, "; cons") if indicator.PressurePositivityLimiterKuzmin - if indicator.PressurePositivityLimiterKuzminExact - print(io, "; pres (Kuzmin ex)") - else - print(io, "; pres (Kuzmin)") - end + print(io, "; $(indicator.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") end indicator.DensityPositivityLimiter && print(io, "; dens pos") (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") @@ -397,6 +412,37 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, ")") end +function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) + @nospecialize indicator # reduce precompilation time + @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = indicator + + if get(io, :compact, false) + show(io, indicator) + else + setup = ["limiter" => ""] + DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) + DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) + SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) + ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) + if indicator.PressurePositivityLimiterKuzmin + setup = [setup..., "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")"] + end + if DensityPositivityLimiter + if indicator.DensityPositivityCorrelationFactor != 0.0 + setup = [setup..., "" => "DensityPositivityLimiter with correlation factor $(indicator.DensityPositivityCorrelationFactor)"] + else + setup = [setup..., "" => "DensityPositivityLimiter"] + end + end + SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) + if indicator.indicator_smooth + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + end + summary_box(io, "IndicatorMCL", setup) + end +end + function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) if !indicator.Plotting return nothing diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index dac598792a..074bd1a67d 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -171,7 +171,7 @@ function solve!(integrator::SimpleIntegratorSSP) # compute du integrator.f(integrator.du, integrator.u, integrator.p, t_stage) - # perfom forward Euler step + # perform forward Euler step @. integrator.u = integrator.u + integrator.dt * integrator.du end @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) From 2cd3486c7fb1debca55c3d2b451dbe0a68b4a70c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 24 May 2023 12:55:39 +0200 Subject: [PATCH 185/423] Fix output --- src/solvers/dg.jl | 14 +++++++------- src/solvers/dgsem_tree/dg_2d.jl | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index cbeae1b62e..1b3bb229ef 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -201,18 +201,18 @@ function VolumeIntegralShockCapturingSubcell(indicator; volume_flux_dg, volume_flux_dg, volume_flux_fv, indicator) end -function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) +function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) @nospecialize integral # reduce precompilation time if get(io, :compact, false) show(io, integral) else - setup = [ - "volume flux dg" => integral.volume_flux_dg, - "volume flux fv" => integral.volume_flux_fv, - "indicator" => integral.indicator - ] - summary_box(io, "VolumeIntegralShockCapturingSubcell", setup) + summary_header(io, "VolumeIntegralShockCapturingSubcell") + summary_line(io, "volume flux DG", integral.volume_flux_dg) + summary_line(io, "volume flux FV", integral.volume_flux_fv) + summary_line(io, "indicator", integral.indicator |> typeof |> nameof) + show(increment_indent(io), mime, integral.indicator) + summary_footer(io) end end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 67a1be8ded..ddd9cab288 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -702,7 +702,7 @@ end # All diagonal entries of `derivative_split` are zero. Thus, we can skip # the computation of the diagonal terms. In addition, we use the symmetry - # of the `volume_flux` to save half of the possible two-poitn flux + # of the `volume_flux` to save half of the possible two-point flux # computations. for ii in (i+1):nnodes(dg) u_node_ii = get_node_vars(u, equations, dg, ii, j, element) From 7ca0d24081a2ddfca066d56c4f8ea51a42cd6c3d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 24 May 2023 13:24:21 +0200 Subject: [PATCH 186/423] Fix parameter type --- src/solvers/dgsem_tree/indicators.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index e059aa6e34..72e7211325 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -234,8 +234,8 @@ struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonline IDPDensityTVD::Bool IDPPressureTVD::Bool IDPPositivity::Bool - variables_cons::Union{Tuple{}, Tuple{LimitingVariablesCons}} # Positivity of conservative variables - variables_nonlinear::Union{Tuple{}, Tuple{LimitingVariablesNonlinear}} # Positivity of nonlinear variables + variables_cons::LimitingVariablesCons # Positivity of conservative variables + variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables IDPSpecEntropy::Bool IDPMathEntropy::Bool BarStates::Bool @@ -289,7 +289,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positCorrFactor), eltype(variables_cons), eltype(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, + IndicatorIDP{typeof(positCorrFactor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG) @@ -331,7 +331,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) IDPDensityTVD && (setup = [setup..., "" => "IDPDensityTVD"]) IDPPressureTVD && (setup = [setup..., "" => "IDPPressureTVD"]) if IDPPositivity - string = "IDPPositivity with variables $(vcat(indicator.variables_cons..., indicator.variables_nonlinear...))" + string = "IDPPositivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" setup = [setup..., "" => string] setup = [setup..., "" => " "^14 * "and positivity correlation factor $(indicator.positCorrFactor)"] end From fcb278e1d64cdc8bd2e113eaf22803ee3f72b397 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 25 May 2023 15:58:12 +0200 Subject: [PATCH 187/423] Delete not needed elixirs --- .../idp_density_entropy_cfl0.9_t10.jl | 30 ------ .../idp_density_entropy_cfl0.9_t3.7.jl | 94 ------------------ .../idp_density_entropy_cfl0.9_t6.7.jl | 30 ------ ..._positivity_density_pressure_cfl0.9_t10.jl | 30 ------ ...positivity_density_pressure_cfl0.9_t3.7.jl | 94 ------------------ ...positivity_density_pressure_cfl0.9_t6.7.jl | 30 ------ ...ivity_density_pressure_sharp_cfl0.9_t10.jl | 31 ------ ...vity_density_pressure_sharp_cfl0.9_t3.7.jl | 97 ------------------- ...vity_density_pressure_sharp_cfl0.9_t6.7.jl | 31 ------ .../mcl_sequential_cfl0.9_t10.jl | 30 ------ .../mcl_sequential_cfl0.9_t3.7.jl | 97 ------------------- .../mcl_sequential_cfl0.9_t6.7.jl | 30 ------ 12 files changed, 624 deletions(-) delete mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl delete mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl delete mode 100644 examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl delete mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl delete mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl delete mode 100644 examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl delete mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl delete mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl delete mode 100644 examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl delete mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl delete mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl delete mode 100644 examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl deleted file mode 100644 index 2ff438084c..0000000000 --- a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t10.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("idp_density_entropy_cfl0.9_t6.7.jl") - -restart_filename = "out_t6_7/restart_050302.h5" - -tspan = (load_time(restart_filename), 10.0) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t10/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t10/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl deleted file mode 100644 index 31e9b958a2..0000000000 --- a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t3.7.jl +++ /dev/null @@ -1,94 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - -A version of the classical Kelvin-Helmholtz instability based on -- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) - A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations - of the Euler Equations - [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) -""" -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_kelvin_helmholtz_instability - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 7 -basis = LobattoLegendreBasis(polydeg) - -indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=false, - IDPDensityTVD=true, - IDPSpecEntropy=true, - BarStates=true, - IDPCheckBounds=true, - indicator_smooth=false) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 3.7) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(output_directory="out_t3_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t3_7/", - interval=50000, - save_final_restart=true) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - stepsize_callback, - save_restart, save_solution) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl deleted file mode 100644 index d3234ef486..0000000000 --- a/examples/tree_2d_dgsem/idp_density_entropy_cfl0.9_t6.7.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("idp_density_entropy_cfl0.9_t3.7.jl") - -restart_filename = "out_t3_7/restart_062276.h5" - -tspan = (load_time(restart_filename), 6.7) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t6_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t6_7/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl deleted file mode 100644 index 1822b46f10..0000000000 --- a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t10.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("idp_positivity_density_pressure_cfl0.9_t6.7.jl") - -restart_filename = "out_t6_7/restart_084955.h5" - -tspan = (load_time(restart_filename), 10.0) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t10/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t10/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl deleted file mode 100644 index d2a4fb5361..0000000000 --- a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t3.7.jl +++ /dev/null @@ -1,94 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - -A version of the classical Kelvin-Helmholtz instability based on -- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) - A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations - of the Euler Equations - [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) -""" -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_kelvin_helmholtz_instability - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 7 -basis = LobattoLegendreBasis(polydeg) - -indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true, - IDPDensityTVD=false, - IDPSpecEntropy=false, - BarStates=true, - IDPCheckBounds=true, - indicator_smooth=false) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 3.7) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(output_directory="out_t3_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t3_7/", - interval=50000, - save_final_restart=true) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - stepsize_callback, - save_restart, save_solution) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl deleted file mode 100644 index f9206ea81f..0000000000 --- a/examples/tree_2d_dgsem/idp_positivity_density_pressure_cfl0.9_t6.7.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("idp_positivity_density_pressure_cfl0.9_t3.7.jl") - -restart_filename = "out_t3_7/restart_063585.h5" - -tspan = (load_time(restart_filename), 6.7) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t6_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t6_7/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl deleted file mode 100644 index 743f47bb70..0000000000 --- a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t10.jl +++ /dev/null @@ -1,31 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl") - -restart_filename = "out_t6_7/restart_3119274.h5" - - -tspan = (load_time(restart_filename), 10.0) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t10/", - interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t10/", - interval=1000000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - maxiters=1e7, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl deleted file mode 100644 index 7bc0f4d332..0000000000 --- a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl +++ /dev/null @@ -1,97 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - -A version of the classical Kelvin-Helmholtz instability based on -- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) - A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations - of the Euler Equations - [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) -""" -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_kelvin_helmholtz_instability - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 7 -basis = LobattoLegendreBasis(polydeg) - -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=true, - DensityPositivityLimiter=true, #DensityPositivityCorrelationFactor=0.0, - SemiDiscEntropyLimiter=false, - indicator_smooth=false, - IDPCheckBounds=true, - Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 3.7) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(output_directory="out_t3_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t3_7/", - interval=50000, - save_final_restart=true) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, save_solution) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - maxiters=1_000_000, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl deleted file mode 100644 index b0a01b1a91..0000000000 --- a/examples/tree_2d_dgsem/mcl_positivity_density_pressure_sharp_cfl0.9_t6.7.jl +++ /dev/null @@ -1,31 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("mcl_positivity_density_pressure_sharp_cfl0.9_t3.7.jl") - -restart_filename = "out_t3_7/restart_063921.h5.h5" - - -tspan = (load_time(restart_filename), 6.7) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t6_7/", - interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t6_7", - interval=500000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - maxiters=1e7, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl deleted file mode 100644 index 704012325b..0000000000 --- a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t10.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("mcl_sequential_cfl0.9_t6.7.jl") - -restart_filename = "out_t6_7/restart_051050.h5" - -tspan = (load_time(restart_filename), 10.0) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t10/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t10/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl deleted file mode 100644 index 0f6e5e955d..0000000000 --- a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t3.7.jl +++ /dev/null @@ -1,97 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - -A version of the classical Kelvin-Helmholtz instability based on -- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) - A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations - of the Euler Equations - [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) -""" -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_kelvin_helmholtz_instability - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 7 -basis = LobattoLegendreBasis(polydeg) - -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=false, - DensityPositivityLimiter=false, - SemiDiscEntropyLimiter=false, - indicator_smooth=false, - IDPCheckBounds=true, - Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 3.7) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(output_directory="out_t3_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t3_7/", - interval=50000, - save_final_restart=true) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, save_solution) - - -############################################################################### -# run the simulation - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - maxiters=1_000_000, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl b/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl deleted file mode 100644 index 725f8ed551..0000000000 --- a/examples/tree_2d_dgsem/mcl_sequential_cfl0.9_t6.7.jl +++ /dev/null @@ -1,30 +0,0 @@ -using OrdinaryDiffEq -using Trixi - -trixi_include("mcl_sequential_cfl0.9_t3.7.jl") - -restart_filename = "out_t3_7/restart_061891.h5" - -tspan = (load_time(restart_filename), 6.7) -ode = semidiscretize(semi, tspan, restart_filename); - -save_solution = SaveSolutionCallback(output_directory="out_t6_7/", - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -save_restart = SaveRestartCallback(output_directory="out_t6_7/", - interval=50000, - save_final_restart=true) - -callbacks = CallbackSet(summary_callback, - stepsize_callback, - analysis_callback, alive_callback, - save_restart, - save_solution) - -sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file From 55380b363351163fe16466ebe7bdb29fa611a61c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 25 May 2023 16:14:45 +0200 Subject: [PATCH 188/423] Implement BoundsCheck as stage callback --- ...elixir_euler_convergence_wavingflag_IDP.jl | 5 +- ...elixir_euler_convergence_wavingflag_MCL.jl | 5 +- .../elixir_euler_double_mach.jl | 8 +- .../elixir_euler_double_mach_MCL.jl | 5 +- .../elixir_euler_free_stream_MCL.jl | 5 +- .../elixir_euler_free_stream_sc_subcell.jl | 7 +- .../elixir_euler_shock_upstream_MCL.jl | 5 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 7 +- .../elixir_euler_astro_jet_MCL.jl | 5 +- .../elixir_euler_astro_jet_subcell.jl | 5 +- .../elixir_euler_blast_wave_MCL.jl | 5 +- .../elixir_euler_convergence_IDP.jl | 5 +- .../elixir_euler_convergence_MCL.jl | 5 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 5 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 7 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 5 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 7 +- src/Trixi.jl | 2 +- src/callbacks_stage/bounds_check.jl | 197 +++++++ src/callbacks_stage/bounds_check_2d.jl | 464 ++++++++++++++++ src/callbacks_stage/callbacks_stage.jl | 1 + src/solvers/dgsem_tree/dg.jl | 10 - src/solvers/dgsem_tree/dg_2d.jl | 500 ------------------ src/solvers/dgsem_tree/indicators.jl | 13 +- src/time_integration/methods_SSP.jl | 85 +-- 25 files changed, 735 insertions(+), 633 deletions(-) create mode 100644 src/callbacks_stage/bounds_check.jl create mode 100644 src/callbacks_stage/bounds_check_2d.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 0a926f439d..180ef30fc4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -20,7 +20,6 @@ indicator_sc = IndicatorIDP(equations, basis; positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), BarStates=true, - IDPCheckBounds=true, indicator_smooth=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -69,7 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index c307a2b166..2604dd7800 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -20,7 +20,6 @@ indicator_sc = IndicatorMCL(equations, basis; ConservativeLimiter=false, DensityPositivityLimiter=true, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - IDPCheckBounds=true, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -69,7 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 917077e1ea..4fa9a2bbe7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -97,8 +97,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=false, IDPSpecEntropy=true, positCorrFactor=0.1, IDPMaxIter=100, - BarStates=true, - IDPCheckBounds=true) + BarStates=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -126,7 +125,6 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval, alive_callback = AliveCallback(analysis_interval=analysis_interval) save_solution = SaveSolutionCallback(interval=1000, - output_directory="../../scratch/doublemach/IDP_density_entropy_cfl0_9_new/out", save_initial_solution=true, save_final_solution=true, solution_variables=cons2prim) @@ -141,7 +139,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index ba4e29d0bc..8ce4ed73ed 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -100,7 +100,6 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, PressurePositivityLimiterKuzmin=false, SemiDiscEntropyLimiter=false, - IDPCheckBounds=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -144,7 +143,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 2be073b558..d1395c31bb 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -22,7 +22,6 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, indicator_smooth=false, - IDPCheckBounds=true, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -85,7 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode; +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 75ae9ef2c1..e510cc8a7e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -21,8 +21,7 @@ indicator_sc = IndicatorIDP(equations, basis; indicator_smooth=false, BarStates=true, positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14), - IDPCheckBounds=true) + newton_tol=(1.0e-12, 1.0e-14)) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, @@ -84,7 +83,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode; +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 45acebe004..3eaec337d7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -44,7 +44,6 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=false, DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, - IDPCheckBounds=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -134,7 +133,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 6529bb715a..604be7dac4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -41,8 +41,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=false, IDPSpecEntropy=true, IDPMaxIter=100, - BarStates=true, - IDPCheckBounds=true) + BarStates=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -131,7 +130,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 2a98547ec6..054fb9ac29 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -50,7 +50,6 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, - IDPCheckBounds=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -92,7 +91,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 8b6e9d76cc..2419623a75 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -46,7 +46,6 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, IDPSpecEntropy=true, - IDPCheckBounds=true, BarStates=true, IDPMaxIter=25) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, @@ -89,7 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 73fde7b6dd..6d02a42dd1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,7 +39,6 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorMCL(equations, basis; - IDPCheckBounds=true, IDPPressure=false, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -86,7 +85,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode; +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 0c251edfe2..33608f6cc8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -20,7 +20,6 @@ indicator_sc = IndicatorIDP(equations, basis; positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), BarStates=true, - IDPCheckBounds=true, indicator_smooth=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -64,7 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index 62babc4c0f..a9ebdbdcaf 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -20,7 +20,6 @@ indicator_sc = IndicatorMCL(equations, basis; ConservativeLimiter=false, DensityPositivityLimiter=true, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - IDPCheckBounds=true, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -64,7 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 7cdc86483a..1c8916e3ea 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -44,7 +44,6 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, - IDPCheckBounds=true, Plotting=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -89,7 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback maxiters=1e7, callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 37ae523a4b..5bd11b1c19 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -40,8 +40,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), IDPDensityTVD=false, IDPSpecEntropy=false, - BarStates=true, - IDPCheckBounds=true) + BarStates=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -85,7 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 87f6285e95..7625b5191c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -49,7 +49,6 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, SemiDiscEntropyLimiter=true, - IDPCheckBounds=true, indicator_smooth=false, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -93,7 +92,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), 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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 635084a42b..1b376c7fe3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -46,8 +46,7 @@ indicator_sc = IndicatorIDP(equations, basis; IDPPositivity=false, IDPSpecEntropy=true, indicator_smooth=false, - BarStates=true, - IDPCheckBounds=true) + BarStates=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -90,7 +89,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callback = BoundsCheckCallback(save_errors=true) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback save_everystep=false, callback=callbacks); summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index e185874d34..0af95f187a 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -231,7 +231,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorLöhner, IndicatorLoehner, IndicatorMax, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu +export PositivityPreservingLimiterZhangShu, BoundsCheckCallback export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl new file mode 100644 index 0000000000..a97c244360 --- /dev/null +++ b/src/callbacks_stage/bounds_check.jl @@ -0,0 +1,197 @@ +# 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 + + +""" + BoundsCheckCallback(; output_directory="out", save_errors=false) + +Bounds checking routine for `IndicatorIDP` and `IndicatorMCL`. Applied as a stage callback for +SSPRK methods. +""" +struct BoundsCheckCallback + output_directory::String + save_errors::Bool +end + +function BoundsCheckCallback(; output_directory="out", save_errors=false) + BoundsCheckCallback(output_directory, save_errors) +end + +function (callback::BoundsCheckCallback)(u_ode, semi::AbstractSemidiscretization, t, iter, laststage) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + u = wrap_array(u_ode, mesh, equations, solver, cache) + + @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, t, iter, laststage, + callback.output_directory, callback.save_errors) +end + +function check_bounds(u, mesh, equations, solver, cache, t, iter, laststage, output_directory, save_errors) + check_bounds(u, mesh, equations, solver, cache, solver.volume_integral, t, iter, laststage, output_directory, save_errors) +end + +function check_bounds(u, mesh, equations, solver, cache, volume_integral::AbstractVolumeIntegral, t, iter, laststage, output_directory, save_errors) + return nothing +end + +function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralShockCapturingSubcell, + t, iter, laststage, output_directory, save_errors) + check_bounds(u, mesh, equations, solver, cache, volume_integral.indicator, t, iter, + laststage, output_directory, save_errors) +end + + +function init_callback(callback, semi) + init_callback(callback, semi, semi.solver.volume_integral) +end + +init_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing + +function init_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) + init_callback(callback, semi, volume_integral.indicator) +end + +function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) + if !callback.save_errors + return nothing + end + + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack output_directory = callback + mkpath(output_directory) + open("$output_directory/deviations.txt", "a") do f; + print(f, "# iter, simu_time") + if IDPDensityTVD + print(f, ", rho_min, rho_max"); + end + if IDPPressureTVD + print(f, ", p_min, p_max"); + end + if IDPSpecEntropy + print(f, ", specEntr_min"); + end + if IDPMathEntropy + print(f, ", mathEntr_max"); + end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + print(f, ", $(variable)_min"); + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + print(f, ", $(variable)_min"); + end + end + println(f) + end + + return nothing +end + +function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorMCL) + if !callback.save_errors + return nothing + end + + @unpack output_directory = callback + mkpath(output_directory) + open("$output_directory/deviations.txt", "a") do f; + print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in varnames(cons2cons, semi.equations))); + if indicator.PressurePositivityLimiterKuzmin + print(f, ", pressure_min") + end + # No check for entropy limiting rn + println(f) + end + + return nothing +end + + +function finalize_callback(callback, semi) + finalize_callback(callback, semi, semi.solver.volume_integral) +end + +finalize_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing + +function finalize_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) + finalize_callback(callback, semi, volume_integral.indicator) +end + + +@inline function finalize_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack idp_bounds_delta = indicator.cache + + println("─"^100) + println("Maximum deviation from bounds:") + println("─"^100) + counter = 1 + if IDPDensityTVD + println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) + counter += 2 + end + if IDPPressureTVD + println("pressure:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) + counter += 2 + end + if IDPSpecEntropy + println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) + counter += 1 + end + if IDPMathEntropy + println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) + counter += 1 + end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + counter += 1 + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + counter += 1 + end + end + println("─"^100 * "\n") + + return nothing +end + + +@inline function finalize_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorMCL) + @unpack idp_bounds_delta = indicator.cache + + println("─"^100) + println("Maximum deviation from bounds:") + println("─"^100) + variables = varnames(cons2cons, semi.equations) + for v in eachvariable(semi.equations) + println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) + end + if indicator.PressurePositivityLimiterKuzmin + println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(semi.equations)+1]) + end + println("─"^100 * "\n") + + return nothing +end + + +include("bounds_check_2d.jl") + + +end # @muladd diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl new file mode 100644 index 0000000000..ee6a4e39c4 --- /dev/null +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -0,0 +1,464 @@ +# 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 + + +@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, + time, iter, laststage, output_directory, save_errors) + @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator + @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack idp_bounds_delta = indicator.cache + + # Save the deviations every x iterations + x = 1 + + save_errors_ = save_errors && laststage && x > 0 && (iter % x == 0) + counter = 1 + if save_errors_ + open("$output_directory/deviations.txt", "a") do f; + print(f, iter, ", ", time); + end + end + if IDPDensityTVD + deviation_min = zero(eltype(u)) + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + deviation_min = max(deviation_min, var_bounds[1][i, j, element] - u[1, i, j, element]) + deviation_max = max(deviation_max, u[1, i, j, element] - var_bounds[2][i, j, element]) + end + idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) + idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) + if save_errors_ + deviation_min_ = deviation_min + deviation_max_ = deviation_max + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_, ", ", deviation_max_); + end + end + counter += 2 + end + if IDPPressureTVD + deviation_min = zero(eltype(u)) + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) + deviation_max = max(deviation_max, p - var_bounds[counter+1][i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], deviation_max) + if save_errors_ + deviation_min_ = deviation_min + deviation_max_ = deviation_max + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_, ", ", deviation_max_); + end + end + counter += 2 + end + if IDPSpecEntropy + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - s) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors_ + deviation_min_ = deviation_min + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end + end + counter += 1 + end + if IDPMathEntropy + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_max = max(deviation_max, s - var_bounds[counter][i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) + if save_errors_ + deviation_max_ = deviation_max + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_max_); + end + end + counter += 1 + end + if IDPPositivity + for variable in indicator.variables_cons + if variable == Trixi.density && IDPDensityTVD + continue + end + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + var = variable(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors_ + deviation_min_ = deviation_min + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end + end + counter += 1 + end + for variable in indicator.variables_nonlinear + if variable == pressure && IDPPressureTVD + continue + end + deviation_min = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + var = variable(get_node_vars(u, equations, solver, i, j, element), equations) + deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + if save_errors_ + deviation_min_ = deviation_min + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_); + end + end + counter += 1 + end + end + if save_errors_ + open("$output_directory/deviations.txt", "a") do f; println(f); end; + end + + return nothing +end + + +@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorMCL, + time, iter, laststage, output_directory, save_errors) + @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates + @unpack idp_bounds_delta = solver.volume_integral.indicator.cache + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + + n_vars = nvariables(equations) + + # Save the deviations every x iterations + x = 1 + + deviation_min = zeros(eltype(u), n_vars + indicator.PressurePositivityLimiterKuzmin) + deviation_max = zeros(eltype(u), n_vars) + + if indicator.DensityLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) + deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + # -y + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) + deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) + end + end + end # indicator.DensityLimiter + + if indicator.SequentialLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + for v in 2:n_vars + var_limited = u[v, i, j, element] / u[1, i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end + + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - velocities and energy (phi): + # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # -y + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) + deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + end + elseif indicator.ConservativeLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + for v in 2:n_vars + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - u[v, i, j, element]) + deviation_max[v] = max(deviation_max[v], u[v, i, j, element] - var_max[v, i, j, element]) + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end + + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - conservative variables (phi): + # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(idp_bounds_delta)) + error_pressure = zero(eltype(idp_bounds_delta)) + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + for v in 2:n_vars + var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # -y + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + for v in 2:n_vars + var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) + deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) + if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + error_pressure += 0.5 * var_limited^2 + end + end + if indicator.PressurePositivityLimiterKuzmin + error_pressure -= var_limited * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + error_pressure = zero(eltype(idp_bounds_delta)) + end + end + end + elseif indicator.PressurePositivityLimiterKuzmin + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + error_pressure = 0.5 * (bar_states1[2, i, j, element] - antidiffusive_flux1[2, i, j, element] / lambda1[i, j, element])^2 + + 0.5 * (bar_states1[3, i, j, element] - antidiffusive_flux1[3, i, j, element] / lambda1[i, j, element])^2 - + (bar_states1[4, i, j, element] - antidiffusive_flux1[4, i, j, element] / lambda1[i, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # +x + rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + error_pressure = 0.5 * (bar_states1[2, i+1, j, element] + antidiffusive_flux1[2, i+1, j, element] / lambda1[i+1, j, element])^2 + + 0.5 * (bar_states1[3, i+1, j, element] + antidiffusive_flux1[3, i+1, j, element] / lambda1[i+1, j, element])^2 - + (bar_states1[4, i+1, j, element] + antidiffusive_flux1[4, i+1, j, element] / lambda1[i+1, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # -y + rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + error_pressure = 0.5 * (bar_states2[2, i, j, element] - antidiffusive_flux2[2, i, j, element] / lambda2[i, j, element])^2 + + 0.5 * (bar_states2[3, i, j, element] - antidiffusive_flux2[3, i, j, element] / lambda2[i, j, element])^2 - + (bar_states2[4, i, j, element] - antidiffusive_flux2[4, i, j, element] / lambda2[i, j, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + # +y + rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + error_pressure = 0.5 * (bar_states2[2, i, j+1, element] + antidiffusive_flux2[2, i, j+1, element] / lambda2[i, j+1, element])^2 + + 0.5 * (bar_states2[3, i, j+1, element] + antidiffusive_flux2[3, i, j+1, element] / lambda2[i, j+1, element])^2 - + (bar_states2[4, i, j+1, element] + antidiffusive_flux2[4, i, j+1, element] / lambda2[i, j+1, element]) * rho_limited + deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) + end + end + end # indicator.PressurePositivityLimiterKuzmin + + if indicator.DensityPositivityLimiter + # New solution u^{n+1} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + deviation_min[1] = max(deviation_min[1], -u[1, i, j, element]) + end + end + + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + beta = indicator.DensityPositivityCorrelationFactor + # Checking the bounds for... + # - density (rho): + # beta * \bar{rho} <= \bar{rho}^{Lim} + for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + # -x + rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + # +x + rho_limited = (1 - beta) * bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + # -y + rho_limited = (1 - beta) * bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + # +y + rho_limited = (1 - beta) * bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] + deviation_min[1] = max(deviation_min[1], -rho_limited) + end + end + end # indicator.DensityPositivityLimiter + + for v in eachvariable(equations) + idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) + idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) + end + if indicator.PressurePositivityLimiterKuzmin + idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) + end + + if !save_errors || !laststage || x == 0 || iter % x != 0 + return nothing + end + open("$output_directory/deviations.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", deviation_min[v], ", ", deviation_max[v]); + end + if indicator.PressurePositivityLimiterKuzmin + print(f, ", ", deviation_min[n_vars+1]); + end + println(f); + end + + return nothing +end + + +end # @muladd diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index f23f96eccf..188d0047e8 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -6,6 +6,7 @@ include("positivity_zhang_shu.jl") +include("bounds_check.jl") end # @muladd diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 130523db0d..c0e0fa9770 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -44,16 +44,6 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, end -@inline function IDP_checkBounds(u_ode, semi, time, iter, laststage, output_directory) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - u = wrap_array(u_ode, mesh, equations, solver, cache) - - IDP_checkBounds(u, mesh, equations, solver, cache, solver.volume_integral.indicator, time, iter, laststage, output_directory) - - return nothing -end - - function volume_jacobian(element, mesh::TreeMesh, cache) return inv(cache.elements.inverse_jacobian[element])^ndims(mesh) end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 855246b205..4764db28f1 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1933,506 +1933,6 @@ end return nothing end -# 2d, IndicatorIDP -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorIDP, time, iter, laststage, output_directory) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator - @unpack var_bounds = solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator - @unpack idp_bounds_delta = solver.volume_integral.indicator.cache - - # Save the deviations every x iterations - x = 1 - - # Headline - if laststage && x > 0 && iter == 1 - open("$output_directory/deviations.txt", "a") do f; - print(f, "# iter, simu_time") - if IDPDensityTVD - print(f, ", rho_min, rho_max"); - end - if IDPPressureTVD - print(f, ", p_min, p_max"); - end - if IDPSpecEntropy - print(f, ", specEntr_min"); - end - if IDPMathEntropy - print(f, ", mathEntr_max"); - end - if IDPPositivity - for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD - continue - end - print(f, ", $(variable)_min"); - end - for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end - print(f, ", $(variable)_min"); - end - end - println(f) - end - end - - save_errors = laststage && x > 0 && (iter % x == 0) - counter = 1 - if save_errors - open("$output_directory/deviations.txt", "a") do f; - print(f, iter, ", ", time); - end - end - if IDPDensityTVD - deviation_min = zero(eltype(u)) - deviation_max = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - deviation_min = max(deviation_min, var_bounds[1][i, j, element] - u[1, i, j, element]) - deviation_max = max(deviation_max, u[1, i, j, element] - var_bounds[2][i, j, element]) - end - idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) - idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) - if save_errors - deviation_min_ = deviation_min - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_, ", ", deviation_max_); - end - end - counter += 2 - end - if IDPPressureTVD - deviation_min = zero(eltype(u)) - deviation_max = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) - deviation_max = max(deviation_max, p - var_bounds[counter+1][i, j, element]) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], deviation_max) - if save_errors - deviation_min_ = deviation_min - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_, ", ", deviation_max_); - end - end - counter += 2 - end - if IDPSpecEntropy - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - s) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_); - end - end - counter += 1 - end - if IDPMathEntropy - deviation_max = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_max = max(deviation_max, s - var_bounds[counter][i, j, element]) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) - if save_errors - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_max_); - end - end - counter += 1 - end - if IDPPositivity - for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD - continue - end - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - var = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_); - end - end - counter += 1 - end - for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - var = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_); - end - end - counter += 1 - end - end - if save_errors - open("$output_directory/deviations.txt", "a") do f; println(f); end; - end - - return nothing -end - -# 2d, IndicatorMCL -@inline function IDP_checkBounds(u::AbstractArray{<:Any,4}, mesh, equations, solver, cache, indicator::IndicatorMCL, time, iter, laststage, output_directory) - @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates - @unpack idp_bounds_delta = solver.volume_integral.indicator.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - - n_vars = nvariables(equations) - vars = varnames(cons2cons, equations) - - # Save the deviations every x iterations - x = 1 - - # Headline - if laststage && x > 0 && iter == 1 - open("$output_directory/deviations.txt", "a") do f; - print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in vars)); - if indicator.PressurePositivityLimiterKuzmin - print(f, ", pressure_min") - end - println(f) - end - end - - deviation_min = zeros(eltype(u), n_vars + indicator.PressurePositivityLimiterKuzmin) - deviation_max = zeros(eltype(u), n_vars) - - if indicator.DensityLimiter - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - u[1, i, j, element]) - deviation_max[1] = max(deviation_max[1], u[1, i, j, element] - var_max[1, i, j, element]) - end - end - - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - density (rho): - # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - # -x - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - # +x - rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - # -y - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - # +y - rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] - deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], rho_limited - var_max[1, i, j, element]) - end - end - end # indicator.DensityLimiter - - if indicator.SequentialLimiter - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - for v in 2:n_vars - var_limited = u[v, i, j, element] / u[1, i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - end - end - end - - - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - velocities and energy (phi): - # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - # -x - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # +x - rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] - for v in 2:n_vars - var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # -y - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # +y - rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] - for v in 2:n_vars - var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - end - end - elseif indicator.ConservativeLimiter - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - for v in 2:n_vars - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - u[v, i, j, element]) - deviation_max[v] = max(deviation_max[v], u[v, i, j, element] - var_max[v, i, j, element]) - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - end - end - end - - - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - conservative variables (phi): - # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - # -x - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - for v in 2:n_vars - var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # +x - rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] - for v in 2:n_vars - var_limited = bar_states1[v, i+1, j, element] + antidiffusive_flux1[v, i+1, j, element] / lambda1[i+1, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # -y - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - for v in 2:n_vars - var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - # +y - rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] - for v in 2:n_vars - var_limited = bar_states2[v, i, j+1, element] + antidiffusive_flux2[v, i, j+1, element] / lambda2[i, j+1, element] - deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) - error_pressure += 0.5 * var_limited^2 - end - end - if indicator.PressurePositivityLimiterKuzmin - error_pressure -= var_limited * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) - end - end - end - elseif indicator.PressurePositivityLimiterKuzmin - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - end - end - - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - # -x - rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - error_pressure = 0.5 * (bar_states1[2, i, j, element] - antidiffusive_flux1[2, i, j, element] / lambda1[i, j, element])^2 + - 0.5 * (bar_states1[3, i, j, element] - antidiffusive_flux1[3, i, j, element] / lambda1[i, j, element])^2 - - (bar_states1[4, i, j, element] - antidiffusive_flux1[4, i, j, element] / lambda1[i, j, element]) * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - # +x - rho_limited = bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] - error_pressure = 0.5 * (bar_states1[2, i+1, j, element] + antidiffusive_flux1[2, i+1, j, element] / lambda1[i+1, j, element])^2 + - 0.5 * (bar_states1[3, i+1, j, element] + antidiffusive_flux1[3, i+1, j, element] / lambda1[i+1, j, element])^2 - - (bar_states1[4, i+1, j, element] + antidiffusive_flux1[4, i+1, j, element] / lambda1[i+1, j, element]) * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - # -y - rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - error_pressure = 0.5 * (bar_states2[2, i, j, element] - antidiffusive_flux2[2, i, j, element] / lambda2[i, j, element])^2 + - 0.5 * (bar_states2[3, i, j, element] - antidiffusive_flux2[3, i, j, element] / lambda2[i, j, element])^2 - - (bar_states2[4, i, j, element] - antidiffusive_flux2[4, i, j, element] / lambda2[i, j, element]) * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - # +y - rho_limited = bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] - error_pressure = 0.5 * (bar_states2[2, i, j+1, element] + antidiffusive_flux2[2, i, j+1, element] / lambda2[i, j+1, element])^2 + - 0.5 * (bar_states2[3, i, j+1, element] + antidiffusive_flux2[3, i, j+1, element] / lambda2[i, j+1, element])^2 - - (bar_states2[4, i, j+1, element] + antidiffusive_flux2[4, i, j+1, element] / lambda2[i, j+1, element]) * rho_limited - deviation_min[n_vars+1] = max(deviation_min[n_vars+1], error_pressure) - end - end - end # indicator.PressurePositivityLimiterKuzmin - - if indicator.DensityPositivityLimiter - # New solution u^{n+1} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], -u[1, i, j, element]) - end - end - - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - beta = indicator.DensityPositivityCorrelationFactor - # Checking the bounds for... - # - density (rho): - # beta * \bar{rho} <= \bar{rho}^{Lim} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - # -x - rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) - # +x - rho_limited = (1 - beta) * bar_states1[1, i+1, j, element] + antidiffusive_flux1[1, i+1, j, element] / lambda1[i+1, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) - # -y - rho_limited = (1 - beta) * bar_states2[1, i, j, element] - antidiffusive_flux2[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) - # +y - rho_limited = (1 - beta) * bar_states2[1, i, j+1, element] + antidiffusive_flux2[1, i, j+1, element] / lambda2[i, j+1, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) - end - end - end # indicator.DensityPositivityLimiter - - for v in eachvariable(equations) - idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) - idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) - end - if indicator.PressurePositivityLimiterKuzmin - idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) - end - - if !laststage || x == 0 || iter % x != 0 - return nothing - end - open("$output_directory/deviations.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", deviation_min[v], ", ", deviation_max[v]); - end - if indicator.PressurePositivityLimiterKuzmin - print(f, ", ", deviation_min[n_vars+1]); - end - println(f); - end - - return nothing -end - # We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 72e7211325..980ba2d417 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -245,7 +245,6 @@ struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonline newton_tol::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method IDPgamma::RealT # Constant for the subcell limiting of convex (nonlinear) constraints # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) - IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator @@ -263,7 +262,6 @@ function IndicatorIDP(equations::AbstractEquations, basis; BarStates=true, positCorrFactor=0.1, IDPMaxIter=10, newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), - IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure) if IDPMathEntropy && IDPSpecEntropy @@ -289,10 +287,9 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positCorrFactor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(IDPDensityTVD, IDPPressureTVD, - IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, BarStates, - cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, IDPCheckBounds, - indicator_smooth, thr_smooth, IndicatorHG) + IndicatorIDP{typeof(positCorrFactor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( + IDPDensityTVD, IDPPressureTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, + BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, indicator_smooth, thr_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -372,7 +369,6 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator DensityPositivityLimiter::Bool DensityPositivityCorrelationFactor::RealT SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix - IDPCheckBounds::Bool indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner thr_smooth::RealT # threshold for smoothness indicator IndicatorHG::Indicator @@ -390,7 +386,6 @@ function IndicatorMCL(equations::AbstractEquations, basis; DensityPositivityLimiter=false, # Impose positivity for cons(1) DensityPositivityCorrelationFactor=0.0,# Correlation Factor for DensityPositivityLimiter in [0,1) SemiDiscEntropyLimiter=false, - IDPCheckBounds=false, indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, Plotting=true) if SequentialLimiter && ConservativeLimiter @@ -407,7 +402,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, DensityPositivityCorrelationFactor, SemiDiscEntropyLimiter, - IDPCheckBounds, indicator_smooth, thr_smooth, IndicatorHG, Plotting) + indicator_smooth, thr_smooth, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 138bfebd43..8a9d132be6 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -18,12 +18,13 @@ The third-order SSP Runge-Kutta method of !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct SimpleSSPRK33 <: SimpleAlgorithmSSP +struct SimpleSSPRK33{StageCallback} <: SimpleAlgorithmSSP a::SVector{3, Float64} b::SVector{3, Float64} c::SVector{3, Float64} + stage_callback::StageCallback - function SimpleSSPRK33() + function SimpleSSPRK33(; stage_callback=nothing) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -36,7 +37,7 @@ struct SimpleSSPRK33 <: SimpleAlgorithmSSP # -------------------- # b | 1/6 1/6 2/3 - new(a, b, c) + new{typeof(stage_callback)}(a, b, c, stage_callback) end end @@ -118,6 +119,10 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, error("unsupported") end + if alg.stage_callback !== nothing + init_callback(alg.stage_callback, integrator.p) + end + solve!(integrator) end @@ -178,10 +183,9 @@ function solve!(integrator::SimpleIntegratorSSP) @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) - # check that we are within bounds - if indicator.IDPCheckBounds + if alg.stage_callback !== nothing laststage = (stage == length(alg.c)) - @trixi_timeit timer() "IDP_checkBounds" IDP_checkBounds(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage, output_directory) + alg.stage_callback(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage) end # perform convex combination @@ -209,9 +213,8 @@ function solve!(integrator::SimpleIntegratorSSP) end end - # Check that we are within bounds - if indicator.IDPCheckBounds - summary_check_bounds(indicator, integrator.p.equations) + if alg.stage_callback !== nothing + finalize_callback(alg.stage_callback, integrator.p) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), @@ -298,69 +301,5 @@ function calc_normal_directions!(ContainerBarStates, mesh::StructuredMesh, equat return nothing end -# check deviation from boundaries of IDP indicator -@inline function summary_check_bounds(indicator::IndicatorIDP, equations::CompressibleEulerEquations2D) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator - @unpack idp_bounds_delta = indicator.cache - - println("─"^100) - println("Maximum deviation from bounds:") - println("─"^100) - counter = 1 - if IDPDensityTVD - println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) - counter += 2 - end - if IDPPressureTVD - println("pressure:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) - counter += 2 - end - if IDPSpecEntropy - println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) - counter += 1 - end - if IDPMathEntropy - println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) - counter += 1 - end - if IDPPositivity - for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD - continue - end - println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 - end - for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end - println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 - end - end - println("─"^100 * "\n") - - return nothing -end - -# check deviation from boundaries of IndicatorMCL -@inline function summary_check_bounds(indicator::IndicatorMCL, equations::CompressibleEulerEquations2D) - @unpack idp_bounds_delta = indicator.cache - - println("─"^100) - println("Maximum deviation from bounds:") - println("─"^100) - variables = varnames(cons2cons, equations) - for v in eachvariable(equations) - println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) - end - if indicator.PressurePositivityLimiterKuzmin - println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(equations)+1]) - end - println("─"^100 * "\n") - - return nothing -end end # @muladd From 8964ea049a86417edaf27fe62380a09da23f0a1d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 25 May 2023 17:21:36 +0200 Subject: [PATCH 189/423] Add `interval` to BoundsCheckCallback --- src/callbacks_stage/bounds_check.jl | 30 +++++++++++++++----------- src/callbacks_stage/bounds_check_2d.jl | 14 ++++-------- src/time_integration/methods_SSP.jl | 7 +++++- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index a97c244360..bd1f323afc 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -6,40 +6,44 @@ """ - BoundsCheckCallback(; output_directory="out", save_errors=false) + BoundsCheckCallback(; output_directory="out", save_errors=false, interval=0) Bounds checking routine for `IndicatorIDP` and `IndicatorMCL`. Applied as a stage callback for -SSPRK methods. +SSPRK methods. If `save_errors` is `true`, the resulting deviations are saved in +`output_directory/deviations.txt` for every `interval` time steps. """ struct BoundsCheckCallback output_directory::String save_errors::Bool + interval::Int end -function BoundsCheckCallback(; output_directory="out", save_errors=false) - BoundsCheckCallback(output_directory, save_errors) +function BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) + BoundsCheckCallback(output_directory, save_errors, interval) end function (callback::BoundsCheckCallback)(u_ode, semi::AbstractSemidiscretization, t, iter, laststage) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, t, iter, laststage, - callback.output_directory, callback.save_errors) + @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, t, iter, + callback.output_directory, min(callback.save_errors, callback.interval > 0, laststage), callback.interval) end -function check_bounds(u, mesh, equations, solver, cache, t, iter, laststage, output_directory, save_errors) - check_bounds(u, mesh, equations, solver, cache, solver.volume_integral, t, iter, laststage, output_directory, save_errors) +function check_bounds(u, mesh, equations, solver, cache, t, iter, output_directory, save_errors, interval) + check_bounds(u, mesh, equations, solver, cache, solver.volume_integral, t, iter, + output_directory, save_errors, interval) end -function check_bounds(u, mesh, equations, solver, cache, volume_integral::AbstractVolumeIntegral, t, iter, laststage, output_directory, save_errors) +function check_bounds(u, mesh, equations, solver, cache, volume_integral::AbstractVolumeIntegral, + t, iter, output_directory, save_errors, interval) return nothing end function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralShockCapturingSubcell, - t, iter, laststage, output_directory, save_errors) + t, iter, output_directory, save_errors, interval) check_bounds(u, mesh, equations, solver, cache, volume_integral.indicator, t, iter, - laststage, output_directory, save_errors) + output_directory, save_errors, interval) end @@ -54,7 +58,7 @@ function init_callback(callback, semi, volume_integral::VolumeIntegralShockCaptu end function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) - if !callback.save_errors + if !callback.save_errors || (callback.interval == 0) return nothing end @@ -96,7 +100,7 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator end function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorMCL) - if !callback.save_errors + if !callback.save_errors || (callback.interval == 0) return nothing end diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index ee6a4e39c4..4137110d93 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -6,15 +6,12 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, - time, iter, laststage, output_directory, save_errors) + time, iter, output_directory, save_errors, interval) @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta = indicator.cache - # Save the deviations every x iterations - x = 1 - - save_errors_ = save_errors && laststage && x > 0 && (iter % x == 0) + save_errors_ = save_errors && (iter % interval == 0) counter = 1 if save_errors_ open("$output_directory/deviations.txt", "a") do f; @@ -135,7 +132,7 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorMCL, - time, iter, laststage, output_directory, save_errors) + time, iter, output_directory, save_errors, interval) @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @@ -143,9 +140,6 @@ end n_vars = nvariables(equations) - # Save the deviations every x iterations - x = 1 - deviation_min = zeros(eltype(u), n_vars + indicator.PressurePositivityLimiterKuzmin) deviation_max = zeros(eltype(u), n_vars) @@ -443,7 +437,7 @@ end idp_bounds_delta[1, n_vars+1] = max(idp_bounds_delta[1, n_vars+1], deviation_min[n_vars+1]) end - if !save_errors || !laststage || x == 0 || iter % x != 0 + if !save_errors || (iter % interval != 0) return nothing end open("$output_directory/deviations.txt", "a") do f; diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 8a9d132be6..234a88a80d 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -153,7 +153,6 @@ function solve!(integrator::SimpleIntegratorSSP) end # Reset alphas for MCL - @unpack indicator = integrator.p.solver.volume_integral if indicator isa IndicatorMCL && indicator.Plotting @unpack alpha, alpha_pressure, alpha_entropy = indicator.cache.ContainerShockCapturingIndicator @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) @@ -250,6 +249,12 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) end function Base.resize!(semi::AbstractSemidiscretization, new_size) + resize!(semi, semi.solver.volume_integral, new_size) +end + +Base.resize!(semi, volume_integral::AbstractVolumeIntegral, new_size) = nothing + +function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell, new_size) # Resize ContainerAntidiffusiveFlux2D resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) From d8d6b61e04d969104de602fcdab71798cfcca5c6 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 26 May 2023 12:48:13 +0200 Subject: [PATCH 190/423] Fix tests --- test/test_tree_2d_euler.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 9a57ced219..fdd99c5a5b 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], - linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], + l2 = [0.2920740202472987, 0.17319888877770634, 0.17324651746054556, 0.6147097239293716], + linf = [1.2348538441211816, 1.017995438469672, 1.0181613013382826, 2.4268315882109], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From c55aa7bf327debf79590a3d301fe8c62d7a77477 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 26 May 2023 18:02:30 +0200 Subject: [PATCH 191/423] Prepare stage callbacks infrastructure for Tuples --- src/callbacks_step/amr.jl | 6 ------ src/time_integration/methods_SSP.jl | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 423881fe05..4655a0b9ef 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -125,12 +125,6 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u, t, integrator) amr_callback = cb.affect! semi = integrator.p - if integrator isa SimpleIntegratorSSP - println("WARNING: The TVD property of IDP-FV-DG subcell blending shock-capturing methods is not - guaranteed when using a non-conforming mesh (i.e. with AMR). Many operations are not implemented - for AMR yet.\n") - end - @trixi_timeit timer() "initial condition AMR" if amr_callback.adapt_initial_condition # iterate until mesh does not change anymore has_changed = amr_callback(integrator, diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 234a88a80d..57349fe2af 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -18,13 +18,13 @@ The third-order SSP Runge-Kutta method of !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct SimpleSSPRK33{StageCallback} <: SimpleAlgorithmSSP +struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP a::SVector{3, Float64} b::SVector{3, Float64} c::SVector{3, Float64} - stage_callback::StageCallback + stage_callbacks::StageCallbacks - function SimpleSSPRK33(; stage_callback=nothing) + function SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -37,7 +37,7 @@ struct SimpleSSPRK33{StageCallback} <: SimpleAlgorithmSSP # -------------------- # b | 1/6 1/6 2/3 - new{typeof(stage_callback)}(a, b, c, stage_callback) + new{typeof(stage_callbacks)}(a, b, c, stage_callbacks) end end @@ -119,8 +119,8 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, error("unsupported") end - if alg.stage_callback !== nothing - init_callback(alg.stage_callback, integrator.p) + for stage_callback in alg.stage_callbacks + init_callback(stage_callback, integrator.p) end solve!(integrator) @@ -182,9 +182,9 @@ function solve!(integrator::SimpleIntegratorSSP) @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) - if alg.stage_callback !== nothing + for stage_callback in alg.stage_callbacks laststage = (stage == length(alg.c)) - alg.stage_callback(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage) + stage_callback(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage) end # perform convex combination @@ -212,8 +212,8 @@ function solve!(integrator::SimpleIntegratorSSP) end end - if alg.stage_callback !== nothing - finalize_callback(alg.stage_callback, integrator.p) + for stage_callback in alg.stage_callbacks + finalize_callback(stage_callback, integrator.p) end return TimeIntegratorSolution((first(prob.tspan), integrator.t), From 64171956261102eb008664cfdb028d46f035ae83 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 28 May 2023 10:50:25 +0200 Subject: [PATCH 192/423] Fix last commit --- src/time_integration/methods_SSP.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 57349fe2af..918031e046 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -24,7 +24,7 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP c::SVector{3, Float64} stage_callbacks::StageCallbacks - function SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) + function SimpleSSPRK33(; stage_callbacks=()) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) From f70ee68015e6c538ea16fa04fcbfb185e871372b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sun, 28 May 2023 10:58:23 +0200 Subject: [PATCH 193/423] Adapt elixirs to new structure --- .../elixir_euler_convergence_wavingflag_IDP.jl | 4 ++-- .../elixir_euler_convergence_wavingflag_MCL.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_double_mach.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl | 4 ++-- .../elixir_euler_free_stream_sc_subcell.jl | 4 ++-- .../structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl | 4 ++-- .../elixir_euler_shock_upstream_sc_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl | 5 +++-- examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl | 4 +++- examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl | 4 ++-- .../elixir_euler_kelvin_helmholtz_instability_MCL.jl | 4 ++-- .../elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl | 4 ++-- .../elixir_euler_sedov_blast_wave_sc_subcell.jl | 4 ++-- 18 files changed, 38 insertions(+), 35 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 180ef30fc4..1836c2b73d 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -68,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index 2604dd7800..598f7529bf 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -68,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 4fa9a2bbe7..5309574999 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -139,9 +139,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 8ce4ed73ed..2b8b2fe8f7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -143,9 +143,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index d1395c31bb..1a0296db17 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -84,9 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index e510cc8a7e..10d6743d6b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -83,9 +83,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 3eaec337d7..37f5d6d91c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -133,9 +133,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 604be7dac4..1d88d71a6f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -130,9 +130,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 054fb9ac29..6fed8ae11d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -91,9 +91,10 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +stage_callbacks = (BoundsCheckCallback(save_errors=true),) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 2419623a75..42c5b13db8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -88,9 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 6d02a42dd1..999e79b6ac 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -85,9 +85,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 58423b5501..3f8a894a45 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -88,7 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode; +stage_callbacks = (BoundsCheckCallback(save_errors=true),) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 33608f6cc8..facfae3169 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -63,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index a9ebdbdcaf..cda56dca07 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -63,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 1c8916e3ea..b333436a98 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -88,9 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback maxiters=1e7, callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 5bd11b1c19..f89ba88c09 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -84,9 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 7625b5191c..4ad228010f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -92,9 +92,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 1b376c7fe3..818999a012 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -89,9 +89,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callback = BoundsCheckCallback(save_errors=true) +stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callback=stage_callback), +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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 From 679274aadd6dadc70c132ea415dfb3f9ce6524d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 30 May 2023 08:56:22 +0200 Subject: [PATCH 194/423] Adapt last elixirs --- .../elixir_euler_source_terms_sc_subcell.jl | 4 +++- .../tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 1e9c8f9bac..4838b88f22 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -66,7 +66,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callbacks = (BoundsCheckCallback(save_errors=true),) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index dc4fd7733e..355f548ba8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -60,7 +60,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = Trixi.solve(ode, +stage_callbacks = (BoundsCheckCallback(save_errors=true),) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), 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 From d72dcdb418dc1412f4d6d0124891e967cd72b046 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 30 May 2023 09:02:09 +0200 Subject: [PATCH 195/423] Shorten code --- src/time_integration/methods_SSP.jl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 918031e046..7f1a04b11f 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -259,19 +259,16 @@ function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) # Resize ContainerShockCapturingIndicator - resize!(semi.solver.volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) + resize!(volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) # Calc subcell normal directions before StepsizeCallback - @unpack indicator = semi.solver.volume_integral + @unpack indicator = volume_integral if indicator isa IndicatorMCL || (indicator isa IndicatorIDP && indicator.BarStates) - resize!(semi.solver.volume_integral.indicator.cache.ContainerBarStates, new_size) + resize!(indicator.cache.ContainerBarStates, new_size) calc_normal_directions!(indicator.cache.ContainerBarStates, mesh_equations_solver_cache(semi)...) end end -function calc_normal_directions!(ContainerBarStates, mesh::TreeMesh, equations, dg, cache) - - return nothing -end +calc_normal_directions!(ContainerBarStates, mesh::TreeMesh, equations, dg, cache) = nothing function calc_normal_directions!(ContainerBarStates, mesh::StructuredMesh, equations, dg, cache) @unpack weights, derivative_matrix = dg.basis From 85bca5ce737dce2e359c723de3f98988bbe33901 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 30 May 2023 09:06:28 +0200 Subject: [PATCH 196/423] Implement antidiffusive stage as stage callback --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- src/Trixi.jl | 2 +- src/callbacks_stage/antidiffusive_stage.jl | 77 +++++++++++++++++++ src/callbacks_stage/bounds_check.jl | 2 +- src/callbacks_stage/callbacks_stage.jl | 1 + src/solvers/dgsem_tree/dg_2d.jl | 49 ------------ src/time_integration/methods_SSP.jl | 3 +- 17 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 src/callbacks_stage/antidiffusive_stage.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 1836c2b73d..ce19d5594a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -68,7 +68,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 5309574999..e4580fcd5a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 10d6743d6b..853641a577 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -83,7 +83,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 1d88d71a6f..05e1e03678 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -130,7 +130,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 4838b88f22..2b08f7d4e2 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -66,7 +66,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 42c5b13db8..bc93be4feb 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -88,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 3f8a894a45..0fc986f8ad 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -88,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index facfae3169..82e2d4729e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -63,7 +63,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index f89ba88c09..c4a91eba13 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 818999a012..42f894c39a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 355f548ba8..fcff16c5bc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -60,7 +60,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/Trixi.jl b/src/Trixi.jl index d3fbdba8bc..467fc90ee4 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -234,7 +234,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorLöhner, IndicatorLoehner, IndicatorMax, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu, BoundsCheckCallback +export PositivityPreservingLimiterZhangShu, AntidiffusiveStage, BoundsCheckCallback export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl new file mode 100644 index 0000000000..3379412b3f --- /dev/null +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -0,0 +1,77 @@ +# 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 + + +""" + AntidiffusiveStage() + +Perform antidiffusive stage for IDP limiting. +""" +struct AntidiffusiveStage end + +function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi::AbstractSemidiscretization, t, dt, iter, laststage) + + antidiffusive_stage!(u_ode, semi, t, dt, semi.solver.volume_integral) +end + +(::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing + +function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::VolumeIntegralShockCapturingSubcell) + + @trixi_timeit timer() "antidiffusive_stage!" antidiffusive_stage!(u_ode, semi, t, dt, volume_integral.indicator) +end + +(::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorMCL) = nothing + +function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorIDP) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + + u = wrap_array(u_ode, mesh, equations, solver, cache) + + @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) + + perform_IDP_correction(u, dt, mesh, equations, solver, cache) + + return nothing +end + +@inline function perform_IDP_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + if dg.volume_integral.indicator.indicator_smooth + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end + + # Loop over blended DG-FV elements + @threaded for element in elements + inverse_jacobian = -cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) + end + end + end + + return nothing +end + +init_callback(callback::AntidiffusiveStage, semi) = nothing + +finalize_callback(antidiffusive_stage!::AntidiffusiveStage, semi) = nothing + + +end # @muladd diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index bd1f323afc..5141c07a7e 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -22,7 +22,7 @@ function BoundsCheckCallback(; output_directory="out", save_errors=false, interv BoundsCheckCallback(output_directory, save_errors, interval) end -function (callback::BoundsCheckCallback)(u_ode, semi::AbstractSemidiscretization, t, iter, laststage) +function (callback::BoundsCheckCallback)(u_ode, semi::AbstractSemidiscretization, t, dt, iter, laststage) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 188d0047e8..7c829a98c5 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -6,6 +6,7 @@ include("positivity_zhang_shu.jl") +include("antidiffusive_stage.jl") include("bounds_check.jl") diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4764db28f1..71c6df5593 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1885,55 +1885,6 @@ end end -@inline function antidiffusive_stage!(u_ode, t, dt, semi, indicator::IndicatorIDP) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - - u = wrap_array(u_ode, mesh, equations, solver, cache) - - @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) - - perform_IDP_correction(u, dt, mesh, equations, solver, cache) - - return nothing -end - -@inline function perform_IDP_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator - if dg.volume_integral.indicator.indicator_smooth - elements = cache.element_ids_dgfv - else - elements = eachelement(dg, cache) - end - - # Loop over blended DG-FV elements - @threaded for element in elements - inverse_jacobian = -cache.elements.inverse_jacobian[element] - - for j in eachnode(dg), i in eachnode(dg) - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) - end - end - end - - return nothing -end - -@inline function antidiffusive_stage!(u_ode, t, dt, semi, indicator::IndicatorMCL) - - return nothing -end - - # We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 7f1a04b11f..13187786b0 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -178,13 +178,12 @@ function solve!(integrator::SimpleIntegratorSSP) # perform forward Euler step @. integrator.u = integrator.u + integrator.dt * integrator.du end - @trixi_timeit timer() "Antidiffusive stage" antidiffusive_stage!(integrator.u, t_stage, integrator.dt, integrator.p, indicator) @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) for stage_callback in alg.stage_callbacks laststage = (stage == length(alg.c)) - stage_callback(integrator.u, integrator.p, integrator.t, integrator.iter+1, laststage) + stage_callback(integrator.u, integrator.p, integrator.t, integrator.dt, integrator.iter+1, laststage) end # perform convex combination From cba64ed558d089ed67cfcad0d83b70a19754374d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 11:50:35 +0200 Subject: [PATCH 197/423] Add MCL tests --- .../elixir_euler_blast_wave_MCL.jl | 15 +++++--- test/test_tree_2d_euler.jl | 36 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 73fde7b6dd..b81c788a85 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,9 +39,16 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorMCL(equations, basis; - IDPCheckBounds=true, - IDPPressure=false, - Plotting=true) + DensityLimiter=true, + DensityAlphaForAll=true, + SequentialLimiter=false, + ConservativeLimiter=true, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=false, + SemiDiscEntropyLimiter=true, + IDPCheckBounds=false, + indicator_smooth=true, + Plotting=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -75,7 +82,7 @@ save_solution = SaveSolutionCallback(interval=500, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index fdd99c5a5b..85b94212c4 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -132,6 +132,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_blast_wave_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_MCL.jl"), + l2 = [0.32716628280821736, 0.17711362716405113, 0.17710881738119433, 0.6192141753914343], + linf = [1.3147680231795071, 1.1313232952582144, 1.1308868661560831, 2.4962119219206], + tspan = (0.0, 0.5), + initial_refinement_level = 4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), l2 = [0.4866953770742574, 0.1673477470091984, 0.16734774700934, 0.6184367248923149], @@ -149,6 +158,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_MCL.jl"), + l2 = [0.4740321851943766, 0.15889871334104985, 0.15889871334104988, 0.6190405536267991], + linf = [4.011954283668753, 1.8527131099524292, 1.8527131099524277, 6.465833729130187], + tspan = (0.0, 1.0), + initial_refinement_level=4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), l2 = [0.0845430093623868, 0.09271459184623232, 0.09271459184623232, 0.4377291875101709], @@ -212,6 +230,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=2,)) end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_MCL.jl"), + l2 = [0.055703165296633834, 0.032987233605927, 0.05224472051711956, 0.08011565264331237], + linf = [0.24091018397460595, 0.1660190071332282, 0.12356154893467916, 0.2695167937393226], + tspan = (0.0, 0.2), + initial_refinement_level=5, + coverage_override = (maxiters=2,)) + end + @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), # This stuff is experimental and annoying to test. In the future, we plan @@ -255,6 +282,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_astro_jet_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_MCL.jl"), + l2 = [0.4142490642847159, 339.10045752248817, 12.41716316125269, 134277.32794840127], + linf = [5.649893737038036, 4628.887032664001, 373.39317079274724, 1.8133961097673306e6], + initial_refinement_level=5, + tspan = (0.0, 1.0e-4), + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), l2 = [0.00013492249515826863, 0.006615696236378061, 0.006782108219800376, 0.016393831451740604], From ad7682e830fd0a99f880f2676c0f74f1da359452 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 12:44:17 +0200 Subject: [PATCH 198/423] Fix test --- test/test_tree_2d_euler.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 85b94212c4..354898e0b5 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.2920740202472987, 0.17319888877770634, 0.17324651746054556, 0.6147097239293716], - linf = [1.2348538441211816, 1.017995438469672, 1.0181613013382826, 2.4268315882109], + l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], + linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From 125cc7ef7ee5ffb38f33c3477f18767882dffb81 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 12:53:37 +0200 Subject: [PATCH 199/423] Remove parameter from elixir --- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 3 +-- test/test_tree_2d_euler.jl | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 5e958e9a11..59576726c4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -46,7 +46,6 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=false, SemiDiscEntropyLimiter=true, - IDPCheckBounds=false, indicator_smooth=true, Plotting=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -93,7 +92,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 85b94212c4..354898e0b5 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.2920740202472987, 0.17319888877770634, 0.17324651746054556, 0.6147097239293716], - linf = [1.2348538441211816, 1.017995438469672, 1.0181613013382826, 2.4268315882109], + l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], + linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From d467f6f042ce5b7f9ee02e06c88dc7d7da8d2206 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 12:55:25 +0200 Subject: [PATCH 200/423] Merge subcell-limiting-bounds-check into branch `subcell-limiting-antidiff-stage` --- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 3 +-- test/test_tree_2d_euler.jl | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 5e958e9a11..59576726c4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -46,7 +46,6 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=false, SemiDiscEntropyLimiter=true, - IDPCheckBounds=false, indicator_smooth=true, Plotting=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; @@ -93,7 +92,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 85b94212c4..354898e0b5 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.2920740202472987, 0.17319888877770634, 0.17324651746054556, 0.6147097239293716], - linf = [1.2348538441211816, 1.017995438469672, 1.0181613013382826, 2.4268315882109], + l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], + linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From 6da2febdbd020e23bd4c9f5d12b163a0407335b1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 13:52:53 +0200 Subject: [PATCH 201/423] Reduce parameters for stage callbacks --- src/callbacks_stage/antidiffusive_stage.jl | 4 ++-- src/callbacks_stage/bounds_check.jl | 10 ++++++---- src/time_integration/methods_SSP.jl | 5 ++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl index 3379412b3f..e1550b77b5 100644 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -12,9 +12,9 @@ Perform antidiffusive stage for IDP limiting. """ struct AntidiffusiveStage end -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi::AbstractSemidiscretization, t, dt, iter, laststage) +function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, integrator, stage) - antidiffusive_stage!(u_ode, semi, t, dt, semi.solver.volume_integral) + antidiffusive_stage!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) end (::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 5141c07a7e..6cc35ae562 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -22,12 +22,14 @@ function BoundsCheckCallback(; output_directory="out", save_errors=false, interv BoundsCheckCallback(output_directory, save_errors, interval) end -function (callback::BoundsCheckCallback)(u_ode, semi::AbstractSemidiscretization, t, dt, iter, laststage) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) +function (callback::BoundsCheckCallback)(u_ode, integrator, stage) + mesh, equations, solver, cache = mesh_equations_solver_cache(integrator.p) + @unpack t, iter, alg = integrator u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, t, iter, - callback.output_directory, min(callback.save_errors, callback.interval > 0, laststage), callback.interval) + save_errors_ = callback.save_errors && (callback.interval > 0) && (stage == length(alg.c)) + @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, t, iter+1, + callback.output_directory, save_errors_, callback.interval) end function check_bounds(u, mesh, equations, solver, cache, t, iter, output_directory, save_errors, interval) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 13187786b0..32c3f44e6a 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -24,7 +24,7 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP c::SVector{3, Float64} stage_callbacks::StageCallbacks - function SimpleSSPRK33(; stage_callbacks=()) + function SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -182,8 +182,7 @@ function solve!(integrator::SimpleIntegratorSSP) @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) for stage_callback in alg.stage_callbacks - laststage = (stage == length(alg.c)) - stage_callback(integrator.u, integrator.p, integrator.t, integrator.dt, integrator.iter+1, laststage) + stage_callback(integrator.u, integrator, stage) end # perform convex combination From 41012ca409c79fb77357b8a7df85b54adb467bc1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 18:16:56 +0200 Subject: [PATCH 202/423] Add MultiComponent Euler elixir --- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 147 ++++++++++++++++++ src/solvers/dgsem_tree/dg_2d.jl | 12 +- test/test_tree_2d_eulermulti.jl | 8 + 3 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl new file mode 100644 index 0000000000..82f1b0f12c --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -0,0 +1,147 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler multicomponent equations + +# 1) Dry Air 2) Helium + 28% Air +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), + gas_constants = (0.287, 1.578)) + +""" + initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + +A shock-bubble testcase for multicomponent Euler equations +- Ayoub Gouasmi, Karthik Duraisamy, Scott Murman + Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations + [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) +""" +function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225-delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +end +initial_condition = initial_condition_shock_bubble + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +density1(u, equations::CompressibleEulerMulticomponentEquations2D) = u[1+3] +density2(u, equations::CompressibleEulerMulticomponentEquations2D) = u[2+3] + +indicator_sc = IndicatorIDP(equations, basis; + IDPPositivity=true, + variables_cons=(density1, density2), + variables_nonlinear=(), positCorrFactor=0.1, + IDPDensityTVD=false, + IDPSpecEntropy=false, + BarStates=true) + +volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.25, -2.225) +coordinates_max = ( 2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(Trixi.density,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=300, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) + +sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), + 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 \ No newline at end of file diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 71c6df5593..14a1225f82 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1193,12 +1193,6 @@ end @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates - # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. - # To avoid further calculations with these values, we replace them by 0. - # It can also happen that the limited flux changes its sign (for instance to -1e-13). - # This does not really make sense in theory and causes problems for the visualization. - # Therefore we make sure that the flux keeps its sign during limiting. - if indicator.Plotting # TODO: Allocations!!! P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) @@ -1212,6 +1206,12 @@ end end end + # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. + # To avoid further calculations with these values, we replace them by 0. + # It can also happen that the limited flux changes its sign (for instance to -1e-13). + # This does not really make sense in theory and causes problems for the visualization. + # Therefore we make sure that the flux keeps its sign during limiting. + # Density limiter if indicator.DensityLimiter for j in eachnode(dg), i in 2:nnodes(dg) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 800dc31f84..6314e3e438 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -19,6 +19,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.001)) end + @trixi_testset "elixir_eulermulti_shock_bubble_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_sc_subcell.jl"), + l2 = [81.56638995751949, 2.749019198753295, 63209.842984371186, 0.1998094346294924, 0.011196332311231447], + linf = [251.3015423089727, 43.842039180642644, 174650.87707064365, 0.7041466370660441, 0.11584512034319161], + initial_refinement_level = 3, + tspan = (0.0, 0.001)) + end + @trixi_testset "elixir_eulermulti_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), l2 = [0.050182236154087095, 0.050189894464434635, 0.2258715597305131, 0.06175171559771687], From 4e0892a87ccbece7c107298a57dff454924a6ad1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 18:28:35 +0200 Subject: [PATCH 203/423] Delete "effictive" alpha --- src/solvers/dgsem_structured/indicators_2d.jl | 15 +--- src/solvers/dgsem_tree/containers_2d.jl | 17 ++--- src/solvers/dgsem_tree/dg_2d.jl | 68 ------------------- src/solvers/dgsem_tree/indicators.jl | 6 -- src/solvers/dgsem_tree/indicators_2d.jl | 15 +--- 5 files changed, 6 insertions(+), 115 deletions(-) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 8da3184230..e435c146ff 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -253,7 +253,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 @@ -279,9 +279,6 @@ end end println(f) end - open("$output_directory/alphas_eff.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end end if iter % x != 0 @@ -290,7 +287,6 @@ end alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), n_vars) - alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) @@ -298,7 +294,6 @@ end for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] - alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end if indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] @@ -334,14 +329,6 @@ end end println(f) end - open("$output_directory/alphas_eff.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha_eff, v, ntuple(_ -> :, n_vars - 1)...))); - print(f, ", ", alpha_eff_avg[v] / total_volume); - end - println(f) - end return nothing end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 71bca1a784..b02ffea85f 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1381,17 +1381,15 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} alpha::Array{uEltype, 4} # [variable, i, j, element] alpha_pressure::Array{uEltype, 3} # [i, j, element] alpha_entropy::Array{uEltype, 3} # [i, j, element] - alpha_eff::Array{uEltype, 4} # [variable, i, j, element] alpha_mean::Array{uEltype, 4} # [variable, i, j, element] - alpha_mean_pressure::Array{uEltype, 3} # [variable, i, j, element] - alpha_mean_entropy::Array{uEltype, 3} # [variable, i, j, element] + alpha_mean_pressure::Array{uEltype, 3} # [variable, i, j, element] + alpha_mean_entropy::Array{uEltype, 3} # [variable, i, j, element] # internal `resize!`able storage _var_min::Vector{uEltype} _var_max::Vector{uEltype} _alpha::Vector{uEltype} _alpha_pressure::Vector{uEltype} _alpha_entropy::Vector{uEltype} - _alpha_eff::Vector{uEltype} _alpha_mean::Vector{uEltype} _alpha_mean_pressure::Vector{uEltype} _alpha_mean_entropy::Vector{uEltype} @@ -1415,9 +1413,6 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) - _alpha_eff = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) - alpha_eff = unsafe_wrap(Array, pointer(_alpha_eff), (n_variables, n_nodes, n_nodes, capacity)) - _alpha_mean = fill(nan_uEltype, n_variables * n_nodes * n_nodes * capacity) alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) @@ -1427,8 +1422,8 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_mean_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, - _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_eff, _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) + return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, + _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) end nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) @@ -1461,10 +1456,6 @@ function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) resize!(_alpha_entropy, n_nodes * n_nodes * capacity) container.alpha_entropy = unsafe_wrap(Array, pointer(_alpha_entropy), (n_nodes, n_nodes, capacity)) - @unpack _alpha_eff = container - resize!(_alpha_eff, n_variables * n_nodes * n_nodes * capacity) - container.alpha_eff = unsafe_wrap(Array, pointer(_alpha_eff), (n_variables, n_nodes, n_nodes, capacity)) - @unpack _alpha_mean = container resize!(_alpha_mean, n_variables * n_nodes * n_nodes * capacity) container.alpha_mean = unsafe_wrap(Array, pointer(_alpha_mean), (n_variables, n_nodes, n_nodes, capacity)) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 14a1225f82..e0fc609f5d 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1194,10 +1194,6 @@ end @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates if indicator.Plotting - # TODO: Allocations!!! - P = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) - Q = zeros(eltype(u), 4, nnodes(dg), nnodes(dg)) - @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) @@ -1239,15 +1235,6 @@ end end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_rho - u[1, i-1, j, element])) - P[1, i-1, j] += aux + abs(flux_limited) - Q[1, i-1, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) - # right node - aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) - P[1, i, j] += aux + abs(flux_limited) - Q[1, i, j] += aux + abs(antidiffusive_flux1[1, i, j, element]) - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1290,15 +1277,6 @@ end end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_rho - u[1, i, j-1, element])) - P[1, i, j-1] += aux + abs(flux_limited) - Q[1, i, j-1] += aux + abs(antidiffusive_flux2[1, i, j, element]) - # right node - aux = abs(lambda * (bar_state_rho - u[1, i, j, element])) - P[1, i, j] += aux + abs(flux_limited) - Q[1, i, j] += aux + abs(antidiffusive_flux2[1, i, j, element]) - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1345,15 +1323,6 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) - P[v, i-1, j] += aux + abs(g_limited) - Q[v, i-1, j] += aux + abs(g) - # right node - aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) - P[v, i, j] += aux + abs(g_limited) - Q[v, i, j] += aux + abs(g) - if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1395,15 +1364,6 @@ end g_limited = max(g, min(g_min, 0.0)) end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) - P[v, i, j-1] += aux + abs(g_limited) - Q[v, i, j-1] += aux + abs(g) - # right node - aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) - P[v, i, j] += aux + abs(g_limited) - Q[v, i, j] += aux + abs(g) - if isapprox(g, 0.0, atol=eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1439,15 +1399,6 @@ end end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_phi - u[v, i-1, j, element])) - P[v, i-1, j] += aux + abs(flux_limited) - Q[v, i-1, j] += aux + abs(antidiffusive_flux1[v, i, j, element]) - # right node - aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) - P[v, i, j] += aux + abs(flux_limited) - Q[v, i, j] += aux + abs(antidiffusive_flux1[v, i, j, element]) - if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1481,15 +1432,6 @@ end end if indicator.Plotting - # left node - aux = abs(lambda * (bar_state_phi - u[v, i, j-1, element])) - P[v, i, j-1] += aux + abs(flux_limited) - Q[v, i, j-1] += aux + abs(antidiffusive_flux2[v, i, j, element]) - # right node - aux = abs(lambda * (bar_state_phi - u[v, i, j, element])) - P[v, i, j] += aux + abs(flux_limited) - Q[v, i, j] += aux + abs(antidiffusive_flux2[v, i, j, element]) - if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol=eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1506,16 +1448,6 @@ end end end # indicator.SequentialLimiter and indicator.ConservativeLimiter - # Compute "effective" alpha using P and Q - if indicator.Plotting - @unpack alpha_eff = indicator.cache.ContainerShockCapturingIndicator - for j in eachnode(dg), i in eachnode(dg) - for v in eachvariable(equations) - alpha_eff[v, i, j, element] = P[v, i, j] / (Q[v, i, j] + eps()) - end - end - end - # Density positivity limiter if indicator.DensityPositivityLimiter beta = indicator.DensityPositivityCorrelationFactor diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 980ba2d417..79f00f6c26 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -476,12 +476,6 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn node_variables[:alpha_entropy] = alpha_entropy end - @unpack alpha_eff = indicator.cache.ContainerShockCapturingIndicator - for v in eachvariable(equations) - s = Symbol("alpha_effective_", variables[v]) - node_variables[s] = alpha_eff[v, ntuple(_ -> :, size(alpha, 2) + 1)...] - end - @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator for v in eachvariable(equations) s = Symbol("alpha_mean_", variables[v]) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 776de603fd..855c5ac00d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -967,7 +967,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_eff, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator # Save the alphas every x iterations x = 1 @@ -993,9 +993,6 @@ end end println(f) end - open("$output_directory/alphas_eff.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end end if iter % x != 0 @@ -1004,7 +1001,6 @@ end alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), n_vars) - alpha_eff_avg = zeros(eltype(alpha), n_vars) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) jacobian = inv(cache.elements.inverse_jacobian[element]) @@ -1012,7 +1008,6 @@ end for v in eachvariable(equations) alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] - alpha_eff_avg[v] += jacobian * weights[i] * weights[j] * alpha_eff[v, i, j, element] end if indicator.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] @@ -1048,14 +1043,6 @@ end end println(f) end - open("$output_directory/alphas_eff.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha_eff, v, ntuple(_ -> :, n_vars - 1)...))); - print(f, ", ", alpha_eff_avg[v] / total_volume); - end - println(f) - end return nothing end From 9872a5636d6e140f6b28d1be7678eead8b6c217a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 31 May 2023 20:26:44 +0200 Subject: [PATCH 204/423] Fix test --- src/solvers/dgsem_tree/containers_2d.jl | 4 ++-- test/test_tree_2d_eulermulti.jl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index b02ffea85f..a01f6064c0 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1382,8 +1382,8 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} alpha_pressure::Array{uEltype, 3} # [i, j, element] alpha_entropy::Array{uEltype, 3} # [i, j, element] alpha_mean::Array{uEltype, 4} # [variable, i, j, element] - alpha_mean_pressure::Array{uEltype, 3} # [variable, i, j, element] - alpha_mean_entropy::Array{uEltype, 3} # [variable, i, j, element] + alpha_mean_pressure::Array{uEltype, 3} # [i, j, element] + alpha_mean_entropy::Array{uEltype, 3} # [i, j, element] # internal `resize!`able storage _var_min::Vector{uEltype} _var_max::Vector{uEltype} diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 6314e3e438..5f0a869674 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -21,8 +21,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_eulermulti_shock_bubble_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_sc_subcell.jl"), - l2 = [81.56638995751949, 2.749019198753295, 63209.842984371186, 0.1998094346294924, 0.011196332311231447], - linf = [251.3015423089727, 43.842039180642644, 174650.87707064365, 0.7041466370660441, 0.11584512034319161], + l2 = [81.56605688335027, 2.7408210722234974, 63210.97229480829, 0.19981152297309326, 0.01118954421258266], + linf = [251.37183832998687, 43.739559735583285, 174650.02501630428, 0.704646775153154, 0.11520289911691287], initial_refinement_level = 3, tspan = (0.0, 0.001)) end From 668c964cfab1e18cbbf2118e5f876f4b61121cc5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 1 Jun 2023 09:52:20 +0200 Subject: [PATCH 205/423] Delete IDPPressureTVD limiter --- .../elixir_euler_free_stream_sc_subcell.jl | 3 +- .../elixir_euler_source_terms_sc_subcell.jl | 7 ++-- .../elixir_euler_blast_wave_sc_subcell.jl | 3 +- src/callbacks_stage/bounds_check.jl | 17 +------- src/callbacks_stage/bounds_check_2d.jl | 24 +---------- src/solvers/dgsem_tree/dg_2d.jl | 31 -------------- src/solvers/dgsem_tree/indicators.jl | 17 +++----- src/solvers/dgsem_tree/indicators_2d.jl | 42 ++++++------------- test/test_tree_2d_euler.jl | 4 +- 9 files changed, 27 insertions(+), 121 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 853641a577..26c6ea596b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -15,8 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=false, - IDPPressureTVD=false, - IDPPositivity=true, + IDPPositivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(density_pressure,), IDPSpecEntropy=false, indicator_smooth=false, BarStates=true, diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 2b08f7d4e2..6c7e783449 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -17,9 +17,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, IDPPositivity=false, - indicator_smooth=true) + indicator_smooth=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -56,7 +55,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -66,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 0fc986f8ad..af23199d77 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -40,7 +40,6 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=true, - IDPPressureTVD=true, IDPMathEntropy=true, BarStates=false, indicator_smooth=true) @@ -77,7 +76,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.3) +stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 6cc35ae562..6a5c357aff 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -64,7 +64,7 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator return nothing end - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator @unpack output_directory = callback mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f; @@ -72,9 +72,6 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator if IDPDensityTVD print(f, ", rho_min, rho_max"); end - if IDPPressureTVD - print(f, ", p_min, p_max"); - end if IDPSpecEntropy print(f, ", specEntr_min"); end @@ -89,9 +86,6 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator print(f, ", $(variable)_min"); end for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end print(f, ", $(variable)_min"); end end @@ -133,7 +127,7 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator @unpack idp_bounds_delta = indicator.cache println("─"^100) @@ -144,10 +138,6 @@ end println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) counter += 2 end - if IDPPressureTVD - println("pressure:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) - counter += 2 - end if IDPSpecEntropy println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) counter += 1 @@ -165,9 +155,6 @@ end counter += 1 end for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 4137110d93..61294c23f0 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -7,7 +7,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, time, iter, output_directory, save_errors, interval) - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta = indicator.cache @@ -36,25 +36,6 @@ end counter += 2 end - if IDPPressureTVD - deviation_min = zero(eltype(u)) - deviation_max = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - p = pressure(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - p) - deviation_max = max(deviation_max, p - var_bounds[counter+1][i, j, element]) - end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - idp_bounds_delta[counter+1] = max(idp_bounds_delta[counter+1], deviation_max) - if save_errors_ - deviation_min_ = deviation_min - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_, ", ", deviation_max_); - end - end - counter += 2 - end if IDPSpecEntropy deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -105,9 +86,6 @@ counter += 1 end for variable in indicator.variables_nonlinear - if variable == pressure && IDPPressureTVD - continue - end deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) var = variable(get_node_vars(u, equations, solver, i, j, element), equations) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e0fc609f5d..4f0f557a02 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -995,37 +995,6 @@ end end counter += 2 end - # Pressure - if indicator.IDPPressureTVD - p_min = var_bounds[counter] - p_max = var_bounds[counter+1] - @threaded for element in eachelement(dg, cache) - p_min[:, :, element] .= typemax(eltype(p_min)) - p_max[:, :, element] .= typemin(eltype(p_max)) - for j in eachnode(dg), i in eachnode(dg) - p = pressure(get_node_vars(u, equations, dg, i, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - # - xi direction - p = pressure(get_node_vars(bar_states1, equations, dg, i, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - # + xi direction - p = pressure(get_node_vars(bar_states1, equations, dg, i+1, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - # - eta direction - p = pressure(get_node_vars(bar_states2, equations, dg, i, j, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - # + eta direction - p = pressure(get_node_vars(bar_states2, equations, dg, i, j+1, element), equations) - p_min[i, j, element] = min(p_min[i, j, element], p) - p_max[i, j, element] = max(p_max[i, j, element], p) - end - end - counter += 2 - end # Specific Entropy if indicator.IDPSpecEntropy s_min = var_bounds[counter] diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 79f00f6c26..b726602ceb 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -232,7 +232,6 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi """ struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator IDPDensityTVD::Bool - IDPPressureTVD::Bool IDPPositivity::Bool variables_cons::LimitingVariablesCons # Positivity of conservative variables variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables @@ -253,7 +252,6 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; IDPDensityTVD=false, - IDPPressureTVD=false, IDPPositivity=false, variables_cons=(first,), variables_nonlinear=(), @@ -274,9 +272,6 @@ function IndicatorIDP(equations::AbstractEquations, basis; if IDPDensityTVD number_bounds += 2 - IDPPositivity * (Trixi.density in variables_cons) end - if IDPPressureTVD - number_bounds += 2 - IDPPositivity * (pressure in variables_nonlinear) - end end cache = create_cache(IndicatorIDP, equations, basis, number_bounds, BarStates) @@ -288,21 +283,20 @@ function IndicatorIDP(equations::AbstractEquations, basis; IndicatorHG = nothing end IndicatorIDP{typeof(positCorrFactor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( - IDPDensityTVD, IDPPressureTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, + IDPDensityTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, indicator_smooth, thr_smooth, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator print(io, "IndicatorIDP(") - if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + if !(IDPDensityTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) print(io, "No limiter selected => pure DG method") else print(io, "limiter=(") IDPDensityTVD && print(io, "IDPDensityTVD, ") - IDPPressureTVD && print(io, "IDPPressureTVD, ") IDPPositivity && print(io, "IDPPositivity, ") IDPSpecEntropy && print(io, "IDPSpecEntropy, ") IDPMathEntropy && print(io, "IDPMathEntropy, ") @@ -316,17 +310,16 @@ end function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator if get(io, :compact, false) show(io, indicator) else - if !(IDPDensityTVD || IDPPressureTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + if !(IDPDensityTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] IDPDensityTVD && (setup = [setup..., "" => "IDPDensityTVD"]) - IDPPressureTVD && (setup = [setup..., "" => "IDPPressureTVD"]) if IDPPositivity string = "IDPPositivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" setup = [setup..., "" => string] diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 855c5ac00d..ddce9d97f2 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -213,8 +213,6 @@ function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSE indicator_IDP.IDPDensityTVD && @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u, t, dt, semi, elements) - indicator_IDP.IDPPressureTVD && - @trixi_timeit timer() "IDPPressureTVD" IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) indicator_IDP.IDPPositivity && @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements) indicator_IDP.IDPSpecEntropy && @@ -580,10 +578,10 @@ end @inline function IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity = indicator_IDP + @unpack IDPDensityTVD, IDPPositivity = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - s_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + 1] + s_min = var_bounds[2 * IDPDensityTVD + 1] if !indicator_IDP.BarStates calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -608,10 +606,10 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol @inline function IDP_mathEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack IDPDensityTVD, IDPPressureTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP + @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - s_max = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + 1] + s_max = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + 1] if !indicator_IDP.BarStates calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -652,7 +650,7 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis - @unpack IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons = indicator_IDP + @unpack IDPDensityTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator @@ -660,12 +658,10 @@ end if Trixi.density == variables_cons[index] var_min = var_bounds[1] else - var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - index - 1] + var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + index - 1] end else - var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - index] + var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + index] end @threaded for element in elements @@ -722,23 +718,13 @@ end @inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack IDPDensityTVD, IDPPressureTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons, variables_nonlinear = indicator_IDP + @unpack IDPDensityTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons, variables_nonlinear = indicator_IDP @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - if pressure in variables_nonlinear && IDPPressureTVD - if pressure == variables_nonlinear[index] - var_min = var_bounds[2 * IDPDensityTVD + 1] - else - var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + - index - 1] - end - else - var_min = var_bounds[2 * (IDPDensityTVD + IDPPressureTVD) + IDPSpecEntropy + IDPMathEntropy + - length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + - index] - end + var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + + length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + + index] @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) @@ -748,11 +734,7 @@ end if var < 0.0 println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") end - if indicator_IDP.IDPPressureTVD - var_min[i, j, element] = max(var_min[i, j, element], positCorrFactor * var) - else - var_min[i, j, element] = positCorrFactor * var - end + var_min[i, j, element] = positCorrFactor * var # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 354898e0b5..cd4550c559 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -125,8 +125,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.2920755759043822, 0.17319961818078095, 0.17324761487648088, 0.6147100442792741], - linf = [1.2346904176617581, 1.0179921490964996, 1.0181645482974628, 2.4268315439038854], + l2 = [0.3078500396564997, 0.1759956708830148, 0.1759417699101888, 0.6141202024471839], + linf = [1.297180993766177, 1.105746322133501, 1.1057676530433822, 2.4364099721878776], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From 1f824c0121c69fd7bec4eacf8766d1bbeb12ba8a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 1 Jun 2023 09:57:37 +0200 Subject: [PATCH 206/423] Implement alpha analysis as Callback --- .../elixir_euler_sedov_blast_wave_MCL.jl | 4 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 3 + src/Trixi.jl | 2 +- src/callbacks_step/callbacks_step.jl | 1 + src/callbacks_step/limiting_analysis.jl | 189 ++++++++++++++++++ src/callbacks_step/limiting_analysis_2d.jl | 112 +++++++++++ src/solvers/dgsem_structured/indicators_2d.jl | 105 ---------- src/solvers/dgsem_tree/dg_2d.jl | 10 +- src/solvers/dgsem_tree/indicators_2d.jl | 140 +------------ src/time_integration/methods_SSP.jl | 21 -- 10 files changed, 319 insertions(+), 268 deletions(-) create mode 100644 src/callbacks_step/limiting_analysis.jl create mode 100644 src/callbacks_step/limiting_analysis_2d.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 4ad228010f..dbb30336f3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -85,9 +85,11 @@ save_solution = SaveSolutionCallback(interval=1000, stepsize_callback = StepsizeCallback(cfl=0.9) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory="out", interval=1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - stepsize_callback, + stepsize_callback, limiting_analysis_callback, save_solution) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 42f894c39a..4d9c8086fc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -82,9 +82,12 @@ save_solution = SaveSolutionCallback(interval=1000, stepsize_callback = StepsizeCallback(cfl=0.9) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory="out", interval=1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, + limiting_analysis_callback, save_solution) ############################################################################### # run the simulation diff --git a/src/Trixi.jl b/src/Trixi.jl index 9d616a6121..b0735c15a8 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -224,7 +224,7 @@ export SemidiscretizationEulerGravity, ParametersEulerGravity, export SummaryCallback, SteadyStateCallback, AnalysisCallback, AliveCallback, SaveRestartCallback, SaveSolutionCallback, TimeSeriesCallback, VisualizationCallback, AveragingCallback, - AMRCallback, StepsizeCallback, + AMRCallback, StepsizeCallback, LimitingAnalysisCallback, GlmSpeedCallback, LBMCollisionCallback, EulerAcousticsCouplingCallback, TrivialCallback diff --git a/src/callbacks_step/callbacks_step.jl b/src/callbacks_step/callbacks_step.jl index 0b2c4ef4d5..97a6f3241e 100644 --- a/src/callbacks_step/callbacks_step.jl +++ b/src/callbacks_step/callbacks_step.jl @@ -60,6 +60,7 @@ include("averaging.jl") include("amr.jl") include("stepsize.jl") +include("limiting_analysis.jl") include("glm_speed.jl") include("lbm_collision.jl") include("euler_acoustics_coupling.jl") diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl new file mode 100644 index 0000000000..d01224dc68 --- /dev/null +++ b/src/callbacks_step/limiting_analysis.jl @@ -0,0 +1,189 @@ +# 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 + + +""" + LimitingAnalysisCallback(; output_directory="out", interval=1) + +Analyze the subcell blending coefficient of IDP limiting (`IndicatorIDP`) and monolithic convex +limiting (MCL) (`IndicatorMCL`) every `interval` time steps and saeves the results +to `output_directory/alpha.txt`. +""" +struct LimitingAnalysisCallback + output_directory::String + interval::Int +end + +function Base.show(io::IO, ::MIME"text/plain", cb::DiscreteCallback{<:Any, <:LimitingAnalysisCallback}) + + return nothing +end + +function LimitingAnalysisCallback(; output_directory="out", interval=1) + + condition = (u, t, integrator) -> interval > 0 && ( (integrator.stats.naccept % interval == 0 && + !(integrator.stats.naccept == 0 && integrator.iter > 0)) || + isfinished(integrator)) + + limiting_analysis_callback = LimitingAnalysisCallback(output_directory, interval) + + DiscreteCallback(condition, limiting_analysis_callback, + save_positions=(false,false), + initialize=initialize!) +end + +function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator) where {Condition, Affect!<:LimitingAnalysisCallback} + if cb.affect!.interval == 0 + return nothing + end + + initialize!(cb, u_ode, t, integrator, integrator.p.solver.volume_integral) + + return nothing +end + +function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator, + volume_integral::AbstractVolumeIntegral) where {Condition, Affect!<:LimitingAnalysisCallback} + + return nothing +end + +function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator, + volume_integral::VolumeIntegralShockCapturingSubcell) where {Condition, Affect!<:LimitingAnalysisCallback} + + initialize!(cb, u_ode, t, integrator, volume_integral.indicator, cb.affect!.output_directory) + + return nothing +end + +function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator, + indicator::IndicatorIDP, output_directory) where {Condition, Affect!<:LimitingAnalysisCallback} + + mkpath(output_directory) + open("$output_directory/alphas.txt", "a") do f; + println(f, "# iter, simu_time, alpha_max, alpha_avg"); + end + + return nothing +end + +function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator, + indicator::IndicatorMCL, output_directory) where {Condition, Affect!<:LimitingAnalysisCallback} + + vars = varnames(cons2cons, integrator.p.equations) + + mkpath(output_directory) + open("$output_directory/alphas_min.txt", "a") do f; + print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + if indicator.PressurePositivityLimiterKuzmin + print(f, ", alpha_min_pressure, alpha_avg_pressure") + end + if indicator.SemiDiscEntropyLimiter + print(f, ", alpha_min_entropy, alpha_avg_entropy") + end + println(f) + end + open("$output_directory/alphas_mean.txt", "a") do f; + print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + if indicator.PressurePositivityLimiterKuzmin + print(f, ", alpha_min_pressure, alpha_avg_pressure") + end + if indicator.SemiDiscEntropyLimiter + print(f, ", alpha_min_entropy, alpha_avg_entropy") + end + println(f) + end + + return nothing +end + + +@inline function (limiting_analysis_callback::LimitingAnalysisCallback)(integrator) + mesh, equations, solver, cache = mesh_equations_solver_cache(integrator.p) + @unpack t = integrator + iter = integrator.stats.naccept + + limiting_analysis_callback(mesh, equations, solver, cache, solver.volume_integral, t, iter) +end + +@inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, solver, cache, + volume_integral::AbstractVolumeIntegral, + t, iter) + return nothing +end + +@inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, solver, cache, + volume_integral::VolumeIntegralShockCapturingSubcell, + t, iter) + if limiting_analysis_callback.interval == 0 || (iter % limiting_analysis_callback.interval != 0) + return nothing + end + + @trixi_timeit timer() "limiting_analysis_callback" limiting_analysis_callback(mesh, equations, solver, cache, + volume_integral.indicator, t, iter) +end + +@inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, dg, cache, + indicator::IndicatorIDP, time, iter) + @unpack output_directory = limiting_analysis_callback + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + + alpha_avg = analyze_coefficient_IDP(mesh, equations, dg, cache, indicator) + + open("$output_directory/alphas.txt", "a") do f; + println(f, iter, ", ", time, ", ", maximum(alpha), ", ", alpha_avg); + end +end + +@inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, dg, cache, + indicator::IndicatorMCL, time, iter) + @unpack output_directory = limiting_analysis_callback + @unpack weights = dg.basis + @unpack alpha, alpha_pressure, alpha_entropy, + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + + n_vars = nvariables(equations) + + alpha_min_avg, alpha_mean_avg = analyze_coefficient_MCL(mesh, equations, dg, cache, indicator) + + open("$output_directory/alphas_min.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_min_avg[v]); + end + if indicator.PressurePositivityLimiterKuzmin + print(f, ", ", minimum(alpha_pressure), ", ", alpha_min_avg[n_vars + 1]) + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + print(f, ", ", minimum(alpha_entropy), ", ", alpha_min_avg[k]) + end + println(f) + end + open("$output_directory/alphas_mean.txt", "a") do f; + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); + print(f, ", ", alpha_mean_avg[v]); + end + if indicator.PressurePositivityLimiterKuzmin + print(f, ", ", minimum(alpha_mean_pressure), ", ", alpha_mean_avg[n_vars + 1]) + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + print(f, ", ", minimum(alpha_mean_entropy), ", ", alpha_mean_avg[k]) + end + println(f) + end + + return nothing +end + +end # @muladd + + +include("limiting_analysis_2d.jl") diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl new file mode 100644 index 0000000000..ac8535f996 --- /dev/null +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -0,0 +1,112 @@ +# 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 + + +@inline function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, indicator) + @unpack weights = dg.basis + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + + alpha_avg_ = zero(eltype(alpha)) + total_volume = zero(eltype(alpha)) + for element in eachelement(dg, cache) + jacobian = inv(cache.elements.inverse_jacobian[element]) + for j in eachnode(dg), i in eachnode(dg) + alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + + return alpha_avg_ / total_volume +end + +@inline function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, indicator) + @unpack weights = dg.basis + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + + alpha_avg_ = zero(eltype(alpha)) + total_volume = zero(eltype(alpha)) + for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) + alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] + total_volume += jacobian * weights[i] * weights[j] + end + end + + return alpha_avg_ / total_volume +end + + +function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, indicator) + @unpack weights = dg.basis + @unpack alpha, alpha_mean, alpha_pressure, + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + + n_vars = nvariables(equations) + + alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) + alpha_mean_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) + total_volume = zero(eltype(alpha)) + + for element in eachelement(dg, cache) + jacobian = inv(cache.elements.inverse_jacobian[element]) + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] + end + if indicator.PressurePositivityLimiterKuzmin + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] + alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * alpha_mean_entropy[i, j, element] + end + total_volume += jacobian * weights[i] * weights[j] + end + end + + return alpha_avg ./ total_volume, alpha_mean_avg ./ total_volume +end + +function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, indicator) + @unpack weights = dg.basis + @unpack alpha, alpha_mean, alpha_pressure, + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + + n_vars = nvariables(equations) + + alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) + alpha_mean_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) + total_volume = zero(eltype(alpha)) + + for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) + for v in eachvariable(equations) + alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] + alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] + end + if indicator.PressurePositivityLimiterKuzmin + alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] + alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] + end + if indicator.SemiDiscEntropyLimiter + k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] + alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * alpha_mean_entropy[i, j, element] + end + total_volume += jacobian * weights[i] * weights[j] + end + end + + return alpha_avg ./ total_volume, alpha_mean_avg ./ total_volume +end + + +end # @muladd diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index e435c146ff..395cfeb0e6 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -229,109 +229,4 @@ function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, end -@inline function update_alpha_max_avg!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::StructuredMesh{2}) - _, _, solver, cache = mesh_equations_solver_cache(semi) - @unpack weights = solver.basis - @unpack alpha_max_avg = indicator.cache - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - - alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) - alpha_avg = zero(eltype(alpha)) - total_volume = zero(eltype(alpha)) - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) - alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] - total_volume += jacobian * weights[i] * weights[j] - end - end - alpha_max_avg[2] += 1/(n_stages * total_volume) * alpha_avg - - return nothing -end - -@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator - - # Save the alphas every x iterations - x = 1 - if x == 0 || !indicator.Plotting - return nothing - end - - n_vars = nvariables(equations) - vars = varnames(cons2cons, equations) - - # Headline - if iter == 1 && x > 0 - open("$output_directory/alphas_min.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end - open("$output_directory/alphas_mean.txt", "a") do f; - print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiterKuzmin - print(f, ", alpha_min_pressure, alpha_avg_pressure") - end - if indicator.SemiDiscEntropyLimiter - print(f, ", alpha_min_entropy, alpha_avg_entropy") - end - println(f) - end - end - - if iter % x != 0 - return nothing - end - - alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) - alpha_mean_avg = zeros(eltype(alpha), n_vars) - total_volume = zero(eltype(alpha)) - for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) - for v in eachvariable(equations) - alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] - alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] - end - if indicator.PressurePositivityLimiterKuzmin - alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 - alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] - end - total_volume += jacobian * weights[i] * weights[j] - end - end - - open("$output_directory/alphas_min.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars)...))); - print(f, ", ", alpha_avg[v] / total_volume); - end - println(f) - end - open("$output_directory/alphas_mean.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); - print(f, ", ", alpha_mean_avg[v] / total_volume); - end - if indicator.PressurePositivityLimiterKuzmin - print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 - print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) - end - println(f) - end - - return nothing -end - - end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4f0f557a02..0c88464cf0 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1163,11 +1163,19 @@ end @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates if indicator.Plotting - @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) + alpha[:, i, j, element] .= one(eltype(alpha)) + if indicator.PressurePositivityLimiterKuzmin + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end + if indicator.SemiDiscEntropyLimiter + alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) + end end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ddce9d97f2..190f89acbe 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -195,11 +195,9 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation cache = (; cache..., ContainerBarStates) end - alpha_max_avg = zeros(real(basis), 2) - idp_bounds_delta = zeros(real(basis), number_bounds) - return (; cache..., alpha_max_avg, ContainerShockCapturingIndicator, idp_bounds_delta) + return (; cache..., ContainerShockCapturingIndicator, idp_bounds_delta) end function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) @@ -881,54 +879,6 @@ end standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) -@inline function update_alpha_max_avg!(indicator::IndicatorIDP, timestep, n_stages, semi, mesh::TreeMesh) - _, _, solver, cache = mesh_equations_solver_cache(semi) - @unpack weights = solver.basis - @unpack alpha_max_avg = indicator.cache - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator - - alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) - alpha_avg = zero(eltype(alpha)) - total_volume = zero(eltype(alpha)) - for element in eachelement(solver, cache) - jacobian = inv(cache.elements.inverse_jacobian[element]) - for j in eachnode(solver), i in eachnode(solver) - alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] - total_volume += jacobian * weights[i] * weights[j] - end - end - alpha_max_avg[2] += 1/(n_stages * total_volume) * alpha_avg - - return nothing -end - -@inline function save_alpha(indicator::IndicatorIDP, time, iter, semi, mesh, output_directory) - @unpack alpha_max_avg = indicator.cache - # The maximum and average values were calculated in `update_alpha_max_avg!` in each RK stage. - # This is necessary if we want the average of the alphas over all stages (discussable). - - # Save the alphas every x iterations - x = 1 - - # Headline - if x > 0 && iter == 1 - open("$output_directory/alphas_min.txt", "a") do f; - println(f, "# iter, simu_time, alpha_max, alpha_avg"); - end - end - - if x == 0 || iter % x != 0 - return nothing - end - open("$output_directory/alphas_min.txt", "a") do f; - println(f, iter, ", ", time, ", ", alpha_max_avg[1], ", ", alpha_max_avg[2]); - end - - # Reset alpha_max_avg - indicator.cache.alpha_max_avg .= zero(eltype(indicator.cache.alpha_max_avg)) - - return nothing -end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, @@ -941,94 +891,6 @@ function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquation return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end -@inline function update_alpha_max_avg!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) - - return nothing -end - -@inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator - - # Save the alphas every x iterations - x = 1 - if x == 0 || !indicator.Plotting - return nothing - end - - n_vars = nvariables(equations) - vars = varnames(cons2cons, equations) - - # Headline - if iter == 1 - open("$output_directory/alphas_min.txt", "a") do f; - println(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - end - open("$output_directory/alphas_mean.txt", "a") do f; - print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiterKuzmin - print(f, ", alpha_min_pressure, alpha_avg_pressure") - end - if indicator.SemiDiscEntropyLimiter - print(f, ", alpha_min_entropy, alpha_avg_entropy") - end - println(f) - end - end - - if iter % x != 0 - return nothing - end - - alpha_avg = zeros(eltype(alpha), n_vars + indicator.PressurePositivityLimiterKuzmin + indicator.SemiDiscEntropyLimiter) - alpha_mean_avg = zeros(eltype(alpha), n_vars) - total_volume = zero(eltype(alpha)) - for element in eachelement(dg, cache) - jacobian = inv(cache.elements.inverse_jacobian[element]) - for j in eachnode(dg), i in eachnode(dg) - for v in eachvariable(equations) - alpha_avg[v] += jacobian * weights[i] * weights[j] * alpha[v, i, j, element] - alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] - end - if indicator.PressurePositivityLimiterKuzmin - alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 - alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] - end - total_volume += jacobian * weights[i] * weights[j] - end - end - - open("$output_directory/alphas_min.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))); - print(f, ", ", alpha_avg[v] / total_volume); - end - println(f) - end - open("$output_directory/alphas_mean.txt", "a") do f; - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))); - print(f, ", ", alpha_mean_avg[v] / total_volume); - end - if indicator.PressurePositivityLimiterKuzmin - print(f, ", ", minimum(alpha_pressure), ", ", alpha_avg[n_vars + 1] / total_volume) - end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 - print(f, ", ", minimum(alpha_entropy), ", ", alpha_avg[k] / total_volume) - end - println(f) - end - - return nothing -end - # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 32c3f44e6a..dd63d1792e 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -127,7 +127,6 @@ function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, end function solve!(integrator::SimpleIntegratorSSP) - @unpack indicator = integrator.p.solver.volume_integral @unpack prob = integrator.sol @unpack alg = integrator t_end = last(prob.tspan) @@ -152,22 +151,6 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - # Reset alphas for MCL - if indicator isa IndicatorMCL && indicator.Plotting - @unpack alpha, alpha_pressure, alpha_entropy = indicator.cache.ContainerShockCapturingIndicator - @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) - for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) - alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiterKuzmin - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) - end - if indicator.SemiDiscEntropyLimiter - alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) - end - end - end - end - @. integrator.r0 = integrator.u for stage in eachindex(alg.c) @trixi_timeit timer() "Runge-Kutta stage" begin @@ -179,8 +162,6 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = integrator.u + integrator.dt * integrator.du end - @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) - for stage_callback in alg.stage_callbacks stage_callback(integrator.u, integrator, stage) end @@ -189,8 +170,6 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u end - @trixi_timeit timer() "save_alpha" save_alpha(indicator, integrator.t, integrator.iter+1, integrator.p, integrator.p.mesh, output_directory) - integrator.iter += 1 integrator.t += integrator.dt From 77be404303e157b073655fb24734b612d8787997 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 1 Jun 2023 14:06:45 +0200 Subject: [PATCH 207/423] Add tests using `StructuredMesh` --- .../elixir_euler_free_stream_sc_subcell.jl | 1 - test/test_structured_2d.jl | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 75ae9ef2c1..b53bb0250a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -15,7 +15,6 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; IDPDensityTVD=false, - IDPPressureTVD=false, IDPPositivity=true, IDPSpecEntropy=false, indicator_smooth=false, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index feaf66c4a7..7f9f1017c7 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -169,6 +169,22 @@ isdir(outdir) && rm(outdir, recursive=true) atol = 7.0e-13) end + @trixi_testset "elixir_euler_free_stream_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_sc_subcell.jl"), + l2 = [2.6224749465938795e-14, 1.6175366858083413e-14, 2.358782725951525e-14, 5.910156539173304e-14], + linf = [1.1945999744966684e-13, 1.084687895058778e-13, 1.7050250100680842e-13, 2.0250467969162855e-13], + atol = 1.0e-13, + cells_per_dimension = (8, 8)) + end + + @trixi_testset "elixir_euler_free_stream_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_MCL.jl"), + l2 = [3.532639560334565e-14, 1.4787576718355913e-14, 2.109573923923632e-14, 2.54649935281524e-14], + linf = [1.3955503419538218e-13, 1.1611545058798356e-13, 1.7619239400801234e-13, 2.007283228522283e-13], + atol = 1.0e-13, + cells_per_dimension = (8, 8)) + end + @trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), surface_flux=FluxRotated(flux_lax_friedrichs), @@ -177,6 +193,22 @@ isdir(outdir) && rm(outdir, recursive=true) atol = 7.0e-13) end + @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), + l2 = [1.6235046821060115, 1.3268082379825517, 2.260222745763045, 13.836104055251756], + linf = [5.325409024016956, 6.709625872864434, 9.083315813037805, 41.99330375684724], + cells_per_dimension = (8, 12), + tspan = (0.0, 1.0)) + end + + @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), + l2 = [1.658656964774321, 1.3774222979640156, 2.3582271089306537, 14.118411580269786], + linf = [5.70562521337294, 9.254765871614621, 11.472661014676802, 45.56200325907666], + cells_per_dimension = (8, 12), + tspan = (0.0, 1.0)) + end + @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), l2 = [2.259440511901724e-6, 2.3188881559075347e-6, 2.3188881559568146e-6, 6.332786324137878e-6], From 6d8e406b19b2ee89c51cd4a6f15362ad098d9469 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 2 Jun 2023 13:35:06 +0200 Subject: [PATCH 208/423] Remove pressure limiting routine --- src/solvers/dgsem_tree/indicators_2d.jl | 70 ------------------------- 1 file changed, 70 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ddce9d97f2..09630ac828 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -505,76 +505,6 @@ end return nothing end -@inline function IDP_pressureTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) - # IDP limiter for pressure based on - # - Kuzmin et al. (2020). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator - - p_min = var_bounds[2 * indicator_IDP.IDPDensityTVD + 1] - p_max = var_bounds[2 * indicator_IDP.IDPDensityTVD + 2] - if !indicator_IDP.BarStates - calc_bounds_2sided!(p_min, p_max, pressure, u, t, semi) - end - - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - @unpack inverse_weights = dg.basis - - @threaded for element in elements - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - end - for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end - p = pressure(get_node_vars(u, equations, dg, i, j, element), equations) - # Real Zalesak type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - - Qp = max(0.0, (p_max[i, j, element] - p) / dt) - Qm = min(0.0, (p_min[i, j, element] - p) / dt) - - # Calculate Pp and Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - v1 = u[2, i, j, element] / u[1, i, j, element] - v2 = u[3, i, j, element] / u[1, i, j, element] - v2s2 = 0.5 * (v1^2 + v2^2) - gamma_m1 = equations.gamma - 1.0 - - val_flux1_local = gamma_m1 * (antidiffusive_flux1[4, i, j, element] + v2s2 * antidiffusive_flux1[1, i, j, element] - - v1 * antidiffusive_flux1[2, i, j, element] - v2 * antidiffusive_flux1[3, i, j, element]) - val_flux1_local_ip1 = gamma_m1 * (antidiffusive_flux1[4, i+1, j, element] + v2s2 * antidiffusive_flux1[1, i+1, j, element] - - v1 * antidiffusive_flux1[2, i+1, j, element] - v2 * antidiffusive_flux1[3, i+1, j, element]) - val_flux2_local = gamma_m1 * (antidiffusive_flux2[4, i, j, element] + v2s2 * antidiffusive_flux2[1, i, j, element] - - v1 * antidiffusive_flux2[2, i, j, element] - v2 * antidiffusive_flux2[3, i, j, element]) - val_flux2_local_jp1 = gamma_m1 * (antidiffusive_flux2[4, i, j+1, element] + v2s2 * antidiffusive_flux2[1, i, j+1, element] - - v1 * antidiffusive_flux2[2, i, j+1, element] - v2 * antidiffusive_flux2[3, i, j+1, element]) - - Pp = max(0.0, inverse_weights[i] * val_flux1_local) + max(0.0, -inverse_weights[i] * val_flux1_local_ip1) + - max(0.0, inverse_weights[j] * val_flux2_local) + max(0.0, -inverse_weights[j] * val_flux2_local_jp1) - Pm = min(0.0, inverse_weights[i] * val_flux1_local) + min(0.0, -inverse_weights[i] * val_flux1_local_ip1) + - min(0.0, inverse_weights[j] * val_flux2_local) + min(0.0, -inverse_weights[j] * val_flux2_local_jp1) - Pp = inverse_jacobian * Pp - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / (abs(Pp) + eps() * 100 * abs(p_max[i, j, element])) - Qm = abs(Qm) / (abs(Pm) + eps() * 100 * abs(p_max[i, j, element])) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1.0, Qp, Qm)) - end - end - - return nothing -end - @inline function IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi From 8e50b1ee388c18a7b6d555e5cc1b3e1b984bbcce Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 2 Jun 2023 16:57:53 +0200 Subject: [PATCH 209/423] Adjust parameter in elixir --- .../elixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- test/test_tree_2d_eulermulti.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index 82f1b0f12c..2475ab5b3a 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -92,7 +92,7 @@ indicator_sc = IndicatorIDP(equations, basis; variables_nonlinear=(), positCorrFactor=0.1, IDPDensityTVD=false, IDPSpecEntropy=false, - BarStates=true) + BarStates=false) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 5f0a869674..2b8951b279 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -21,8 +21,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_eulermulti_shock_bubble_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_sc_subcell.jl"), - l2 = [81.56605688335027, 2.7408210722234974, 63210.97229480829, 0.19981152297309326, 0.01118954421258266], - linf = [251.37183832998687, 43.739559735583285, 174650.02501630428, 0.704646775153154, 0.11520289911691287], + l2 = [81.52845664909304, 2.5455678559421346, 63229.190712645846, 0.19929478404550321, 0.011068604228443425], + linf = [249.21708417382013, 40.33299887640794, 174205.0118831558, 0.6881458768113586, 0.11274401158173972], initial_refinement_level = 3, tspan = (0.0, 0.001)) end From 9920815f9153873b3087a416622bb44bc80e4366 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 5 Jun 2023 12:09:29 +0200 Subject: [PATCH 210/423] Implement suggestions (Renaming variables and functions) --- ...elixir_euler_convergence_wavingflag_IDP.jl | 14 +- .../elixir_euler_double_mach.jl | 10 +- .../elixir_euler_free_stream_MCL.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 14 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 10 +- .../elixir_euler_source_terms_sc_subcell.jl | 6 +- .../elixir_euler_astro_jet_subcell.jl | 8 +- .../elixir_euler_blast_wave_MCL.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 8 +- .../elixir_euler_convergence_IDP.jl | 14 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 8 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 10 +- .../elixir_euler_source_terms_sc_subcell.jl | 8 +- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 10 +- src/callbacks_stage/antidiffusive_stage.jl | 6 +- src/callbacks_stage/bounds_check.jl | 24 +-- src/callbacks_stage/bounds_check_2d.jl | 26 +-- src/callbacks_step/stepsize.jl | 2 +- src/callbacks_step/stepsize_dg2d.jl | 6 +- src/solvers/dg.jl | 2 +- src/solvers/dgsem_structured/dg_2d.jl | 25 ++- src/solvers/dgsem_tree/containers_2d.jl | 44 ++--- src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 60 +++--- src/solvers/dgsem_tree/indicators.jl | 130 ++++++------- src/solvers/dgsem_tree/indicators_2d.jl | 172 +++++++++--------- src/time_integration/methods_SSP.jl | 2 +- 28 files changed, 308 insertions(+), 319 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index ce19d5594a..ae9f72da3c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -14,13 +14,13 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=false, - IDPPositivity=true, - IDPSpecEntropy=false, - positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14), - BarStates=true, - indicator_smooth=false) + density_tvd=false, + positivity=true, + spec_entropy=false, + positivity_correction_factor=0.1, max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), + bar_states=true, + smoothness_indicator=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index e4580fcd5a..2da995f6b1 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -93,11 +93,11 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=false, - IDPSpecEntropy=true, - positCorrFactor=0.1, IDPMaxIter=100, - BarStates=true) + density_tvd=true, + positivity=false, + spec_entropy=true, + positivity_correction_factor=0.1, max_iterations_newton=100, + bar_states=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 1a0296db17..5bacc7971e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -21,7 +21,7 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, - indicator_smooth=false, + smoothness_indicator=false, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index b2629e5ca6..6cd0ce7fb7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -14,13 +14,13 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=false, - IDPPositivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), - IDPSpecEntropy=false, - indicator_smooth=false, - BarStates=true, - positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14)) + density_tvd=false, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + spec_entropy=false, + smoothness_indicator=false, + bar_states=true, + positivity_correction_factor=0.1, max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14)) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 05e1e03678..0865225816 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -37,11 +37,11 @@ polydeg = 5 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=false, - IDPSpecEntropy=true, - IDPMaxIter=100, - BarStates=true) + density_tvd=true, + positivity=false, + spec_entropy=true, + max_iterations_newton=100, + bar_states=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 6c7e783449..540b78d9a9 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -16,9 +16,9 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=false, - indicator_smooth=false) + density_tvd=true, + positivity=false, + smoothness_indicator=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index bc93be4feb..38d8042dc4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -44,10 +44,10 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPSpecEntropy=true, - BarStates=true, - IDPMaxIter=25) + density_tvd=true, + spec_entropy=true, + bar_states=true, + max_iterations_newton=25) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 59576726c4..136d8839e5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -46,7 +46,7 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=false, SemiDiscEntropyLimiter=true, - indicator_smooth=true, + smoothness_indicator=true, Plotting=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index af23199d77..c12054b3d7 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,10 +39,10 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPMathEntropy=true, - BarStates=false, - indicator_smooth=true) + density_tvd=true, + math_entropy=true, + bar_states=false, + smoothness_indicator=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 82e2d4729e..7f847c81da 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -14,13 +14,13 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=false, - IDPPositivity=true, - IDPSpecEntropy=false, - positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14), - BarStates=true, - indicator_smooth=false) + density_tvd=false, + positivity=true, + spec_entropy=false, + positivity_correction_factor=0.1, max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), + bar_states=true, + smoothness_indicator=false) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index c4a91eba13..c2c3e5d813 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,10 +37,10 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), - IDPDensityTVD=false, - IDPSpecEntropy=false, - BarStates=true) + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + density_tvd=false, + spec_entropy=false, + bar_states=true) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 4ad228010f..cec2298157 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -49,7 +49,7 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, SemiDiscEntropyLimiter=true, - indicator_smooth=false, + smoothness_indicator=false, Plotting=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 42f894c39a..c790b8a639 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,11 +42,11 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=false, - IDPSpecEntropy=true, - indicator_smooth=false, - BarStates=true) + density_tvd=true, + positivity=false, + spec_entropy=true, + smoothness_indicator=false, + bar_states=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index fcff16c5bc..89924b1cce 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -14,10 +14,10 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - IDPDensityTVD=true, - IDPPositivity=false, - BarStates=true, - indicator_smooth=true) + density_tvd=true, + positivity=false, + bar_states=true, + smoothness_indicator=true) volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index 2475ab5b3a..b24c413834 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -87,12 +87,12 @@ density1(u, equations::CompressibleEulerMulticomponentEquations2D) = u[1+3] density2(u, equations::CompressibleEulerMulticomponentEquations2D) = u[2+3] indicator_sc = IndicatorIDP(equations, basis; - IDPPositivity=true, + positivity=true, variables_cons=(density1, density2), - variables_nonlinear=(), positCorrFactor=0.1, - IDPDensityTVD=false, - IDPSpecEntropy=false, - BarStates=false) + variables_nonlinear=(), positivity_correction_factor=0.1, + density_tvd=false, + spec_entropy=false, + bar_states=false) volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl index e1550b77b5..8960a14f3d 100644 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -33,16 +33,16 @@ function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicato @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) - perform_IDP_correction(u, dt, mesh, equations, solver, cache) + perform_idp_correction(u, dt, mesh, equations, solver, cache) return nothing end -@inline function perform_IDP_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) +@inline function perform_idp_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator - if dg.volume_integral.indicator.indicator_smooth + if dg.volume_integral.indicator.smoothness_indicator elements = cache.element_ids_dgfv else elements = eachelement(dg, cache) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 6a5c357aff..c0fcfb294a 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -64,23 +64,23 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator return nothing end - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator @unpack output_directory = callback mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f; print(f, "# iter, simu_time") - if IDPDensityTVD + if density_tvd print(f, ", rho_min, rho_max"); end - if IDPSpecEntropy + if spec_entropy print(f, ", specEntr_min"); end - if IDPMathEntropy + if math_entropy print(f, ", mathEntr_max"); end - if IDPPositivity + if positivity for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD + if variable == Trixi.density && density_tvd continue end print(f, ", $(variable)_min"); @@ -127,28 +127,28 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator @unpack idp_bounds_delta = indicator.cache println("─"^100) println("Maximum deviation from bounds:") println("─"^100) counter = 1 - if IDPDensityTVD + if density_tvd println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) counter += 2 end - if IDPSpecEntropy + if spec_entropy println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) counter += 1 end - if IDPMathEntropy + if math_entropy println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) counter += 1 end - if IDPPositivity + if positivity for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD + if variable == Trixi.density && density_tvd continue end println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 61294c23f0..2c31f40662 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -7,8 +7,8 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, time, iter, output_directory, save_errors, interval) - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = solver.volume_integral.indicator - @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack density_tvd, positivity, spec_entropy, math_entropy = solver.volume_integral.indicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator @unpack idp_bounds_delta = indicator.cache save_errors_ = save_errors && (iter % interval == 0) @@ -18,12 +18,12 @@ print(f, iter, ", ", time); end end - if IDPDensityTVD + if density_tvd deviation_min = zero(eltype(u)) deviation_max = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - deviation_min = max(deviation_min, var_bounds[1][i, j, element] - u[1, i, j, element]) - deviation_max = max(deviation_max, u[1, i, j, element] - var_bounds[2][i, j, element]) + deviation_min = max(deviation_min, variable_bounds[1][i, j, element] - u[1, i, j, element]) + deviation_max = max(deviation_max, u[1, i, j, element] - variable_bounds[2][i, j, element]) end idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) @@ -36,11 +36,11 @@ end counter += 2 end - if IDPSpecEntropy + if spec_entropy deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - s) + deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - s) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors_ @@ -51,11 +51,11 @@ end counter += 1 end - if IDPMathEntropy + if math_entropy deviation_max = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_max = max(deviation_max, s - var_bounds[counter][i, j, element]) + deviation_max = max(deviation_max, s - variable_bounds[counter][i, j, element]) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) if save_errors_ @@ -66,15 +66,15 @@ end counter += 1 end - if IDPPositivity + if positivity for variable in indicator.variables_cons - if variable == Trixi.density && IDPDensityTVD + if variable == Trixi.density && density_tvd continue end deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) var = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - var) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors_ @@ -89,7 +89,7 @@ deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) var = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, var_bounds[counter][i, j, element] - var) + deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - var) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) if save_errors_ diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index c5d47391a6..20253b3f01 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -92,7 +92,7 @@ max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral:: @inline function max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) @unpack indicator = volume_integral - if indicator isa IndicatorIDP && !indicator.BarStates + if indicator isa IndicatorIDP && !indicator.bar_states return max_dt(u, t, mesh, constant_speed, equations, dg, cache) else return max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, indicator) diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index fe9154add7..b9977a9d4f 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -47,11 +47,11 @@ end @unpack inverse_weights = dg.basis @trixi_timeit timer() "calc_lambda!" calc_lambdas_bar_states!(u, t, mesh, have_nonconservative_terms(equations), equations, indicator, dg, cache, semi.boundary_conditions; - calcBarStates=false) + calc_bar_states=false) @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates maxdt = typemax(eltype(u)) - if indicator.indicator_smooth + if indicator.smoothness_indicator @unpack element_ids_dg, element_ids_dgfv = cache alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, mesh, equations, dg, cache) pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, dg, cache) @@ -74,7 +74,7 @@ end end end - if indicator.indicator_smooth && !isempty(element_ids_dg) + if indicator.smoothness_indicator && !isempty(element_ids_dg) maxdt = min(maxdt, max_dt_RK(u, t, mesh, constant_speed, equations, dg, cache, indicator, element_ids_dg)) end diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 1b3bb229ef..a65aafef74 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -218,7 +218,7 @@ end function get_element_variables!(element_variables, u, mesh, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) - if volume_integral.indicator.indicator_smooth + if volume_integral.indicator.smoothness_indicator # call the indicator to get up-to-date values for IO volume_integral.indicator.IndicatorHG(u, mesh, equations, dg, cache) get_element_variables!(element_variables, volume_integral.indicator, volume_integral) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 5f1aa57d17..934109c493 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -417,9 +417,8 @@ end @inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, - nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calcBarStates=true) - - if indicator isa IndicatorIDP && !indicator.BarStates + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calc_bar_states=true) + if indicator isa IndicatorIDP && !indicator.bar_states return nothing end @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates @@ -437,7 +436,7 @@ end lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, normal_direction, equations) - !calcBarStates && continue + !calc_bar_states && continue flux1 = flux(u_node, normal_direction, equations) flux1_im1 = flux(u_node_im1, normal_direction, equations) @@ -454,7 +453,7 @@ end lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, normal_direction, equations) - !calcBarStates && continue + !calc_bar_states && continue flux2 = flux(u_node, normal_direction, equations) flux2_jm1 = flux(u_node_jm1, normal_direction, equations) @@ -481,7 +480,7 @@ end lambda1[nnodes(dg)+1, i, left] = lambda lambda1[1, i, element] = lambda - !calcBarStates && continue + !calc_bar_states && continue flux_left = flux(u_left, Ja1, equations) flux_element = flux(u_element, Ja1, equations) @@ -503,7 +502,7 @@ end lambda2[i, nnodes(dg)+1, lower] = lambda lambda2[i, 1, element] = lambda - !calcBarStates && continue + !calc_bar_states && continue flux_lower = flux(u_lower, Ja2, equations) flux_element = flux(u_element, Ja2, equations) @@ -532,7 +531,7 @@ end equations, dg, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) @@ -551,7 +550,7 @@ end equations, dg, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, Ja1, equations) flux_outer = flux(u_outer, Ja1, equations) @@ -572,7 +571,7 @@ end equations, dg, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) @@ -591,7 +590,7 @@ end equations, dg, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, Ja2, equations) flux_outer = flux(u_outer, Ja2, equations) @@ -605,12 +604,12 @@ end return nothing end -@inline function perform_IDP_correction(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) +@inline function perform_idp_correction(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator - if dg.volume_integral.indicator.indicator_smooth + if dg.volume_integral.indicator.smoothness_indicator elements = cache.element_ids_dgfv else elements = eachelement(dg, cache) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index a01f6064c0..2dac94866c 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1314,19 +1314,19 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) end -mutable struct ContainerShockCapturingIndicatorIDP{uEltype<:Real} +mutable struct ContainerShockCapturingIndicatorIDP2D{uEltype<:Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} - var_bounds::Vector{Array{uEltype, 3}} + variable_bounds::Vector{Array{uEltype, 3}} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} - _var_bounds::Vector{Vector{uEltype}} + _variable_bounds::Vector{Vector{uEltype}} end -function ContainerShockCapturingIndicatorIDP{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real +function ContainerShockCapturingIndicatorIDP2D{uEltype}(capacity::Integer, n_nodes, length) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1337,25 +1337,25 @@ function ContainerShockCapturingIndicatorIDP{uEltype}(capacity::Integer, n_nodes _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes+1) * capacity) alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes+1, capacity)) - _var_bounds = Vector{Vector{uEltype}}(undef, length) - var_bounds = Vector{Array{uEltype, 3}}(undef, length) + _variable_bounds = Vector{Vector{uEltype}}(undef, length) + variable_bounds = Vector{Array{uEltype, 3}}(undef, length) for i in 1:length - _var_bounds[i] = fill(nan_uEltype, n_nodes * n_nodes * capacity) - var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) + _variable_bounds[i] = fill(nan_uEltype, n_nodes * n_nodes * capacity) + variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), (n_nodes, n_nodes, capacity)) end - return ContainerShockCapturingIndicatorIDP{uEltype}(alpha, alpha1, alpha2, var_bounds, - _alpha, _alpha1, _alpha2, _var_bounds) + return ContainerShockCapturingIndicatorIDP2D{uEltype}(alpha, alpha1, alpha2, variable_bounds, + _alpha, _alpha1, _alpha2, _variable_bounds) end -nnodes(indicator::ContainerShockCapturingIndicatorIDP) = size(indicator.alpha, 1) +nnodes(indicator::ContainerShockCapturingIndicatorIDP2D) = size(indicator.alpha, 1) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) +function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP2D, capacity) n_nodes = nnodes(indicator) @unpack _alpha, _alpha1, _alpha2 = indicator @@ -1366,16 +1366,16 @@ function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP, capacity) resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - @unpack _var_bounds = indicator - for i in 1:length(_var_bounds) - resize!(_var_bounds[i], n_nodes * n_nodes * capacity) - indicator.var_bounds[i] = unsafe_wrap(Array, pointer(_var_bounds[i]), (n_nodes, n_nodes, capacity)) + @unpack _variable_bounds = indicator + for i in 1:length(_variable_bounds) + resize!(_variable_bounds[i], n_nodes * n_nodes * capacity) + indicator.variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), (n_nodes, n_nodes, capacity)) end return nothing end -mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} +mutable struct ContainerShockCapturingIndicatorMCL2D{uEltype<:Real} var_min::Array{uEltype, 4} # [variable, i, j, element] var_max::Array{uEltype, 4} # [variable, i, j, element] alpha::Array{uEltype, 4} # [variable, i, j, element] @@ -1395,7 +1395,7 @@ mutable struct ContainerShockCapturingIndicatorMCL{uEltype<:Real} _alpha_mean_entropy::Vector{uEltype} end -function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real +function ContainerShockCapturingIndicatorMCL2D{uEltype}(capacity::Integer, n_variables, n_nodes) where uEltype<:Real nan_uEltype = convert(uEltype, NaN) _var_min = Vector{uEltype}(undef, n_variables*n_nodes^2*capacity) @@ -1422,19 +1422,19 @@ function ContainerShockCapturingIndicatorMCL{uEltype}(capacity::Integer, n_varia _alpha_mean_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, + return ContainerShockCapturingIndicatorMCL2D{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) end -nvariables(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 1) -nnodes(container::ContainerShockCapturingIndicatorMCL) = size(container.var_min, 2) +nvariables(container::ContainerShockCapturingIndicatorMCL2D) = size(container.var_min, 1) +nnodes(container::ContainerShockCapturingIndicatorMCL2D) = size(container.var_min, 2) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(container::ContainerShockCapturingIndicatorMCL, capacity) +function Base.resize!(container::ContainerShockCapturingIndicatorMCL2D, capacity) n_variables = nvariables(container) n_nodes = nnodes(container) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index c0e0fa9770..47539f5991 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -28,7 +28,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) if dg.volume_integral isa VolumeIntegralShockCapturingSubcell - tol = dg.volume_integral.indicator.thr_smooth + tol = dg.volume_integral.indicator.threshold_smoothness_indicator else tol = 1e-12 end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4f0f557a02..c0693a8aa7 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -81,11 +81,10 @@ end function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) - cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) - if volume_integral.indicator.indicator_smooth + if volume_integral.indicator.smoothness_indicator element_ids_dg = Int[] element_ids_dgfv = Int[] cache = (; cache..., element_ids_dg, element_ids_dgfv) @@ -541,9 +540,9 @@ function calc_volume_integral!(du, u, @trixi_timeit timer() "calc_lambdas_bar_states!" calc_lambdas_bar_states!(u, t, mesh, nonconservative_terms, equations, indicator, dg, cache, boundary_conditions) # Calculate boundaries - @trixi_timeit timer() "calc_var_bounds!" calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) + @trixi_timeit timer() "calc_variable_bounds!" calc_variable_bounds!(u, mesh, nonconservative_terms, equations, indicator, dg, cache) - if indicator.indicator_smooth + if indicator.smoothness_indicator @unpack element_ids_dg, element_ids_dgfv = cache # Calculate element-wise blending factors α alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, mesh, equations, dg, cache) @@ -567,7 +566,7 @@ function calc_volume_integral!(du, u, volume_integral, indicator, dg, cache) end - else # indicator.indicator_smooth == false + else # indicator.smoothness_indicator == false # Loop over all elements @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for element in eachelement(dg, cache) subcell_limiting_kernel!(du, u, element, mesh, @@ -667,15 +666,10 @@ end end -# calcflux_fhat!(fhat1, fhat2, u, mesh, -# nonconservative_terms, equations, volume_flux_dg, dg, element, cache) -# # Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element # (**without non-conservative terms**). # -# # Arguments -# - `fhat1::AbstractArray{<:Real, 3}` -# - `fhat2::AbstractArray{<:Real, 3}` +# See also `flux_differencing_kernel!`. @inline function calcflux_fhat!(fhat1, fhat2, u, mesh::TreeMesh{2}, nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) @@ -744,6 +738,7 @@ end return nothing end +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @@ -793,9 +788,8 @@ end end @inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calcBarStates=true) - - if indicator isa IndicatorIDP && !indicator.BarStates + nonconservative_terms, equations, indicator, dg, cache, boundary_conditions; calc_bar_states=true) + if indicator isa IndicatorIDP && !indicator.bar_states return nothing end @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates @@ -807,7 +801,7 @@ end u_node_im1 = get_node_vars(u, equations, dg, i-1, j, element) lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, equations) - !calcBarStates && continue + !calc_bar_states && continue flux1 = flux(u_node, 1, equations) flux1_im1 = flux(u_node_im1, 1, equations) @@ -821,7 +815,7 @@ end u_node_jm1 = get_node_vars(u, equations, dg, i, j-1, element) lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, equations) - !calcBarStates && continue + !calc_bar_states && continue flux2 = flux(u_node, 2, equations) flux2_jm1 = flux(u_node_jm1, 2, equations) @@ -848,7 +842,7 @@ end lambda1[nnodes(dg)+1, j, left_id] = lambda lambda1[1, j, right_id] = lambda - !calcBarStates && continue + !calc_bar_states && continue flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) @@ -867,7 +861,7 @@ end lambda2[i, nnodes(dg)+1, left_id] = lambda lambda2[i, 1, right_id] = lambda - !calcBarStates && continue + !calc_bar_states && continue flux_left = flux(u_left, orientation, equations) flux_right = flux(u_right, orientation, equations) @@ -894,7 +888,7 @@ end equations, dg, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -910,7 +904,7 @@ end equations, dg, nnodes(dg), j, element) lambda1[nnodes(dg)+1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -928,7 +922,7 @@ end equations, dg, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -944,7 +938,7 @@ end equations, dg, i, nnodes(dg), element) lambda2[i, nnodes(dg)+1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) - !calcBarStates && continue + !calc_bar_states && continue flux_inner = flux(u_inner, orientation, equations) flux_outer = flux(u_outer, orientation, equations) @@ -960,18 +954,18 @@ end return nothing end -@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) - if !indicator.BarStates +@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, cache) + if !indicator.bar_states return nothing end - @unpack var_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2 = indicator.cache.ContainerBarStates counter = 1 # Density - if indicator.IDPDensityTVD - rho_min = var_bounds[1] - rho_max = var_bounds[2] + if indicator.density_tvd + rho_min = variable_bounds[1] + rho_max = variable_bounds[2] @threaded for element in eachelement(dg, cache) rho_min[:, :, element] .= typemax(eltype(rho_min)) rho_max[:, :, element] .= typemin(eltype(rho_max)) @@ -996,8 +990,8 @@ end counter += 2 end # Specific Entropy - if indicator.IDPSpecEntropy - s_min = var_bounds[counter] + if indicator.spec_entropy + s_min = variable_bounds[counter] @threaded for element in eachelement(dg, cache) s_min[:, :, element] .= typemax(eltype(s_min)) for j in eachnode(dg), i in eachnode(dg) @@ -1021,8 +1015,8 @@ end counter += 1 end # Mathematical entropy - if indicator.IDPMathEntropy - s_max = var_bounds[counter] + if indicator.math_entropy + s_max = variable_bounds[counter] @threaded for element in eachelement(dg, cache) s_max[:, :, element] .= typemin(eltype(s_max)) for j in eachnode(dg), i in eachnode(dg) @@ -1047,7 +1041,7 @@ end return nothing end -@inline function calc_var_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) +@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b726602ceb..e1c85b407e 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -231,105 +231,105 @@ Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturi This is an experimental feature and may change in future releases. """ struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator - IDPDensityTVD::Bool - IDPPositivity::Bool + density_tvd::Bool + positivity::Bool variables_cons::LimitingVariablesCons # Positivity of conservative variables variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables - IDPSpecEntropy::Bool - IDPMathEntropy::Bool - BarStates::Bool + spec_entropy::Bool + math_entropy::Bool + bar_states::Bool cache::Cache - positCorrFactor::RealT # Correction factor for IDPPositivity - IDPMaxIter::Int # Maximal number of iterations for Newton's method - newton_tol::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method - IDPgamma::RealT # Constant for the subcell limiting of convex (nonlinear) constraints - # (must be IDPgamma>=2*d, where d is the number of dimensions of the problem) - indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner - thr_smooth::RealT # threshold for smoothness indicator + positivity_correction_factor::RealT # Correction factor for positivity + max_iterations_newton::Int # Maximal number of iterations for Newton's method + newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method + gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints + # (gamma_constant_newton>=2*d, where d=#dimensions) + smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner + threshold_smoothness_indicator::RealT # threshold for smoothness indicator IndicatorHG::Indicator end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; - IDPDensityTVD=false, - IDPPositivity=false, - variables_cons=(first,), + density_tvd=false, + positivity=false, + variables_cons=(), variables_nonlinear=(), - IDPSpecEntropy=false, - IDPMathEntropy=false, - BarStates=true, - positCorrFactor=0.1, IDPMaxIter=10, - newton_tol=(1.0e-12, 1.0e-14), IDP_gamma=2*ndims(equations), - indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure) - - if IDPMathEntropy && IDPSpecEntropy - error("Only one of the two can be selected: IDPMathEntropy/IDPSpecEntropy") + spec_entropy=false, + math_entropy=false, + bar_states=true, + positivity_correction_factor=0.1, max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), gamma_constant_newton=2*ndims(equations), + smoothness_indicator=false, threshold_smoothness_indicator=0.1, + variable_smoothness_indicator=density_pressure) + if math_entropy && spec_entropy + error("Only one of the two can be selected: math_entropy/spec_entropy") end - number_bounds = IDPPositivity * (length(variables_cons) + length(variables_nonlinear)) + - IDPSpecEntropy + IDPMathEntropy + number_bounds = positivity * (length(variables_cons) + length(variables_nonlinear)) + + spec_entropy + math_entropy if equations isa AbstractCompressibleEulerEquations - if IDPDensityTVD - number_bounds += 2 - IDPPositivity * (Trixi.density in variables_cons) + if density_tvd + number_bounds += 2 - positivity * (Trixi.density in variables_cons) end end - cache = create_cache(IndicatorIDP, equations, basis, number_bounds, BarStates) + cache = create_cache(IndicatorIDP, equations, basis, number_bounds, bar_states) - if indicator_smooth + if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max=1.0, alpha_smooth=false, - variable=variable_smooth) + variable=variable_smoothness_indicator) else IndicatorHG = nothing end - IndicatorIDP{typeof(positCorrFactor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( - IDPDensityTVD, IDPPositivity, variables_cons, variables_nonlinear, IDPSpecEntropy, IDPMathEntropy, - BarStates, cache, positCorrFactor, IDPMaxIter, newton_tol, IDP_gamma, indicator_smooth, thr_smooth, IndicatorHG) + IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( + density_tvd, positivity, variables_cons, variables_nonlinear, spec_entropy, math_entropy, + bar_states, cache, positivity_correction_factor, max_iterations_newton, newton_tolerances, gamma_constant_newton, smoothness_indicator, threshold_smoothness_indicator, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator print(io, "IndicatorIDP(") - if !(IDPDensityTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + if !(density_tvd || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else print(io, "limiter=(") - IDPDensityTVD && print(io, "IDPDensityTVD, ") - IDPPositivity && print(io, "IDPPositivity, ") - IDPSpecEntropy && print(io, "IDPSpecEntropy, ") - IDPMathEntropy && print(io, "IDPMathEntropy, ") + density_tvd && print(io, "density, ") + positivity && print(io, "positivity, ") + spec_entropy && print(io, "specific entropy, ") + math_entropy && print(io, "mathematical entropy, ") print(io, "), ") end - indicator.indicator_smooth && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, - " with threshold ", indicator.thr_smooth, "), ") - print(io, "Local bounds with $(indicator.BarStates ? "Bar States" : "FV solution")") + indicator.smoothness_indicator && print(io, ", Smoothness indicator: ", indicator.IndicatorHG, + " with threshold ", indicator.threshold_smoothness_indicator, "), ") + print(io, "Local bounds with $(indicator.bar_states ? "Bar States" : "FV solution")") print(io, ")") end function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy, IDPMathEntropy = indicator + @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator if get(io, :compact, false) show(io, indicator) else - if !(IDPDensityTVD || IDPPositivity || IDPSpecEntropy || IDPMathEntropy) + if !(density_tvd || positivity || spec_entropy || math_entropy) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] - IDPDensityTVD && (setup = [setup..., "" => "IDPDensityTVD"]) - if IDPPositivity - string = "IDPPositivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" + density_tvd && (setup = [setup..., "" => "density"]) + if positivity + string = "positivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" setup = [setup..., "" => string] - setup = [setup..., "" => " "^14 * "and positivity correlation factor $(indicator.positCorrFactor)"] + setup = [setup..., "" => " "^14 * "and positivity correlation factor $(indicator.positivity_correction_factor)"] end - IDPSpecEntropy && (setup = [setup..., "" => "IDPSpecEntropy"]) - IDPMathEntropy && (setup = [setup..., "" => "IDPMathEntropy"]) - setup = [setup..., "Local bounds" => (indicator.BarStates ? "Bar States" : "FV solution")] - if indicator.indicator_smooth - setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + spec_entropy && (setup = [setup..., "" => "specific entropy"]) + math_entropy && (setup = [setup..., "" => "mathematical entropy"]) + setup = [setup..., "Local bounds" => (indicator.bar_states ? "Bar States" : "FV solution")] + if indicator.smoothness_indicator + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.threshold_smoothness_indicator)"] end end summary_box(io, "IndicatorIDP", setup) @@ -362,8 +362,8 @@ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator DensityPositivityLimiter::Bool DensityPositivityCorrelationFactor::RealT SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix - indicator_smooth::Bool # activates smoothness indicator: IndicatorHennemannGassner - thr_smooth::RealT # threshold for smoothness indicator + smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner + threshold_smoothness_indicator::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end @@ -379,23 +379,23 @@ function IndicatorMCL(equations::AbstractEquations, basis; DensityPositivityLimiter=false, # Impose positivity for cons(1) DensityPositivityCorrelationFactor=0.0,# Correlation Factor for DensityPositivityLimiter in [0,1) SemiDiscEntropyLimiter=false, - indicator_smooth=false, thr_smooth=0.1, variable_smooth=density_pressure, + smoothness_indicator=false, threshold_smoothness_indicator=0.1, variable_smoothness_indicator=density_pressure, Plotting=true) if SequentialLimiter && ConservativeLimiter error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") end cache = create_cache(IndicatorMCL, equations, basis, PressurePositivityLimiterKuzmin) - if indicator_smooth + if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth=false, - variable=variable_smooth) + variable=variable_smoothness_indicator) else IndicatorHG = nothing end - IndicatorMCL{typeof(thr_smooth), typeof(cache), typeof(IndicatorHG)}(cache, + IndicatorMCL{typeof(threshold_smoothness_indicator), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, DensityPositivityCorrelationFactor, SemiDiscEntropyLimiter, - indicator_smooth, thr_smooth, IndicatorHG, Plotting) + smoothness_indicator, threshold_smoothness_indicator, IndicatorHG, Plotting) end function Base.show(io::IO, indicator::IndicatorMCL) @@ -412,8 +412,8 @@ function Base.show(io::IO, indicator::IndicatorMCL) indicator.DensityPositivityLimiter && print(io, "; dens pos") (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") - indicator.indicator_smooth && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, - " with threshold ", indicator.thr_smooth) + indicator.smoothness_indicator && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, + " with threshold ", indicator.threshold_smoothness_indicator) print(io, ")") end @@ -441,8 +441,8 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) end end SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) - if indicator.indicator_smooth - setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.thr_smooth)"] + if indicator.smoothness_indicator + setup = [setup..., "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.threshold_smoothness_indicator)"] end summary_box(io, "IndicatorMCL", setup) end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 09630ac828..ed59f1545c 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -186,11 +186,11 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, BarStates) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP{real(basis)}(0, nnodes(basis), number_bounds) +function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, bar_states) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP2D{real(basis)}(0, nnodes(basis), number_bounds) cache = (; ) - if BarStates + if bar_states ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) cache = (; cache..., ContainerBarStates) end @@ -202,26 +202,26 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation return (; cache..., alpha_max_avg, ContainerShockCapturingIndicator, idp_bounds_delta) end -function (indicator_IDP::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) - @unpack alpha = indicator_IDP.cache.ContainerShockCapturingIndicator - alpha .= 0.0 - if indicator_IDP.indicator_smooth +function (indicator::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) + @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + alpha .= zero(eltype(alpha)) + if indicator.smoothness_indicator elements = semi.cache.element_ids_dgfv else elements = eachelement(dg, semi.cache) end - indicator_IDP.IDPDensityTVD && - @trixi_timeit timer() "IDPDensityTVD" IDP_densityTVD!( alpha, indicator_IDP, u, t, dt, semi, elements) - indicator_IDP.IDPPositivity && - @trixi_timeit timer() "IDPPositivity" IDP_positivity!( alpha, indicator_IDP, u, dt, semi, elements) - indicator_IDP.IDPSpecEntropy && - @trixi_timeit timer() "IDPSpecEntropy" IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) - indicator_IDP.IDPMathEntropy && - @trixi_timeit timer() "IDPMathEntropy" IDP_mathEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) + indicator.density_tvd && + @trixi_timeit timer() "density_tvd" idp_density_tvd!( alpha, indicator, u, t, dt, semi, elements) + indicator.positivity && + @trixi_timeit timer() "positivity" idp_positivity!( alpha, indicator, u, dt, semi, elements) + indicator.spec_entropy && + @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) + indicator.math_entropy && + @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack alpha1, alpha2 = indicator.cache.ContainerShockCapturingIndicator @threaded for element in elements for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) @@ -446,14 +446,14 @@ end return nothing end -@inline function IDP_densityTVD!(alpha, indicator_IDP, u, t, dt, semi, elements) +@inline function idp_density_tvd!(alpha, indicator, u, t, dt, semi, elements) mesh, _, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - rho_min = var_bounds[1] - rho_max = var_bounds[2] - if !indicator_IDP.BarStates + rho_min = variable_bounds[1] + rho_max = variable_bounds[2] + if !indicator.bar_states calc_bounds_2sided!(rho_min, rho_max, density, u, t, semi) end @@ -475,8 +475,8 @@ end # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qp = max(0.0, (rho_max[i, j, element] - rho) / dt) - Qm = min(0.0, (rho_min[i, j, element] - rho) / dt) + Qp = max(0, (rho_max[i, j, element] - rho) / dt) + Qm = min(0, (rho_min[i, j, element] - rho) / dt) # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -485,10 +485,10 @@ end val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] - Pp = max(0.0, val_flux1_local) + max(0.0, val_flux1_local_ip1) + - max(0.0, val_flux2_local) + max(0.0, val_flux2_local_jp1) - Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) Pp = inverse_jacobian * Pp Pm = inverse_jacobian * Pm @@ -498,21 +498,21 @@ end Qm = abs(Qm) / (abs(Pm) + eps() * 100 * abs(rho_max[i, j, element])) # Calculate alpha at nodes - alpha[i, j, element] = 1 - min(1.0, Qp, Qm) + alpha[i, j, element] = 1 - min(1, Qp, Qm) end end return nothing end -@inline function IDP_specEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) +@inline function idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack IDPDensityTVD, IDPPositivity = indicator_IDP - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack density_tvd, positivity = indicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - s_min = var_bounds[2 * IDPDensityTVD + 1] - if !indicator_IDP.BarStates + s_min = variable_bounds[2 * density_tvd + 1] + if !indicator.bar_states calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -522,7 +522,7 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator) end end @@ -533,14 +533,14 @@ specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_mathEntropy!(alpha, indicator_IDP, u, t, dt, semi, elements) +@inline function idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack IDPDensityTVD, IDPPositivity, IDPSpecEntropy = indicator_IDP - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack density_tvd, positivity, spec_entropy = indicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - s_max = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + 1] - if !indicator_IDP.BarStates + s_max = variable_bounds[2 * density_tvd + spec_entropy + 1] + if !indicator.bar_states calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -550,7 +550,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator) end end @@ -561,37 +561,37 @@ mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entropy(u, equations), dt * antidiffusive_flux) mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) -@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements) +@inline function idp_positivity!(alpha, indicator, u, dt, semi, elements) # Conservative variables - for (index, variable) in enumerate(indicator_IDP.variables_cons) - IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) + for (index, variable) in enumerate(indicator.variables_cons) + idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) end # Nonlinear variables - for (index, variable) in enumerate(indicator_IDP.variables_nonlinear) - IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) + for (index, variable) in enumerate(indicator.variables_nonlinear) + idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) end return nothing end -@inline function IDP_positivity!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) +@inline function idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D @unpack inverse_weights = dg.basis - @unpack IDPDensityTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons = indicator_IDP + @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons = indicator - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - if Trixi.density in variables_cons && IDPDensityTVD + if Trixi.density in variables_cons && density_tvd if Trixi.density == variables_cons[index] - var_min = var_bounds[1] + var_min = variable_bounds[1] else - var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + index - 1] + var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index - 1] end else - var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + index] + var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index] end @threaded for element in elements @@ -605,14 +605,14 @@ end var = variable(get_node_vars(u, equations, dg, i, j, element), equations) if var < 0.0 - println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end # Compute bound - if indicator_IDP.IDPDensityTVD - var_min[i, j, element] = max(var_min[i, j, element], positCorrFactor * var) + if indicator.density_tvd + var_min[i, j, element] = max(var_min[i, j, element], positivity_correction_factor * var) else - var_min[i, j, element] = positCorrFactor * var + var_min[i, j, element] = positivity_correction_factor * var end # Real one-sided Zalesak-type limiter @@ -620,7 +620,7 @@ end # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qm = min(0.0, (var_min[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. @@ -629,8 +629,8 @@ end val_flux2_local = inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) val_flux2_local_jp1 = -inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) - Pm = min(0.0, val_flux1_local) + min(0.0, val_flux1_local_ip1) + - min(0.0, val_flux2_local) + min(0.0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) Pm = inverse_jacobian * Pm # Compute blending coefficient avoiding division by zero @@ -646,15 +646,15 @@ end end -@inline function IDP_positivity_newton!(alpha, indicator_IDP, u, dt, semi, elements, variable, index) +@inline function idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack IDPDensityTVD, IDPSpecEntropy, IDPMathEntropy, positCorrFactor, variables_cons, variables_nonlinear = indicator_IDP + @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons, variables_nonlinear = indicator - @unpack var_bounds = indicator_IDP.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - var_min = var_bounds[2 * IDPDensityTVD + IDPSpecEntropy + IDPMathEntropy + - length(variables_cons) - min(IDPDensityTVD, Trixi.density in variables_cons) + - index] + var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + + length(variables_cons) - min(density_tvd, Trixi.density in variables_cons) + + index] @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) @@ -662,14 +662,14 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) var = variable(u_local, equations) if var < 0.0 - println("Error: safe $variable is not safe. element=$element, node: $i $j, value=$var") + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end - var_min[i, j, element] = positCorrFactor * var + var_min[i, j, element] = positivity_correction_factor * var # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, - dt, mesh, equations, dg, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator) end end @@ -683,7 +683,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - dt, mesh, equations, dg, cache, indicator_IDP) + dt, mesh, equations, dg, cache, indicator) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D if mesh isa TreeMesh @@ -692,35 +692,35 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - @unpack IDPgamma = indicator_IDP + @unpack gamma_constant_newton = indicator # negative xi direction - antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator, antidiffusive_flux) # positive xi direction - antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator, antidiffusive_flux) # negative eta direction - antidiffusive_flux = IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator, antidiffusive_flux) # positive eta direction - antidiffusive_flux = -IDPgamma * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator_IDP, antidiffusive_flux) + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, equations, dt, indicator, antidiffusive_flux) return nothing end @inline function newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - equations, dt, indicator_IDP, antidiffusive_flux) - newton_reltol, newton_abstol = indicator_IDP.newton_tol + equations, dt, indicator, antidiffusive_flux) + newton_reltol, newton_abstol = indicator.newton_tolerances - beta = 1.0 - alpha[i, j, element] + beta = 1 - alpha[i, j, element] - beta_L = 0.0 # alpha = 1 + beta_L = 0 # alpha = 1 beta_R = beta # No higher beta (lower alpha) than the current one u_curr = u + beta * dt * antidiffusive_flux @@ -733,7 +733,7 @@ end end # Newton iterations - for iter in 1:indicator_IDP.IDPMaxIter + for iter in 1:indicator.max_iterations_newton beta_old = beta # If the state is valid, evaluate d(goal)/d(beta) @@ -793,10 +793,6 @@ end if finalCheck(bound, as, newton_abstol) break end - - # if iter == indicator_IDP.IDPMaxIter - # @warn "Maximum number of iterations for the Newton-bisection algorithm reached." - # end end new_alpha = 1.0 - beta @@ -863,7 +859,7 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL{real(basis)}(0, nvariables(equations), nnodes(basis)) + ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL2D{real(basis)}(0, nvariables(equations), nnodes(basis)) ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiterKuzmin) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 32c3f44e6a..3c08ea04b1 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -260,7 +260,7 @@ function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell resize!(volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) # Calc subcell normal directions before StepsizeCallback @unpack indicator = volume_integral - if indicator isa IndicatorMCL || (indicator isa IndicatorIDP && indicator.BarStates) + if indicator isa IndicatorMCL || (indicator isa IndicatorIDP && indicator.bar_states) resize!(indicator.cache.ContainerBarStates, new_size) calc_normal_directions!(indicator.cache.ContainerBarStates, mesh_equations_solver_cache(semi)...) end From ce1022089c708ce09f81673c8f37c1b483c26d31 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 09:42:44 +0200 Subject: [PATCH 211/423] Relocate `perform_antidiffusive_stage!` --- src/callbacks_stage/antidiffusive_stage.jl | 34 +-------- src/callbacks_stage/antidiffusive_stage_2d.jl | 74 +++++++++++++++++++ src/solvers/dgsem_structured/dg_2d.jl | 32 -------- 3 files changed, 76 insertions(+), 64 deletions(-) create mode 100644 src/callbacks_stage/antidiffusive_stage_2d.jl diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl index 8960a14f3d..b22a707ce9 100644 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -33,38 +33,7 @@ function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicato @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) - perform_idp_correction(u, dt, mesh, equations, solver, cache) - - return nothing -end - -@inline function perform_idp_correction(u, dt, mesh::TreeMesh2D, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator - if dg.volume_integral.indicator.smoothness_indicator - elements = cache.element_ids_dgfv - else - elements = eachelement(dg, cache) - end - - # Loop over blended DG-FV elements - @threaded for element in elements - inverse_jacobian = -cache.elements.inverse_jacobian[element] - - for j in eachnode(dg), i in eachnode(dg) - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) - end - end - end + perform_idp_correction!(u, dt, mesh, equations, solver, cache) return nothing end @@ -73,5 +42,6 @@ init_callback(callback::AntidiffusiveStage, semi) = nothing finalize_callback(antidiffusive_stage!::AntidiffusiveStage, semi) = nothing +include("antidiffusive_stage_2d.jl") end # @muladd diff --git a/src/callbacks_stage/antidiffusive_stage_2d.jl b/src/callbacks_stage/antidiffusive_stage_2d.jl new file mode 100644 index 0000000000..9e066148c8 --- /dev/null +++ b/src/callbacks_stage/antidiffusive_stage_2d.jl @@ -0,0 +1,74 @@ +# 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 + + +@inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + if dg.volume_integral.indicator.smoothness_indicator + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end + + # Loop over blended DG-FV elements + @threaded for element in elements + # Sign switch as in apply_jacobian! + inverse_jacobian = -cache.elements.inverse_jacobian[element] + + for j in eachnode(dg), i in eachnode(dg) + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) + end + end + end + + return nothing +end + + +@inline function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + + if dg.volume_integral.indicator.smoothness_indicator + elements = cache.element_ids_dgfv + else + elements = eachelement(dg, cache) + end + + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + # Sign switch as in apply_jacobian! + inverse_jacobian = -cache.elements.inverse_jacobian[i, j, element] + + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) + alpha_flux1_ip1 = (1 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) + alpha_flux2 = (1 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) + alpha_flux2_jp1 = (1 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) + end + end + end + + return nothing +end + + +end # @muladd diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 934109c493..31a399da18 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -604,38 +604,6 @@ end return nothing end -@inline function perform_idp_correction(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator - - if dg.volume_integral.indicator.smoothness_indicator - elements = cache.element_ids_dgfv - else - elements = eachelement(dg, cache) - end - - @threaded for element in elements - # @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = -cache.elements.inverse_jacobian[i, j, element] - - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1.0 - alpha1[i, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - alpha_flux1_ip1 = (1.0 - alpha1[i+1, j, element]) * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element) - alpha_flux2 = (1.0 - alpha2[i, j, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - alpha_flux2_jp1 = (1.0 - alpha2[i, j+1, element]) * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * (inverse_weights[i] * (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * (alpha_flux2_jp1[v] - alpha_flux2[v]) ) - end - end - end - - return nothing -end - function calc_interface_flux!(cache, u, mesh::StructuredMesh{2}, From ba29ec9fe19604072006194e6ce98843fc5e8254 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 10:34:15 +0200 Subject: [PATCH 212/423] Use `snake_case` for container variable --- src/callbacks_stage/antidiffusive_stage_2d.jl | 4 ++-- src/callbacks_stage/bounds_check_2d.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 12 ++++++------ src/solvers/dgsem_tree/indicators_2d.jl | 6 +++--- src/time_integration/methods_SSP.jl | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/callbacks_stage/antidiffusive_stage_2d.jl b/src/callbacks_stage/antidiffusive_stage_2d.jl index 9e066148c8..9e7c365781 100644 --- a/src/callbacks_stage/antidiffusive_stage_2d.jl +++ b/src/callbacks_stage/antidiffusive_stage_2d.jl @@ -7,7 +7,7 @@ @inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator if dg.volume_integral.indicator.smoothness_indicator elements = cache.element_ids_dgfv @@ -40,7 +40,7 @@ end @inline function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator if dg.volume_integral.indicator.smoothness_indicator diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 2c31f40662..75f45f41d0 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -114,7 +114,7 @@ end @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates @unpack idp_bounds_delta = solver.volume_integral.indicator.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux n_vars = nvariables(equations) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c0693a8aa7..3eb274de64 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -98,9 +98,9 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg)+1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - ContainerAntidiffusiveFlux2D = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) + container_antidiffusive_flux = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., ContainerAntidiffusiveFlux2D, fhat1_threaded, fhat2_threaded, flux_temp_threaded) + return (; cache..., container_antidiffusive_flux, fhat1_threaded, fhat2_threaded, flux_temp_threaded) end @@ -651,7 +651,7 @@ end calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache, fstar1_L, fstar2_L) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * (fstar1_L[v, i+1, j] - fstar1_R[v, i, j]) + @@ -741,7 +741,7 @@ end # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorIDP, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -765,7 +765,7 @@ end @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -1152,7 +1152,7 @@ end @inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache, fstar1, fstar2) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ed59f1545c..8990d7d823 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -457,7 +457,7 @@ end calc_bounds_2sided!(rho_min, rho_max, density, u, t, semi) end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack inverse_weights = dg.basis @threaded for element in elements @@ -578,7 +578,7 @@ end @inline function idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack inverse_weights = dg.basis @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons = indicator @@ -685,7 +685,7 @@ pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -ma goal_fct, dgoal_fct, initialCheck, finalCheck, dt, mesh, equations, dg, cache, indicator) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.ContainerAntidiffusiveFlux2D + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux if mesh isa TreeMesh inverse_jacobian = cache.elements.inverse_jacobian[element] else # mesh isa StructuredMesh diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 3c08ea04b1..0e1b8ffd87 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -253,8 +253,8 @@ end Base.resize!(semi, volume_integral::AbstractVolumeIntegral, new_size) = nothing function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell, new_size) - # Resize ContainerAntidiffusiveFlux2D - resize!(semi.cache.ContainerAntidiffusiveFlux2D, new_size) + # Resize container_antidiffusive_flux + resize!(semi.cache.container_antidiffusive_flux, new_size) # Resize ContainerShockCapturingIndicator resize!(volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) From bcda26e288d09207b38254e06fcac85be72476c5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 10:36:18 +0200 Subject: [PATCH 213/423] Implement other suggestions --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- ...elixir_euler_convergence_wavingflag_MCL.jl | 2 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_double_mach_MCL.jl | 2 +- .../elixir_euler_free_stream_MCL.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_shock_upstream_MCL.jl | 2 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_MCL.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_MCL.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- .../elixir_euler_convergence_MCL.jl | 2 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 2 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- src/callbacks_stage/antidiffusive_stage.jl | 7 +++- src/solvers/dgsem_tree/indicators_2d.jl | 37 ++++++++++--------- src/time_integration/methods_SSP.jl | 15 +++++--- 24 files changed, 55 insertions(+), 46 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index ae9f72da3c..543846eb80 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -70,7 +70,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index 598f7529bf..fb2b0120dd 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -70,7 +70,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 2da995f6b1..ab4ba667fe 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -141,7 +141,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 2b8b2fe8f7..083e2a33d1 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -145,7 +145,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 5bacc7971e..25211ad7c0 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -86,7 +86,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 6cd0ce7fb7..d0cae7a4d7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 37f5d6d91c..3cba12047e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -135,7 +135,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 0865225816..b72a88551c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -132,7 +132,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 540b78d9a9..8235d51d89 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -67,7 +67,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 6fed8ae11d..3a3fa30bba 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -94,7 +94,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 38d8042dc4..e539ff43b5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -90,7 +90,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 136d8839e5..29701cc063 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -94,7 +94,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index c12054b3d7..8193ddcdb1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 7f847c81da..0c4930479b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -65,7 +65,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index cda56dca07..1e33b664e1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -65,7 +65,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index b333436a98..464ae20782 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -90,7 +90,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback maxiters=1e7, callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index c2c3e5d813..71054ec974 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -86,7 +86,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index cec2298157..c5268e3d3d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -94,7 +94,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=true),) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index c790b8a639..4ed757e38e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -91,7 +91,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 89924b1cce..cbe12a5e00 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -62,7 +62,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index b24c413834..0e9ff85b94 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -141,7 +141,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode; alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks), +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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 \ No newline at end of file diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl index b22a707ce9..27468dda17 100644 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -24,14 +24,17 @@ function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, volume_i @trixi_timeit timer() "antidiffusive_stage!" antidiffusive_stage!(u_ode, semi, t, dt, volume_integral.indicator) end -(::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorMCL) = nothing +(::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "alpha calculation" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) + # Calculate blending factor alpha in [0,1] + # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij + # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij + @trixi_timeit timer() "blending factor alpha" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) perform_idp_correction!(u, dt, mesh, equations, solver, cache) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 8990d7d823..ee5f9c7e6d 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -211,14 +211,18 @@ function (indicator::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t elements = eachelement(dg, semi.cache) end - indicator.density_tvd && + if indicator.density_tvd @trixi_timeit timer() "density_tvd" idp_density_tvd!( alpha, indicator, u, t, dt, semi, elements) - indicator.positivity && + end + if indicator.positivity @trixi_timeit timer() "positivity" idp_positivity!( alpha, indicator, u, dt, semi, elements) - indicator.spec_entropy && + end + if indicator.spec_entropy @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) - indicator.math_entropy && + end + if indicator.math_entropy @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) + end # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = indicator.cache.ContainerShockCapturingIndicator @@ -494,8 +498,8 @@ end # Compute blending coefficient avoiding division by zero # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / (abs(Pp) + eps() * 100 * abs(rho_max[i, j, element])) - Qm = abs(Qm) / (abs(Pm) + eps() * 100 * abs(rho_max[i, j, element])) + Qp = abs(Qp) / (abs(Pp) + eps(typeof(Qp)) * 100 * abs(rho_max[i, j, element])) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100 * abs(rho_max[i, j, element])) # Calculate alpha at nodes alpha[i, j, element] = 1 - min(1, Qp, Qm) @@ -604,7 +608,7 @@ end end var = variable(get_node_vars(u, equations, dg, i, j, element), equations) - if var < 0.0 + if var < 0 error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end @@ -635,7 +639,7 @@ end # Compute blending coefficient avoiding division by zero # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qm = abs(Qm) / (abs(Pm) + eps() * 100) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) # Calculate alpha alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) @@ -661,7 +665,7 @@ end # Compute bound u_local = get_node_vars(u, equations, dg, i, j, element) var = variable(u_local, equations) - if var < 0.0 + if var < 0 error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end var_min[i, j, element] = positivity_correction_factor * var @@ -678,7 +682,7 @@ end pressure_goal(bound, u, equations) = bound - pressure(u, equations) pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(dpdu(u, equations), dt * antidiffusive_flux) -pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0.0 +pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0 pressure_finalCheck(bound, goal, newton_abstol) = (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, @@ -740,16 +744,16 @@ end if isValidState(u_curr, equations) dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) else # Otherwise, perform a bisection step - dSdbeta = 0.0 + dSdbeta = 0 end - if dSdbeta != 0.0 + if dSdbeta != 0 # Update beta with Newton's method beta = beta - as / dSdbeta end # Check bounds - if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0.0) || isnan(beta) + if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0) || isnan(beta) # Out of bounds, do a bisection step beta = 0.5 * (beta_L + beta_R) # Get new u @@ -795,7 +799,7 @@ end end end - new_alpha = 1.0 - beta + new_alpha = 1 - beta if alpha[i, j, element] > new_alpha + newton_abstol error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") else @@ -867,10 +871,7 @@ function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquation return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) end -@inline function update_alpha_max_avg!(indicator::IndicatorMCL, timestep, n_stages, semi, mesh) - - return nothing -end +update_alpha_max_avg!(indicator::AbstractIndicator, timestep, n_stages, semi, mesh) = nothing @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 0e1b8ffd87..2afbbaf244 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -10,10 +10,15 @@ abstract type SimpleAlgorithmSSP end """ - SimpleSSPRK33() + SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) -The third-order SSP Runge-Kutta method of - Shu, Osher (1988) Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes, eq. 2.18. +The third-order SSP Runge-Kutta method of Shu and Osher. + +## References + +- Shu, Osher (1988) + "Efficient Implementation of Essentially Non-oscillatory Shock-Capturing Schemes" (Eq. 2.18) + [DOI: 10.1016/0021-9991(88)90177-5](https://doi.org/10.1016/0021-9991(88)90177-5) !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. @@ -85,7 +90,7 @@ function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) end """ - solve(ode; dt, callbacks, kwargs...) + solve(ode, alg; dt, callbacks, kwargs...) The following structures and methods provide a implementation of the third-order SSP Runge-Kutta method [`SimpleSSPRK33`](@ref). @@ -93,7 +98,7 @@ method [`SimpleSSPRK33`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -function solve(ode::ODEProblem; alg=SimpleSSPRK33()::SimpleAlgorithmSSP, +function solve(ode::ODEProblem, alg=SimpleSSPRK33()::SimpleAlgorithmSSP; dt, callback=nothing, kwargs...) u = copy(ode.u0) du = similar(u) From 70ec95750f2fcb02b5b03624fafdf8ef2595c657 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 11:56:26 +0200 Subject: [PATCH 214/423] Merge branch 'IDPlimiting-positivity-cons' into subcell-limiting --- .../elixir_euler_shockcapturing_subcell.jl | 92 +++++++++++++++++++ ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- src/callbacks_stage/antidiffusive_stage.jl | 3 + src/time_integration/methods_SSP.jl | 2 +- test/test_tree_2d_euler.jl | 6 ++ 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl new file mode 100644 index 0000000000..69e502a184 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -0,0 +1,92 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +A medium blast wave (modified to lower density and higher pressure) taken from +- Sebastian Hennemann, Gregor J. 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) +""" +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables "normal" medium blast wave + rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorIDP(equations, basis; + positivity=true, variables_cons=(Trixi.density,), positivity_correction_factor=0.5, + bar_states=false) +volume_integral = VolumeIntegralShockCapturingSubcell(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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=5, + n_cells_max=100_000) + +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 = 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=0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) + +sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); + 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_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index 0e9ff85b94..e92cbde352 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -102,7 +102,7 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.25, -2.225) coordinates_max = ( 2.20, 2.225) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, + initial_refinement_level=3, n_cells_max=1_000_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl index 27468dda17..896add78ab 100644 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ b/src/callbacks_stage/antidiffusive_stage.jl @@ -9,6 +9,9 @@ AntidiffusiveStage() Perform antidiffusive stage for IDP limiting. + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. """ struct AntidiffusiveStage end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 2afbbaf244..69f33c0311 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -4,7 +4,7 @@ # See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. @muladd begin -# Abstract base type for time integration schemes of explicit strong stabilitypreserving (SSP) +# Abstract base type for time integration schemes of explicit strong stability-preserving (SSP) # Runge-Kutta (RK) methods. They are high-order time discretizations that guarantee the TVD property. abstract type SimpleAlgorithmSSP end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index cd4550c559..36a24bc5ae 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -63,6 +63,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) end + @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), + l2 = [0.08508147906199143, 0.04510299017724501, 0.045103019801950375, 0.6930704343869766], + linf = [0.31123546471463326, 0.5616274869594462, 0.5619692712224448, 2.88670199345138]) + end + @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), l2 = [0.14170569763947993, 0.11647068900798814, 0.11647072556898294, 0.3391989213659599], From 8d58c7dbf5ee28060896be01dfcacc49f04c4917 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 12:22:44 +0200 Subject: [PATCH 215/423] Rename container variables using `snake_case` --- src/callbacks_stage/antidiffusive_stage_2d.jl | 4 +- src/callbacks_stage/bounds_check_2d.jl | 6 +-- src/callbacks_step/stepsize_dg2d.jl | 2 +- src/solvers/dgsem_structured/dg_2d.jl | 4 +- src/solvers/dgsem_structured/indicators_2d.jl | 4 +- src/solvers/dgsem_tree/dg_2d.jl | 44 +++++++++---------- src/solvers/dgsem_tree/indicators.jl | 16 +++---- src/solvers/dgsem_tree/indicators_2d.jl | 32 +++++++------- src/time_integration/methods_SSP.jl | 16 +++---- 9 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/callbacks_stage/antidiffusive_stage_2d.jl b/src/callbacks_stage/antidiffusive_stage_2d.jl index 9e7c365781..7b13897103 100644 --- a/src/callbacks_stage/antidiffusive_stage_2d.jl +++ b/src/callbacks_stage/antidiffusive_stage_2d.jl @@ -8,7 +8,7 @@ @inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.container_shock_capturing if dg.volume_integral.indicator.smoothness_indicator elements = cache.element_ids_dgfv else @@ -41,7 +41,7 @@ end @inline function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.ContainerShockCapturingIndicator + @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.container_shock_capturing if dg.volume_integral.indicator.smoothness_indicator elements = cache.element_ids_dgfv diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 75f45f41d0..61e7757fc3 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -8,7 +8,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, time, iter, output_directory, save_errors, interval) @unpack density_tvd, positivity, spec_entropy, math_entropy = solver.volume_integral.indicator - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing @unpack idp_bounds_delta = indicator.cache save_errors_ = save_errors && (iter % interval == 0) @@ -111,8 +111,8 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorMCL, time, iter, output_directory, save_errors, interval) - @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates + @unpack var_min, var_max = indicator.cache.container_shock_capturing + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states @unpack idp_bounds_delta = solver.volume_integral.indicator.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index b9977a9d4f..27af7932f7 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -48,7 +48,7 @@ end @trixi_timeit timer() "calc_lambda!" calc_lambdas_bar_states!(u, t, mesh, have_nonconservative_terms(equations), equations, indicator, dg, cache, semi.boundary_conditions; calc_bar_states=false) - @unpack lambda1, lambda2 = indicator.cache.ContainerBarStates + @unpack lambda1, lambda2 = indicator.cache.container_bar_states maxdt = typemax(eltype(u)) if indicator.smoothness_indicator diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 31a399da18..985e38fdfb 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -421,10 +421,10 @@ end if indicator isa IndicatorIDP && !indicator.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.container_bar_states @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = indicator.cache.ContainerBarStates + @unpack normal_direction_xi, normal_direction_eta = indicator.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index e435c146ff..17a49bdebd 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -233,7 +233,7 @@ end _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis @unpack alpha_max_avg = indicator.cache - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha = indicator.cache.container_shock_capturing alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) alpha_avg = zero(eltype(alpha)) @@ -253,7 +253,7 @@ end @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::StructuredMesh{2}, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.container_shock_capturing # Save the alphas every x iterations x = 1 diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 3eb274de64..474a6a16ad 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -792,7 +792,7 @@ end if indicator isa IndicatorIDP && !indicator.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.ContainerBarStates + @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) @@ -958,8 +958,8 @@ end if !indicator.bar_states return nothing end - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2 = indicator.cache.ContainerBarStates + @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack bar_states1, bar_states2 = indicator.cache.container_bar_states counter = 1 # Density @@ -1042,8 +1042,8 @@ end end @inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, indicator::IndicatorMCL, dg, cache) - @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates + @unpack var_min, var_max = indicator.cache.container_shock_capturing + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states @threaded for element in eachelement(dg, cache) for v in eachvariable(equations) @@ -1153,11 +1153,11 @@ end @inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, indicator, dg, element, cache, fstar1, fstar2) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack var_min, var_max = indicator.cache.ContainerShockCapturingIndicator - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.ContainerBarStates + @unpack var_min, var_max = indicator.cache.container_shock_capturing + @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states if indicator.Plotting - @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.container_shock_capturing for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) @@ -1198,7 +1198,7 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) alpha_mean[1, i-1, j, element] += coefficient @@ -1240,7 +1240,7 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) alpha_mean[1, i, j-1, element] += coefficient @@ -1291,7 +1291,7 @@ end else coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i-1, j, element] += coefficient @@ -1332,7 +1332,7 @@ end else coefficient = min(1, (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i, j-1, element] += coefficient @@ -1367,7 +1367,7 @@ end else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux1[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[v, i-1, j, element] = min(alpha[v, i-1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i-1, j, element] += coefficient @@ -1400,7 +1400,7 @@ end else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / (antidiffusive_flux2[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[v, i, j-1, element] = min(alpha[v, i, j-1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) alpha_mean[v, i, j-1, element] += coefficient @@ -1436,7 +1436,7 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[1, i-1, j, element] = min(alpha[1, i-1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) if !indicator.DensityLimiter @@ -1477,7 +1477,7 @@ end end if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing alpha[1, i, j-1, element] = min(alpha[1, i, j-1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) if !indicator.DensityLimiter @@ -1499,7 +1499,7 @@ end # Divide alpha_mean by number of additions if indicator.Plotting - @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean = indicator.cache.container_shock_capturing # Interfaces contribute with 1.0 if indicator.DensityLimiter || indicator.DensityPositivityLimiter for i in eachnode(dg) @@ -1529,7 +1529,7 @@ end # Limit pressure à la Kuzmin if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_pressure, alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_pressure, alpha_mean_pressure = indicator.cache.container_shock_capturing for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + antidiffusive_flux1[3, i, j, element]^2 @@ -1610,7 +1610,7 @@ end end end if indicator.Plotting - @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean_pressure = indicator.cache.container_shock_capturing # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_pressure[i, 1, element] += 1.0 @@ -1660,7 +1660,7 @@ end end end if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing alpha_entropy[i-1, j, element] = min(alpha_entropy[i-1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) alpha_mean_entropy[i-1, j, element] += alpha @@ -1700,7 +1700,7 @@ end end end if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing alpha_entropy[i, j-1, element] = min(alpha_entropy[i, j-1, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) alpha_mean_entropy[i, j-1, element] += alpha @@ -1708,7 +1708,7 @@ end end end if indicator.Plotting - @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean_entropy = indicator.cache.container_shock_capturing # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_entropy[i, 1, element] += 1.0 diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index e1c85b407e..7e955364d1 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -337,7 +337,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) end function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) - node_variables[:indicator_shock_capturing] = indicator.cache.ContainerShockCapturingIndicator.alpha + node_variables[:indicator_shock_capturing] = indicator.cache.container_shock_capturing.alpha # TODO BB: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. return nothing end @@ -452,7 +452,7 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn if !indicator.Plotting return nothing end - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha = indicator.cache.container_shock_capturing variables = varnames(cons2cons, equations) for v in eachvariable(equations) s = Symbol("alpha_", variables[v]) @@ -460,30 +460,28 @@ function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIn end if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_pressure = indicator.cache.container_shock_capturing node_variables[:alpha_pressure] = alpha_pressure end if indicator.SemiDiscEntropyLimiter - @unpack alpha_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_entropy = indicator.cache.container_shock_capturing node_variables[:alpha_entropy] = alpha_entropy end - @unpack alpha_mean = indicator.cache.ContainerShockCapturingIndicator for v in eachvariable(equations) + @unpack alpha_mean = indicator.cache.container_shock_capturing s = Symbol("alpha_mean_", variables[v]) node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) end - @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_mean_pressure = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean_pressure = indicator.cache.container_shock_capturing node_variables[:alpha_mean_pressure] = alpha_mean_pressure end - @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator if indicator.SemiDiscEntropyLimiter - @unpack alpha_mean_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha_mean_entropy = indicator.cache.container_shock_capturing node_variables[:alpha_mean_entropy] = alpha_mean_entropy end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index ee5f9c7e6d..8a1a1ab995 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -187,23 +187,23 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, bar_states) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorIDP2D{real(basis)}(0, nnodes(basis), number_bounds) + container_shock_capturing = Trixi.ContainerShockCapturingIndicatorIDP2D{real(basis)}(0, nnodes(basis), number_bounds) cache = (; ) if bar_states - ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) - cache = (; cache..., ContainerBarStates) + container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) + cache = (; cache..., container_bar_states) end alpha_max_avg = zeros(real(basis), 2) idp_bounds_delta = zeros(real(basis), number_bounds) - return (; cache..., alpha_max_avg, ContainerShockCapturingIndicator, idp_bounds_delta) + return (; cache..., alpha_max_avg, container_shock_capturing, idp_bounds_delta) end function (indicator::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t, dt; kwargs...) - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha = indicator.cache.container_shock_capturing alpha .= zero(eltype(alpha)) if indicator.smoothness_indicator elements = semi.cache.element_ids_dgfv @@ -225,7 +225,7 @@ function (indicator::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t end # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha1, alpha2 = indicator.cache.container_shock_capturing @threaded for element in elements for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i-1, j, element], alpha[i, j, element]) @@ -453,7 +453,7 @@ end @inline function idp_density_tvd!(alpha, indicator, u, t, dt, semi, elements) mesh, _, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing rho_min = variable_bounds[1] rho_max = variable_bounds[2] @@ -513,7 +513,7 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack density_tvd, positivity = indicator - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing s_min = variable_bounds[2 * density_tvd + 1] if !indicator.bar_states @@ -541,7 +541,7 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack density_tvd, positivity, spec_entropy = indicator - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing s_max = variable_bounds[2 * density_tvd + spec_entropy + 1] if !indicator.bar_states @@ -586,7 +586,7 @@ end @unpack inverse_weights = dg.basis @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons = indicator - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing if Trixi.density in variables_cons && density_tvd if Trixi.density == variables_cons[index] @@ -654,7 +654,7 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons, variables_nonlinear = indicator - @unpack variable_bounds = indicator.cache.ContainerShockCapturingIndicator + @unpack variable_bounds = indicator.cache.container_shock_capturing var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + length(variables_cons) - min(density_tvd, Trixi.density in variables_cons) + @@ -815,7 +815,7 @@ standard_finalCheck(bound, goal, newton_abstol) = abs(goal) < max(newton_abstol, _, _, solver, cache = mesh_equations_solver_cache(semi) @unpack weights = solver.basis @unpack alpha_max_avg = indicator.cache - @unpack alpha = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha = indicator.cache.container_shock_capturing alpha_max_avg[1] = max(alpha_max_avg[1], maximum(alpha)) alpha_avg = zero(eltype(alpha)) @@ -863,12 +863,12 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) - ContainerShockCapturingIndicator = Trixi.ContainerShockCapturingIndicatorMCL2D{real(basis)}(0, nvariables(equations), nnodes(basis)) - ContainerBarStates = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) + container_shock_capturing = Trixi.ContainerShockCapturingIndicatorMCL2D{real(basis)}(0, nvariables(equations), nnodes(basis)) + container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiterKuzmin) - return (; ContainerShockCapturingIndicator, ContainerBarStates, idp_bounds_delta) + return (; container_shock_capturing, container_bar_states, idp_bounds_delta) end update_alpha_max_avg!(indicator::AbstractIndicator, timestep, n_stages, semi, mesh) = nothing @@ -876,7 +876,7 @@ update_alpha_max_avg!(indicator::AbstractIndicator, timestep, n_stages, semi, me @inline function save_alpha(indicator::IndicatorMCL, time, iter, semi, mesh::TreeMesh2D, output_directory) _, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack weights = dg.basis - @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy, alpha_mean = indicator.cache.container_shock_capturing # Save the alphas every x iterations x = 1 diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 69f33c0311..959c0bd653 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -159,7 +159,7 @@ function solve!(integrator::SimpleIntegratorSSP) # Reset alphas for MCL if indicator isa IndicatorMCL && indicator.Plotting - @unpack alpha, alpha_pressure, alpha_entropy = indicator.cache.ContainerShockCapturingIndicator + @unpack alpha, alpha_pressure, alpha_entropy = indicator.cache.container_shock_capturing @threaded for element in eachelement(integrator.p.solver, integrator.p.cache) for j in eachnode(integrator.p.solver), i in eachnode(integrator.p.solver) alpha[:, i, j, element] .= one(eltype(alpha)) @@ -261,23 +261,23 @@ function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell # Resize container_antidiffusive_flux resize!(semi.cache.container_antidiffusive_flux, new_size) - # Resize ContainerShockCapturingIndicator - resize!(volume_integral.indicator.cache.ContainerShockCapturingIndicator, new_size) + # Resize container_shock_capturing + resize!(volume_integral.indicator.cache.container_shock_capturing, new_size) # Calc subcell normal directions before StepsizeCallback @unpack indicator = volume_integral if indicator isa IndicatorMCL || (indicator isa IndicatorIDP && indicator.bar_states) - resize!(indicator.cache.ContainerBarStates, new_size) - calc_normal_directions!(indicator.cache.ContainerBarStates, mesh_equations_solver_cache(semi)...) + resize!(indicator.cache.container_bar_states, new_size) + calc_normal_directions!(indicator.cache.container_bar_states, mesh_equations_solver_cache(semi)...) end end -calc_normal_directions!(ContainerBarStates, mesh::TreeMesh, equations, dg, cache) = nothing +calc_normal_directions!(container_bar_states, mesh::TreeMesh, equations, dg, cache) = nothing -function calc_normal_directions!(ContainerBarStates, mesh::StructuredMesh, equations, dg, cache) +function calc_normal_directions!(container_bar_states, mesh::StructuredMesh, equations, dg, cache) @unpack weights, derivative_matrix = dg.basis @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = ContainerBarStates + @unpack normal_direction_xi, normal_direction_eta = container_bar_states @threaded for element in eachelement(dg, cache) for j in eachnode(dg) normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, element) From 9e1b5d82f4817cd544cf193fd8c8cbd491c88257 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 12:43:14 +0200 Subject: [PATCH 216/423] Delete timer --- src/time_integration/methods_SSP.jl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 959c0bd653..29482c6e7c 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -146,7 +146,7 @@ function solve!(integrator::SimpleIntegratorSSP) end integrator.finalstep = false - @trixi_timeit timer() "main loop" while !integrator.finalstep + while !integrator.finalstep if isnan(integrator.dt) error("time step size `dt` is NaN") end @@ -175,14 +175,12 @@ function solve!(integrator::SimpleIntegratorSSP) @. integrator.r0 = integrator.u for stage in eachindex(alg.c) - @trixi_timeit timer() "Runge-Kutta stage" begin - t_stage = integrator.t + integrator.dt * alg.c[stage] - # compute du - integrator.f(integrator.du, integrator.u, integrator.p, t_stage) + t_stage = integrator.t + integrator.dt * alg.c[stage] + # compute du + integrator.f(integrator.du, integrator.u, integrator.p, t_stage) - # perform forward Euler step - @. integrator.u = integrator.u + integrator.dt * integrator.du - end + # perform forward Euler step + @. integrator.u = integrator.u + integrator.dt * integrator.du @trixi_timeit timer() "update_alpha_max_avg!" update_alpha_max_avg!(indicator, integrator.iter+1, length(alg.c), integrator.p, integrator.p.mesh) From 54d877ac5914ea99f1f84c6b95553aee1eab2c97 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 15:21:28 +0200 Subject: [PATCH 217/423] Update docstrings and explanations --- src/callbacks_stage/bounds_check_2d.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 2 +- src/solvers/dgsem_tree/indicators.jl | 139 ++++++++++++++++++------- 3 files changed, 104 insertions(+), 39 deletions(-) diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 61e7757fc3..a7195d6767 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -385,7 +385,7 @@ end end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - beta = indicator.DensityPositivityCorrelationFactor + beta = indicator.DensityPositivityCorrectionFactor # Checking the bounds for... # - density (rho): # beta * \bar{rho} <= \bar{rho}^{Lim} diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 474a6a16ad..4181b3a9a0 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1413,7 +1413,7 @@ end # Density positivity limiter if indicator.DensityPositivityLimiter - beta = indicator.DensityPositivityCorrelationFactor + beta = indicator.DensityPositivityCorrectionFactor for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 7e955364d1..cd0c40adf7 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -216,16 +216,43 @@ end """ - IndicatorIDP + IndicatorIDP(equations::AbstractEquations, basis; + density_tvd=false, + positivity=false, + variables_cons=(), + variables_nonlinear=(), + spec_entropy=false, + math_entropy=false, + bar_states=true, + positivity_correction_factor=0.1, max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), gamma_constant_newton=2*ndims(equations), + smoothness_indicator=false, threshold_smoothness_indicator=0.1, + variable_smoothness_indicator=density_pressure) + +Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralShockCapturingSubcell`](@ref) +including: +- two-sided Zalesak-type limiting for density (`density_tvd`) +- positivity limiting for conservative and non-linear variables (`positivity`) +- one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) + +The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity +limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. +The Newton-bisection method for the limiting of non-linear variables uses maximal `max_iterations_newton` +iterations, tolerances `newton_tolerances` and the gamma constant `gamma_constant_newton` +(gamma_constant_newton>=2*d, where d=#dimensions). + +A hard-switch [IndicatorHennemannGassner](@ref) can be activated (`smoothness_indicator`) with +`variable_smoothness_indicator`, which disables subcell blending for element-wise +indicator values <= `threshold_smoothness_indicator`. -TODO: docstring +## References -Blending indicator used for subcell shock-capturing [`VolumeIntegralShockCapturingSubcell`](@ref) proposed by - Rueda-Ramírez, Pazner, Gassner (2022) - "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" + Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods + [DOI: 10.1016/j.compfluid.2022.105627](https://doi.org/10.1016/j.compfluid.2022.105627) - Pazner (2020) - "Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting" - [arXiv:2004.08503](https://doi.org/10.1016/j.cma.2021.113876) + Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting + [DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876) !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. @@ -239,13 +266,12 @@ struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonline math_entropy::Bool bar_states::Bool cache::Cache - positivity_correction_factor::RealT # Correction factor for positivity - max_iterations_newton::Int # Maximal number of iterations for Newton's method + positivity_correction_factor::RealT + max_iterations_newton::Int newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints - # (gamma_constant_newton>=2*d, where d=#dimensions) - smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner - threshold_smoothness_indicator::RealT # threshold for smoothness indicator + smoothness_indicator::Bool + threshold_smoothness_indicator::RealT IndicatorHG::Indicator end @@ -323,7 +349,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) if positivity string = "positivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" setup = [setup..., "" => string] - setup = [setup..., "" => " "^14 * "and positivity correlation factor $(indicator.positivity_correction_factor)"] + setup = [setup..., "" => " "^14 * "and positivity correction factor $(indicator.positivity_correction_factor)"] end spec_entropy && (setup = [setup..., "" => "specific entropy"]) math_entropy && (setup = [setup..., "" => "mathematical entropy"]) @@ -338,48 +364,85 @@ end function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) node_variables[:indicator_shock_capturing] = indicator.cache.container_shock_capturing.alpha - # TODO BB: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. + # TODO: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. return nothing end """ -IndicatorMCL + IndicatorMCL(equations::AbstractEquations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, + PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=false, + DensityPositivityCorrectionFactor=0.0, + SemiDiscEntropyLimiter=false, + smoothness_indicator=false, threshold_smoothness_indicator=0.1, + variable_smoothness_indicator=density_pressure, + Plotting=true) + +Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralShockCapturingSubcell`](@ref) including: +- local two-sided limiting for `cons(1)` (`DensityLimiter`) +- transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) +- local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) +- local two-sided limiting for conservative variables (`ConservativeLimiter`) +- positivity limiting for `cons(1)` (`DensityPositivityLimiter`) and pressure (`PressurePositivityLimiterKuzmin`) +- semidiscrete entropy fix (`SemiDiscEntropyLimiter`) + +The pressure positivity limiting preserves a sharp version (`PressurePositivityLimiterKuzminExact`) +and a more cautious one. The density positivity limiter uses a `DensityPositivityCorrectionFactor` +such that `u^new >= positivity_correction_factor * u^FV`. All additional analyses for plotting routines +can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). + +A hard-switch [IndicatorHennemannGassner](@ref) can be activated (`smoothness_indicator`) with +`variable_smoothness_indicator`, which disables subcell blending for element-wise +indicator values <= `threshold_smoothness_indicator`. + +## References -TODO: docstring +- Rueda-Ramírez, Bolm, Kuzmin, Gassner (2023) + Monolithic Convex Limiting for Legendre-Gauss-Lobatto Discontinuous Galerkin Spectral Element Methods + [arXiv:2303.00374](https://doi.org/10.48550/arXiv.2303.00374) +- Kuzmin (2020) + Monolithic convex limiting for continuous finite element discretizations of hyperbolic conservation laws + [DOI: 10.1016/j.cma.2019.112804](https://doi.org/10.1016/j.cma.2019.112804) !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ struct IndicatorMCL{RealT<:Real, Cache, Indicator} <: AbstractIndicator cache::Cache - DensityLimiter::Bool - DensityAlphaForAll::Bool - SequentialLimiter::Bool - ConservativeLimiter::Bool - PressurePositivityLimiterKuzmin::Bool # synchronized pressure limiting à la Kuzmin + DensityLimiter::Bool # Impose local maximum/minimum for cons(1) based on bar states + DensityAlphaForAll::Bool # Use the cons(1) blending coefficient for all quantities + SequentialLimiter::Bool # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states + ConservativeLimiter::Bool # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states + PressurePositivityLimiterKuzmin::Bool # Impose positivity for pressure â la Kuzmin PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - DensityPositivityLimiter::Bool - DensityPositivityCorrelationFactor::RealT + DensityPositivityLimiter::Bool # Impose positivity for cons(1) + DensityPositivityCorrectionFactor::RealT # Correction Factor for DensityPositivityLimiter in [0,1) SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix - smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner - threshold_smoothness_indicator::RealT # threshold for smoothness indicator + smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner + threshold_smoothness_indicator::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorMCL(equations::AbstractEquations, basis; - DensityLimiter=true, # Impose local maximum/minimum for cons(1) based on bar states - DensityAlphaForAll=false, # Use the cons(1) blending coefficient for all quantities - SequentialLimiter=true, # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states - ConservativeLimiter=false, # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states - PressurePositivityLimiterKuzmin=false,# Impose positivity for pressure â la Kuzmin - PressurePositivityLimiterKuzminExact=true,# Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - DensityPositivityLimiter=false, # Impose positivity for cons(1) - DensityPositivityCorrelationFactor=0.0,# Correlation Factor for DensityPositivityLimiter in [0,1) + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, + PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=false, + DensityPositivityCorrectionFactor=0.0, SemiDiscEntropyLimiter=false, - smoothness_indicator=false, threshold_smoothness_indicator=0.1, variable_smoothness_indicator=density_pressure, + smoothness_indicator=false, threshold_smoothness_indicator=0.1, + variable_smoothness_indicator=density_pressure, Plotting=true) if SequentialLimiter && ConservativeLimiter error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") @@ -394,7 +457,7 @@ function IndicatorMCL(equations::AbstractEquations, basis; IndicatorMCL{typeof(threshold_smoothness_indicator), typeof(cache), typeof(IndicatorHG)}(cache, DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, PressurePositivityLimiterKuzmin, PressurePositivityLimiterKuzminExact, - DensityPositivityLimiter, DensityPositivityCorrelationFactor, SemiDiscEntropyLimiter, + DensityPositivityLimiter, DensityPositivityCorrectionFactor, SemiDiscEntropyLimiter, smoothness_indicator, threshold_smoothness_indicator, IndicatorHG, Plotting) end @@ -410,7 +473,9 @@ function Base.show(io::IO, indicator::IndicatorMCL) print(io, "; $(indicator.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") end indicator.DensityPositivityLimiter && print(io, "; dens pos") - (indicator.DensityPositivityCorrelationFactor != 0.0) && print(io, " with correlation factor $(indicator.DensityPositivityCorrelationFactor)") + if indicator.DensityPositivityCorrectionFactor != 0 + print(io, " with correction factor $(indicator.DensityPositivityCorrectionFactor)") + end indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") indicator.smoothness_indicator && print(io, "; Smoothness indicator: ", indicator.IndicatorHG, " with threshold ", indicator.threshold_smoothness_indicator) @@ -434,8 +499,8 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) setup = [setup..., "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")"] end if DensityPositivityLimiter - if indicator.DensityPositivityCorrelationFactor != 0.0 - setup = [setup..., "" => "DensityPositivityLimiter with correlation factor $(indicator.DensityPositivityCorrelationFactor)"] + if indicator.DensityPositivityCorrectionFactor != 0.0 + setup = [setup..., "" => "DensityPositivityLimiter with correction factor $(indicator.DensityPositivityCorrectionFactor)"] else setup = [setup..., "" => "DensityPositivityLimiter"] end From 59c8632a799f6ace7fc1c6395433edebfcbb0c4c Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 16:05:26 +0200 Subject: [PATCH 218/423] Fix references in docstrings --- src/solvers/dgsem_tree/indicators.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index cd0c40adf7..0e6bb07c2a 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -241,7 +241,7 @@ The Newton-bisection method for the limiting of non-linear variables uses maxima iterations, tolerances `newton_tolerances` and the gamma constant `gamma_constant_newton` (gamma_constant_newton>=2*d, where d=#dimensions). -A hard-switch [IndicatorHennemannGassner](@ref) can be activated (`smoothness_indicator`) with +A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with `variable_smoothness_indicator`, which disables subcell blending for element-wise indicator values <= `threshold_smoothness_indicator`. @@ -397,7 +397,7 @@ and a more cautious one. The density positivity limiter uses a `DensityPositivit such that `u^new >= positivity_correction_factor * u^FV`. All additional analyses for plotting routines can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). -A hard-switch [IndicatorHennemannGassner](@ref) can be activated (`smoothness_indicator`) with +A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with `variable_smoothness_indicator`, which disables subcell blending for element-wise indicator values <= `threshold_smoothness_indicator`. From b3f07dd3c1026bface652de9d4a512dc3f53c38e Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 17:39:37 +0200 Subject: [PATCH 219/423] Fix call of algorithm --- .../elixir_euler_convergence_wavingflag_IDP.jl | 4 ++-- .../elixir_euler_convergence_wavingflag_MCL.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_double_mach.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl | 4 ++-- examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl | 4 ++-- .../elixir_euler_free_stream_sc_subcell.jl | 4 ++-- .../structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl | 4 ++-- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl | 4 ++-- .../elixir_euler_kelvin_helmholtz_instability_MCL.jl | 4 ++-- .../elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl | 4 ++-- .../tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl | 4 ++-- examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl | 2 +- .../tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl | 4 ++-- .../elixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- src/callbacks_stage/bounds_check.jl | 2 +- 23 files changed, 40 insertions(+), 40 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 543846eb80..47d4d334c9 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -68,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index fb2b0120dd..8cffae7ec4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -68,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index ab4ba667fe..a42cf9ab37 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -139,9 +139,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 083e2a33d1..a9d5321586 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -143,9 +143,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 25211ad7c0..45d256d963 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -84,9 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index d0cae7a4d7..bb00fb7487 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -82,9 +82,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 3cba12047e..a6a187067f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -133,9 +133,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index b72a88551c..5f7a6b8852 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -132,7 +132,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 8235d51d89..d347650510 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -67,7 +67,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 3a3fa30bba..e882314d0e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -92,9 +92,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index e539ff43b5..e3f1d283f9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -88,9 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 29701cc063..7cbdb68858 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -94,7 +94,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 8193ddcdb1..8ee46141dc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -87,9 +87,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 0c4930479b..4c8fa1fca1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -63,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index 1e33b664e1..21841f69df 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -63,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 464ae20782..97fe311374 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -88,9 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback maxiters=1e7, callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 71054ec974..abd7767fe0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -84,9 +84,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback callback=callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index c5268e3d3d..c8d008f4aa 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -92,9 +92,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=true),) +stage_callbacks = (BoundsCheckCallback(save_errors=false),) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 4ed757e38e..9c605657c2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -89,9 +89,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 69e502a184..83da7dee8c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -86,7 +86,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index cbe12a5e00..27bfa942df 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -60,9 +60,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index e92cbde352..c77667afaa 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -141,7 +141,7 @@ callbacks = CallbackSet(summary_callback, stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) -sol = Trixi.solve(ode, alg=Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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 \ No newline at end of file diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index c0fcfb294a..2cde50d307 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -6,7 +6,7 @@ """ - BoundsCheckCallback(; output_directory="out", save_errors=false, interval=0) + BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) Bounds checking routine for `IndicatorIDP` and `IndicatorMCL`. Applied as a stage callback for SSPRK methods. If `save_errors` is `true`, the resulting deviations are saved in From 86c656a73934532f034e5af68a4b6052c3990de5 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 6 Jun 2023 17:40:14 +0200 Subject: [PATCH 220/423] Remove analysis output --- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 5f7a6b8852..0e86db0c0c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -130,7 +130,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=true)) +stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback From 2dbf41bc9a66f473d713c9481c283171e1ea2cfc Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 7 Jun 2023 14:10:32 +0200 Subject: [PATCH 221/423] Fix typo --- src/callbacks_step/limiting_analysis.jl | 31 +++++++++------------- src/callbacks_step/limiting_analysis_2d.jl | 12 ++++----- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index ba1c0ed7b0..0d3f5c3841 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -9,7 +9,7 @@ LimitingAnalysisCallback(; output_directory="out", interval=1) Analyze the subcell blending coefficient of IDP limiting (`IndicatorIDP`) and monolithic convex -limiting (MCL) (`IndicatorMCL`) every `interval` time steps and saeves the results +limiting (MCL) (`IndicatorMCL`) every `interval` time steps and save the results to `output_directory/alpha.txt`. """ struct LimitingAnalysisCallback @@ -76,25 +76,17 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrat vars = varnames(cons2cons, integrator.p.equations) mkpath(output_directory) - open("$output_directory/alphas_min.txt", "a") do f; - print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiterKuzmin - print(f, ", alpha_min_pressure, alpha_avg_pressure") - end - if indicator.SemiDiscEntropyLimiter - print(f, ", alpha_min_entropy, alpha_avg_entropy") + for file in ["alphas_min.txt", "alphas_mean.txt"] + open("$output_directory/$file", "a") do f; + print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); + if indicator.PressurePositivityLimiterKuzmin + print(f, ", alpha_min_pressure, alpha_avg_pressure") + end + if indicator.SemiDiscEntropyLimiter + print(f, ", alpha_min_entropy, alpha_avg_entropy") + end + println(f) end - println(f) - end - open("$output_directory/alphas_mean.txt", "a") do f; - print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)); - if indicator.PressurePositivityLimiterKuzmin - print(f, ", alpha_min_pressure, alpha_avg_pressure") - end - if indicator.SemiDiscEntropyLimiter - print(f, ", alpha_min_entropy, alpha_avg_entropy") - end - println(f) end return nothing @@ -183,6 +175,7 @@ end return nothing end + end # @muladd diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index 2a395f53ef..6684e1a7e4 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -9,34 +9,34 @@ @unpack weights = dg.basis @unpack alpha = indicator.cache.container_shock_capturing - alpha_avg_ = zero(eltype(alpha)) + alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) jacobian = inv(cache.elements.inverse_jacobian[element]) for j in eachnode(dg), i in eachnode(dg) - alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] + alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - return alpha_avg_ / total_volume + return alpha_avg / total_volume end @inline function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, indicator) @unpack weights = dg.basis @unpack alpha = indicator.cache.container_shock_capturing - alpha_avg_ = zero(eltype(alpha)) + alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) for j in eachnode(dg), i in eachnode(dg) jacobian = inv(cache.elements.inverse_jacobian[i, j, element]) - alpha_avg_ += jacobian * weights[i] * weights[j] * alpha[i, j, element] + alpha_avg += jacobian * weights[i] * weights[j] * alpha[i, j, element] total_volume += jacobian * weights[i] * weights[j] end end - return alpha_avg_ / total_volume + return alpha_avg / total_volume end From 3b5b7635a2de9794184bf7dce874cd7148b0e0b7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 7 Jun 2023 14:27:49 +0200 Subject: [PATCH 222/423] Revise docstring --- src/callbacks_step/limiting_analysis.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index 0d3f5c3841..b1ca21d063 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -9,8 +9,10 @@ LimitingAnalysisCallback(; output_directory="out", interval=1) Analyze the subcell blending coefficient of IDP limiting (`IndicatorIDP`) and monolithic convex -limiting (MCL) (`IndicatorMCL`) every `interval` time steps and save the results -to `output_directory/alpha.txt`. +limiting (MCL) (`IndicatorMCL`) in the last RK stage of every `interval` time steps. This contains +a volume-weighted average of the node coefficients. For MCL, the node coefficients are calculated +using either the minimum or the mean of the adjacent subcell interfaces. The results are saved in +`alphas.txt` (for IDP limiting), `alpha_min.txt` and `alphas_mean.txt` (for MCL) in `output_directory`. """ struct LimitingAnalysisCallback output_directory::String From 675aa4685ca9f3a92ca6553d2b42fdd15339f2fa Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 7 Jun 2023 14:57:42 +0200 Subject: [PATCH 223/423] Revise reset structure --- src/solvers/dgsem_tree/containers_2d.jl | 6 ++++-- src/solvers/dgsem_tree/dg_2d.jl | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 2dac94866c..89efae1869 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1422,8 +1422,10 @@ function ContainerShockCapturingIndicatorMCL2D{uEltype}(capacity::Integer, n_var _alpha_mean_entropy = fill(nan_uEltype, n_nodes * n_nodes * capacity) alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL2D{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, alpha_mean, alpha_mean_pressure, alpha_mean_entropy, - _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) + return ContainerShockCapturingIndicatorMCL2D{uEltype}(var_min, var_max, alpha, alpha_pressure, alpha_entropy, + alpha_mean, alpha_mean_pressure, alpha_mean_entropy, + _var_min, _var_max, _alpha, _alpha_pressure, _alpha_entropy, + _alpha_mean, _alpha_mean_pressure, _alpha_mean_entropy) end nvariables(container::ContainerShockCapturingIndicatorMCL2D) = size(container.var_min, 1) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 5909d848bf..376019c9d0 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -1161,13 +1161,13 @@ end alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.container_shock_capturing for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) - alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) - alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) alpha[:, i, j, element] .= one(eltype(alpha)) if indicator.PressurePositivityLimiterKuzmin + alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end if indicator.SemiDiscEntropyLimiter + alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) end end From bc81d017ea4834fd88c5355a54c9e1be083062c0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 9 Jun 2023 15:25:56 +0200 Subject: [PATCH 224/423] Renaming to `APosterioriLimiter` --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_shockcapturing_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- src/Trixi.jl | 2 +- src/callbacks_stage/a_posteriori_limiter.jl | 53 +++++++++++++++++++ ...stage_2d.jl => a_posteriori_limiter_2d.jl} | 0 src/callbacks_stage/antidiffusive_stage.jl | 53 ------------------- src/callbacks_stage/callbacks_stage.jl | 2 +- src/time_integration/methods_SSP.jl | 8 +-- 19 files changed, 72 insertions(+), 72 deletions(-) create mode 100644 src/callbacks_stage/a_posteriori_limiter.jl rename src/callbacks_stage/{antidiffusive_stage_2d.jl => a_posteriori_limiter_2d.jl} (100%) delete mode 100644 src/callbacks_stage/antidiffusive_stage.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 47d4d334c9..52b3e931c8 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -68,7 +68,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index a42cf9ab37..66496e62b2 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index bb00fb7487..d53dff44f4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -82,7 +82,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 0e86db0c0c..dc1f8cb676 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -130,7 +130,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index d347650510..fc20b05bb3 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -65,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index e3f1d283f9..1a5de0aef4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -88,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 8ee46141dc..fa05049bcb 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -87,7 +87,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 4c8fa1fca1..8129d29006 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -63,7 +63,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index abd7767fe0..0fb72177bd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 9c605657c2..2c2920ed3a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 83da7dee8c..ab527ebd2a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 27bfa942df..0dc0eb0228 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -60,7 +60,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index c77667afaa..3bb3bf07a2 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/Trixi.jl b/src/Trixi.jl index 9d616a6121..8d35d389a3 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -234,7 +234,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorLöhner, IndicatorLoehner, IndicatorMax, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu, AntidiffusiveStage, BoundsCheckCallback +export PositivityPreservingLimiterZhangShu, APosterioriLimiter, BoundsCheckCallback export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl new file mode 100644 index 0000000000..b1649ed1b3 --- /dev/null +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -0,0 +1,53 @@ +# 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 + + +""" + APosterioriLimiter() + +Perform antidiffusive stage for a posteriori IDP limiting. + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +struct APosterioriLimiter end + +function (limiter!::APosterioriLimiter)(u_ode, integrator, stage) + + limiter!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) +end + +(::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing + +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralShockCapturingSubcell) + + @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, volume_integral.indicator) +end + +(::APosterioriLimiter)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing + +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, indicator::IndicatorIDP) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + + u = wrap_array(u_ode, mesh, equations, solver, cache) + + # Calculate blending factor alpha in [0,1] + # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij + # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij + @trixi_timeit timer() "blending factors" solver.volume_integral.indicator(u, semi, solver, t, dt) + + perform_idp_correction!(u, dt, mesh, equations, solver, cache) + + return nothing +end + +init_callback(limiter!::APosterioriLimiter, semi) = nothing + +finalize_callback(limiter!::APosterioriLimiter, semi) = nothing + +include("a_posteriori_limiter_2d.jl") + +end # @muladd diff --git a/src/callbacks_stage/antidiffusive_stage_2d.jl b/src/callbacks_stage/a_posteriori_limiter_2d.jl similarity index 100% rename from src/callbacks_stage/antidiffusive_stage_2d.jl rename to src/callbacks_stage/a_posteriori_limiter_2d.jl diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl deleted file mode 100644 index 896add78ab..0000000000 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ /dev/null @@ -1,53 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin - - -""" - AntidiffusiveStage() - -Perform antidiffusive stage for IDP limiting. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. -""" -struct AntidiffusiveStage end - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, integrator, stage) - - antidiffusive_stage!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) -end - -(::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::VolumeIntegralShockCapturingSubcell) - - @trixi_timeit timer() "antidiffusive_stage!" antidiffusive_stage!(u_ode, semi, t, dt, volume_integral.indicator) -end - -(::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorIDP) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - - u = wrap_array(u_ode, mesh, equations, solver, cache) - - # Calculate blending factor alpha in [0,1] - # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij - # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij - @trixi_timeit timer() "blending factor alpha" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) - - perform_idp_correction!(u, dt, mesh, equations, solver, cache) - - return nothing -end - -init_callback(callback::AntidiffusiveStage, semi) = nothing - -finalize_callback(antidiffusive_stage!::AntidiffusiveStage, semi) = nothing - -include("antidiffusive_stage_2d.jl") - -end # @muladd diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 7c829a98c5..4901feb6ae 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -6,7 +6,7 @@ include("positivity_zhang_shu.jl") -include("antidiffusive_stage.jl") +include("a_posteriori_limiter.jl") include("bounds_check.jl") diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 29482c6e7c..e23f959718 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -10,7 +10,7 @@ abstract type SimpleAlgorithmSSP end """ - SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) + SimpleSSPRK33(; stage_callbacks=(APosterioriLimiter(), BoundsCheckCallback())) The third-order SSP Runge-Kutta method of Shu and Osher. @@ -29,7 +29,7 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP c::SVector{3, Float64} stage_callbacks::StageCallbacks - function SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) + function SimpleSSPRK33(; stage_callbacks=(APosterioriLimiter(), BoundsCheckCallback())) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -92,8 +92,8 @@ end """ solve(ode, alg; dt, callbacks, kwargs...) -The following structures and methods provide a implementation of the third-order SSP Runge-Kutta -method [`SimpleSSPRK33`](@ref). +The following structures and methods provide the infrastructure for SSP Runge-Kutta methods +of type `SimpleAlgorithmSSP`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. From cbce791cec61706fcf6006b7092dca8e9a8a5721 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 9 Jun 2023 15:47:09 +0200 Subject: [PATCH 225/423] Rename volume integral --- ...elixir_euler_convergence_wavingflag_IDP.jl | 6 ++--- ...elixir_euler_convergence_wavingflag_MCL.jl | 6 ++--- .../elixir_euler_double_mach.jl | 4 +-- .../elixir_euler_double_mach_MCL.jl | 4 +-- .../elixir_euler_free_stream_MCL.jl | 6 ++--- .../elixir_euler_free_stream_sc_subcell.jl | 6 ++--- .../elixir_euler_shock_upstream_MCL.jl | 4 +-- .../elixir_euler_shock_upstream_sc_subcell.jl | 4 +-- .../elixir_euler_source_terms_sc_subcell.jl | 6 ++--- .../elixir_euler_astro_jet_MCL.jl | 4 +-- .../elixir_euler_astro_jet_subcell.jl | 4 +-- .../elixir_euler_blast_wave_MCL.jl | 6 ++--- .../elixir_euler_blast_wave_sc_subcell.jl | 6 ++--- .../elixir_euler_convergence_IDP.jl | 6 ++--- .../elixir_euler_convergence_MCL.jl | 6 ++--- ..._euler_kelvin_helmholtz_instability_MCL.jl | 4 +-- ...kelvin_helmholtz_instability_sc_subcell.jl | 4 +-- .../elixir_euler_sedov_blast_wave_MCL.jl | 6 ++--- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 6 ++--- .../elixir_euler_shockcapturing_subcell.jl | 6 ++--- .../elixir_euler_source_terms_sc_subcell.jl | 6 ++--- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 4 +-- src/Trixi.jl | 2 +- src/callbacks_stage/a_posteriori_limiter.jl | 2 +- src/callbacks_stage/bounds_check.jl | 6 ++--- src/callbacks_step/stepsize.jl | 2 +- src/solvers/dg.jl | 26 ++++++++----------- src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 4 +-- src/solvers/dgsem_tree/indicators.jl | 12 ++++----- src/time_integration/methods_SSP.jl | 2 +- 31 files changed, 84 insertions(+), 88 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 52b3e931c8..f601163b10 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; bar_states=true, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index 8cffae7ec4..d6dc886a29 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 66496e62b2..410b94acab 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -98,8 +98,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, positivity_correction_factor=0.1, max_iterations_newton=100, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index a9d5321586..746db116d5 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -101,8 +101,8 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 45d256d963..2a460464ac 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -24,9 +24,9 @@ indicator_sc = IndicatorMCL(equations, basis; smoothness_indicator=false, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index d53dff44f4..81d52aa387 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14)) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index a6a187067f..8c9baaed20 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -45,8 +45,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index dc1f8cb676..db091f968c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -42,8 +42,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, max_iterations_newton=100, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index fc20b05bb3..d4eaa92e48 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -19,9 +19,9 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, positivity=false, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Waving flag diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index e882314d0e..5d5b76a434 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -51,8 +51,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 1a5de0aef4..8dab1611aa 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -48,8 +48,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, bar_states=true, max_iterations_newton=25) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 7cbdb68858..81577ba511 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -48,9 +48,9 @@ indicator_sc = IndicatorMCL(equations, basis; SemiDiscEntropyLimiter=true, smoothness_indicator=true, Plotting=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index fa05049bcb..3bb2241519 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -43,9 +43,9 @@ indicator_sc = IndicatorIDP(equations, basis; math_entropy=true, bar_states=false, smoothness_indicator=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 8129d29006..c04aa60f94 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; bar_states=true, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index 21841f69df..3bd33c3b2c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 97fe311374..35ad491e15 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -45,8 +45,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 0fb72177bd..1dfa60dd88 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -41,8 +41,8 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, spec_entropy=false, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index c8d008f4aa..7686f0b451 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -51,9 +51,9 @@ indicator_sc = IndicatorMCL(equations, basis; SemiDiscEntropyLimiter=true, smoothness_indicator=false, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 2c2920ed3a..e1fcf46c00 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -47,9 +47,9 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, smoothness_indicator=false, bar_states=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index ab527ebd2a..76948193f4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -41,9 +41,9 @@ basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; positivity=true, variables_cons=(Trixi.density,), positivity_correction_factor=0.5, bar_states=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 0dc0eb0228..a5ec60f667 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -18,9 +18,9 @@ indicator_sc = IndicatorIDP(equations, basis; positivity=false, bar_states=true, smoothness_indicator=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index 3bb3bf07a2..e226f6907e 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -94,8 +94,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=false, bar_states=false) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/src/Trixi.jl b/src/Trixi.jl index 8d35d389a3..ccae19895c 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -203,7 +203,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralShockCapturingSubcell, IndicatorIDP, IndicatorMCL, + VolumeIntegralSubcellLimiting, IndicatorIDP, IndicatorMCL, VolumeIntegralUpwind, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, SurfaceIntegralUpwind, diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index b1649ed1b3..5afa5e237e 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -22,7 +22,7 @@ end (::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing -function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralShockCapturingSubcell) +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralSubcellLimiting) @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, volume_integral.indicator) end diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 2cde50d307..32f003832b 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -42,7 +42,7 @@ function check_bounds(u, mesh, equations, solver, cache, volume_integral::Abstra return nothing end -function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralShockCapturingSubcell, +function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralSubcellLimiting, t, iter, output_directory, save_errors, interval) check_bounds(u, mesh, equations, solver, cache, volume_integral.indicator, t, iter, output_directory, save_errors, interval) @@ -55,7 +55,7 @@ end init_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function init_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) +function init_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) init_callback(callback, semi, volume_integral.indicator) end @@ -121,7 +121,7 @@ end finalize_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function finalize_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) +function finalize_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) finalize_callback(callback, semi, volume_integral.indicator) end diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 20253b3f01..fbf699b534 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -90,7 +90,7 @@ max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral:: max_dt(u, t, mesh, constant_speed, equations, dg, cache) @inline function max_dt(u, t, mesh, - constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) + constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralSubcellLimiting) @unpack indicator = volume_integral if indicator isa IndicatorIDP && !indicator.bar_states return max_dt(u, t, mesh, constant_speed, equations, dg, cache) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index a65aafef74..a5b0ae1965 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -176,38 +176,34 @@ end """ - VolumeIntegralShockCapturingSubcell(indicator; - volume_flux_dg, volume_flux_fv) + VolumeIntegralSubcellLimiting(indicator; + volume_flux_dg, volume_flux_fv) -A shock-capturing volume integral type for DG methods based on a subcell blending approach -with a low-order FV method from the preprint paper -- Rueda-Ramírez, Pazner, Gassner (2022) - "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" +A subcell limiting volume integral type for DG methods based on subcell blending approaches +with a low-order FV method. Used with the indicators [`IndicatorIDP`](@ref) and [`IndicatorMCL`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. - -See also: [`VolumeIntegralShockCapturingHG`](@ref) """ -struct VolumeIntegralShockCapturingSubcell{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral +struct VolumeIntegralSubcellLimiting{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG volume_flux_fv::VolumeFluxFV indicator::Indicator end -function VolumeIntegralShockCapturingSubcell(indicator; volume_flux_dg, +function VolumeIntegralSubcellLimiting(indicator; volume_flux_dg, volume_flux_fv) - VolumeIntegralShockCapturingSubcell{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( + VolumeIntegralSubcellLimiting{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( volume_flux_dg, volume_flux_fv, indicator) end -function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) +function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralSubcellLimiting) @nospecialize integral # reduce precompilation time if get(io, :compact, false) show(io, integral) else - summary_header(io, "VolumeIntegralShockCapturingSubcell") + summary_header(io, "VolumeIntegralSubcellLimiting") summary_line(io, "volume flux DG", integral.volume_flux_dg) summary_line(io, "volume flux FV", integral.volume_flux_fv) summary_line(io, "indicator", integral.indicator |> typeof |> nameof) @@ -217,7 +213,7 @@ function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShock end function get_element_variables!(element_variables, u, mesh, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) if volume_integral.indicator.smoothness_indicator # call the indicator to get up-to-date values for IO volume_integral.indicator.IndicatorHG(u, mesh, equations, dg, cache) @@ -226,7 +222,7 @@ function get_element_variables!(element_variables, u, mesh, equations, end function get_node_variables!(node_variables, mesh, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) get_node_variables!(node_variables, volume_integral.indicator, volume_integral, equations) end diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 47539f5991..459a95d2df 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -27,7 +27,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) - if dg.volume_integral isa VolumeIntegralShockCapturingSubcell + if dg.volume_integral isa VolumeIntegralSubcellLimiting tol = dg.volume_integral.indicator.threshold_smoothness_indicator else tol = 1e-12 diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 4181b3a9a0..5c0edd30ec 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -80,7 +80,7 @@ end function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) + volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) @@ -532,7 +532,7 @@ end function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, + volume_integral::VolumeIntegralSubcellLimiting, dg::DGSEM, cache, t, boundary_conditions) @unpack indicator = volume_integral diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 0e6bb07c2a..b096cdd4e2 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -16,7 +16,7 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end -function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) +function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralSubcellLimiting) element_variables[:smooth_indicator_elementwise] = indicator.IndicatorHG.cache.alpha return nothing end @@ -229,7 +229,7 @@ end smoothness_indicator=false, threshold_smoothness_indicator=0.1, variable_smoothness_indicator=density_pressure) -Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralShockCapturingSubcell`](@ref) +Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - two-sided Zalesak-type limiting for density (`density_tvd`) - positivity limiting for conservative and non-linear variables (`positivity`) @@ -362,9 +362,9 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) end end -function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) +function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralSubcellLimiting, equations) node_variables[:indicator_shock_capturing] = indicator.cache.container_shock_capturing.alpha - # TODO: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. + # TODO: alpha is not filled before the first timestep. return nothing end @@ -384,7 +384,7 @@ end variable_smoothness_indicator=density_pressure, Plotting=true) -Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralShockCapturingSubcell`](@ref) including: +Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: - local two-sided limiting for `cons(1)` (`DensityLimiter`) - transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) - local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) @@ -513,7 +513,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) end end -function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) +function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralSubcellLimiting, equations) if !indicator.Plotting return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index e23f959718..e31973794a 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -255,7 +255,7 @@ end Base.resize!(semi, volume_integral::AbstractVolumeIntegral, new_size) = nothing -function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell, new_size) +function Base.resize!(semi, volume_integral::VolumeIntegralSubcellLimiting, new_size) # Resize container_antidiffusive_flux resize!(semi.cache.container_antidiffusive_flux, new_size) From b33178c4904d46c15aec025098a4c047901684b9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 9 Jun 2023 17:27:49 +0200 Subject: [PATCH 226/423] Merge `subcell-limiting` (Renaming) --- ...elixir_euler_convergence_wavingflag_IDP.jl | 8 +-- ...elixir_euler_convergence_wavingflag_MCL.jl | 6 +-- .../elixir_euler_double_mach.jl | 6 +-- .../elixir_euler_double_mach_MCL.jl | 4 +- .../elixir_euler_free_stream_MCL.jl | 6 +-- .../elixir_euler_free_stream_sc_subcell.jl | 8 +-- .../elixir_euler_shock_upstream_MCL.jl | 4 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 6 +-- .../elixir_euler_source_terms_sc_subcell.jl | 8 +-- .../elixir_euler_astro_jet_MCL.jl | 4 +- .../elixir_euler_astro_jet_subcell.jl | 6 +-- .../elixir_euler_blast_wave_MCL.jl | 6 +-- .../elixir_euler_blast_wave_sc_subcell.jl | 8 +-- .../elixir_euler_convergence_IDP.jl | 8 +-- .../elixir_euler_convergence_MCL.jl | 6 +-- ..._euler_kelvin_helmholtz_instability_MCL.jl | 4 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 6 +-- .../elixir_euler_sedov_blast_wave_MCL.jl | 6 +-- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 8 +-- .../elixir_euler_shockcapturing_subcell.jl | 8 +-- .../elixir_euler_source_terms_sc_subcell.jl | 8 +-- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 6 +-- src/Trixi.jl | 4 +- src/callbacks_stage/a_posteriori_limiter.jl | 53 +++++++++++++++++++ ...stage_2d.jl => a_posteriori_limiter_2d.jl} | 0 src/callbacks_stage/antidiffusive_stage.jl | 53 ------------------- src/callbacks_stage/bounds_check.jl | 6 +-- src/callbacks_stage/callbacks_stage.jl | 2 +- src/callbacks_step/limiting_analysis.jl | 4 +- src/callbacks_step/stepsize.jl | 2 +- src/solvers/dg.jl | 26 ++++----- src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 4 +- src/solvers/dgsem_tree/indicators.jl | 12 ++--- src/time_integration/methods_SSP.jl | 10 ++-- 35 files changed, 157 insertions(+), 161 deletions(-) create mode 100644 src/callbacks_stage/a_posteriori_limiter.jl rename src/callbacks_stage/{antidiffusive_stage_2d.jl => a_posteriori_limiter_2d.jl} (100%) delete mode 100644 src/callbacks_stage/antidiffusive_stage.jl diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 47d4d334c9..f601163b10 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; bar_states=true, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, @@ -68,7 +68,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index 8cffae7ec4..d6dc886a29 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index a42cf9ab37..410b94acab 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -98,8 +98,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, positivity_correction_factor=0.1, max_iterations_newton=100, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index a9d5321586..746db116d5 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -101,8 +101,8 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 45d256d963..2a460464ac 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -24,9 +24,9 @@ indicator_sc = IndicatorMCL(equations, basis; smoothness_indicator=false, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index bb00fb7487..81d52aa387 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14)) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. @@ -82,7 +82,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index a6a187067f..8c9baaed20 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -45,8 +45,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 0e86db0c0c..db091f968c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -42,8 +42,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, max_iterations_newton=100, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain @@ -130,7 +130,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index d347650510..d4eaa92e48 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -19,9 +19,9 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, positivity=false, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Waving flag @@ -65,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index e882314d0e..5d5b76a434 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -51,8 +51,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=false, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index e3f1d283f9..8dab1611aa 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -48,8 +48,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, bar_states=true, max_iterations_newton=25) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) @@ -88,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 7cbdb68858..81577ba511 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -48,9 +48,9 @@ indicator_sc = IndicatorMCL(equations, basis; SemiDiscEntropyLimiter=true, smoothness_indicator=true, Plotting=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 8ee46141dc..3bb2241519 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -43,9 +43,9 @@ indicator_sc = IndicatorIDP(equations, basis; math_entropy=true, bar_states=false, smoothness_indicator=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) @@ -87,7 +87,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 4c8fa1fca1..c04aa60f94 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorIDP(equations, basis; bar_states=true, smoothness_indicator=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) @@ -63,7 +63,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index 21841f69df..3bd33c3b2c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -22,9 +22,9 @@ indicator_sc = IndicatorMCL(equations, basis; PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 97fe311374..35ad491e15 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -45,8 +45,8 @@ indicator_sc = IndicatorMCL(equations, basis; DensityPositivityLimiter=true, SemiDiscEntropyLimiter=false, Plotting=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index abd7767fe0..1dfa60dd88 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -41,8 +41,8 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, spec_entropy=false, bar_states=true) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 33881fc212..cedb276c79 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -51,9 +51,9 @@ indicator_sc = IndicatorMCL(equations, basis; SemiDiscEntropyLimiter=true, smoothness_indicator=false, Plotting=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index a64863121b..40010a58ae 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -47,9 +47,9 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=true, smoothness_indicator=false, bar_states=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) @@ -92,7 +92,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 83da7dee8c..76948193f4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -41,9 +41,9 @@ basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; positivity=true, variables_cons=(Trixi.density,), positivity_correction_factor=0.5, bar_states=false) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(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) @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 27bfa942df..a5ec60f667 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -18,9 +18,9 @@ indicator_sc = IndicatorIDP(equations, basis; positivity=false, bar_states=true, smoothness_indicator=true) -volume_integral = VolumeIntegralShockCapturingSubcell(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) @@ -60,7 +60,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index c77667afaa..e226f6907e 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -94,8 +94,8 @@ indicator_sc = IndicatorIDP(equations, basis; spec_entropy=false, bar_states=false) -volume_integral=VolumeIntegralShockCapturingSubcell(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (AntidiffusiveStage(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/Trixi.jl b/src/Trixi.jl index b0735c15a8..b5b531c728 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -203,7 +203,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralShockCapturingSubcell, IndicatorIDP, IndicatorMCL, + VolumeIntegralSubcellLimiting, IndicatorIDP, IndicatorMCL, VolumeIntegralUpwind, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, SurfaceIntegralUpwind, @@ -234,7 +234,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorLöhner, IndicatorLoehner, IndicatorMax, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu, AntidiffusiveStage, BoundsCheckCallback +export PositivityPreservingLimiterZhangShu, APosterioriLimiter, BoundsCheckCallback export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl new file mode 100644 index 0000000000..5afa5e237e --- /dev/null +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -0,0 +1,53 @@ +# 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 + + +""" + APosterioriLimiter() + +Perform antidiffusive stage for a posteriori IDP limiting. + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +struct APosterioriLimiter end + +function (limiter!::APosterioriLimiter)(u_ode, integrator, stage) + + limiter!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) +end + +(::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing + +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralSubcellLimiting) + + @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, volume_integral.indicator) +end + +(::APosterioriLimiter)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing + +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, indicator::IndicatorIDP) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + + u = wrap_array(u_ode, mesh, equations, solver, cache) + + # Calculate blending factor alpha in [0,1] + # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij + # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij + @trixi_timeit timer() "blending factors" solver.volume_integral.indicator(u, semi, solver, t, dt) + + perform_idp_correction!(u, dt, mesh, equations, solver, cache) + + return nothing +end + +init_callback(limiter!::APosterioriLimiter, semi) = nothing + +finalize_callback(limiter!::APosterioriLimiter, semi) = nothing + +include("a_posteriori_limiter_2d.jl") + +end # @muladd diff --git a/src/callbacks_stage/antidiffusive_stage_2d.jl b/src/callbacks_stage/a_posteriori_limiter_2d.jl similarity index 100% rename from src/callbacks_stage/antidiffusive_stage_2d.jl rename to src/callbacks_stage/a_posteriori_limiter_2d.jl diff --git a/src/callbacks_stage/antidiffusive_stage.jl b/src/callbacks_stage/antidiffusive_stage.jl deleted file mode 100644 index 896add78ab..0000000000 --- a/src/callbacks_stage/antidiffusive_stage.jl +++ /dev/null @@ -1,53 +0,0 @@ -# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). -# Since these FMAs can increase the performance of many numerical algorithms, -# we need to opt-in explicitly. -# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. -@muladd begin - - -""" - AntidiffusiveStage() - -Perform antidiffusive stage for IDP limiting. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. -""" -struct AntidiffusiveStage end - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, integrator, stage) - - antidiffusive_stage!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) -end - -(::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, volume_integral::VolumeIntegralShockCapturingSubcell) - - @trixi_timeit timer() "antidiffusive_stage!" antidiffusive_stage!(u_ode, semi, t, dt, volume_integral.indicator) -end - -(::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing - -function (antidiffusive_stage!::AntidiffusiveStage)(u_ode, semi, t, dt, indicator::IndicatorIDP) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) - - u = wrap_array(u_ode, mesh, equations, solver, cache) - - # Calculate blending factor alpha in [0,1] - # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij - # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij - @trixi_timeit timer() "blending factor alpha" semi.solver.volume_integral.indicator(u, semi, solver, t, dt) - - perform_idp_correction!(u, dt, mesh, equations, solver, cache) - - return nothing -end - -init_callback(callback::AntidiffusiveStage, semi) = nothing - -finalize_callback(antidiffusive_stage!::AntidiffusiveStage, semi) = nothing - -include("antidiffusive_stage_2d.jl") - -end # @muladd diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 2cde50d307..32f003832b 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -42,7 +42,7 @@ function check_bounds(u, mesh, equations, solver, cache, volume_integral::Abstra return nothing end -function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralShockCapturingSubcell, +function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralSubcellLimiting, t, iter, output_directory, save_errors, interval) check_bounds(u, mesh, equations, solver, cache, volume_integral.indicator, t, iter, output_directory, save_errors, interval) @@ -55,7 +55,7 @@ end init_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function init_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) +function init_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) init_callback(callback, semi, volume_integral.indicator) end @@ -121,7 +121,7 @@ end finalize_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function finalize_callback(callback, semi, volume_integral::VolumeIntegralShockCapturingSubcell) +function finalize_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) finalize_callback(callback, semi, volume_integral.indicator) end diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 7c829a98c5..4901feb6ae 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -6,7 +6,7 @@ include("positivity_zhang_shu.jl") -include("antidiffusive_stage.jl") +include("a_posteriori_limiter.jl") include("bounds_check.jl") diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index b1ca21d063..2bd3a83904 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -54,7 +54,7 @@ function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrat end function initialize!(cb::DiscreteCallback{Condition,Affect!}, u_ode, t, integrator, - volume_integral::VolumeIntegralShockCapturingSubcell) where {Condition, Affect!<:LimitingAnalysisCallback} + volume_integral::VolumeIntegralSubcellLimiting) where {Condition, Affect!<:LimitingAnalysisCallback} initialize!(cb, u_ode, t, integrator, volume_integral.indicator, cb.affect!.output_directory) @@ -110,7 +110,7 @@ end end @inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, solver, cache, - volume_integral::VolumeIntegralShockCapturingSubcell, + volume_integral::VolumeIntegralSubcellLimiting, t, iter) if limiting_analysis_callback.interval == 0 || (iter % limiting_analysis_callback.interval != 0) return nothing diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 20253b3f01..fbf699b534 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -90,7 +90,7 @@ max_dt(u, t, mesh, constant_speed, equations, semi, dg, cache, volume_integral:: max_dt(u, t, mesh, constant_speed, equations, dg, cache) @inline function max_dt(u, t, mesh, - constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralShockCapturingSubcell) + constant_speed, equations, semi, dg, cache, volume_integral::VolumeIntegralSubcellLimiting) @unpack indicator = volume_integral if indicator isa IndicatorIDP && !indicator.bar_states return max_dt(u, t, mesh, constant_speed, equations, dg, cache) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index a65aafef74..a5b0ae1965 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -176,38 +176,34 @@ end """ - VolumeIntegralShockCapturingSubcell(indicator; - volume_flux_dg, volume_flux_fv) + VolumeIntegralSubcellLimiting(indicator; + volume_flux_dg, volume_flux_fv) -A shock-capturing volume integral type for DG methods based on a subcell blending approach -with a low-order FV method from the preprint paper -- Rueda-Ramírez, Pazner, Gassner (2022) - "Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods" +A subcell limiting volume integral type for DG methods based on subcell blending approaches +with a low-order FV method. Used with the indicators [`IndicatorIDP`](@ref) and [`IndicatorMCL`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. - -See also: [`VolumeIntegralShockCapturingHG`](@ref) """ -struct VolumeIntegralShockCapturingSubcell{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral +struct VolumeIntegralSubcellLimiting{VolumeFluxDG, VolumeFluxFV, Indicator} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG volume_flux_fv::VolumeFluxFV indicator::Indicator end -function VolumeIntegralShockCapturingSubcell(indicator; volume_flux_dg, +function VolumeIntegralSubcellLimiting(indicator; volume_flux_dg, volume_flux_fv) - VolumeIntegralShockCapturingSubcell{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( + VolumeIntegralSubcellLimiting{typeof(volume_flux_dg), typeof(volume_flux_fv), typeof(indicator)}( volume_flux_dg, volume_flux_fv, indicator) end -function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShockCapturingSubcell) +function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralSubcellLimiting) @nospecialize integral # reduce precompilation time if get(io, :compact, false) show(io, integral) else - summary_header(io, "VolumeIntegralShockCapturingSubcell") + summary_header(io, "VolumeIntegralSubcellLimiting") summary_line(io, "volume flux DG", integral.volume_flux_dg) summary_line(io, "volume flux FV", integral.volume_flux_fv) summary_line(io, "indicator", integral.indicator |> typeof |> nameof) @@ -217,7 +213,7 @@ function Base.show(io::IO, mime::MIME"text/plain", integral::VolumeIntegralShock end function get_element_variables!(element_variables, u, mesh, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) if volume_integral.indicator.smoothness_indicator # call the indicator to get up-to-date values for IO volume_integral.indicator.IndicatorHG(u, mesh, equations, dg, cache) @@ -226,7 +222,7 @@ function get_element_variables!(element_variables, u, mesh, equations, end function get_node_variables!(node_variables, mesh, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg, cache) + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) get_node_variables!(node_variables, volume_integral.indicator, volume_integral, equations) end diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 47539f5991..459a95d2df 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -27,7 +27,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) - if dg.volume_integral isa VolumeIntegralShockCapturingSubcell + if dg.volume_integral isa VolumeIntegralSubcellLimiting tol = dg.volume_integral.indicator.threshold_smoothness_indicator else tol = 1e-12 diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 376019c9d0..0d55a488b9 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -80,7 +80,7 @@ end function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, dg::DG, uEltype) + volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) @@ -532,7 +532,7 @@ end function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, - volume_integral::VolumeIntegralShockCapturingSubcell, + volume_integral::VolumeIntegralSubcellLimiting, dg::DGSEM, cache, t, boundary_conditions) @unpack indicator = volume_integral diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 0e6bb07c2a..b096cdd4e2 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -16,7 +16,7 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end -function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralShockCapturingSubcell) +function get_element_variables!(element_variables, indicator::AbstractIndicator, ::VolumeIntegralSubcellLimiting) element_variables[:smooth_indicator_elementwise] = indicator.IndicatorHG.cache.alpha return nothing end @@ -229,7 +229,7 @@ end smoothness_indicator=false, threshold_smoothness_indicator=0.1, variable_smoothness_indicator=density_pressure) -Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralShockCapturingSubcell`](@ref) +Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - two-sided Zalesak-type limiting for density (`density_tvd`) - positivity limiting for conservative and non-linear variables (`positivity`) @@ -362,9 +362,9 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) end end -function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralShockCapturingSubcell, equations) +function get_node_variables!(node_variables, indicator::IndicatorIDP, ::VolumeIntegralSubcellLimiting, equations) node_variables[:indicator_shock_capturing] = indicator.cache.container_shock_capturing.alpha - # TODO: Im ersten Zeitschritt scheint alpha noch nicht befüllt zu sein. + # TODO: alpha is not filled before the first timestep. return nothing end @@ -384,7 +384,7 @@ end variable_smoothness_indicator=density_pressure, Plotting=true) -Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralShockCapturingSubcell`](@ref) including: +Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: - local two-sided limiting for `cons(1)` (`DensityLimiter`) - transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) - local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) @@ -513,7 +513,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) end end -function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralShockCapturingSubcell, equations) +function get_node_variables!(node_variables, indicator::IndicatorMCL, ::VolumeIntegralSubcellLimiting, equations) if !indicator.Plotting return nothing end diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index e60d3c0f40..dc16d0ca23 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -10,7 +10,7 @@ abstract type SimpleAlgorithmSSP end """ - SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) + SimpleSSPRK33(; stage_callbacks=(APosterioriLimiter(), BoundsCheckCallback())) The third-order SSP Runge-Kutta method of Shu and Osher. @@ -29,7 +29,7 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP c::SVector{3, Float64} stage_callbacks::StageCallbacks - function SimpleSSPRK33(; stage_callbacks=(AntidiffusiveStage(), BoundsCheckCallback())) + function SimpleSSPRK33(; stage_callbacks=(APosterioriLimiter(), BoundsCheckCallback())) a = SVector(0.0, 3/4, 1/3) b = SVector(1.0, 1/4, 2/3) c = SVector(0.0, 1.0, 1/2) @@ -92,8 +92,8 @@ end """ solve(ode, alg; dt, callbacks, kwargs...) -The following structures and methods provide a implementation of the third-order SSP Runge-Kutta -method [`SimpleSSPRK33`](@ref). +The following structures and methods provide the infrastructure for SSP Runge-Kutta methods +of type `SimpleAlgorithmSSP`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. @@ -234,7 +234,7 @@ end Base.resize!(semi, volume_integral::AbstractVolumeIntegral, new_size) = nothing -function Base.resize!(semi, volume_integral::VolumeIntegralShockCapturingSubcell, new_size) +function Base.resize!(semi, volume_integral::VolumeIntegralSubcellLimiting, new_size) # Resize container_antidiffusive_flux resize!(semi.cache.container_antidiffusive_flux, new_size) From 2c6bd4bc48a78a66107a56af06bde6320f8f1e73 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Sat, 10 Jun 2023 11:23:05 +0200 Subject: [PATCH 227/423] Add dispatch to APosterioriLimiter --- src/Trixi.jl | 2 +- src/callbacks_stage/a_posteriori_limiter.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index ccae19895c..f6cb57c374 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -115,10 +115,10 @@ include("semidiscretization/semidiscretization.jl") include("semidiscretization/semidiscretization_hyperbolic.jl") include("semidiscretization/semidiscretization_hyperbolic_parabolic.jl") include("semidiscretization/semidiscretization_euler_acoustics.jl") +include("time_integration/time_integration.jl") include("callbacks_step/callbacks_step.jl") include("callbacks_stage/callbacks_stage.jl") include("semidiscretization/semidiscretization_euler_gravity.jl") -include("time_integration/time_integration.jl") # `trixi_include` and special elixirs such as `convergence_test` include("auxiliary/special_elixirs.jl") diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index 5afa5e237e..6471cc96d5 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -15,7 +15,7 @@ Perform antidiffusive stage for a posteriori IDP limiting. """ struct APosterioriLimiter end -function (limiter!::APosterioriLimiter)(u_ode, integrator, stage) +function (limiter!::APosterioriLimiter)(u_ode, integrator::Trixi.SimpleIntegratorSSP, stage) limiter!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) end From 87c38023d64234ded555da42f1f5f4b27b0643fe Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 12 Jun 2023 12:49:44 +0200 Subject: [PATCH 228/423] Revise posititivity limiter for cons variables --- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- ..._kelvin_helmholtz_instability_sc_subcell.jl | 2 +- .../elixir_euler_shockcapturing_subcell.jl | 2 +- ...lixir_eulermulti_shock_bubble_sc_subcell.jl | 5 +---- src/callbacks_stage/bounds_check.jl | 11 ++++++----- src/callbacks_stage/bounds_check_2d.jl | 6 +++--- src/solvers/dgsem_tree/indicators.jl | 18 +++++++++--------- src/solvers/dgsem_tree/indicators_2d.jl | 16 ++++++++-------- 8 files changed, 30 insertions(+), 32 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 81d52aa387..411a797a8a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1,], variables_nonlinear=(pressure,), spec_entropy=false, smoothness_indicator=false, bar_states=true, diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 1dfa60dd88..a79dea1a22 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,7 +37,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1,], variables_nonlinear=(pressure,), density_tvd=false, spec_entropy=false, bar_states=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 76948193f4..310d4f6817 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=(Trixi.density,), positivity_correction_factor=0.5, + positivity=true, variables_cons=[1,], positivity_correction_factor=0.5, bar_states=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index e226f6907e..182bc6d8c7 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -83,12 +83,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -density1(u, equations::CompressibleEulerMulticomponentEquations2D) = u[1+3] -density2(u, equations::CompressibleEulerMulticomponentEquations2D) = u[2+3] - indicator_sc = IndicatorIDP(equations, basis; positivity=true, - variables_cons=(density1, density2), + variables_cons=[(i+3 for i in eachcomponent(equations))...], variables_nonlinear=(), positivity_correction_factor=0.1, density_tvd=false, spec_entropy=false, diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 32f003832b..1d1925a161 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -79,11 +79,12 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator print(f, ", mathEntr_max"); end if positivity - for variable in indicator.variables_cons - if variable == Trixi.density && density_tvd + variables = varnames(cons2cons, semi.equations) + for index in indicator.variables_cons + if index == 1 && density_tvd continue end - print(f, ", $(variable)_min"); + print(f, ", $(variables[index])_min"); end for variable in indicator.variables_nonlinear print(f, ", $(variable)_min"); @@ -147,8 +148,8 @@ end counter += 1 end if positivity - for variable in indicator.variables_cons - if variable == Trixi.density && density_tvd + for index in indicator.variables_cons + if index == 1 && density_tvd continue end println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index a7195d6767..e594c2f01b 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -67,13 +67,13 @@ counter += 1 end if positivity - for variable in indicator.variables_cons - if variable == Trixi.density && density_tvd + for index in indicator.variables_cons + if index == 1 && density_tvd continue end deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - var = variable(get_node_vars(u, equations, solver, i, j, element), equations) + var = get_node_vars(u, equations, solver, i, j, element)[index] deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - var) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index b096cdd4e2..32e271253c 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -219,7 +219,7 @@ end IndicatorIDP(equations::AbstractEquations, basis; density_tvd=false, positivity=false, - variables_cons=(), + variables_cons=[], variables_nonlinear=(), spec_entropy=false, math_entropy=false, @@ -257,10 +257,10 @@ indicator values <= `threshold_smoothness_indicator`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT<:Real, LimitingVariablesCons, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator +struct IndicatorIDP{RealT<:Real, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator density_tvd::Bool positivity::Bool - variables_cons::LimitingVariablesCons # Positivity of conservative variables + variables_cons::Vector{Int} # Impose positivity for conservative variables variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables spec_entropy::Bool math_entropy::Bool @@ -279,7 +279,7 @@ end function IndicatorIDP(equations::AbstractEquations, basis; density_tvd=false, positivity=false, - variables_cons=(), + variables_cons=[], variables_nonlinear=(), spec_entropy=false, math_entropy=false, @@ -296,7 +296,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; spec_entropy + math_entropy if equations isa AbstractCompressibleEulerEquations if density_tvd - number_bounds += 2 - positivity * (Trixi.density in variables_cons) + number_bounds += 2 - positivity * (1 in variables_cons) end end @@ -308,7 +308,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_cons), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( + IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( density_tvd, positivity, variables_cons, variables_nonlinear, spec_entropy, math_entropy, bar_states, cache, positivity_correction_factor, max_iterations_newton, newton_tolerances, gamma_constant_newton, smoothness_indicator, threshold_smoothness_indicator, IndicatorHG) end @@ -323,7 +323,7 @@ function Base.show(io::IO, indicator::IndicatorIDP) else print(io, "limiter=(") density_tvd && print(io, "density, ") - positivity && print(io, "positivity, ") + positivity && print(io, "positivity, ") spec_entropy && print(io, "specific entropy, ") math_entropy && print(io, "mathematical entropy, ") print(io, "), ") @@ -347,9 +347,9 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) setup = ["limiter" => ""] density_tvd && (setup = [setup..., "" => "density"]) if positivity - string = "positivity with variables $(tuple(indicator.variables_cons..., indicator.variables_nonlinear...))" + string = "positivity with conservative variables $(indicator.variables_cons) and $(indicator.variables_nonlinear)" setup = [setup..., "" => string] - setup = [setup..., "" => " "^14 * "and positivity correction factor $(indicator.positivity_correction_factor)"] + setup = [setup..., "" => " "^11 * "and positivity correction factor $(indicator.positivity_correction_factor)"] end spec_entropy && (setup = [setup..., "" => "specific entropy"]) math_entropy && (setup = [setup..., "" => "mathematical entropy"]) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 69a0152637..e0cadcd00b 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -586,8 +586,8 @@ end @unpack variable_bounds = indicator.cache.container_shock_capturing - if Trixi.density in variables_cons && density_tvd - if Trixi.density == variables_cons[index] + if 1 in variables_cons && density_tvd + if variables_cons[variable] == 1 var_min = variable_bounds[1] else var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index - 1] @@ -605,7 +605,7 @@ end inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var = get_node_vars(u, equations, dg, i, j, element)[variable] if var < 0 error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end @@ -626,10 +626,10 @@ end # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * variable(get_node_vars(antidiffusive_flux1, equations, dg, i, j, element), equations) - val_flux1_local_ip1 = -inverse_weights[i] * variable(get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element), equations) - val_flux2_local = inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j, element), equations) - val_flux2_local_jp1 = -inverse_weights[j] * variable(get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element), equations) + val_flux1_local = inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element)[variable] + val_flux1_local_ip1 = -inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element)[variable] + val_flux2_local = inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element)[variable] + val_flux2_local_jp1 = -inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element)[variable] Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) @@ -655,7 +655,7 @@ end @unpack variable_bounds = indicator.cache.container_shock_capturing var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + - length(variables_cons) - min(density_tvd, Trixi.density in variables_cons) + + length(variables_cons) - min(density_tvd, 1 in variables_cons) + index] @threaded for element in elements From 00ef4904c04cd474e0b9b960be148c7489a3c4c0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 11:01:50 +0200 Subject: [PATCH 229/423] Adapt elixirs and add tests --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 4 +- test/test_structured_2d.jl | 38 +++++++++++++++++++ test/test_tree_2d_euler.jl | 12 ++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index f601163b10..ed352f4478 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index c04aa60f94..ddbcea0299 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index a5ec60f667..68c889d4e3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; @@ -51,7 +51,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 7f9f1017c7..395036dcff 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -109,6 +109,20 @@ isdir(outdir) && rm(outdir, recursive=true) restart_file="restart_000036.h5") end + @trixi_testset "elixir_euler_convergence_wavingflag_IDP.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_IDP.jl"), + l2 = [0.3398358793878119, 0.03398358793878129, 0.06796717587756244, 0.008495896984696072], + linf = [0.8360446582060936, 0.08360446582060972, 0.16720893164122444, 0.02090111645397741], + tspan = (0.0, 0.5)) + end + + @trixi_testset "elixir_euler_convergence_wavingflag_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_MCL.jl"), + l2 = [0.33983417649330827, 0.033983417649330924, 0.06796683529866161, 0.008495854412336827], + linf = [0.8360446582068146, 0.083604465820679, 0.16720893164136671, 0.02090111645399162], + tspan = (0.0, 0.5)) + end + @trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), # Expected errors are exactly the same as with TreeMesh! @@ -156,6 +170,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [8.297006495561199e-5, 8.663281475951301e-5, 0.00012264160606778596, 0.00041818802502024965]) end + @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + # Somehow the test fails because of replacing docs. Keeping it here for orientation. + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), + l2 = [0.0005410073263272928, 0.0004202892126963879, 0.00041243815462826874, 0.0008337413923563841], + linf = [0.002820853944058177, 0.002920003618928524, 0.0028228964420637936, 0.004689604214830556], + tspan = (0.0, 0.5)) + end + @trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_waving_flag.jl"), l2 = [2.991891317562739e-5, 3.6063177168283174e-5, 2.7082941743640572e-5, 0.00011414695350996946], @@ -193,6 +215,22 @@ isdir(outdir) && rm(outdir, recursive=true) atol = 7.0e-13) end + @trixi_testset "elixir_euler_double_mach.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), + l2 = [0.8955457632754655, 6.8117495933240235, 3.2697118944675716, 77.5174041919109], + linf = [10.16165871096883, 133.2522870057006, 38.23157147773949, 1470.3950960145828], + initial_refinement_level = 3, + tspan = (0.0, 0.05)) + end + + @trixi_testset "elixir_euler_double_mach_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), + l2 = [0.9266313242695542, 7.071517579972717, 3.2627078543492787, 80.24631724351916], + linf = [14.244598580563007, 138.4745277257612, 38.69633620234036, 1574.6686216469134], + initial_refinement_level = 3, + tspan = (0.0, 0.05)) + end + @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2 = [1.6235046821060115, 1.3268082379825517, 2.260222745763045, 13.836104055251756], diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 36a24bc5ae..a32227b356 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -14,12 +14,24 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5]) end + @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), + l2 = [2.0633069593983843e-6, 1.9337331005472223e-6, 1.9337331005227536e-6, 5.885362117543159e-6], + linf = [1.636984098429828e-5, 1.5579038690871627e-5, 1.557903868998345e-5, 5.260532107742577e-5]) + end + @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), l2 = [0.026440292358506527, 0.013245905852168414, 0.013245905852168479, 0.03912520302609374], linf = [0.042130817806361964, 0.022685499230187034, 0.022685499230187922, 0.06999771202145322]) end + @trixi_testset "elixir_euler_convergence_IDP.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_IDP.jl"), + l2 = [0.1289984161854359, 0.012899841618543363, 0.025799683237087086, 0.003224960404636081], + linf = [0.9436588685021441, 0.0943658868502173, 0.1887317737004306, 0.02359147170911058]) + end + @trixi_testset "elixir_euler_density_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), l2 = [0.0010600778457964775, 0.00010600778457634275, 0.00021201556915872665, 2.650194614399671e-5], From 49aa713391f88266197354d3c7615d09f0dab152 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 11:04:10 +0200 Subject: [PATCH 230/423] Adapt old elixirs and add tests --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 4 +- test/test_structured_2d.jl | 38 +++++++++++++++++++ test/test_tree_2d_euler.jl | 12 ++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index f601163b10..ed352f4478 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index c04aa60f94..ddbcea0299 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index a5ec60f667..68c889d4e3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, + positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; @@ -51,7 +51,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl=0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 7f9f1017c7..395036dcff 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -109,6 +109,20 @@ isdir(outdir) && rm(outdir, recursive=true) restart_file="restart_000036.h5") end + @trixi_testset "elixir_euler_convergence_wavingflag_IDP.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_IDP.jl"), + l2 = [0.3398358793878119, 0.03398358793878129, 0.06796717587756244, 0.008495896984696072], + linf = [0.8360446582060936, 0.08360446582060972, 0.16720893164122444, 0.02090111645397741], + tspan = (0.0, 0.5)) + end + + @trixi_testset "elixir_euler_convergence_wavingflag_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_MCL.jl"), + l2 = [0.33983417649330827, 0.033983417649330924, 0.06796683529866161, 0.008495854412336827], + linf = [0.8360446582068146, 0.083604465820679, 0.16720893164136671, 0.02090111645399162], + tspan = (0.0, 0.5)) + end + @trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), # Expected errors are exactly the same as with TreeMesh! @@ -156,6 +170,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [8.297006495561199e-5, 8.663281475951301e-5, 0.00012264160606778596, 0.00041818802502024965]) end + @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + # Somehow the test fails because of replacing docs. Keeping it here for orientation. + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), + l2 = [0.0005410073263272928, 0.0004202892126963879, 0.00041243815462826874, 0.0008337413923563841], + linf = [0.002820853944058177, 0.002920003618928524, 0.0028228964420637936, 0.004689604214830556], + tspan = (0.0, 0.5)) + end + @trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_waving_flag.jl"), l2 = [2.991891317562739e-5, 3.6063177168283174e-5, 2.7082941743640572e-5, 0.00011414695350996946], @@ -193,6 +215,22 @@ isdir(outdir) && rm(outdir, recursive=true) atol = 7.0e-13) end + @trixi_testset "elixir_euler_double_mach.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), + l2 = [0.8955457632754655, 6.8117495933240235, 3.2697118944675716, 77.5174041919109], + linf = [10.16165871096883, 133.2522870057006, 38.23157147773949, 1470.3950960145828], + initial_refinement_level = 3, + tspan = (0.0, 0.05)) + end + + @trixi_testset "elixir_euler_double_mach_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), + l2 = [0.9266313242695542, 7.071517579972717, 3.2627078543492787, 80.24631724351916], + linf = [14.244598580563007, 138.4745277257612, 38.69633620234036, 1574.6686216469134], + initial_refinement_level = 3, + tspan = (0.0, 0.05)) + end + @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2 = [1.6235046821060115, 1.3268082379825517, 2.260222745763045, 13.836104055251756], diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 36a24bc5ae..a32227b356 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -14,12 +14,24 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5]) end + @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), + l2 = [2.0633069593983843e-6, 1.9337331005472223e-6, 1.9337331005227536e-6, 5.885362117543159e-6], + linf = [1.636984098429828e-5, 1.5579038690871627e-5, 1.557903868998345e-5, 5.260532107742577e-5]) + end + @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), l2 = [0.026440292358506527, 0.013245905852168414, 0.013245905852168479, 0.03912520302609374], linf = [0.042130817806361964, 0.022685499230187034, 0.022685499230187922, 0.06999771202145322]) end + @trixi_testset "elixir_euler_convergence_IDP.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_IDP.jl"), + l2 = [0.1289984161854359, 0.012899841618543363, 0.025799683237087086, 0.003224960404636081], + linf = [0.9436588685021441, 0.0943658868502173, 0.1887317737004306, 0.02359147170911058]) + end + @trixi_testset "elixir_euler_density_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), l2 = [0.0010600778457964775, 0.00010600778457634275, 0.00021201556915872665, 2.650194614399671e-5], From 4731bd7783c25065b3eb8c44b0a92999f0e5998d Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 11:18:51 +0200 Subject: [PATCH 231/423] Adapt last elixirs --- .../elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl | 2 +- .../elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl | 2 +- examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl | 2 +- src/callbacks_stage/bounds_check_2d.jl | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index ed352f4478..e59f70ee4c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 411a797a8a..5f867befaa 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=[1,], variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, smoothness_indicator=false, bar_states=true, diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index ddbcea0299..93b064bc3d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index a79dea1a22..1fe475aba1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,7 +37,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=[1,], variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), density_tvd=false, spec_entropy=false, bar_states=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 310d4f6817..a2339db8ce 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=[1,], positivity_correction_factor=0.5, + positivity=true, variables_cons=[1], positivity_correction_factor=0.5, bar_states=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 68c889d4e3..6f1c64630f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=true, variables_cons=(Trixi.density,), variables_nonlinear=(pressure,), + positivity=false, variables_cons=[1], variables_nonlinear=(pressure,), bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index e594c2f01b..3361a6e4e1 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -73,7 +73,7 @@ end deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - var = get_node_vars(u, equations, solver, i, j, element)[index] + var = u[index, i, j, element] deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - var) end idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) From 6813142bfe561e72f8e5cdc1fc693f24b0bd03a9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 11:35:53 +0200 Subject: [PATCH 232/423] Generalize state limiting --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 4 +- ...ixir_eulermulti_shock_bubble_sc_subcell.jl | 2 +- src/callbacks_stage/bounds_check.jl | 30 +++--- src/callbacks_stage/bounds_check_2d.jl | 36 +++---- src/solvers/dgsem_structured/indicators_2d.jl | 16 ++-- src/solvers/dgsem_tree/dg_2d.jl | 50 +++++----- src/solvers/dgsem_tree/indicators.jl | 39 ++++---- src/solvers/dgsem_tree/indicators_2d.jl | 96 ++++++++++++------- 18 files changed, 168 insertions(+), 125 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index e59f70ee4c..19f524422d 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -14,7 +14,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=false, + state_tvd=false, positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 410b94acab..cb433bb389 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -93,7 +93,7 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], positivity=false, spec_entropy=true, positivity_correction_factor=0.1, max_iterations_newton=100, diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 5f867befaa..528649e9ea 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -14,7 +14,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=false, + state_tvd=false, positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, smoothness_indicator=false, diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index db091f968c..de89e9d70d 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -37,7 +37,7 @@ polydeg = 5 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], positivity=false, spec_entropy=true, max_iterations_newton=100, diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index d4eaa92e48..a439d578ac 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -16,7 +16,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], positivity=false, smoothness_indicator=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 8dab1611aa..31c0bcaaf5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -44,7 +44,7 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], spec_entropy=true, bar_states=true, max_iterations_newton=25) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 3bb2241519..7e8d90c90c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], math_entropy=true, bar_states=false, smoothness_indicator=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 93b064bc3d..654d842ecd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -14,7 +14,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=false, + state_tvd=false, positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 1fe475aba1..75c86e8230 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -38,7 +38,7 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), - density_tvd=false, + state_tvd=false, spec_entropy=false, bar_states=true) volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 40010a58ae..1543e80f01 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,7 +42,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, + state_tvd=true, variables_states=[1], positivity=false, spec_entropy=true, smoothness_indicator=false, diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 6f1c64630f..55ccc01a36 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -14,8 +14,8 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - density_tvd=true, - positivity=false, variables_cons=[1], variables_nonlinear=(pressure,), + state_tvd=true, variables_states=[1], + positivity=false, bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl index 182bc6d8c7..95806035f0 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl @@ -87,7 +87,7 @@ indicator_sc = IndicatorIDP(equations, basis; positivity=true, variables_cons=[(i+3 for i in eachcomponent(equations))...], variables_nonlinear=(), positivity_correction_factor=0.1, - density_tvd=false, + state_tvd=false, spec_entropy=false, bar_states=false) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 1d1925a161..4c182feac1 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -64,13 +64,17 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator return nothing end - @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator + @unpack state_tvd, positivity, spec_entropy, math_entropy = indicator @unpack output_directory = callback + variables = varnames(cons2cons, semi.equations) + mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f; print(f, "# iter, simu_time") - if density_tvd - print(f, ", rho_min, rho_max"); + if state_tvd + for index in indicator.variables_states + print(f, ", $(variables[index])_min, $(variables[index])_max"); + end end if spec_entropy print(f, ", specEntr_min"); @@ -79,9 +83,8 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator print(f, ", mathEntr_max"); end if positivity - variables = varnames(cons2cons, semi.equations) for index in indicator.variables_cons - if index == 1 && density_tvd + if state_tvd && index in indicator.variables_states continue end print(f, ", $(variables[index])_min"); @@ -128,16 +131,21 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) - @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator + @unpack state_tvd, positivity, spec_entropy, math_entropy = indicator @unpack idp_bounds_delta = indicator.cache + variables = varnames(cons2cons, semi.equations) println("─"^100) println("Maximum deviation from bounds:") println("─"^100) counter = 1 - if density_tvd - println("rho:\n- lower bound: ", idp_bounds_delta[counter], "\n- upper bound: ", idp_bounds_delta[counter+1]) - counter += 2 + if state_tvd + for index in indicator.variables_states + println("$(variables[index]):") + println("-lower bound: ", idp_bounds_delta[counter]) + println("-upper bound: ", idp_bounds_delta[counter + 1]) + counter += 2 + end end if spec_entropy println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) @@ -149,10 +157,10 @@ end end if positivity for index in indicator.variables_cons - if index == 1 && density_tvd + if state_tvd && (index in indicator.variables_states) continue end - println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + println("$(variables[index]):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end for variable in indicator.variables_nonlinear diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 3361a6e4e1..6d51ec4f2b 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -7,7 +7,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, indicator::IndicatorIDP, time, iter, output_directory, save_errors, interval) - @unpack density_tvd, positivity, spec_entropy, math_entropy = solver.volume_integral.indicator + @unpack state_tvd, positivity, spec_entropy, math_entropy = solver.volume_integral.indicator @unpack variable_bounds = indicator.cache.container_shock_capturing @unpack idp_bounds_delta = indicator.cache @@ -18,23 +18,25 @@ print(f, iter, ", ", time); end end - if density_tvd - deviation_min = zero(eltype(u)) - deviation_max = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - deviation_min = max(deviation_min, variable_bounds[1][i, j, element] - u[1, i, j, element]) - deviation_max = max(deviation_max, u[1, i, j, element] - variable_bounds[2][i, j, element]) - end - idp_bounds_delta[1] = max(idp_bounds_delta[1], deviation_min) - idp_bounds_delta[2] = max(idp_bounds_delta[2], deviation_max) - if save_errors_ - deviation_min_ = deviation_min - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f; - print(f, ", ", deviation_min_, ", ", deviation_max_); + if state_tvd + for index in indicator.variables_states + deviation_min = zero(eltype(u)) + deviation_max = zero(eltype(u)) + for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) + deviation_min = max(deviation_min, variable_bounds[counter][i, j, element] - u[index, i, j, element]) + deviation_max = max(deviation_max, u[index, i, j, element] - variable_bounds[counter + 1][i, j, element]) + end + idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[counter + 1] = max(idp_bounds_delta[counter + 1], deviation_max) + if save_errors_ + deviation_min_ = deviation_min + deviation_max_ = deviation_max + open("$output_directory/deviations.txt", "a") do f; + print(f, ", ", deviation_min_, ", ", deviation_max_); + end end + counter += 2 end - counter += 2 end if spec_entropy deviation_min = zero(eltype(u)) @@ -68,7 +70,7 @@ end if positivity for index in indicator.variables_cons - if index == 1 && density_tvd + if state_tvd && (index in indicator.variables_states) continue end deviation_min = zero(eltype(u)) diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 395cfeb0e6..876d0fc28c 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -40,8 +40,8 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m if left != 0 for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, left), equations) - var_element = variable(get_node_vars(u, equations, dg, 1, j, element), equations) + var_left = u[variable, nnodes(dg), j, left] + var_element = u[variable, 1, j, element] var_min[1, j, element] = min(var_min[1, j, element], var_left) var_max[1, j, element] = max(var_max[1, j, element], var_left) @@ -52,8 +52,8 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m end if lower != 0 for i in eachnode(dg) - var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), lower), equations) - var_element = variable(get_node_vars(u, equations, dg, i, 1, element), equations) + var_lower = u[variable, i, nnodes(dg), lower] + var_element = u[variable, i, 1, element] var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) @@ -78,7 +78,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[1, j, element] = min(var_min[1, j, element], var_outer) var_max[1, j, element] = max(var_max[1, j, element], var_outer) @@ -92,7 +92,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], var_outer) @@ -108,7 +108,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) @@ -122,7 +122,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, m u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], var_outer) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 0d55a488b9..7095f7d595 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -962,32 +962,34 @@ end @unpack bar_states1, bar_states2 = indicator.cache.container_bar_states counter = 1 - # Density - if indicator.density_tvd - rho_min = variable_bounds[1] - rho_max = variable_bounds[2] - @threaded for element in eachelement(dg, cache) - rho_min[:, :, element] .= typemax(eltype(rho_min)) - rho_max[:, :, element] .= typemin(eltype(rho_max)) - for j in eachnode(dg), i in eachnode(dg) - rho_min[i, j, element] = min(rho_min[i, j, element], u[1, i, j, element]) - rho_max[i, j, element] = max(rho_max[i, j, element], u[1, i, j, element]) - # TODO: Add source term! - # - xi direction - rho_min[i, j, element] = min(rho_min[i, j, element], bar_states1[1, i, j, element]) - rho_max[i, j, element] = max(rho_max[i, j, element], bar_states1[1, i, j, element]) - # + xi direction - rho_min[i, j, element] = min(rho_min[i, j, element], bar_states1[1, i+1, j, element]) - rho_max[i, j, element] = max(rho_max[i, j, element], bar_states1[1, i+1, j, element]) - # - eta direction - rho_min[i, j, element] = min(rho_min[i, j, element], bar_states2[1, i, j, element]) - rho_max[i, j, element] = max(rho_max[i, j, element], bar_states2[1, i, j, element]) - # + eta direction - rho_min[i, j, element] = min(rho_min[i, j, element], bar_states2[1, i, j+1, element]) - rho_max[i, j, element] = max(rho_max[i, j, element], bar_states2[1, i, j+1, element]) + # state variables + if indicator.state_tvd + for index in indicator.variables_states + var_min = variable_bounds[counter] + var_max = variable_bounds[counter + 1] + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + for j in eachnode(dg), i in eachnode(dg) + var_min[i, j, element] = min(var_min[i, j, element], u[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], u[index, i, j, element]) + # TODO: Add source term! + # - xi direction + var_min[i, j, element] = min(var_min[i, j, element], bar_states1[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], bar_states1[index, i, j, element]) + # + xi direction + var_min[i, j, element] = min(var_min[i, j, element], bar_states1[index, i+1, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], bar_states1[index, i+1, j, element]) + # - eta direction + var_min[i, j, element] = min(var_min[i, j, element], bar_states2[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], bar_states2[index, i, j, element]) + # + eta direction + var_min[i, j, element] = min(var_min[i, j, element], bar_states2[index, i, j+1, element]) + var_max[i, j, element] = max(var_max[i, j, element], bar_states2[index, i, j+1, element]) + end end + counter += 2 end - counter += 2 end # Specific Entropy if indicator.spec_entropy diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 32e271253c..a0496ca231 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -217,7 +217,8 @@ end """ IndicatorIDP(equations::AbstractEquations, basis; - density_tvd=false, + state_tvd=false, + variables_states=[], positivity=false, variables_cons=[], variables_nonlinear=(), @@ -231,7 +232,7 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- two-sided Zalesak-type limiting for density (`density_tvd`) +- two-sided Zalesak-type limiting for conservative variables (`state_tvd`) - positivity limiting for conservative and non-linear variables (`positivity`) - one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) @@ -258,10 +259,11 @@ indicator values <= `threshold_smoothness_indicator`. This is an experimental feature and may change in future releases. """ struct IndicatorIDP{RealT<:Real, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator - density_tvd::Bool + state_tvd::Bool + variables_states::Vector{Int} # Impose state limiting positivity::Bool variables_cons::Vector{Int} # Impose positivity for conservative variables - variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables + variables_nonlinear::LimitingVariablesNonlinear # Impose positivity of nonlinear variables spec_entropy::Bool math_entropy::Bool bar_states::Bool @@ -277,7 +279,8 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; - density_tvd=false, + state_tvd=false, + variables_states=[], positivity=false, variables_cons=[], variables_nonlinear=(), @@ -292,11 +295,13 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: math_entropy/spec_entropy") end - number_bounds = positivity * (length(variables_cons) + length(variables_nonlinear)) + + number_bounds = state_tvd * 2 * length(variables_states) + positivity * length(variables_nonlinear) + spec_entropy + math_entropy - if equations isa AbstractCompressibleEulerEquations - if density_tvd - number_bounds += 2 - positivity * (1 in variables_cons) + if positivity + for index in variables_cons + if !(state_tvd && index in variables_states) + number_bounds += 1 + end end end @@ -309,20 +314,20 @@ function IndicatorIDP(equations::AbstractEquations, basis; IndicatorHG = nothing end IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}( - density_tvd, positivity, variables_cons, variables_nonlinear, spec_entropy, math_entropy, + state_tvd, variables_states, positivity, variables_cons, variables_nonlinear, spec_entropy, math_entropy, bar_states, cache, positivity_correction_factor, max_iterations_newton, newton_tolerances, gamma_constant_newton, smoothness_indicator, threshold_smoothness_indicator, IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator + @unpack state_tvd, positivity, spec_entropy, math_entropy = indicator print(io, "IndicatorIDP(") - if !(density_tvd || positivity || spec_entropy || math_entropy) + if !(state_tvd || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else print(io, "limiter=(") - density_tvd && print(io, "density, ") + state_tvd && print(io, "states, ") positivity && print(io, "positivity, ") spec_entropy && print(io, "specific entropy, ") math_entropy && print(io, "mathematical entropy, ") @@ -336,16 +341,18 @@ end function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) @nospecialize indicator # reduce precompilation time - @unpack density_tvd, positivity, spec_entropy, math_entropy = indicator + @unpack state_tvd, positivity, spec_entropy, math_entropy = indicator if get(io, :compact, false) show(io, indicator) else - if !(density_tvd || positivity || spec_entropy || math_entropy) + if !(state_tvd || positivity || spec_entropy || math_entropy) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] - density_tvd && (setup = [setup..., "" => "density"]) + if state_tvd + setup = [setup..., "" => "state limiting for conservative variables $(indicator.variables_states)"] + end if positivity string = "positivity with conservative variables $(indicator.variables_cons) and $(indicator.variables_nonlinear)" setup = [setup..., "" => string] diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index e0cadcd00b..2897eb867f 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -209,8 +209,8 @@ function (indicator::IndicatorIDP)(u::AbstractArray{<:Any,4}, semi, dg::DGSEM, t elements = eachelement(dg, semi.cache) end - if indicator.density_tvd - @trixi_timeit timer() "density_tvd" idp_density_tvd!( alpha, indicator, u, t, dt, semi, elements) + if indicator.state_tvd + @trixi_timeit timer() "state_tvd" idp_state_tvd!( alpha, indicator, u, t, dt, semi, elements) end if indicator.positivity @trixi_timeit timer() "positivity" idp_positivity!( alpha, indicator, u, dt, semi, elements) @@ -248,7 +248,7 @@ end var_max[:, :, element] .= typemin(eltype(var_max)) # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var = u[variable, i, j, element] var_min[i, j, element] = min(var_min[i, j, element], var) var_max[i, j, element] = max(var_max[i, j, element], var) @@ -293,8 +293,8 @@ end index_left = reverse(index_left) index_right = reverse(index_right) end - var_left = variable(get_node_vars(u, equations, dg, index_left..., left), equations) - var_right = variable(get_node_vars(u, equations, dg, index_right..., right), equations) + var_left = u[variable, index_left..., left] + var_right = u[variable, index_right..., right] var_min[index_right..., right] = min(var_min[index_right..., right], var_left) var_max[index_right..., right] = max(var_max[index_right..., right], var_left) @@ -325,7 +325,7 @@ end u_inner = get_node_vars(u, equations, dg, index..., element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[boundary_index], orientation, boundary_index, equations, dg, index..., element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[index..., element] = min(var_min[index..., element], var_outer) var_max[index..., element] = max(var_max[index..., element], var_outer) @@ -448,15 +448,23 @@ end return nothing end -@inline function idp_density_tvd!(alpha, indicator, u, t, dt, semi, elements) +@inline function idp_state_tvd!(alpha, indicator, u, t, dt, semi, elements) + for (index, variable) in enumerate(indicator.variables_states) + idp_state_tvd!(alpha, indicator, u, t, dt, semi, elements, variable, index) + end + + return nothing +end + +@inline function idp_state_tvd!(alpha, indicator, u, t, dt, semi, elements, variable, index) mesh, _, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi @unpack variable_bounds = indicator.cache.container_shock_capturing - rho_min = variable_bounds[1] - rho_max = variable_bounds[2] + var_min = variable_bounds[index] + var_max = variable_bounds[index + 1] if !indicator.bar_states - calc_bounds_2sided!(rho_min, rho_max, density, u, t, semi) + calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @@ -470,22 +478,22 @@ end if mesh isa StructuredMesh inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - rho = u[1, i, j, element] + var = u[variable, i, j, element] # Real Zalesak type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is # for each interface, not each node - Qp = max(0, (rho_max[i, j, element] - rho) / dt) - Qm = min(0, (rho_min[i, j, element] - rho) / dt) + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * antidiffusive_flux1[1, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[1, i+1, j, element] - val_flux2_local = inverse_weights[j] * antidiffusive_flux2[1, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[1, i, j+1, element] + val_flux1_local = inverse_weights[i] * antidiffusive_flux1[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[variable, i+1, j, element] + val_flux2_local = inverse_weights[j] * antidiffusive_flux2[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[variable, i, j+1, element] Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) @@ -496,8 +504,8 @@ end # Compute blending coefficient avoiding division by zero # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / (abs(Pp) + eps(typeof(Qp)) * 100 * abs(rho_max[i, j, element])) - Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100 * abs(rho_max[i, j, element])) + Qp = abs(Qp) / (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) # Calculate alpha at nodes alpha[i, j, element] = 1 - min(1, Qp, Qm) @@ -510,10 +518,10 @@ end @inline function idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack density_tvd, positivity = indicator + @unpack state_tvd, positivity = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing - s_min = variable_bounds[2 * density_tvd + 1] + s_min = variable_bounds[state_tvd * 2 * length(indicator.variables_states) + 1] if !indicator.bar_states calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -538,10 +546,10 @@ specEntropy_initialCheck(bound, goal, newton_abstol) = goal <= max(newton_abstol @inline function idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack boundary_conditions = semi - @unpack density_tvd, positivity, spec_entropy = indicator + @unpack state_tvd, positivity, spec_entropy = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing - s_max = variable_bounds[2 * density_tvd + spec_entropy + 1] + s_max = variable_bounds[state_tvd * 2 * length(indicator.variables_states) + spec_entropy + 1] if !indicator.bar_states calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -564,9 +572,10 @@ mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) = -dot(cons2entrop mathEntropy_initialCheck(bound, goal, newton_abstol) = goal >= -max(newton_abstol, abs(bound) * newton_abstol) @inline function idp_positivity!(alpha, indicator, u, dt, semi, elements) + @unpack state_tvd, spec_entropy, math_entropy, variables_states, variables_cons = indicator # Conservative variables - for (index, variable) in enumerate(indicator.variables_cons) + for (index, variable) in enumerate(variables_cons) idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) end @@ -582,18 +591,29 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack inverse_weights = dg.basis - @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons = indicator + @unpack state_tvd, spec_entropy, math_entropy, positivity_correction_factor = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing - if 1 in variables_cons && density_tvd - if variables_cons[variable] == 1 - var_min = variable_bounds[1] + counter = state_tvd * 2 * length(indicator.variables_states) + spec_entropy + math_entropy + if state_tvd + if variable in indicator.variables_states + for (index_, variable_) in enumerate(indicator.variables_states) + if variable == variable_ + var_min = variable_bounds[2 * (index_ - 1) + 1] + break + end + end else - var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index - 1] + for variable_ in indicator.variables_cons[1:index] + if !(variable_ in indicator.variable_states) + counter += 1 + end + end + var_min = variable_bounds[counter] end else - var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index] + var_min = variable_bounds[counter + index] end @threaded for element in elements @@ -605,13 +625,13 @@ end inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - var = get_node_vars(u, equations, dg, i, j, element)[variable] + var = u[variable, i, j, element] if var < 0 error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end # Compute bound - if indicator.density_tvd + if state_tvd && variable in indicator.variables_states var_min[i, j, element] = max(var_min[i, j, element], positivity_correction_factor * var) else var_min[i, j, element] = positivity_correction_factor * var @@ -650,13 +670,17 @@ end @inline function idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons, variables_nonlinear = indicator + @unpack state_tvd, spec_entropy, math_entropy, positivity_correction_factor = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing - var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + - length(variables_cons) - min(density_tvd, 1 in variables_cons) + - index] + index_ = state_tvd * 2 * length(indicator.variables_states) + spec_entropy + math_entropy + index + for variable_ in indicator.variables_cons + if !(state_tvd && variable_ in indicator.variables_states) + index_ += 1 + end + end + var_min = variable_bounds[index_] @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) From 0185f83bb12173c9a266f7dbec4b22678e8bada7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 12:52:25 +0200 Subject: [PATCH 233/423] Fix `finalize_callback` --- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- src/callbacks_stage/bounds_check.jl | 3 ++- src/solvers/dgsem_tree/indicators.jl | 11 +++++++---- src/solvers/dgsem_tree/indicators_2d.jl | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 6f1c64630f..b2d6ed4f08 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,7 +15,7 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, variables_cons=[1], variables_nonlinear=(pressure,), + positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 1d1925a161..7a4f4e6d7f 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -148,11 +148,12 @@ end counter += 1 end if positivity + variables = varnames(cons2cons, semi.equations) for index in indicator.variables_cons if index == 1 && density_tvd continue end - println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) + println("$(variables[index]):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end for variable in indicator.variables_nonlinear diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 32e271253c..8b1531ada7 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -292,11 +292,14 @@ function IndicatorIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: math_entropy/spec_entropy") end - number_bounds = positivity * (length(variables_cons) + length(variables_nonlinear)) + + number_bounds = 2 * density_tvd + positivity * length(variables_nonlinear) + spec_entropy + math_entropy - if equations isa AbstractCompressibleEulerEquations - if density_tvd - number_bounds += 2 - positivity * (1 in variables_cons) + + if positivity + for index in variables_cons + if !(density_tvd && index == 1) + number_bounds += 1 + end end end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index e0cadcd00b..7029b07b64 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -605,7 +605,7 @@ end inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - var = get_node_vars(u, equations, dg, i, j, element)[variable] + var = u[variable, i, j, element] if var < 0 error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") end From cb8e25e448e773750f355562a4cdee223de23b56 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 13 Jun 2023 15:25:03 +0200 Subject: [PATCH 234/423] Fix state limiting and add elixir --- ...ulermulti_shock_bubble_sc_subcell_state.jl | 144 ++++++++++++++++++ src/solvers/dgsem_tree/indicators_2d.jl | 6 +- test/test_tree_2d_eulermulti.jl | 8 + 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell_state.jl diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell_state.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell_state.jl new file mode 100644 index 0000000000..f1a83a1823 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell_state.jl @@ -0,0 +1,144 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler multicomponent equations + +# 1) Dry Air 2) Helium + 28% Air +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), + gas_constants = (0.287, 1.578)) + +""" + initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + +A shock-bubble testcase for multicomponent Euler equations +- Ayoub Gouasmi, Karthik Duraisamy, Scott Murman + Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations + [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) +""" +function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225-delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +end +initial_condition = initial_condition_shock_bubble + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +indicator_sc = IndicatorIDP(equations, basis; + positivity=false, + variables_cons=[(i+3 for i in eachcomponent(equations))...], + variables_nonlinear=(), positivity_correction_factor=0.1, + state_tvd=true, variables_states=[(i+3 for i in eachcomponent(equations))...], + spec_entropy=false, + bar_states=true) + +volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.25, -2.225) +coordinates_max = ( 2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + n_cells_max=1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(Trixi.density,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=600, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); + 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 \ No newline at end of file diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 2897eb867f..453b44e7e5 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -461,8 +461,8 @@ end @unpack boundary_conditions = semi @unpack variable_bounds = indicator.cache.container_shock_capturing - var_min = variable_bounds[index] - var_max = variable_bounds[index + 1] + var_min = variable_bounds[2 * (index - 1) + 1] + var_max = variable_bounds[2 * (index - 1) + 2] if !indicator.bar_states calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) end @@ -508,7 +508,7 @@ end Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) # Calculate alpha at nodes - alpha[i, j, element] = 1 - min(1, Qp, Qm) + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) end end diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 2b8951b279..2babe02cc8 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -27,6 +27,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.001)) end + @trixi_testset "elixir_eulermulti_shock_bubble_sc_subcell_state.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_sc_subcell_state.jl"), + l2 = [76.59096367977872, 1.9879932386864356, 59851.34515039375, 0.18710988181124935, 0.010631432251136084], + linf = [212.71245739310544, 27.399221359958894, 158389.9681231281, 0.6524718882809865, 0.10630137919864985], + initial_refinement_level = 3, + tspan = (0.0, 0.001)) + end + @trixi_testset "elixir_eulermulti_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), l2 = [0.050182236154087095, 0.050189894464434635, 0.2258715597305131, 0.06175171559771687], From 158ba508118474bc0cec88563f9d4d0a911d9185 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 14 Jun 2023 11:11:34 +0200 Subject: [PATCH 235/423] Simplify flux evaluation --- src/solvers/dgsem_tree/indicators_2d.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 7029b07b64..ac76d42ce7 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -626,10 +626,10 @@ end # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element)[variable] - val_flux1_local_ip1 = -inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i+1, j, element)[variable] - val_flux2_local = inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element)[variable] - val_flux2_local_jp1 = -inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j+1, element)[variable] + val_flux1_local = inverse_weights[i] * antidiffusive_flux1[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * antidiffusive_flux1[variable, i+1, j, element] + val_flux2_local = inverse_weights[j] * antidiffusive_flux2[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * antidiffusive_flux2[variable, i, j+1, element] Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) From c5c1413a59f20eed517d39bf1e04520fa9cb56b9 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 14 Jun 2023 12:28:12 +0200 Subject: [PATCH 236/423] Implement suggestions --- ...multi_shock_bubble_shockcapturing_subcell.jl} | 0 src/callbacks_stage/a_posteriori_limiter.jl | 16 +++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) rename examples/tree_2d_dgsem/{elixir_eulermulti_shock_bubble_sc_subcell.jl => elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl} (100%) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl similarity index 100% rename from examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_sc_subcell.jl rename to examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index 6471cc96d5..9f50fbde4f 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -8,10 +8,20 @@ """ APosterioriLimiter() -Perform antidiffusive stage for a posteriori IDP limiting. +Perform antidiffusive stage for the a posteriori IDP limiter called with +[`VolumeIntegralSubcellLimiting`](@ref) using [`IndicatorIDP`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. + +## References + +- Rueda-Ramírez, Pazner, Gassner (2022) + Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods + [DOI: 10.1016/j.compfluid.2022.105627](https://doi.org/10.1016/j.compfluid.2022.105627) +- Pazner (2020) + Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting + [DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876) """ struct APosterioriLimiter end @@ -20,15 +30,11 @@ function (limiter!::APosterioriLimiter)(u_ode, integrator::Trixi.SimpleIntegrato limiter!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) end -(::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::AbstractVolumeIntegral) = nothing - function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralSubcellLimiting) @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, volume_integral.indicator) end -(::APosterioriLimiter)(u_ode, semi, t, dt, indicator::AbstractIndicator) = nothing - function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, indicator::IndicatorIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) From 80055b89aceb43a2fc4a248080c1165412ec0ab0 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 14 Jun 2023 14:09:33 +0200 Subject: [PATCH 237/423] Rename file in tests --- test/test_tree_2d_eulermulti.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 2b8951b279..653be581e1 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -19,8 +19,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.001)) end - @trixi_testset "elixir_eulermulti_shock_bubble_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_sc_subcell.jl"), + @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl"), l2 = [81.52845664909304, 2.5455678559421346, 63229.190712645846, 0.19929478404550321, 0.011068604228443425], linf = [249.21708417382013, 40.33299887640794, 174205.0118831558, 0.6881458768113586, 0.11274401158173972], initial_refinement_level = 3, From f070558d596eb238d97707bfaaf5d7022ae81525 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 16 Jun 2023 14:53:27 +0200 Subject: [PATCH 238/423] Fix format --- utils/trixi2txt.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index 8b04554eb0..12a3d46760 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -267,9 +267,9 @@ function read_datafile(filename::String) node_variables = Dict{String, Union{Vector{Float64}, Vector{Int}}}() index = 1 while haskey(file, "node_variables_$index") - varname = read(attributes(file["node_variables_$index"])["name"]) - node_variables[varname] = read(file["node_variables_$index"]) - index +=1 + varname = read(attributes(file["node_variables_$index"])["name"]) + node_variables[varname] = read(file["node_variables_$index"]) + index += 1 end return labels, data, n_elements, n_nodes, element_variables, node_variables, time From db99396d7bda0345871f566d382869c7f0d609f4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Tue, 20 Jun 2023 13:42:08 +0200 Subject: [PATCH 239/423] Update docstring and remove unnecessary Type --- src/solvers/dgsem_tree/indicators.jl | 105 +++++++++++++++------------ 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 988ed61670..9edbd9e624 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -223,17 +223,20 @@ end """ IndicatorIDP(equations::AbstractEquations, basis; - density_tvd=false, - positivity=false, - variables_cons=[], - variables_nonlinear=(), - spec_entropy=false, - math_entropy=false, - bar_states=true, - positivity_correction_factor=0.1, max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14), gamma_constant_newton=2*ndims(equations), - smoothness_indicator=false, threshold_smoothness_indicator=0.1, - variable_smoothness_indicator=density_pressure) + density_tvd = false, + positivity = false, + variables_cons = [], + variables_nonlinear = (), + spec_entropy = false, + math_entropy = false, + bar_states = true, + positivity_correction_factor = 0.1, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations), + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: @@ -263,12 +266,12 @@ indicator values <= `threshold_smoothness_indicator`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT <: Real, LimitingVariablesCons, LimitingVariablesNonlinear, +struct IndicatorIDP{RealT <: Real, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator density_tvd::Bool positivity::Bool - variables_cons::Vector{Int} # Impose positivity for conservative variables - variables_nonlinear::LimitingVariablesNonlinear # Positivity of nonlinear variables + variables_cons::Vector{Int} # Positivity for conservative variables + variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables spec_entropy::Bool math_entropy::Bool bar_states::Bool @@ -321,22 +324,22 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_cons), - typeof(variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(density_tvd, - positivity, - variables_cons, - variables_nonlinear, - spec_entropy, - math_entropy, - bar_states, - cache, - positivity_correction_factor, - max_iterations_newton, - newton_tolerances, - gamma_constant_newton, - smoothness_indicator, - threshold_smoothness_indicator, - IndicatorHG) + IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_nonlinear), + typeof(cache), typeof(IndicatorHG)}(density_tvd, + positivity, + variables_cons, + variables_nonlinear, + spec_entropy, + math_entropy, + bar_states, + cache, + positivity_correction_factor, + max_iterations_newton, + newton_tolerances, + gamma_constant_newton, + smoothness_indicator, + threshold_smoothness_indicator, + IndicatorHG) end function Base.show(io::IO, indicator::IndicatorIDP) @@ -373,18 +376,23 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] - density_tvd && (setup = [setup..., "" => "density"]) + if density_tvd + setup = [setup..., "" => "local maximum/minimum bounds for density"] + end if positivity - string = "positivity with conservative variables $(indicator.variables_cons) and $(indicator.variables_nonlinear)" + string = "positivity for conservative variables $(indicator.variables_cons) and $(indicator.variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., - "" => " "^11 * - "and positivity correction factor $(indicator.positivity_correction_factor)", + "" => " positivity correction factor = $(indicator.positivity_correction_factor)", ] end - spec_entropy && (setup = [setup..., "" => "specific entropy"]) - math_entropy && (setup = [setup..., "" => "mathematical entropy"]) + if spec_entropy + setup = [setup..., "" => "local minimum bound for specific entropy"] + end + if math_entropy + setup = [setup..., "" => "local maximum bound for mathematical entropy"] + end setup = [ setup..., "Local bounds" => (indicator.bar_states ? "Bar States" : "FV solution"), @@ -409,18 +417,19 @@ end """ IndicatorMCL(equations::AbstractEquations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=false, - PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=false, - DensityPositivityCorrectionFactor=0.0, - SemiDiscEntropyLimiter=false, - smoothness_indicator=false, threshold_smoothness_indicator=0.1, - variable_smoothness_indicator=density_pressure, - Plotting=true) + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = false, + DensityPositivityCorrectionFactor = 0.0, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure, + Plotting = true) Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: - local two-sided limiting for `cons(1)` (`DensityLimiter`) From 0d6d63d30c6922629681cf2073a7c9648e32e42b Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 21 Jun 2023 12:48:45 +0200 Subject: [PATCH 240/423] Remove parameter `positivity`; Rename vector/tuple --- ...elixir_euler_convergence_wavingflag_IDP.jl | 3 +- .../elixir_euler_double_mach.jl | 1 - .../elixir_euler_free_stream_sc_subcell.jl | 3 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 1 - .../elixir_euler_source_terms_sc_subcell.jl | 1 - .../elixir_euler_convergence_IDP.jl | 3 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 3 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 1 - .../elixir_euler_shockcapturing_subcell.jl | 3 +- .../elixir_euler_source_terms_sc_subcell.jl | 3 +- ...lti_shock_bubble_shockcapturing_subcell.jl | 6 +-- src/callbacks_stage/bounds_check.jl | 8 ++-- src/callbacks_stage/bounds_check_2d.jl | 4 +- src/solvers/dgsem_tree/indicators.jl | 42 +++++++++---------- src/solvers/dgsem_tree/indicators_2d.jl | 22 ++++------ 15 files changed, 51 insertions(+), 53 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index e59f70ee4c..e1dd4abf8e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -15,7 +15,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 410b94acab..ad5b549d79 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -94,7 +94,6 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, spec_entropy=true, positivity_correction_factor=0.1, max_iterations_newton=100, bar_states=true) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 5f867befaa..f12754e437 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -15,7 +15,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), spec_entropy=false, smoothness_indicator=false, bar_states=true, diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index db091f968c..8563b2db13 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -38,7 +38,6 @@ basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, spec_entropy=true, max_iterations_newton=100, bar_states=true) diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index d4eaa92e48..adbaa4d1d0 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -17,7 +17,6 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, smoothness_indicator=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 93b064bc3d..28e5d6c01f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -15,7 +15,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, - positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), spec_entropy=false, positivity_correction_factor=0.1, max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 1fe475aba1..89c7d21521 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -37,7 +37,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), density_tvd=false, spec_entropy=false, bar_states=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 40010a58ae..f62e616815 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -43,7 +43,6 @@ volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=false, spec_entropy=true, smoothness_indicator=false, bar_states=true) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index a2339db8ce..974cd667ed 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -39,7 +39,8 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, variables_cons=[1], positivity_correction_factor=0.5, + positivity_variables_cons=[1], + positivity_correction_factor=0.5, bar_states=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index b2d6ed4f08..299674e120 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,7 +15,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - positivity=true, variables_cons=[1], variables_nonlinear=(pressure,), + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), bar_states=true, smoothness_indicator=true) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl index 182bc6d8c7..4a207873a9 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl @@ -84,9 +84,9 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorIDP(equations, basis; - positivity=true, - variables_cons=[(i+3 for i in eachcomponent(equations))...], - variables_nonlinear=(), positivity_correction_factor=0.1, + positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...], + positivity_variables_nonlinear=(), + positivity_correction_factor=0.1, density_tvd=false, spec_entropy=false, bar_states=false) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 673f8bbc2b..297aba526f 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -86,13 +86,13 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator end if positivity variables = varnames(cons2cons, semi.equations) - for index in indicator.variables_cons + for index in indicator.positivity_variables_cons if index == 1 && density_tvd continue end print(f, ", $(variables[index])_min") end - for variable in indicator.variables_nonlinear + for variable in indicator.positivity_variables_nonlinear print(f, ", $(variable)_min") end end @@ -157,14 +157,14 @@ end end if positivity variables = varnames(cons2cons, semi.equations) - for index in indicator.variables_cons + for index in indicator.positivity_variables_cons if index == 1 && density_tvd continue end println("$(variables[index]):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end - for variable in indicator.variables_nonlinear + for variable in indicator.positivity_variables_nonlinear println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 934f8f5ae1..c46bdc851d 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -80,7 +80,7 @@ counter += 1 end if positivity - for index in indicator.variables_cons + for index in indicator.positivity_variables_cons if index == 1 && density_tvd continue end @@ -101,7 +101,7 @@ end counter += 1 end - for variable in indicator.variables_nonlinear + for variable in indicator.positivity_variables_nonlinear deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 9edbd9e624..bdac5518e9 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -224,13 +224,12 @@ end """ IndicatorIDP(equations::AbstractEquations, basis; density_tvd = false, - positivity = false, - variables_cons = [], - variables_nonlinear = (), + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, spec_entropy = false, math_entropy = false, bar_states = true, - positivity_correction_factor = 0.1, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations), @@ -241,7 +240,7 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - two-sided Zalesak-type limiting for density (`density_tvd`) -- positivity limiting for conservative and non-linear variables (`positivity`) +- positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) - one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity @@ -270,8 +269,8 @@ struct IndicatorIDP{RealT <: Real, LimitingVariablesNonlinear, Cache, Indicator} <: AbstractIndicator density_tvd::Bool positivity::Bool - variables_cons::Vector{Int} # Positivity for conservative variables - variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables + positivity_variables_cons::Vector{Int} # Positivity for conservative variables + positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables spec_entropy::Bool math_entropy::Bool bar_states::Bool @@ -288,30 +287,30 @@ end # this method is used when the indicator is constructed as for shock-capturing volume integrals function IndicatorIDP(equations::AbstractEquations, basis; density_tvd = false, - positivity = false, - variables_cons = [], - variables_nonlinear = (), + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, spec_entropy = false, math_entropy = false, bar_states = true, - positivity_correction_factor = 0.1, max_iterations_newton = 10, + max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations), smoothness_indicator = false, threshold_smoothness_indicator = 0.1, variable_smoothness_indicator = density_pressure) + positivity = (length(positivity_variables_cons) + + length(positivity_variables_nonlinear) > 0) if math_entropy && spec_entropy error("Only one of the two can be selected: math_entropy/spec_entropy") end - number_bounds = 2 * density_tvd + positivity * length(variables_nonlinear) + + number_bounds = 2 * density_tvd + length(positivity_variables_nonlinear) + spec_entropy + math_entropy - if positivity - for index in variables_cons - if !(density_tvd && index == 1) - number_bounds += 1 - end + for index in positivity_variables_cons + if !(density_tvd && index == 1) + number_bounds += 1 end end @@ -324,11 +323,12 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positivity_correction_factor), typeof(variables_nonlinear), + IndicatorIDP{typeof(positivity_correction_factor), + typeof(positivity_variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(density_tvd, positivity, - variables_cons, - variables_nonlinear, + positivity_variables_cons, + positivity_variables_nonlinear, spec_entropy, math_entropy, bar_states, @@ -380,7 +380,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) setup = [setup..., "" => "local maximum/minimum bounds for density"] end if positivity - string = "positivity for conservative variables $(indicator.variables_cons) and $(indicator.variables_nonlinear)" + string = "positivity for conservative variables $(indicator.positivity_variables_cons) and $(indicator.positivity_variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index f08c0375ea..b62e60b7c9 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -500,7 +500,6 @@ end @inline function idp_density_tvd!(alpha, indicator, u, t, dt, semi, elements) mesh, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi @unpack variable_bounds = indicator.cache.container_shock_capturing rho_min = variable_bounds[1] @@ -563,8 +562,7 @@ end @inline function idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack density_tvd, positivity = indicator + @unpack density_tvd = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing s_min = variable_bounds[2 * density_tvd + 1] @@ -596,8 +594,7 @@ end @inline function idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack density_tvd, positivity, spec_entropy = indicator + @unpack density_tvd, spec_entropy = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing s_max = variable_bounds[2 * density_tvd + spec_entropy + 1] @@ -628,14 +625,13 @@ function mathEntropy_initialCheck(bound, goal, newton_abstol) end @inline function idp_positivity!(alpha, indicator, u, dt, semi, elements) - # Conservative variables - for (index, variable) in enumerate(indicator.variables_cons) + for (index, variable) in enumerate(indicator.positivity_variables_cons) idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) end # Nonlinear variables - for (index, variable) in enumerate(indicator.variables_nonlinear) + for (index, variable) in enumerate(indicator.positivity_variables_nonlinear) idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) end @@ -647,12 +643,12 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack inverse_weights = dg.basis - @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons = indicator + @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing - if 1 in variables_cons && density_tvd - if variables_cons[variable] == 1 + if 1 in indicator.positivity_variables_cons && density_tvd + if indicator.positivity_variables_cons[variable] == 1 var_min = variable_bounds[1] else var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + index - 1] @@ -720,12 +716,12 @@ end @inline function idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, variables_cons, variables_nonlinear = indicator + @unpack density_tvd, spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = indicator @unpack variable_bounds = indicator.cache.container_shock_capturing var_min = variable_bounds[2 * density_tvd + spec_entropy + math_entropy + - length(variables_cons) - min(density_tvd, 1 in variables_cons) + index] + length(positivity_variables_cons) - min(density_tvd, 1 in positivity_variables_cons) + index] @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) From 68e2f372ca5b7e2a742f3c0a20261b503bb4684a Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 21 Jun 2023 14:08:33 +0200 Subject: [PATCH 241/423] Clean up FV bounds calculation --- ...elixir_euler_convergence_wavingflag_IDP.jl | 3 ++- .../elixir_euler_free_stream_sc_subcell.jl | 3 ++- .../elixir_euler_convergence_IDP.jl | 3 ++- ...bble_shockcapturing_subcell_positivity.jl} | 0 src/solvers/dgsem_structured/indicators_2d.jl | 20 ++++++++----------- src/solvers/dgsem_tree/indicators.jl | 6 +++--- src/solvers/dgsem_tree/indicators_2d.jl | 12 +++++------ test/test_tree_2d_eulermulti.jl | 4 ++-- 8 files changed, 24 insertions(+), 27 deletions(-) rename examples/tree_2d_dgsem/{elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl => elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl} (100%) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index e1dd4abf8e..17cc79fa4f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -17,8 +17,9 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, positivity_variables_cons=[1], positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, spec_entropy=false, - positivity_correction_factor=0.1, max_iterations_newton=10, + max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), bar_states=true, smoothness_indicator=false) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index f12754e437..dd68e0d9ae 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -17,10 +17,11 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, positivity_variables_cons=[1], positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, spec_entropy=false, smoothness_indicator=false, bar_states=true, - positivity_correction_factor=0.1, max_iterations_newton=10, + max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14)) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 28e5d6c01f..f5b69c2ff9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -17,8 +17,9 @@ indicator_sc = IndicatorIDP(equations, basis; density_tvd=false, positivity_variables_cons=[1], positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, spec_entropy=false, - positivity_correction_factor=0.1, max_iterations_newton=10, + max_iterations_newton=10, newton_tolerances=(1.0e-12, 1.0e-14), bar_states=true, smoothness_indicator=false) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl similarity index 100% rename from examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl rename to examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 3d1851cd7b..8f6b54459e 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -41,10 +41,8 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, if left != 0 for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, - left), equations) - var_element = variable(get_node_vars(u, equations, dg, 1, j, element), - equations) + var_left = u[variable, nnodes(dg), j, left] + var_element = u[variable, 1, j, element] var_min[1, j, element] = min(var_min[1, j, element], var_left) var_max[1, j, element] = max(var_max[1, j, element], var_left) @@ -57,10 +55,8 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, end if lower != 0 for i in eachnode(dg) - var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), - lower), equations) - var_element = variable(get_node_vars(u, equations, dg, i, 1, element), - equations) + var_lower = u[variable, i, nnodes(dg), lower] + var_element = u[variable, i, 1, element] var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) @@ -88,7 +84,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[1, j, element] = min(var_min[1, j, element], var_outer) var_max[1, j, element] = max(var_max[1, j, element], var_outer) @@ -105,7 +101,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, boundary_conditions[2], Ja1, 2, equations, dg, nnodes(dg), j, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], var_outer) @@ -124,7 +120,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) @@ -141,7 +137,7 @@ function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, boundary_conditions[4], Ja2, 4, equations, dg, i, nnodes(dg), element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], var_outer) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index bdac5518e9..7e753a7d48 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -239,7 +239,7 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- two-sided Zalesak-type limiting for density (`density_tvd`) +- maximum/minimum Zalesak-type limiting for density (`density_tvd`) - positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) - one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) @@ -271,11 +271,11 @@ struct IndicatorIDP{RealT <: Real, LimitingVariablesNonlinear, positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables + positivity_correction_factor::RealT spec_entropy::Bool math_entropy::Bool bar_states::Bool cache::Cache - positivity_correction_factor::RealT max_iterations_newton::Int newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints @@ -329,11 +329,11 @@ function IndicatorIDP(equations::AbstractEquations, basis; positivity, positivity_variables_cons, positivity_variables_nonlinear, + positivity_correction_factor, spec_entropy, math_entropy, bar_states, cache, - positivity_correction_factor, max_iterations_newton, newton_tolerances, gamma_constant_newton, diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index b62e60b7c9..9c7cbcaa5e 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -263,7 +263,7 @@ end var_max[:, :, element] .= typemin(eltype(var_max)) # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) - var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var = u[variable, i, j, element] var_min[i, j, element] = min(var_min[i, j, element], var) var_max[i, j, element] = max(var_max[i, j, element], var) @@ -309,10 +309,8 @@ end index_left = reverse(index_left) index_right = reverse(index_right) end - var_left = variable(get_node_vars(u, equations, dg, index_left..., left), - equations) - var_right = variable(get_node_vars(u, equations, dg, index_right..., right), - equations) + var_left = u[variable, index_left..., left] + var_right = u[variable, index_right..., right] var_min[index_right..., right] = min(var_min[index_right..., right], var_left) @@ -347,7 +345,7 @@ end boundary_conditions[boundary_index], orientation, boundary_index, equations, dg, index..., element) - var_outer = variable(u_outer, equations) + var_outer = u_outer[variable] var_min[index..., element] = min(var_min[index..., element], var_outer) var_max[index..., element] = max(var_max[index..., element], var_outer) @@ -505,7 +503,7 @@ end rho_min = variable_bounds[1] rho_max = variable_bounds[2] if !indicator.bar_states - calc_bounds_2sided!(rho_min, rho_max, density, u, t, semi) + calc_bounds_2sided!(rho_min, rho_max, 1, u, t, semi) end @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 653be581e1..606afca103 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -19,8 +19,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.001)) end - @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell.jl"), + @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl"), l2 = [81.52845664909304, 2.5455678559421346, 63229.190712645846, 0.19929478404550321, 0.011068604228443425], linf = [249.21708417382013, 40.33299887640794, 174205.0118831558, 0.6881458768113586, 0.11274401158173972], initial_refinement_level = 3, From fa9a1beea448ad245a3d10a077f88db9755c9950 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 21 Jun 2023 17:09:51 +0200 Subject: [PATCH 242/423] Add test for "show" routines --- test/test_unit.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_unit.jl b/test/test_unit.jl index 2156e9bac3..2fa6a04237 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -402,6 +402,12 @@ isdir(outdir) && rm(outdir, recursive=true) indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) + indicator_idp = IndicatorIDP(true, true, [1], ("variable",), 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) + @test_nowarn show(stdout, indicator_idp) + + indicator_mcl = IndicatorMCL("cache", true, true, true, true, true, true, true, 1.0, true, true, 1.0, nothing, true) + @test_nowarn show(stdout, indicator_mcl) + indicator_loehner = IndicatorLöhner(1.0, "variable", (; cache=nothing)) @test_nowarn show(stdout, indicator_loehner) From 5b6073a020e629fd518425f8c0b91c89b9b38b11 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 22 Jun 2023 10:15:47 +0200 Subject: [PATCH 243/423] Adapt test to test FV bounds for StructuredMesh --- .../elixir_euler_source_terms_sc_subcell.jl | 5 +++-- test/test_structured_2d.jl | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index adbaa4d1d0..a86b56cd21 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -17,7 +17,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorIDP(equations, basis; density_tvd=true, - smoothness_indicator=false) + spec_entropy=true, + bar_states=false) volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -54,7 +55,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index fe820786db..45069861a2 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -186,8 +186,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin # Somehow the test fails because of replacing docs. Keeping it here for orientation. @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [0.0005410073263272928, 0.0004202892126963879, 0.00041243815462826874, 0.0008337413923563841], - linf = [0.002820853944058177, 0.002920003618928524, 0.0028228964420637936, 0.004689604214830556], + l2 = [0.008160130912696845, 0.00865825700844846, 0.009351906012699371, 0.027757016247441632], + linf = [0.027225637159330685, 0.040734035628746224, 0.038194094936598866, 0.0808065518907406], tspan = (0.0, 0.5)) end From a2833c3a10d02f87132e4fc82485f154e99b2e64 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 22 Jun 2023 13:52:21 +0200 Subject: [PATCH 244/423] Fix test --- test/test_structured_2d.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 45069861a2..cf766b7a98 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -184,10 +184,9 @@ isdir(outdir) && rm(outdir, recursive=true) end @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin - # Somehow the test fails because of replacing docs. Keeping it here for orientation. @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [0.008160130912696845, 0.00865825700844846, 0.009351906012699371, 0.027757016247441632], - linf = [0.027225637159330685, 0.040734035628746224, 0.038194094936598866, 0.0808065518907406], + l2 = [0.008160130056105786, 0.008658251740761163, 0.009351904344378272, 0.027757009375556807], + linf = [0.027225634762642947, 0.040734047009665986, 0.03819407519909657, 0.08080651960614205], tspan = (0.0, 0.5)) end From 43f9517f7aaf29df1c32de8fc6a500035dd537c2 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 5 Jul 2023 13:54:56 +0200 Subject: [PATCH 245/423] Rename Limiters and Containers --- ...elixir_euler_convergence_wavingflag_IDP.jl | 22 +- ...elixir_euler_convergence_wavingflag_MCL.jl | 20 +- .../elixir_euler_double_mach.jl | 15 +- .../elixir_euler_double_mach_MCL.jl | 24 +- .../elixir_euler_free_stream_MCL.jl | 24 +- .../elixir_euler_free_stream_sc_subcell.jl | 22 +- .../elixir_euler_shock_upstream_MCL.jl | 23 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 15 +- .../elixir_euler_source_terms_sc_subcell.jl | 10 +- .../elixir_euler_astro_jet_MCL.jl | 21 +- .../elixir_euler_astro_jet_subcell.jl | 15 +- .../elixir_euler_blast_wave_MCL.jl | 23 +- .../elixir_euler_blast_wave_sc_subcell.jl | 12 +- .../elixir_euler_convergence_IDP.jl | 22 +- .../elixir_euler_convergence_MCL.jl | 20 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 23 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 15 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 22 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 12 +- .../elixir_euler_shockcapturing_subcell.jl | 10 +- .../elixir_euler_source_terms_sc_subcell.jl | 14 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 14 +- ...ubble_shockcapturing_subcell_positivity.jl | 19 +- src/Trixi.jl | 2 +- src/callbacks_stage/a_posteriori_limiter.jl | 12 +- .../a_posteriori_limiter_2d.jl | 8 +- src/callbacks_stage/bounds_check.jl | 48 +-- src/callbacks_stage/bounds_check_2d.jl | 84 ++--- src/callbacks_step/limiting_analysis.jl | 47 +-- src/callbacks_step/limiting_analysis_2d.jl | 44 +-- src/callbacks_step/stepsize.jl | 6 +- src/callbacks_step/stepsize_dg2d.jl | 26 +- src/solvers/dg.jl | 29 +- src/solvers/dgsem_structured/dg_2d.jl | 8 +- src/solvers/dgsem_tree/containers_2d.jl | 66 ++-- src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_2d.jl | 196 +++++----- src/solvers/dgsem_tree/indicators.jl | 335 +++++++++--------- src/solvers/dgsem_tree/indicators_2d.jl | 140 ++++---- src/time_integration/methods_SSP.jl | 15 +- test/test_unit.jl | 4 +- 41 files changed, 754 insertions(+), 735 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 43268e72e6..585ac50d0d 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -13,17 +13,17 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14), - bar_states=true, - smoothness_indicator=false) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, + spec_entropy=false, + max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), + bar_states=true, + smoothness_indicator=false) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index d6dc886a29..fa59e5e0d3 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -13,16 +13,16 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - Plotting=true) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + Plotting=true) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 1313767231..a7f01ac250 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -92,13 +92,14 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - max_iterations_newton=100, - bar_states=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + spec_entropy=true, + positivity_correction_factor=0.1, max_iterations_newton=100, + bar_states=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 746db116d5..9c3d7c8943 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -92,17 +92,18 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - DensityPositivityLimiter=false, - PressurePositivityLimiterKuzmin=false, - SemiDiscEntropyLimiter=false, - Plotting=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + DensityPositivityLimiter=false, + PressurePositivityLimiterKuzmin=false, + SemiDiscEntropyLimiter=false, + Plotting=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 @@ -132,7 +133,6 @@ save_solution = SaveSolutionCallback(interval=1000, save_final_solution=true, solution_variables=cons2prim) - stepsize_callback = StepsizeCallback(cfl=0.9) callbacks = CallbackSet(summary_callback, diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 2a460464ac..8999d435ec 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -13,18 +13,18 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=true, - SemiDiscEntropyLimiter=false, - smoothness_indicator=false, - Plotting=true) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=true, + SemiDiscEntropyLimiter=false, + smoothness_indicator=false, + Plotting=true) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index c177b972e9..3d36144546 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -13,17 +13,17 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - smoothness_indicator=false, - bar_states=true, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14)) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, + spec_entropy=false, + smoothness_indicator=false, + bar_states=true, + max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14)) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 8c9baaed20..2d4f8f608a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -36,17 +36,18 @@ volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=false, - DensityPositivityLimiter=false, - SemiDiscEntropyLimiter=false, - Plotting=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=false, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, + Plotting=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 31d80f808a..ff64933b83 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -36,13 +36,14 @@ volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - max_iterations_newton=100, - bar_states=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + spec_entropy=true, + max_iterations_newton=100, + bar_states=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 9568546c1d..347ae70570 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -15,11 +15,11 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - bar_states=false) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + spec_entropy=true, + bar_states=false) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 5d5b76a434..f51b73dd49 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -43,16 +43,17 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=true, - SequentialLimiter=true, - PressurePositivityLimiterKuzmin=true, - DensityPositivityLimiter=false, - SemiDiscEntropyLimiter=false, - Plotting=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=true, + SequentialLimiter=true, + PressurePositivityLimiterKuzmin=true, + DensityPositivityLimiter=false, + SemiDiscEntropyLimiter=false, + Plotting=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index fe6671a2d1..12c0259914 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -43,13 +43,14 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - bar_states=true, - max_iterations_newton=25) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + spec_entropy=true, + bar_states=true, + max_iterations_newton=25) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 81577ba511..0e5a85e00a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -38,17 +38,18 @@ initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=true, - SequentialLimiter=false, - ConservativeLimiter=true, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=false, - SemiDiscEntropyLimiter=true, - smoothness_indicator=true, - Plotting=false) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=true, + SequentialLimiter=false, + ConservativeLimiter=true, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, + PressurePositivityLimiterKuzminExact=false, + SemiDiscEntropyLimiter=true, + smoothness_indicator=true, + Plotting=false) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 904ae809ca..2c18b0186e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -38,12 +38,12 @@ initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - math_entropy=true, - bar_states=false, - smoothness_indicator=true) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + math_entropy=true, + bar_states=false, + smoothness_indicator=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 4f3b20d697..fbf695c412 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -13,17 +13,17 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14), - bar_states=true, - smoothness_indicator=false) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), + positivity_correction_factor=0.1, + spec_entropy=false, + max_iterations_newton=10, + newton_tolerances=(1.0e-12, 1.0e-14), + bar_states=true, + smoothness_indicator=false) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index 3bd33c3b2c..d7e4250bb6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -13,16 +13,16 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - Plotting=true) - -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + DensityPositivityLimiter=true, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + Plotting=true) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 35ad491e15..3be50d0199 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -36,17 +36,18 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=true, - SemiDiscEntropyLimiter=false, - Plotting=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=false, + DensityAlphaForAll=false, + SequentialLimiter=false, + ConservativeLimiter=false, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + DensityPositivityLimiter=true, + SemiDiscEntropyLimiter=false, + Plotting=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 38cf1d6000..66297c8eb7 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -36,13 +36,14 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - spec_entropy=false, - bar_states=true) -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), + spec_entropy=false, + bar_states=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index cedb276c79..af239b7c1a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -41,17 +41,17 @@ initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - DensityPositivityLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - SemiDiscEntropyLimiter=true, - smoothness_indicator=false, - Plotting=true) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_mcl = SubcellLimiterMCL(equations, basis; + DensityLimiter=true, + DensityAlphaForAll=false, + SequentialLimiter=true, + ConservativeLimiter=false, + DensityPositivityLimiter=false, + PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, + SemiDiscEntropyLimiter=true, + smoothness_indicator=false, + Plotting=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 70fadce921..e8eaa5ea32 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -41,12 +41,12 @@ initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - smoothness_indicator=false, - bar_states=true) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + spec_entropy=true, + smoothness_indicator=false, + bar_states=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 974cd667ed..65b8f72de3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -38,11 +38,11 @@ initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[1], - positivity_correction_factor=0.5, - bar_states=false) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_correction_factor=0.5, + bar_states=false) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 670f49ce20..8ac4b2091f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -13,13 +13,13 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[1], - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - bar_states=true, - smoothness_indicator=true) -volume_integral = VolumeIntegralSubcellLimiting(indicator_sc; +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1], + positivity_variables_cons=[1], + positivity_variables_nonlinear=(pressure,), + bar_states=true, + smoothness_indicator=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 83aea4ee2a..55c87cab3b 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -83,13 +83,13 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - local_minmax_variables_cons=[(i+3 for i in eachcomponent(equations))...], - spec_entropy=false, - bar_states=true) - -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[(i+3 for i in eachcomponent(equations))...], + spec_entropy=false, + bar_states=true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index aadf21f1e1..d3b41dfb33 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -83,15 +83,16 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorIDP(equations, basis; - positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...], - positivity_variables_nonlinear=(), - positivity_correction_factor=0.1, - spec_entropy=false, - bar_states=false) - -volume_integral=VolumeIntegralSubcellLimiting(indicator_sc; volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...], + positivity_variables_nonlinear=(), + positivity_correction_factor=0.1, + spec_entropy=false, + bar_states=false) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) diff --git a/src/Trixi.jl b/src/Trixi.jl index 61340d4330..a3a73b578c 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -217,7 +217,7 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralSubcellLimiting, IndicatorIDP, IndicatorMCL, + VolumeIntegralSubcellLimiting, SubcellLimiterIDP, SubcellLimiterMCL, VolumeIntegralUpwind, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, SurfaceIntegralUpwind, diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index fb7e024786..c85088ad93 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -9,7 +9,7 @@ APosterioriLimiter() Perform antidiffusive stage for the a posteriori IDP limiter called with -[`VolumeIntegralSubcellLimiting`](@ref) using [`IndicatorIDP`](@ref). +[`VolumeIntegralSubcellLimiting`](@ref) using [`SubcellLimiterIDP`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. @@ -34,10 +34,10 @@ end function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, volume_integral::VolumeIntegralSubcellLimiting) @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, - volume_integral.indicator) + volume_integral.limiter) end -function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, indicator::IndicatorIDP) +function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, limiter::SubcellLimiterIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -45,9 +45,9 @@ function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, indicator::Indicator # Calculate blending factor alpha in [0,1] # f_ij = alpha_ij * f^(FV)_ij + (1 - alpha_ij) * f^(DG)_ij # = f^(FV)_ij + (1 - alpha_ij) * f^(antidiffusive)_ij - @trixi_timeit timer() "blending factors" solver.volume_integral.indicator(u, semi, - solver, t, - dt) + @trixi_timeit timer() "blending factors" solver.volume_integral.limiter(u, semi, + solver, t, + dt) perform_idp_correction!(u, dt, mesh, equations, solver, cache) diff --git a/src/callbacks_stage/a_posteriori_limiter_2d.jl b/src/callbacks_stage/a_posteriori_limiter_2d.jl index 965afdcc19..a3c7f6c047 100644 --- a/src/callbacks_stage/a_posteriori_limiter_2d.jl +++ b/src/callbacks_stage/a_posteriori_limiter_2d.jl @@ -8,8 +8,8 @@ @inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.container_shock_capturing - if dg.volume_integral.indicator.smoothness_indicator + @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter + if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else elements = eachelement(dg, cache) @@ -52,9 +52,9 @@ end cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.indicator.cache.container_shock_capturing + @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter - if dg.volume_integral.indicator.smoothness_indicator + if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else elements = eachelement(dg, cache) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 773aa3e1f4..1d56d725c8 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -8,9 +8,9 @@ """ BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) -Bounds checking routine for `IndicatorIDP` and `IndicatorMCL`. Applied as a stage callback for -SSPRK methods. If `save_errors` is `true`, the resulting deviations are saved in -`output_directory/deviations.txt` for every `interval` time steps. +Bounds checking routine for [`SubcellLimiterIDP`](@ref) and [`SubcellLimiterMCL`](@ref). Applied +as a stage callback for SSPRK methods. If `save_errors` is `true`, the resulting deviations are +saved in `output_directory/deviations.txt` for every `interval` time steps. """ struct BoundsCheckCallback output_directory::String @@ -51,7 +51,7 @@ end function check_bounds(u, mesh, equations, solver, cache, volume_integral::VolumeIntegralSubcellLimiting, t, iter, output_directory, save_errors, interval) - check_bounds(u, mesh, equations, solver, cache, volume_integral.indicator, t, iter, + check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter, t, iter, output_directory, save_errors, interval) end @@ -62,15 +62,15 @@ end init_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing function init_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) - init_callback(callback, semi, volume_integral.indicator) + init_callback(callback, semi, volume_integral.limiter) end -function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorIDP) +function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) if !callback.save_errors || (callback.interval == 0) return nothing end - @unpack local_minmax, positivity, spec_entropy, math_entropy = indicator + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter @unpack output_directory = callback variables = varnames(cons2cons, semi.equations) @@ -78,7 +78,7 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time") if local_minmax - for index in indicator.local_minmax_variables_cons + for index in limiter.local_minmax_variables_cons print(f, ", $(variables[index])_min, $(variables[index])_max") end end @@ -89,13 +89,13 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator print(f, ", mathEntr_max") end if positivity - for index in indicator.positivity_variables_cons - if index in indicator.local_minmax_variables_cons + for index in limiter.positivity_variables_cons + if index in limiter.local_minmax_variables_cons continue end print(f, ", $(variables[index])_min") end - for variable in indicator.positivity_variables_nonlinear + for variable in limiter.positivity_variables_nonlinear print(f, ", $(variable)_min") end end @@ -105,7 +105,7 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator return nothing end -function init_callback(callback::BoundsCheckCallback, semi, indicator::IndicatorMCL) +function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterMCL) if !callback.save_errors || (callback.interval == 0) return nothing end @@ -115,7 +115,7 @@ function init_callback(callback::BoundsCheckCallback, semi, indicator::Indicator open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in varnames(cons2cons, semi.equations))) - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin print(f, ", pressure_min") end # No check for entropy limiting rn @@ -133,13 +133,13 @@ finalize_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = not function finalize_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) - finalize_callback(callback, semi, volume_integral.indicator) + finalize_callback(callback, semi, volume_integral.limiter) end @inline function finalize_callback(callback::BoundsCheckCallback, semi, - indicator::IndicatorIDP) - @unpack local_minmax, positivity, spec_entropy, math_entropy = indicator - @unpack idp_bounds_delta = indicator.cache + limiter::SubcellLimiterIDP) + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter + @unpack idp_bounds_delta = limiter.cache variables = varnames(cons2cons, semi.equations) println("─"^100) @@ -147,7 +147,7 @@ end println("─"^100) counter = 1 if local_minmax - for index in indicator.local_minmax_variables_cons + for index in limiter.local_minmax_variables_cons println("$(variables[index]):") println("-lower bound: ", idp_bounds_delta[counter]) println("-upper bound: ", idp_bounds_delta[counter + 1]) @@ -163,14 +163,14 @@ end counter += 1 end if positivity - for index in indicator.positivity_variables_cons - if index in indicator.local_minmax_variables_cons + for index in limiter.positivity_variables_cons + if index in limiter.local_minmax_variables_cons continue end println("$(variables[index]):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end - for variable in indicator.positivity_variables_nonlinear + for variable in limiter.positivity_variables_nonlinear println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) counter += 1 end @@ -181,8 +181,8 @@ end end @inline function finalize_callback(callback::BoundsCheckCallback, semi, - indicator::IndicatorMCL) - @unpack idp_bounds_delta = indicator.cache + limiter::SubcellLimiterMCL) + @unpack idp_bounds_delta = limiter.cache println("─"^100) println("Maximum deviation from bounds:") @@ -192,7 +192,7 @@ end println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], "\n- upper bound: ", idp_bounds_delta[2, v]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin println("pressure:\n- lower bound: ", idp_bounds_delta[1, nvariables(semi.equations) + 1]) end diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 5d20ac2d24..600ff07751 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -6,11 +6,11 @@ #! format: noindent @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, - indicator::IndicatorIDP, + limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors, interval) - @unpack local_minmax, positivity, spec_entropy, math_entropy = solver.volume_integral.indicator - @unpack variable_bounds = indicator.cache.container_shock_capturing - @unpack idp_bounds_delta = indicator.cache + @unpack local_minmax, positivity, spec_entropy, math_entropy = solver.volume_integral.limiter + @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack idp_bounds_delta = limiter.cache save_errors_ = save_errors && (iter % interval == 0) counter = 1 @@ -20,7 +20,7 @@ end end if local_minmax - for index in indicator.local_minmax_variables_cons + for index in limiter.local_minmax_variables_cons deviation_min = zero(eltype(u)) deviation_max = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), @@ -85,8 +85,8 @@ counter += 1 end if positivity - for index in indicator.positivity_variables_cons - if (index in indicator.local_minmax_variables_cons) + for index in limiter.positivity_variables_cons + if index in limiter.local_minmax_variables_cons continue end deviation_min = zero(eltype(u)) @@ -106,7 +106,7 @@ counter += 1 end end - for variable in indicator.positivity_variables_nonlinear + for variable in limiter.positivity_variables_nonlinear deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -136,19 +136,19 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, - indicator::IndicatorMCL, + limiter::SubcellLimiterMCL, time, iter, output_directory, save_errors, interval) - @unpack var_min, var_max = indicator.cache.container_shock_capturing - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states - @unpack idp_bounds_delta = solver.volume_integral.indicator.cache + @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states + @unpack idp_bounds_delta = limiter.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux n_vars = nvariables(equations) - deviation_min = zeros(eltype(u), n_vars + indicator.PressurePositivityLimiterKuzmin) + deviation_min = zeros(eltype(u), n_vars + limiter.PressurePositivityLimiterKuzmin) deviation_max = zeros(eltype(u), n_vars) - if indicator.DensityLimiter + if limiter.DensityLimiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -199,9 +199,9 @@ end rho_limited - var_max[1, i, j, element]) end end - end # indicator.DensityLimiter + end # limiter.DensityLimiter - if indicator.SequentialLimiter + if limiter.SequentialLimiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -212,7 +212,7 @@ end deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] @@ -246,11 +246,11 @@ end deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -270,11 +270,11 @@ end deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -294,11 +294,11 @@ end deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -318,11 +318,11 @@ end deviation_max[v] = max(deviation_max[v], var_limited / rho_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -330,7 +330,7 @@ end end end end - elseif indicator.ConservativeLimiter + elseif limiter.ConservativeLimiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -342,7 +342,7 @@ end u[v, i, j, element] - var_max[v, i, j, element]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] @@ -374,11 +374,11 @@ end var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -396,11 +396,11 @@ end var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -418,11 +418,11 @@ end var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -440,11 +440,11 @@ end var_min[v, i, j, element] - var_limited) deviation_max[v] = max(deviation_max[v], var_limited - var_max[v, i, j, element]) - if indicator.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -452,7 +452,7 @@ end end end end - elseif indicator.PressurePositivityLimiterKuzmin + elseif limiter.PressurePositivityLimiterKuzmin # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -539,9 +539,9 @@ end error_pressure) end end - end # indicator.PressurePositivityLimiterKuzmin + end # limiter.PressurePositivityLimiterKuzmin - if indicator.DensityPositivityLimiter + if limiter.DensityPositivityLimiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -550,7 +550,7 @@ end end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - beta = indicator.DensityPositivityCorrectionFactor + beta = limiter.DensityPositivityCorrectionFactor # Checking the bounds for... # - density (rho): # beta * \bar{rho} <= \bar{rho}^{Lim} @@ -578,13 +578,13 @@ end deviation_min[1] = max(deviation_min[1], -rho_limited) end end - end # indicator.DensityPositivityLimiter + end # limiter.DensityPositivityLimiter for v in eachvariable(equations) idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin idp_bounds_delta[1, n_vars + 1] = max(idp_bounds_delta[1, n_vars + 1], deviation_min[n_vars + 1]) end @@ -597,7 +597,7 @@ end for v in eachvariable(equations) print(f, ", ", deviation_min[v], ", ", deviation_max[v]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin print(f, ", ", deviation_min[n_vars + 1]) end println(f) diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index f0ed439213..65d280f33d 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -8,11 +8,12 @@ """ LimitingAnalysisCallback(; output_directory="out", interval=1) -Analyze the subcell blending coefficient of IDP limiting (`IndicatorIDP`) and monolithic convex -limiting (MCL) (`IndicatorMCL`) in the last RK stage of every `interval` time steps. This contains -a volume-weighted average of the node coefficients. For MCL, the node coefficients are calculated -using either the minimum or the mean of the adjacent subcell interfaces. The results are saved in -`alphas.txt` (for IDP limiting), `alpha_min.txt` and `alphas_mean.txt` (for MCL) in `output_directory`. +Analyze the subcell blending coefficient of IDP limiting ([`SubcellLimiterIDP`](@ref)) and +monolithic convex limiting (MCL) ([`SubcellLimiterMCL`](@ref)) in the last RK stage of every +`interval` time steps. This contains a volume-weighted average of the node coefficients. For MCL, +the node coefficients are calculated using either the minimum or the mean of the adjacent subcell +interfaces. The results are saved in `alphas.txt` (for IDP limiting), `alpha_min.txt` and +`alphas_mean.txt` (for MCL) in `output_directory`. """ struct LimitingAnalysisCallback output_directory::String @@ -61,14 +62,14 @@ function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integra Affect! <: LimitingAnalysisCallback } - initialize!(cb, u_ode, t, integrator, volume_integral.indicator, + initialize!(cb, u_ode, t, integrator, volume_integral.limiter, cb.affect!.output_directory) return nothing end function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integrator, - indicator::IndicatorIDP, + limiter::SubcellLimiterIDP, output_directory) where {Condition, Affect! <: LimitingAnalysisCallback} mkpath(output_directory) @@ -80,7 +81,7 @@ function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integra end function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integrator, - indicator::IndicatorMCL, + limiter::SubcellLimiterMCL, output_directory) where {Condition, Affect! <: LimitingAnalysisCallback} vars = varnames(cons2cons, integrator.p.equations) @@ -90,10 +91,10 @@ function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integra open("$output_directory/$file", "a") do f print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)) - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin print(f, ", alpha_min_pressure, alpha_avg_pressure") end - if indicator.SemiDiscEntropyLimiter + if limiter.SemiDiscEntropyLimiter print(f, ", alpha_min_entropy, alpha_avg_entropy") end println(f) @@ -132,19 +133,19 @@ end equations, solver, cache, - volume_integral.indicator, + volume_integral.limiter, t, iter) end @inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, dg, cache, - indicator::IndicatorIDP, + limiter::SubcellLimiterIDP, time, iter) @unpack output_directory = limiting_analysis_callback - @unpack alpha = indicator.cache.container_shock_capturing + @unpack alpha = limiter.cache.container_subcell_limiter - alpha_avg = analyze_coefficient_IDP(mesh, equations, dg, cache, indicator) + alpha_avg = analyze_coefficient_IDP(mesh, equations, dg, cache, limiter) open("$output_directory/alphas.txt", "a") do f println(f, iter, ", ", time, ", ", maximum(alpha), ", ", alpha_avg) @@ -153,17 +154,17 @@ end @inline function (limiting_analysis_callback::LimitingAnalysisCallback)(mesh, equations, dg, cache, - indicator::IndicatorMCL, + limiter::SubcellLimiterMCL, time, iter) @unpack output_directory = limiting_analysis_callback @unpack weights = dg.basis @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.container_shock_capturing + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter n_vars = nvariables(equations) alpha_min_avg, alpha_mean_avg = analyze_coefficient_MCL(mesh, equations, dg, cache, - indicator) + limiter) open("$output_directory/alphas_min.txt", "a") do f print(f, iter, ", ", time) @@ -171,11 +172,11 @@ end print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))) print(f, ", ", alpha_min_avg[v]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_pressure), ", ", alpha_min_avg[n_vars + 1]) end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + if limiter.SemiDiscEntropyLimiter + k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 print(f, ", ", minimum(alpha_entropy), ", ", alpha_min_avg[k]) end println(f) @@ -186,12 +187,12 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))) print(f, ", ", alpha_mean_avg[v]) end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin print(f, ", ", minimum(alpha_mean_pressure), ", ", alpha_mean_avg[n_vars + 1]) end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + if limiter.SemiDiscEntropyLimiter + k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 print(f, ", ", minimum(alpha_mean_entropy), ", ", alpha_mean_avg[k]) end println(f) diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index 4b38980aa8..4ef4a29531 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -6,9 +6,9 @@ #! format: noindent @inline function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, - indicator) + limiter) @unpack weights = dg.basis - @unpack alpha = indicator.cache.container_shock_capturing + @unpack alpha = limiter.cache.container_subcell_limiter alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) @@ -24,9 +24,9 @@ end @inline function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, - indicator) + limiter) @unpack weights = dg.basis - @unpack alpha = indicator.cache.container_shock_capturing + @unpack alpha = limiter.cache.container_subcell_limiter alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) @@ -41,19 +41,19 @@ end return alpha_avg / total_volume end -function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, indicator) +function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, - alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter n_vars = nvariables(equations) alpha_avg = zeros(eltype(alpha), - n_vars + indicator.PressurePositivityLimiterKuzmin + - indicator.SemiDiscEntropyLimiter) + n_vars + limiter.PressurePositivityLimiterKuzmin + + limiter.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), - n_vars + indicator.PressurePositivityLimiterKuzmin + - indicator.SemiDiscEntropyLimiter) + n_vars + limiter.PressurePositivityLimiterKuzmin + + limiter.SemiDiscEntropyLimiter) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -65,14 +65,14 @@ function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, indicat alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + if limiter.SemiDiscEntropyLimiter + k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * @@ -86,19 +86,19 @@ function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, indicat end function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, - indicator) + limiter) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, - alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter n_vars = nvariables(equations) alpha_avg = zeros(eltype(alpha), - n_vars + indicator.PressurePositivityLimiterKuzmin + - indicator.SemiDiscEntropyLimiter) + n_vars + limiter.PressurePositivityLimiterKuzmin + + limiter.SemiDiscEntropyLimiter) alpha_mean_avg = zeros(eltype(alpha), - n_vars + indicator.PressurePositivityLimiterKuzmin + - indicator.SemiDiscEntropyLimiter) + n_vars + limiter.PressurePositivityLimiterKuzmin + + limiter.SemiDiscEntropyLimiter) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -110,14 +110,14 @@ function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] end - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] end - if indicator.SemiDiscEntropyLimiter - k = n_vars + indicator.PressurePositivityLimiterKuzmin + 1 + if limiter.SemiDiscEntropyLimiter + k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 08926aef18..5c11494ac9 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -98,12 +98,12 @@ end @inline function max_dt(u, t, mesh, constant_speed, equations, semi, solver, cache, volume_integral::VolumeIntegralSubcellLimiting) - @unpack indicator = volume_integral - if indicator isa IndicatorIDP && !indicator.bar_states + @unpack limiter = volume_integral + if limiter isa SubcellLimiterIDP && !limiter.bar_states return max_dt(u, t, mesh, constant_speed, equations, solver, cache) else return max_dt(u, t, mesh, constant_speed, equations, semi, solver, cache, - indicator) + limiter) end end diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index ee1ee4f731..fa1fc29f54 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -45,24 +45,24 @@ end @inline function max_dt(u, t, mesh::Union{TreeMesh, StructuredMesh}, constant_speed::False, equations, semi, dg::DG, cache, - indicator::Union{IndicatorIDP, IndicatorMCL}) + limiter::Union{SubcellLimiterIDP, SubcellLimiterMCL}) @unpack inverse_weights = dg.basis @trixi_timeit timer() "calc_lambda!" calc_lambdas_bar_states!(u, t, mesh, have_nonconservative_terms(equations), equations, - indicator, dg, cache, + limiter, dg, cache, semi.boundary_conditions; calc_bar_states = false) - @unpack lambda1, lambda2 = indicator.cache.container_bar_states + @unpack lambda1, lambda2 = limiter.cache.container_bar_states maxdt = typemax(eltype(u)) - if indicator.smoothness_indicator + if limiter.smoothness_indicator @unpack element_ids_dg, element_ids_dgfv = cache - alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, - mesh, - equations, - dg, - cache) + alpha_element = @trixi_timeit timer() "element-wise blending factors" limiter.IndicatorHG(u, + mesh, + equations, + dg, + cache) pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, dg, cache) else @@ -86,17 +86,17 @@ end end end - if indicator.smoothness_indicator && !isempty(element_ids_dg) + if limiter.smoothness_indicator && !isempty(element_ids_dg) maxdt = min(maxdt, max_dt_RK(u, t, mesh, constant_speed, equations, dg, cache, - indicator, element_ids_dg)) + limiter, element_ids_dg)) end return maxdt end @inline function max_dt_RK(u, t, mesh::TreeMesh2D, constant_speed, equations, dg::DG, - cache, indicator, element_ids_dg) + cache, limiter, element_ids_dg) max_scaled_speed = nextfloat(zero(t)) for idx_element in eachindex(element_ids_dg) element = element_ids_dg[idx_element] @@ -115,7 +115,7 @@ end end @inline function max_dt_RK(u, t, mesh::StructuredMesh{2}, constant_speed, equations, - dg::DG, cache, indicator, element_ids_dg) + dg::DG, cache, limiter, element_ids_dg) @unpack contravariant_vectors, inverse_jacobian = cache.elements max_scaled_speed = nextfloat(zero(t)) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 450e00e731..ae97929517 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -180,27 +180,28 @@ function Base.show(io::IO, ::MIME"text/plain", end """ - VolumeIntegralSubcellLimiting(indicator; + VolumeIntegralSubcellLimiting(limiter; volume_flux_dg, volume_flux_fv) A subcell limiting volume integral type for DG methods based on subcell blending approaches -with a low-order FV method. Used with the indicators [`IndicatorIDP`](@ref) and [`IndicatorMCL`](@ref). +with a low-order FV method. Used with the limiters [`SubcellLimiterIDP`](@ref) and +[`SubcellLimiterMCL`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct VolumeIntegralSubcellLimiting{VolumeFluxDG, VolumeFluxFV, Indicator} <: +struct VolumeIntegralSubcellLimiting{VolumeFluxDG, VolumeFluxFV, Limiter} <: AbstractVolumeIntegral volume_flux_dg::VolumeFluxDG volume_flux_fv::VolumeFluxFV - indicator::Indicator + limiter::Limiter end -function VolumeIntegralSubcellLimiting(indicator; volume_flux_dg, +function VolumeIntegralSubcellLimiting(limiter; volume_flux_dg, volume_flux_fv) VolumeIntegralSubcellLimiting{typeof(volume_flux_dg), typeof(volume_flux_fv), - typeof(indicator)}(volume_flux_dg, volume_flux_fv, - indicator) + typeof(limiter)}(volume_flux_dg, volume_flux_fv, + limiter) end function Base.show(io::IO, mime::MIME"text/plain", @@ -213,8 +214,8 @@ function Base.show(io::IO, mime::MIME"text/plain", summary_header(io, "VolumeIntegralSubcellLimiting") summary_line(io, "volume flux DG", integral.volume_flux_dg) summary_line(io, "volume flux FV", integral.volume_flux_fv) - summary_line(io, "indicator", integral.indicator |> typeof |> nameof) - show(increment_indent(io), mime, integral.indicator) + summary_line(io, "limiter", integral.limiter |> typeof |> nameof) + show(increment_indent(io), mime, integral.limiter) summary_footer(io) end end @@ -222,17 +223,17 @@ end function get_element_variables!(element_variables, u, mesh, equations, volume_integral::VolumeIntegralSubcellLimiting, dg, cache) - if volume_integral.indicator.smoothness_indicator - # call the indicator to get up-to-date values for IO - volume_integral.indicator.IndicatorHG(u, mesh, equations, dg, cache) - get_element_variables!(element_variables, volume_integral.indicator, + if volume_integral.limiter.smoothness_indicator + # call the element-wise limiter to get up-to-date values for IO + volume_integral.limiter.IndicatorHG(u, mesh, equations, dg, cache) + get_element_variables!(element_variables, volume_integral.limiter, volume_integral) end end function get_node_variables!(node_variables, mesh, equations, volume_integral::VolumeIntegralSubcellLimiting, dg, cache) - get_node_variables!(node_variables, volume_integral.indicator, volume_integral, + get_node_variables!(node_variables, volume_integral.limiter, volume_integral, equations) end diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 871900bfbb..f674497296 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -475,16 +475,16 @@ end end @inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, - nonconservative_terms, equations, indicator, + nonconservative_terms, equations, limiter, dg, cache, boundary_conditions; calc_bar_states = true) - if indicator isa IndicatorIDP && !indicator.bar_states + if limiter isa SubcellLimiterIDP && !limiter.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.container_bar_states + @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states @unpack contravariant_vectors = cache.elements - @unpack normal_direction_xi, normal_direction_eta = indicator.cache.container_bar_states + @unpack normal_direction_xi, normal_direction_eta = limiter.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index c6eb69a2ed..c64e63345d 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1320,7 +1320,7 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) return nothing end -mutable struct ContainerShockCapturingIndicatorIDP2D{uEltype <: Real} +mutable struct ContainerSubcellLimiterIDP2D{uEltype <: Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} @@ -1332,8 +1332,8 @@ mutable struct ContainerShockCapturingIndicatorIDP2D{uEltype <: Real} _variable_bounds::Vector{Vector{uEltype}} end -function ContainerShockCapturingIndicatorIDP2D{uEltype}(capacity::Integer, n_nodes, - length) where {uEltype <: Real} +function ContainerSubcellLimiterIDP2D{uEltype}(capacity::Integer, n_nodes, + length) where {uEltype <: Real} nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1352,43 +1352,43 @@ function ContainerShockCapturingIndicatorIDP2D{uEltype}(capacity::Integer, n_nod (n_nodes, n_nodes, capacity)) end - return ContainerShockCapturingIndicatorIDP2D{uEltype}(alpha, alpha1, alpha2, - variable_bounds, - _alpha, _alpha1, _alpha2, - _variable_bounds) + return ContainerSubcellLimiterIDP2D{uEltype}(alpha, alpha1, alpha2, + variable_bounds, + _alpha, _alpha1, _alpha2, + _variable_bounds) end -nnodes(indicator::ContainerShockCapturingIndicatorIDP2D) = size(indicator.alpha, 1) +nnodes(container::ContainerSubcellLimiterIDP2D) = size(container.alpha, 1) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(indicator::ContainerShockCapturingIndicatorIDP2D, capacity) - n_nodes = nnodes(indicator) +function Base.resize!(container::ContainerSubcellLimiterIDP2D, capacity) + n_nodes = nnodes(container) - @unpack _alpha, _alpha1, _alpha2 = indicator + @unpack _alpha, _alpha1, _alpha2 = container resize!(_alpha, n_nodes * n_nodes * capacity) - indicator.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) resize!(_alpha1, (n_nodes + 1) * n_nodes * capacity) - indicator.alpha1 = unsafe_wrap(Array, pointer(_alpha1), + container.alpha1 = unsafe_wrap(Array, pointer(_alpha1), (n_nodes + 1, n_nodes, capacity)) resize!(_alpha2, n_nodes * (n_nodes + 1) * capacity) - indicator.alpha2 = unsafe_wrap(Array, pointer(_alpha2), + container.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - @unpack _variable_bounds = indicator + @unpack _variable_bounds = container for i in 1:length(_variable_bounds) resize!(_variable_bounds[i], n_nodes * n_nodes * capacity) - indicator.variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), + container.variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), (n_nodes, n_nodes, capacity)) end return nothing end -mutable struct ContainerShockCapturingIndicatorMCL2D{uEltype <: Real} +mutable struct ContainerSubcellLimiterMCL2D{uEltype <: Real} var_min::Array{uEltype, 4} # [variable, i, j, element] var_max::Array{uEltype, 4} # [variable, i, j, element] alpha::Array{uEltype, 4} # [variable, i, j, element] @@ -1408,8 +1408,8 @@ mutable struct ContainerShockCapturingIndicatorMCL2D{uEltype <: Real} _alpha_mean_entropy::Vector{uEltype} end -function ContainerShockCapturingIndicatorMCL2D{uEltype}(capacity::Integer, n_variables, - n_nodes) where {uEltype <: Real} +function ContainerSubcellLimiterMCL2D{uEltype}(capacity::Integer, n_variables, + n_nodes) where {uEltype <: Real} nan_uEltype = convert(uEltype, NaN) _var_min = Vector{uEltype}(undef, n_variables * n_nodes^2 * capacity) @@ -1444,30 +1444,30 @@ function ContainerShockCapturingIndicatorMCL2D{uEltype}(capacity::Integer, n_var alpha_mean_entropy = unsafe_wrap(Array, pointer(_alpha_mean_entropy), (n_nodes, n_nodes, capacity)) - return ContainerShockCapturingIndicatorMCL2D{uEltype}(var_min, var_max, alpha, - alpha_pressure, alpha_entropy, - alpha_mean, - alpha_mean_pressure, - alpha_mean_entropy, - _var_min, _var_max, _alpha, - _alpha_pressure, - _alpha_entropy, - _alpha_mean, - _alpha_mean_pressure, - _alpha_mean_entropy) + return ContainerSubcellLimiterMCL2D{uEltype}(var_min, var_max, alpha, + alpha_pressure, alpha_entropy, + alpha_mean, + alpha_mean_pressure, + alpha_mean_entropy, + _var_min, _var_max, _alpha, + _alpha_pressure, + _alpha_entropy, + _alpha_mean, + _alpha_mean_pressure, + _alpha_mean_entropy) end -function nvariables(container::ContainerShockCapturingIndicatorMCL2D) +function nvariables(container::ContainerSubcellLimiterMCL2D) size(container.var_min, 1) end -nnodes(container::ContainerShockCapturingIndicatorMCL2D) = size(container.var_min, 2) +nnodes(container::ContainerSubcellLimiterMCL2D) = size(container.var_min, 2) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` # them whenever needed. Then, we reuse the same memory by # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. -function Base.resize!(container::ContainerShockCapturingIndicatorMCL2D, capacity) +function Base.resize!(container::ContainerSubcellLimiterMCL2D, capacity) n_variables = nvariables(container) n_nodes = nnodes(container) diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index f541dccc4e..2ebefac573 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -28,7 +28,7 @@ function pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha, for element in eachelement(dg, cache) # Clip blending factor for values close to zero (-> pure DG) if dg.volume_integral isa VolumeIntegralSubcellLimiting - tol = dg.volume_integral.indicator.threshold_smoothness_indicator + tol = dg.volume_integral.limiter.threshold_smoothness_indicator else tol = 1e-12 end diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b84cdc2a44..b6e4a74325 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -94,7 +94,7 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) - if volume_integral.indicator.smoothness_indicator + if volume_integral.limiter.smoothness_indicator element_ids_dg = Int[] element_ids_dgfv = Int[] cache = (; cache..., element_ids_dg, element_ids_dgfv) @@ -573,31 +573,31 @@ function calc_volume_integral!(du, u, nonconservative_terms, equations, volume_integral::VolumeIntegralSubcellLimiting, dg::DGSEM, cache, t, boundary_conditions) - @unpack indicator = volume_integral + @unpack limiter = volume_integral # Calculate lambdas and bar states @trixi_timeit timer() "calc_lambdas_bar_states!" calc_lambdas_bar_states!(u, t, mesh, nonconservative_terms, equations, - indicator, + limiter, dg, cache, boundary_conditions) # Calculate boundaries @trixi_timeit timer() "calc_variable_bounds!" calc_variable_bounds!(u, mesh, nonconservative_terms, equations, - indicator, dg, + limiter, dg, cache) - if indicator.smoothness_indicator + if limiter.smoothness_indicator @unpack element_ids_dg, element_ids_dgfv = cache # Calculate element-wise blending factors α - alpha_element = @trixi_timeit timer() "element-wise blending factors" indicator.IndicatorHG(u, - mesh, - equations, - dg, - cache) + alpha_element = @trixi_timeit timer() "element-wise blending factors" limiter.IndicatorHG(u, + mesh, + equations, + dg, + cache) # Determine element ids for DG-only and subcell-wise blended DG-FV volume integral pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, @@ -616,16 +616,16 @@ function calc_volume_integral!(du, u, element = element_ids_dgfv[idx_element] subcell_limiting_kernel!(du, u, element, mesh, nonconservative_terms, equations, - volume_integral, indicator, + volume_integral, limiter, dg, cache) end - else # indicator.smoothness_indicator == false + else # limiter.smoothness_indicator == false # Loop over all elements @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for element in eachelement(dg, cache) subcell_limiting_kernel!(du, u, element, mesh, nonconservative_terms, equations, - volume_integral, indicator, + volume_integral, limiter, dg, cache) end end @@ -635,7 +635,7 @@ end element, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms::False, equations, - volume_integral, indicator::IndicatorIDP, + volume_integral, limiter::SubcellLimiterIDP, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv = volume_integral @@ -660,7 +660,7 @@ end # antidiffusive flux calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, indicator, dg, element, + nonconservative_terms, equations, limiter, dg, element, cache) # Calculate volume integral contribution of low-order FV flux @@ -680,7 +680,7 @@ end element, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms::False, equations, - volume_integral, indicator::IndicatorMCL, + volume_integral, limiter::SubcellLimiterMCL, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv = volume_integral @@ -703,12 +703,12 @@ end # antidiffusive flux calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, indicator, dg, + u, mesh, nonconservative_terms, equations, limiter, dg, element, cache) # limit antidiffusive flux calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, - indicator, dg, element, cache, + limiter, dg, element, cache, fstar1_L, fstar2_L) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @@ -810,7 +810,7 @@ end # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, - indicator::IndicatorIDP, dg, element, cache) + limiter::SubcellLimiterIDP, dg, element, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux for j in eachnode(dg), i in 2:nnodes(dg) @@ -835,7 +835,7 @@ end @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, - indicator::IndicatorMCL, dg, element, cache) + limiter::SubcellLimiterMCL, dg, element, cache) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux for j in eachnode(dg), i in 2:nnodes(dg) @@ -859,13 +859,13 @@ end end @inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, indicator, + nonconservative_terms, equations, limiter, dg, cache, boundary_conditions; calc_bar_states = true) - if indicator isa IndicatorIDP && !indicator.bar_states + if limiter isa SubcellLimiterIDP && !limiter.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = indicator.cache.container_bar_states + @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) @@ -1060,17 +1060,17 @@ end end @inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, - indicator::IndicatorIDP, dg, cache) - if !indicator.bar_states + limiter::SubcellLimiterIDP, dg, cache) + if !limiter.bar_states return nothing end - @unpack variable_bounds = indicator.cache.container_shock_capturing - @unpack bar_states1, bar_states2 = indicator.cache.container_bar_states + @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states counter = 1 # state variables - if indicator.local_minmax - for index in indicator.local_minmax_variables_cons + if limiter.local_minmax + for index in limiter.local_minmax_variables_cons var_min = variable_bounds[counter] var_max = variable_bounds[counter + 1] @threaded for element in eachelement(dg, cache) @@ -1108,7 +1108,7 @@ end end end # Specific Entropy - if indicator.spec_entropy + if limiter.spec_entropy s_min = variable_bounds[counter] @threaded for element in eachelement(dg, cache) s_min[:, :, element] .= typemax(eltype(s_min)) @@ -1138,7 +1138,7 @@ end counter += 1 end # Mathematical entropy - if indicator.math_entropy + if limiter.math_entropy s_max = variable_bounds[counter] @threaded for element in eachelement(dg, cache) s_max[:, :, element] .= typemin(eltype(s_max)) @@ -1170,9 +1170,9 @@ end end @inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, - indicator::IndicatorMCL, dg, cache) - @unpack var_min, var_max = indicator.cache.container_shock_capturing - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states + limiter::SubcellLimiterMCL, dg, cache) + @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @threaded for element in eachelement(dg, cache) for v in eachvariable(equations) @@ -1180,7 +1180,7 @@ end var_max[v, :, :, element] .= typemin(eltype(var_max)) end - if indicator.DensityLimiter + if limiter.DensityLimiter for j in eachnode(dg), i in eachnode(dg) # Previous solution var_min[1, i, j, element] = min(var_min[1, i, j, element], @@ -1212,9 +1212,9 @@ end var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) end - end #indicator.DensityLimiter + end #limiter.DensityLimiter - if indicator.SequentialLimiter + if limiter.SequentialLimiter for j in eachnode(dg), i in eachnode(dg) # Previous solution for v in 2:nvariables(equations) @@ -1259,7 +1259,7 @@ end bar_state_phi) end end - elseif indicator.ConservativeLimiter + elseif limiter.ConservativeLimiter for j in eachnode(dg), i in eachnode(dg) # Previous solution for v in 2:nvariables(equations) @@ -1308,24 +1308,24 @@ end end @inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, - equations, indicator, dg, element, + equations, limiter, dg, element, cache, fstar1, fstar2) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack var_min, var_max = indicator.cache.container_shock_capturing - @unpack bar_states1, bar_states2, lambda1, lambda2 = indicator.cache.container_bar_states + @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states - if indicator.Plotting + if limiter.Plotting @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = indicator.cache.container_shock_capturing + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha[:, i, j, element] .= one(eltype(alpha)) - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end - if indicator.SemiDiscEntropyLimiter + if limiter.SemiDiscEntropyLimiter alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) end @@ -1339,7 +1339,7 @@ end # Therefore we make sure that the flux keeps its sign during limiting. # Density limiter - if indicator.DensityLimiter + if limiter.DensityLimiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1359,7 +1359,7 @@ end min(f_min, 0.0)) end - if indicator.Plotting || indicator.DensityAlphaForAll + if limiter.Plotting || limiter.DensityAlphaForAll if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1369,8 +1369,8 @@ end sign(flux_limited) * eps())) end - if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1381,7 +1381,7 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if indicator.DensityAlphaForAll + if limiter.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, @@ -1409,7 +1409,7 @@ end min(f_min, 0.0)) end - if indicator.Plotting || indicator.DensityAlphaForAll + if limiter.Plotting || limiter.DensityAlphaForAll if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1419,8 +1419,8 @@ end sign(flux_limited) * eps())) end - if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1431,7 +1431,7 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if indicator.DensityAlphaForAll + if limiter.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, @@ -1439,10 +1439,10 @@ end end end end - end # if indicator.DensityLimiter + end # if limiter.DensityLimiter # Sequential limiter - if indicator.SequentialLimiter + if limiter.SequentialLimiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1473,7 +1473,7 @@ end g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end - if indicator.Plotting + if limiter.Plotting if isapprox(g, 0.0, atol = eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1481,7 +1481,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1524,7 +1524,7 @@ end g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min g_limited = max(g, min(g_min, 0.0)) end - if indicator.Plotting + if limiter.Plotting if isapprox(g, 0.0, atol = eps()) coefficient = 1.0 # g_limited is zero as well else @@ -1532,7 +1532,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1546,7 +1546,7 @@ end end end # Conservative limiter - elseif indicator.ConservativeLimiter + elseif limiter.ConservativeLimiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] for v in 2:nvariables(equations) @@ -1566,7 +1566,7 @@ end min(f_min, 0.0)) end - if indicator.Plotting + if limiter.Plotting if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well @@ -1576,7 +1576,7 @@ end (antidiffusive_flux1[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1606,7 +1606,7 @@ end min(f_min, 0.0)) end - if indicator.Plotting + if limiter.Plotting if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well @@ -1616,7 +1616,7 @@ end (antidiffusive_flux2[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1626,11 +1626,11 @@ end antidiffusive_flux2[v, i, j, element] = flux_limited end end - end # indicator.SequentialLimiter and indicator.ConservativeLimiter + end # limiter.SequentialLimiter and limiter.ConservativeLimiter # Density positivity limiter - if indicator.DensityPositivityLimiter - beta = indicator.DensityPositivityCorrectionFactor + if limiter.DensityPositivityLimiter + beta = limiter.DensityPositivityCorrectionFactor for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1647,19 +1647,19 @@ end min(f_min, 0.0)) end - if indicator.Plotting || indicator.DensityAlphaForAll + if limiter.Plotting || limiter.DensityAlphaForAll if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] end - if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !indicator.DensityLimiter + if !limiter.DensityLimiter alpha_mean[1, i - 1, j, element] += coefficient alpha_mean[1, i, j, element] += coefficient end @@ -1668,7 +1668,7 @@ end antidiffusive_flux1[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if indicator.DensityAlphaForAll + if limiter.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux1[v, i, j, element] = coefficient * antidiffusive_flux1[v, i, j, @@ -1693,19 +1693,19 @@ end min(f_min, 0.0)) end - if indicator.Plotting || indicator.DensityAlphaForAll + if limiter.Plotting || limiter.DensityAlphaForAll if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] end - if indicator.Plotting - @unpack alpha, alpha_mean = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !indicator.DensityLimiter + if !limiter.DensityLimiter alpha_mean[1, i, j - 1, element] += coefficient alpha_mean[1, i, j, element] += coefficient end @@ -1714,7 +1714,7 @@ end antidiffusive_flux2[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if indicator.DensityAlphaForAll + if limiter.DensityAlphaForAll for v in 2:nvariables(equations) antidiffusive_flux2[v, i, j, element] = coefficient * antidiffusive_flux2[v, i, j, @@ -1722,13 +1722,13 @@ end end end end - end #if indicator.DensityPositivityLimiter + end #if limiter.DensityPositivityLimiter # Divide alpha_mean by number of additions - if indicator.Plotting - @unpack alpha_mean = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha_mean = limiter.cache.container_subcell_limiter # Interfaces contribute with 1.0 - if indicator.DensityLimiter || indicator.DensityPositivityLimiter + if limiter.DensityLimiter || limiter.DensityPositivityLimiter for i in eachnode(dg) alpha_mean[1, i, 1, element] += 1.0 alpha_mean[1, i, nnodes(dg), element] += 1.0 @@ -1739,7 +1739,7 @@ end alpha_mean[1, i, j, element] /= 4 end end - if indicator.SequentialLimiter || indicator.ConservativeLimiter + if limiter.SequentialLimiter || limiter.ConservativeLimiter for v in 2:nvariables(equations) for i in eachnode(dg) alpha_mean[v, i, 1, element] += 1.0 @@ -1755,8 +1755,8 @@ end end # Limit pressure à la Kuzmin - if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_pressure, alpha_mean_pressure = indicator.cache.container_shock_capturing + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.container_subcell_limiter for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 @@ -1767,7 +1767,7 @@ end (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) - if indicator.PressurePositivityLimiterKuzminExact + if limiter.PressurePositivityLimiterKuzminExact # exact calculation of max(R_ij, R_ji) R_max = lambda1[i, j, element] * abs(bar_states1[2, i, j, element] * @@ -1802,7 +1802,7 @@ end antidiffusive_flux1[v, i, j, element] *= alpha end end - if indicator.Plotting + if limiter.Plotting alpha_pressure[i - 1, j, element] = min(alpha_pressure[i - 1, j, element], alpha) alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], @@ -1822,7 +1822,7 @@ end (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) - if indicator.PressurePositivityLimiterKuzminExact + if limiter.PressurePositivityLimiterKuzminExact # exact calculation of max(R_ij, R_ji) R_max = lambda2[i, j, element] * abs(bar_states2[2, i, j, element] * @@ -1857,7 +1857,7 @@ end antidiffusive_flux2[v, i, j, element] *= alpha end end - if indicator.Plotting + if limiter.Plotting alpha_pressure[i, j - 1, element] = min(alpha_pressure[i, j - 1, element], alpha) alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], @@ -1866,8 +1866,8 @@ end alpha_mean_pressure[i, j, element] += alpha end end - if indicator.Plotting - @unpack alpha_mean_pressure = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_pressure[i, 1, element] += 1.0 @@ -1884,7 +1884,7 @@ end # Limit entropy # TODO: This is a very inefficient function. We compute the entropy four times at each node. # TODO: For now, this only works for Cartesian meshes. - if indicator.SemiDiscEntropyLimiter + if limiter.SemiDiscEntropyLimiter for j in eachnode(dg), i in 2:nnodes(dg) antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) @@ -1920,8 +1920,8 @@ end element] end end - if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter alpha_entropy[i - 1, j, element] = min(alpha_entropy[i - 1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1965,8 +1965,8 @@ end element] end end - if indicator.Plotting - @unpack alpha_entropy, alpha_mean_entropy = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter alpha_entropy[i, j - 1, element] = min(alpha_entropy[i, j - 1, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1974,8 +1974,8 @@ end alpha_mean_entropy[i, j, element] += alpha end end - if indicator.Plotting - @unpack alpha_mean_entropy = indicator.cache.container_shock_capturing + if limiter.Plotting + @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_entropy[i, 1, element] += 1.0 diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 9864a85942..c54983509f 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -18,12 +18,6 @@ function get_element_variables!(element_variables, indicator::AbstractIndicator, return nothing end -function get_element_variables!(element_variables, indicator::AbstractIndicator, - ::VolumeIntegralSubcellLimiting) - element_variables[:smooth_indicator_elementwise] = indicator.IndicatorHG.cache.alpha - return nothing -end - """ IndicatorHennemannGassner(equations::AbstractEquations, basis; alpha_max=0.5, @@ -221,21 +215,34 @@ const IndicatorLoehner = IndicatorLöhner return num / den end +abstract type AbstractSubcellLimiter end + +function create_cache(typ::Type{LimiterType}, + semi) where {LimiterType <: AbstractSubcellLimiter} + create_cache(typ, mesh_equations_solver_cache(semi)...) +end + +function get_element_variables!(element_variables, limiter::AbstractSubcellLimiter, + ::VolumeIntegralSubcellLimiting) + element_variables[:smooth_indicator_elementwise] = limiter.IndicatorHG.cache.alpha + return nothing +end + """ - IndicatorIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], - positivity_variables_nonlinear = (), - positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, - bar_states = true, - max_iterations_newton = 10, - newton_tolerances = (1.0e-12, 1.0e-14), - gamma_constant_newton = 2 * ndims(equations), - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure) + SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, + bar_states = true, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations), + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: @@ -265,8 +272,8 @@ indicator values <= `threshold_smoothness_indicator`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorIDP{RealT <: Real, LimitingVariablesNonlinear, - Cache, Indicator} <: AbstractIndicator +struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, + Cache, Indicator} <: AbstractSubcellLimiter local_minmax::Bool local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables positivity::Bool @@ -285,21 +292,21 @@ struct IndicatorIDP{RealT <: Real, LimitingVariablesNonlinear, IndicatorHG::Indicator end -# this method is used when the indicator is constructed as for shock-capturing volume integrals -function IndicatorIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], - positivity_variables_nonlinear = (), - positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, - bar_states = true, - max_iterations_newton = 10, - newton_tolerances = (1.0e-12, 1.0e-14), - gamma_constant_newton = 2 * ndims(equations), - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure) +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, + bar_states = true, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations), + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure) local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) @@ -317,7 +324,7 @@ function IndicatorIDP(equations::AbstractEquations, basis; end end - cache = create_cache(IndicatorIDP, equations, basis, number_bounds, bar_states) + cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds, bar_states) if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max = 1.0, @@ -326,31 +333,31 @@ function IndicatorIDP(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorIDP{typeof(positivity_correction_factor), - typeof(positivity_variables_nonlinear), - typeof(cache), typeof(IndicatorHG)}(local_minmax, - local_minmax_variables_cons, - positivity, - positivity_variables_cons, - positivity_variables_nonlinear, - positivity_correction_factor, - spec_entropy, - math_entropy, - bar_states, - cache, - max_iterations_newton, - newton_tolerances, - gamma_constant_newton, - smoothness_indicator, - threshold_smoothness_indicator, - IndicatorHG) -end - -function Base.show(io::IO, indicator::IndicatorIDP) - @nospecialize indicator # reduce precompilation time - @unpack local_minmax, positivity, spec_entropy, math_entropy = indicator - - print(io, "IndicatorIDP(") + SubcellLimiterIDP{typeof(positivity_correction_factor), + typeof(positivity_variables_nonlinear), + typeof(cache), typeof(IndicatorHG)}(local_minmax, + local_minmax_variables_cons, + positivity, + positivity_variables_cons, + positivity_variables_nonlinear, + positivity_correction_factor, + spec_entropy, + math_entropy, + bar_states, + cache, + max_iterations_newton, + newton_tolerances, + gamma_constant_newton, + smoothness_indicator, + threshold_smoothness_indicator, + IndicatorHG) +end + +function Base.show(io::IO, limiter::SubcellLimiterIDP) + @nospecialize limiter # reduce precompilation time + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter + + print(io, "SubcellLimiterIDP(") if !(local_minmax || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else @@ -361,20 +368,20 @@ function Base.show(io::IO, indicator::IndicatorIDP) math_entropy && print(io, "mathematical entropy, ") print(io, "), ") end - indicator.smoothness_indicator && - print(io, ", Smoothness indicator: ", indicator.IndicatorHG, - " with threshold ", indicator.threshold_smoothness_indicator, "), ") + limiter.smoothness_indicator && + print(io, ", Smoothness indicator: ", limiter.IndicatorHG, + " with threshold ", limiter.threshold_smoothness_indicator, "), ") print(io, - "Local bounds with $(indicator.bar_states ? "Bar States" : "FV solution")") + "Local bounds with $(limiter.bar_states ? "Bar States" : "FV solution")") print(io, ")") end -function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) - @nospecialize indicator # reduce precompilation time - @unpack local_minmax, positivity, spec_entropy, math_entropy = indicator +function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) + @nospecialize limiter # reduce precompilation time + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter if get(io, :compact, false) - show(io, indicator) + show(io, limiter) else if !(local_minmax || positivity || spec_entropy || math_entropy) setup = ["limiter" => "No limiter selected => pure DG method"] @@ -383,15 +390,15 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) if local_minmax setup = [ setup..., - "" => "local maximum/minimum bounds for conservative variables $(indicator.local_minmax_variables_cons)", + "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", ] end if positivity - string = "positivity for conservative variables $(indicator.positivity_variables_cons) and $(indicator.positivity_variables_nonlinear)" + string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., - "" => " positivity correction factor = $(indicator.positivity_correction_factor)", + "" => " positivity correction factor = $(limiter.positivity_correction_factor)", ] end if spec_entropy @@ -402,41 +409,41 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorIDP) end setup = [ setup..., - "Local bounds" => (indicator.bar_states ? "Bar States" : "FV solution"), + "Local bounds" => (limiter.bar_states ? "Bar States" : "FV solution"), ] - if indicator.smoothness_indicator + if limiter.smoothness_indicator setup = [ setup..., - "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.threshold_smoothness_indicator)", + "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", ] end - summary_box(io, "IndicatorIDP", setup) + summary_box(io, "SubcellLimiterIDP", setup) end end end -function get_node_variables!(node_variables, indicator::IndicatorIDP, +function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, ::VolumeIntegralSubcellLimiting, equations) - node_variables[:indicator_shock_capturing] = indicator.cache.container_shock_capturing.alpha + node_variables[:alpha_limiter] = limiter.cache.container_subcell_limiter.alpha # TODO: alpha is not filled before the first timestep. return nothing end """ - IndicatorMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure, - Plotting = true) + SubcellLimiterMCL(equations::AbstractEquations, basis; + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = false, + DensityPositivityCorrectionFactor = 0.0, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure, + Plotting = true) Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: - local two-sided limiting for `cons(1)` (`DensityLimiter`) @@ -467,7 +474,7 @@ indicator values <= `threshold_smoothness_indicator`. !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct IndicatorMCL{RealT <: Real, Cache, Indicator} <: AbstractIndicator +struct SubcellLimiterMCL{RealT <: Real, Cache, Indicator} <: AbstractSubcellLimiter cache::Cache DensityLimiter::Bool # Impose local maximum/minimum for cons(1) based on bar states DensityAlphaForAll::Bool # Use the cons(1) blending coefficient for all quantities @@ -484,25 +491,25 @@ struct IndicatorMCL{RealT <: Real, Cache, Indicator} <: AbstractIndicator Plotting::Bool end -# this method is used when the indicator is constructed as for shock-capturing volume integrals -function IndicatorMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure, - Plotting = true) +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function SubcellLimiterMCL(equations::AbstractEquations, basis; + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = false, + DensityPositivityCorrectionFactor = 0.0, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure, + Plotting = true) if SequentialLimiter && ConservativeLimiter error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") end - cache = create_cache(IndicatorMCL, equations, basis, + cache = create_cache(SubcellLimiterMCL, equations, basis, PressurePositivityLimiterKuzmin) if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth = false, @@ -510,119 +517,119 @@ function IndicatorMCL(equations::AbstractEquations, basis; else IndicatorHG = nothing end - IndicatorMCL{typeof(threshold_smoothness_indicator), typeof(cache), - typeof(IndicatorHG)}(cache, - DensityLimiter, DensityAlphaForAll, - SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, - PressurePositivityLimiterKuzminExact, - DensityPositivityLimiter, - DensityPositivityCorrectionFactor, - SemiDiscEntropyLimiter, - smoothness_indicator, - threshold_smoothness_indicator, IndicatorHG, - Plotting) -end - -function Base.show(io::IO, indicator::IndicatorMCL) - @nospecialize indicator # reduce precompilation time - - print(io, "IndicatorMCL(") - indicator.DensityLimiter && print(io, "; dens") - indicator.DensityAlphaForAll && print(io, "; dens alpha ∀") - indicator.SequentialLimiter && print(io, "; seq") - indicator.ConservativeLimiter && print(io, "; cons") - if indicator.PressurePositivityLimiterKuzmin + SubcellLimiterMCL{typeof(threshold_smoothness_indicator), typeof(cache), + typeof(IndicatorHG)}(cache, + DensityLimiter, DensityAlphaForAll, + SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzmin, + PressurePositivityLimiterKuzminExact, + DensityPositivityLimiter, + DensityPositivityCorrectionFactor, + SemiDiscEntropyLimiter, + smoothness_indicator, + threshold_smoothness_indicator, IndicatorHG, + Plotting) +end + +function Base.show(io::IO, limiter::SubcellLimiterMCL) + @nospecialize limiter # reduce precompilation time + + print(io, "SubcellLimiterMCL(") + limiter.DensityLimiter && print(io, "; dens") + limiter.DensityAlphaForAll && print(io, "; dens alpha ∀") + limiter.SequentialLimiter && print(io, "; seq") + limiter.ConservativeLimiter && print(io, "; cons") + if limiter.PressurePositivityLimiterKuzmin print(io, - "; $(indicator.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") + "; $(limiter.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") end - indicator.DensityPositivityLimiter && print(io, "; dens pos") - if indicator.DensityPositivityCorrectionFactor != 0 + limiter.DensityPositivityLimiter && print(io, "; dens pos") + if limiter.DensityPositivityCorrectionFactor != 0 print(io, - " with correction factor $(indicator.DensityPositivityCorrectionFactor)") + " with correction factor $(limiter.DensityPositivityCorrectionFactor)") end - indicator.SemiDiscEntropyLimiter && print(io, "; semid. entropy") - indicator.smoothness_indicator && - print(io, "; Smoothness indicator: ", indicator.IndicatorHG, - " with threshold ", indicator.threshold_smoothness_indicator) + limiter.SemiDiscEntropyLimiter && print(io, "; semid. entropy") + limiter.smoothness_indicator && + print(io, "; Smoothness indicator: ", limiter.IndicatorHG, + " with threshold ", limiter.threshold_smoothness_indicator) print(io, ")") end -function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMCL) - @nospecialize indicator # reduce precompilation time +function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) + @nospecialize limiter # reduce precompilation time @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = indicator + PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = limiter if get(io, :compact, false) - show(io, indicator) + show(io, limiter) else setup = ["limiter" => ""] DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) - if indicator.PressurePositivityLimiterKuzmin + if limiter.PressurePositivityLimiterKuzmin setup = [ setup..., "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")", ] end if DensityPositivityLimiter - if indicator.DensityPositivityCorrectionFactor != 0.0 + if limiter.DensityPositivityCorrectionFactor != 0.0 setup = [ setup..., - "" => "DensityPositivityLimiter with correction factor $(indicator.DensityPositivityCorrectionFactor)", + "" => "DensityPositivityLimiter with correction factor $(limiter.DensityPositivityCorrectionFactor)", ] else setup = [setup..., "" => "DensityPositivityLimiter"] end end SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) - if indicator.smoothness_indicator + if limiter.smoothness_indicator setup = [ setup..., - "Smoothness indicator" => "$(indicator.IndicatorHG) using threshold $(indicator.threshold_smoothness_indicator)", + "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", ] end - summary_box(io, "IndicatorMCL", setup) + summary_box(io, "SubcellLimiterMCL", setup) end end -function get_node_variables!(node_variables, indicator::IndicatorMCL, +function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, ::VolumeIntegralSubcellLimiting, equations) - if !indicator.Plotting + if !limiter.Plotting return nothing end - @unpack alpha = indicator.cache.container_shock_capturing + @unpack alpha = limiter.cache.container_subcell_limiter variables = varnames(cons2cons, equations) for v in eachvariable(equations) s = Symbol("alpha_", variables[v]) node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] end - if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_pressure = indicator.cache.container_shock_capturing + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_pressure = limiter.cache.container_subcell_limiter node_variables[:alpha_pressure] = alpha_pressure end - if indicator.SemiDiscEntropyLimiter - @unpack alpha_entropy = indicator.cache.container_shock_capturing + if limiter.SemiDiscEntropyLimiter + @unpack alpha_entropy = limiter.cache.container_subcell_limiter node_variables[:alpha_entropy] = alpha_entropy end for v in eachvariable(equations) - @unpack alpha_mean = indicator.cache.container_shock_capturing + @unpack alpha_mean = limiter.cache.container_subcell_limiter s = Symbol("alpha_mean_", variables[v]) node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) end - if indicator.PressurePositivityLimiterKuzmin - @unpack alpha_mean_pressure = indicator.cache.container_shock_capturing + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter node_variables[:alpha_mean_pressure] = alpha_mean_pressure end - if indicator.SemiDiscEntropyLimiter - @unpack alpha_mean_entropy = indicator.cache.container_shock_capturing + if limiter.SemiDiscEntropyLimiter + @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter node_variables[:alpha_mean_entropy] = alpha_mean_entropy end diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 6755433095..a34d4f63aa 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -189,10 +189,10 @@ function (löhner::IndicatorLöhner)(u::AbstractArray{<:Any, 4}, return alpha end -# this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquations{2}, +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, bar_states) - container_shock_capturing = Trixi.ContainerShockCapturingIndicatorIDP2D{real(basis) + container_subcell_limiter = Trixi.ContainerSubcellLimiterIDP2D{real(basis) }(0, nnodes(basis), number_bounds) @@ -207,42 +207,42 @@ function create_cache(indicator::Type{IndicatorIDP}, equations::AbstractEquation idp_bounds_delta = zeros(real(basis), number_bounds) - return (; cache..., container_shock_capturing, idp_bounds_delta) + return (; cache..., container_subcell_limiter, idp_bounds_delta) end -function (indicator::IndicatorIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; - kwargs...) - @unpack alpha = indicator.cache.container_shock_capturing +function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; + kwargs...) + @unpack alpha = limiter.cache.container_subcell_limiter alpha .= zero(eltype(alpha)) - if indicator.smoothness_indicator + if limiter.smoothness_indicator elements = semi.cache.element_ids_dgfv else elements = eachelement(dg, semi.cache) end - if indicator.local_minmax + if limiter.local_minmax @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, - indicator, u, + limiter, u, t, dt, semi, elements) end - if indicator.positivity - @trixi_timeit timer() "positivity" idp_positivity!(alpha, indicator, u, dt, + if limiter.positivity + @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi, elements) end - if indicator.spec_entropy - @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, indicator, u, t, + if limiter.spec_entropy + @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) end - if indicator.math_entropy - @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, indicator, u, t, + if limiter.math_entropy + @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) end # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = indicator.cache.container_shock_capturing + @unpack alpha1, alpha2 = limiter.cache.container_subcell_limiter @threaded for element in elements for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) @@ -265,7 +265,7 @@ end @threaded for element in eachelement(dg, cache) var_min[:, :, element] .= typemax(eltype(var_min)) var_max[:, :, element] .= typemin(eltype(var_max)) - # Calculate indicator variables at Gauss-Lobatto nodes + # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) var = u[variable, i, j, element] var_min[i, j, element] = min(var_min[i, j, element], var) @@ -366,7 +366,7 @@ end @threaded for element in eachelement(dg, cache) var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) - # Calculate indicator variables at Gauss-Lobatto nodes + # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) var = variable(get_node_vars(u, equations, dg, i, j, element), equations) var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) @@ -500,22 +500,22 @@ end return nothing end -@inline function idp_local_minmax!(alpha, indicator, u, t, dt, semi, elements) - for (index, variable) in enumerate(indicator.local_minmax_variables_cons) - idp_local_minmax!(alpha, indicator, u, t, dt, semi, elements, variable, index) +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) + for (index, variable) in enumerate(limiter.local_minmax_variables_cons) + idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) end return nothing end -@inline function idp_local_minmax!(alpha, indicator, u, t, dt, semi, elements, variable, +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) mesh, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack variable_bounds = limiter.cache.container_subcell_limiter var_min = variable_bounds[2 * (index - 1) + 1] var_max = variable_bounds[2 * (index - 1) + 2] - if !indicator.bar_states + if !limiter.bar_states calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) end @@ -577,12 +577,12 @@ end return nothing end -@inline function idp_spec_entropy!(alpha, indicator, u, t, dt, semi, elements) +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack variable_bounds = limiter.cache.container_subcell_limiter - s_min = variable_bounds[2 * length(indicator.local_minmax_variables_cons) + 1] - if !indicator.bar_states + s_min = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + 1] + if !limiter.bar_states calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -593,7 +593,7 @@ end newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, specEntropy_goal, specEntropy_dGoal_dbeta, specEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, indicator) + dt, mesh, equations, dg, cache, limiter) end end @@ -608,13 +608,13 @@ function specEntropy_initialCheck(bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function idp_math_entropy!(alpha, indicator, u, t, dt, semi, elements) +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy = indicator - @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack spec_entropy = limiter + @unpack variable_bounds = limiter.cache.container_subcell_limiter - s_max = variable_bounds[2 * length(indicator.local_minmax_variables_cons) + spec_entropy + 1] - if !indicator.bar_states + s_max = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + spec_entropy + 1] + if !limiter.bar_states calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -625,7 +625,7 @@ end newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, mathEntropy_goal, mathEntropy_dGoal_dbeta, mathEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, indicator) + dt, mesh, equations, dg, cache, limiter) end end @@ -640,42 +640,42 @@ function mathEntropy_initialCheck(bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline function idp_positivity!(alpha, indicator, u, dt, semi, elements) +@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) # Conservative variables - for (index, variable) in enumerate(indicator.positivity_variables_cons) - idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, index) + for (index, variable) in enumerate(limiter.positivity_variables_cons) + idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) end # Nonlinear variables - for (index, variable) in enumerate(indicator.positivity_variables_nonlinear) - idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, variable, index) + for (index, variable) in enumerate(limiter.positivity_variables_nonlinear) + idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, variable, index) end return nothing end -@inline function idp_positivity!(alpha, indicator, u, dt, semi, elements, variable, +@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack inverse_weights = dg.basis - @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = indicator + @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = limiter - @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack variable_bounds = limiter.cache.container_subcell_limiter - counter = 2 * length(indicator.local_minmax_variables_cons) + spec_entropy + + counter = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + math_entropy if local_minmax - if variable in indicator.local_minmax_variables_cons - for (index_, variable_) in enumerate(indicator.local_minmax_variables_cons) + if variable in limiter.local_minmax_variables_cons + for (index_, variable_) in enumerate(limiter.local_minmax_variables_cons) if variable == variable_ var_min = variable_bounds[2 * (index_ - 1) + 1] break end end else - for variable_ in indicator.positivity_variables_cons[1:index] - if !(variable_ in indicator.local_minmax_variables_cons) + for variable_ in limiter.positivity_variables_cons[1:index] + if !(variable_ in limiter.local_minmax_variables_cons) counter += 1 end end @@ -700,7 +700,7 @@ end end # Compute bound - if indicator.local_minmax + if limiter.local_minmax var_min[i, j, element] = max(var_min[i, j, element], positivity_correction_factor * var) else @@ -741,16 +741,16 @@ end return nothing end -@inline function idp_positivity_newton!(alpha, indicator, u, dt, semi, elements, +@inline function idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = indicator - @unpack variable_bounds = indicator.cache.container_shock_capturing + @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = limiter + @unpack variable_bounds = limiter.cache.container_subcell_limiter - index_ = 2 * length(indicator.local_minmax_variables_cons) + spec_entropy + + index_ = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + math_entropy + index - for variable_ in indicator.positivity_variables_cons - if !(variable_ in indicator.local_minmax_variables_cons) + for variable_ in limiter.positivity_variables_cons + if !(variable_ in limiter.local_minmax_variables_cons) index_ += 1 end end @@ -770,7 +770,7 @@ end newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, pressure_goal, pressure_dgoal_dbeta, pressure_initialCheck, pressure_finalCheck, - dt, mesh, equations, dg, cache, indicator) + dt, mesh, equations, dg, cache, limiter) end end @@ -788,7 +788,7 @@ end @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - dt, mesh, equations, dg, cache, indicator) + dt, mesh, equations, dg, cache, limiter) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux if mesh isa TreeMesh @@ -797,14 +797,14 @@ end inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] end - @unpack gamma_constant_newton = indicator + @unpack gamma_constant_newton = limiter # negative xi direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, indicator, antidiffusive_flux) + finalCheck, equations, dt, limiter, antidiffusive_flux) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * @@ -812,14 +812,14 @@ end get_node_vars(antidiffusive_flux1, equations, dg, i + 1, j, element) newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, indicator, antidiffusive_flux) + finalCheck, equations, dt, limiter, antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, indicator, antidiffusive_flux) + finalCheck, equations, dt, limiter, antidiffusive_flux) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * @@ -827,15 +827,15 @@ end get_node_vars(antidiffusive_flux2, equations, dg, i, j + 1, element) newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, indicator, antidiffusive_flux) + finalCheck, equations, dt, limiter, antidiffusive_flux) return nothing end @inline function newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, finalCheck, - equations, dt, indicator, antidiffusive_flux) - newton_reltol, newton_abstol = indicator.newton_tolerances + equations, dt, limiter, antidiffusive_flux) + newton_reltol, newton_abstol = limiter.newton_tolerances beta = 1 - alpha[i, j, element] @@ -852,7 +852,7 @@ end end # Newton iterations - for iter in 1:(indicator.max_iterations_newton) + for iter in 1:limiter.max_iterations_newton beta_old = beta # If the state is valid, evaluate d(goal)/d(beta) @@ -928,10 +928,10 @@ function standard_finalCheck(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end -# this method is used when the indicator is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquations{2}, +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) - container_shock_capturing = Trixi.ContainerShockCapturingIndicatorMCL2D{real(basis) + container_subcell_limiter = Trixi.ContainerSubcellLimiterMCL2D{real(basis) }(0, nvariables(equations), nnodes(basis)) @@ -942,7 +942,7 @@ function create_cache(indicator::Type{IndicatorMCL}, equations::AbstractEquation idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiterKuzmin) - return (; container_shock_capturing, container_bar_states, idp_bounds_delta) + return (; container_subcell_limiter, container_bar_states, idp_bounds_delta) end # this method is used when the indicator is constructed as for shock-capturing volume integrals diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index a6e12c980c..1af9e849ee 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -243,14 +243,15 @@ function Base.resize!(semi, volume_integral::VolumeIntegralSubcellLimiting, new_ # Resize container_antidiffusive_flux resize!(semi.cache.container_antidiffusive_flux, new_size) - # Resize container_shock_capturing - resize!(volume_integral.indicator.cache.container_shock_capturing, new_size) + # Resize container_subcell_limiter + @unpack limiter = volume_integral + resize!(limiter.cache.container_subcell_limiter, new_size) # Calc subcell normal directions before StepsizeCallback - @unpack indicator = volume_integral - if indicator isa IndicatorMCL || - (indicator isa IndicatorIDP && indicator.bar_states) - resize!(indicator.cache.container_bar_states, new_size) - calc_normal_directions!(indicator.cache.container_bar_states, + + if limiter isa SubcellLimiterMCL || + (limiter isa SubcellLimiterIDP && limiter.bar_states) + resize!(limiter.cache.container_bar_states, new_size) + calc_normal_directions!(limiter.cache.container_bar_states, mesh_equations_solver_cache(semi)...) end end diff --git a/test/test_unit.jl b/test/test_unit.jl index 8d23336cb2..7ff8c5afed 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -402,10 +402,10 @@ isdir(outdir) && rm(outdir, recursive=true) indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = IndicatorIDP(true, [1], true, [1], ("variable",), 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) + indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ("variable",), 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) @test_nowarn show(stdout, indicator_idp) - indicator_mcl = IndicatorMCL("cache", true, true, true, true, true, true, true, 1.0, true, true, 1.0, nothing, true) + indicator_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, 1.0, true, true, 1.0, nothing, true) @test_nowarn show(stdout, indicator_mcl) indicator_loehner = IndicatorLöhner(1.0, "variable", (; cache=nothing)) From b68fe4b79b22de91ee6b2a3ef4e5368297841a0f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 5 Jul 2023 14:03:28 +0200 Subject: [PATCH 246/423] Fix format --- src/solvers/dgsem_tree/indicators.jl | 20 ++++++++++---------- src/solvers/dgsem_tree/indicators_2d.jl | 17 +++++++++-------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index c54983509f..1bfc0a428b 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -519,16 +519,16 @@ function SubcellLimiterMCL(equations::AbstractEquations, basis; end SubcellLimiterMCL{typeof(threshold_smoothness_indicator), typeof(cache), typeof(IndicatorHG)}(cache, - DensityLimiter, DensityAlphaForAll, - SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, - PressurePositivityLimiterKuzminExact, - DensityPositivityLimiter, - DensityPositivityCorrectionFactor, - SemiDiscEntropyLimiter, - smoothness_indicator, - threshold_smoothness_indicator, IndicatorHG, - Plotting) + DensityLimiter, DensityAlphaForAll, + SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzmin, + PressurePositivityLimiterKuzminExact, + DensityPositivityLimiter, + DensityPositivityCorrectionFactor, + SemiDiscEntropyLimiter, + smoothness_indicator, + threshold_smoothness_indicator, IndicatorHG, + Plotting) end function Base.show(io::IO, limiter::SubcellLimiterMCL) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index a34d4f63aa..48177fce79 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -193,9 +193,9 @@ end function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, bar_states) container_subcell_limiter = Trixi.ContainerSubcellLimiterIDP2D{real(basis) - }(0, - nnodes(basis), - number_bounds) + }(0, + nnodes(basis), + number_bounds) cache = (;) if bar_states @@ -210,7 +210,8 @@ function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquat return (; cache..., container_subcell_limiter, idp_bounds_delta) end -function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; +function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, + dt; kwargs...) @unpack alpha = limiter.cache.container_subcell_limiter alpha .= zero(eltype(alpha)) @@ -852,7 +853,7 @@ end end # Newton iterations - for iter in 1:limiter.max_iterations_newton + for iter in 1:(limiter.max_iterations_newton) beta_old = beta # If the state is valid, evaluate d(goal)/d(beta) @@ -932,9 +933,9 @@ end function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) container_subcell_limiter = Trixi.ContainerSubcellLimiterMCL2D{real(basis) - }(0, - nvariables(equations), - nnodes(basis)) + }(0, + nvariables(equations), + nnodes(basis)) container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) From 00144cfd9524a081028bbc8068e9dc0b4659f2a8 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 6 Jul 2023 14:47:33 +0200 Subject: [PATCH 247/423] Add note about togetherness of IDP limiter and correction callback --- src/callbacks_stage/a_posteriori_limiter.jl | 12 ++++++++---- src/solvers/dgsem_tree/indicators.jl | 4 ++++ src/time_integration/methods_SSP.jl | 6 ++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index c85088ad93..4211fe752d 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -8,11 +8,12 @@ """ APosterioriLimiter() -Perform antidiffusive stage for the a posteriori IDP limiter called with -[`VolumeIntegralSubcellLimiting`](@ref) using [`SubcellLimiterIDP`](@ref). +Perform antidiffusive correction stage for the a posteriori IDP limiter [`SubcellLimiterIDP`](@ref) +called with [`VolumeIntegralSubcellLimiting`](@ref). -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. +!!! note + This callback and the actual limiter [`SubcellLimiterIDP`](@ref) only work together. + This is not a replacement but a necessary addition. ## References @@ -22,6 +23,9 @@ Perform antidiffusive stage for the a posteriori IDP limiter called with - Pazner (2020) Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting [DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876) + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. """ struct APosterioriLimiter end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 1bfc0a428b..fe8e61c7e9 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -260,6 +260,10 @@ A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_ `variable_smoothness_indicator`, which disables subcell blending for element-wise indicator values <= `threshold_smoothness_indicator`. +!!! note + This limiter and the correction callback [`APosterioriLimiter`](@ref) only work together. + Without the callback, no limiting takes place, leading to a standard flux-differencing DGSEM scheme. + ## References - Rueda-Ramírez, Pazner, Gassner (2022) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 1af9e849ee..87275bcdfb 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -10,7 +10,7 @@ abstract type SimpleAlgorithmSSP end """ - SimpleSSPRK33(; stage_callbacks=(APosterioriLimiter(), BoundsCheckCallback())) + SimpleSSPRK33(; stage_callbacks=()) The third-order SSP Runge-Kutta method of Shu and Osher. @@ -29,9 +29,7 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP c::SVector{3, Float64} stage_callbacks::StageCallbacks - function SimpleSSPRK33(; - stage_callbacks = (APosterioriLimiter(), - BoundsCheckCallback())) + function SimpleSSPRK33(; stage_callbacks = ()) a = SVector(0.0, 3 / 4, 1 / 3) b = SVector(1.0, 1 / 4, 2 / 3) c = SVector(0.0, 1.0, 1 / 2) From 2827f71d4a56f1562d28ff47427121af5475c537 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 6 Jul 2023 15:12:36 +0200 Subject: [PATCH 248/423] Rename antidiffusive correction stage callback --- ...elixir_euler_convergence_wavingflag_IDP.jl | 2 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 2 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 2 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_shockcapturing_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...ubble_shockcapturing_subcell_positivity.jl | 2 +- src/Trixi.jl | 2 +- src/callbacks_stage/a_posteriori_limiter.jl | 20 ++++++++++--------- src/solvers/dgsem_tree/indicators.jl | 2 +- 17 files changed, 27 insertions(+), 25 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 585ac50d0d..5761e638e4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -69,7 +69,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index a7f01ac250..ede3f6b382 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -139,7 +139,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 3d36144546..6b70438044 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -83,7 +83,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index ff64933b83..5d26662976 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -130,7 +130,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 347ae70570..13ed29db2b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -65,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 12c0259914..5b95fef374 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 2c18b0186e..0e44f62c7b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -87,7 +87,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index fbf695c412..bf6064dc21 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -64,7 +64,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 66297c8eb7..42b529cb63 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -85,7 +85,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index e8eaa5ea32..9886106441 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -91,7 +91,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 65b8f72de3..810c37ff5b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -85,7 +85,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 8ac4b2091f..5c92414e66 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -61,7 +61,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 55c87cab3b..1c6cbef533 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -133,7 +133,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index d3b41dfb33..4fe08a5512 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -136,7 +136,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (APosterioriLimiter(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/Trixi.jl b/src/Trixi.jl index a3a73b578c..3b5a094f2a 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -251,7 +251,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu, APosterioriLimiter, BoundsCheckCallback +export PositivityPreservingLimiterZhangShu, SubcellLimiterIDPCorrection, BoundsCheckCallback export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/a_posteriori_limiter.jl index 4211fe752d..b6734f6d51 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/a_posteriori_limiter.jl @@ -6,7 +6,7 @@ #! format: noindent """ - APosterioriLimiter() + SubcellLimiterIDPCorrection() Perform antidiffusive correction stage for the a posteriori IDP limiter [`SubcellLimiterIDP`](@ref) called with [`VolumeIntegralSubcellLimiting`](@ref). @@ -27,21 +27,23 @@ called with [`VolumeIntegralSubcellLimiting`](@ref). !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct APosterioriLimiter end +struct SubcellLimiterIDPCorrection end -function (limiter!::APosterioriLimiter)(u_ode, integrator::Trixi.SimpleIntegratorSSP, - stage) +function (limiter!::SubcellLimiterIDPCorrection)(u_ode, + integrator::Trixi.SimpleIntegratorSSP, + stage) limiter!(u_ode, integrator.p, integrator.t, integrator.dt, integrator.p.solver.volume_integral) end -function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, - volume_integral::VolumeIntegralSubcellLimiting) +function (limiter!::SubcellLimiterIDPCorrection)(u_ode, semi, t, dt, + volume_integral::VolumeIntegralSubcellLimiting) @trixi_timeit timer() "a posteriori limiter" limiter!(u_ode, semi, t, dt, volume_integral.limiter) end -function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, limiter::SubcellLimiterIDP) +function (limiter!::SubcellLimiterIDPCorrection)(u_ode, semi, t, dt, + limiter::SubcellLimiterIDP) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array(u_ode, mesh, equations, solver, cache) @@ -58,9 +60,9 @@ function (limiter!::APosterioriLimiter)(u_ode, semi, t, dt, limiter::SubcellLimi return nothing end -init_callback(limiter!::APosterioriLimiter, semi) = nothing +init_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing -finalize_callback(limiter!::APosterioriLimiter, semi) = nothing +finalize_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing include("a_posteriori_limiter_2d.jl") end # @muladd diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index fe8e61c7e9..51d0f6a6f2 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -261,7 +261,7 @@ A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_ indicator values <= `threshold_smoothness_indicator`. !!! note - This limiter and the correction callback [`APosterioriLimiter`](@ref) only work together. + This limiter and the correction callback [`SubcellLimiterIDPCorrection`](@ref) only work together. Without the callback, no limiting takes place, leading to a standard flux-differencing DGSEM scheme. ## References From aa0204cfb570255b3a3655f52e372b63f53fd418 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Thu, 6 Jul 2023 15:15:23 +0200 Subject: [PATCH 249/423] Rename file of antidiffusive correction stage callback --- src/callbacks_stage/callbacks_stage.jl | 2 +- ..._posteriori_limiter.jl => subcell_limiter_idp_correction.jl} | 2 +- ...riori_limiter_2d.jl => subcell_limiter_idp_correction_2d.jl} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/callbacks_stage/{a_posteriori_limiter.jl => subcell_limiter_idp_correction.jl} (98%) rename src/callbacks_stage/{a_posteriori_limiter_2d.jl => subcell_limiter_idp_correction_2d.jl} (100%) diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 63c31a33f5..294450507a 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -6,6 +6,6 @@ #! format: noindent include("positivity_zhang_shu.jl") -include("a_posteriori_limiter.jl") +include("subcell_limiter_idp_correction.jl") include("bounds_check.jl") end # @muladd diff --git a/src/callbacks_stage/a_posteriori_limiter.jl b/src/callbacks_stage/subcell_limiter_idp_correction.jl similarity index 98% rename from src/callbacks_stage/a_posteriori_limiter.jl rename to src/callbacks_stage/subcell_limiter_idp_correction.jl index b6734f6d51..f7c3aacc7e 100644 --- a/src/callbacks_stage/a_posteriori_limiter.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction.jl @@ -64,5 +64,5 @@ init_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing finalize_callback(limiter!::SubcellLimiterIDPCorrection, semi) = nothing -include("a_posteriori_limiter_2d.jl") +include("subcell_limiter_idp_correction_2d.jl") end # @muladd diff --git a/src/callbacks_stage/a_posteriori_limiter_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl similarity index 100% rename from src/callbacks_stage/a_posteriori_limiter_2d.jl rename to src/callbacks_stage/subcell_limiter_idp_correction_2d.jl From 787ecc70bfbf2454c942fcb5ab9848b9e651f814 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Fri, 7 Jul 2023 13:36:25 +0200 Subject: [PATCH 250/423] Relocate subcell limiting code --- src/solvers/dgsem_structured/dg.jl | 3 + src/solvers/dgsem_structured/dg_2d.jl | 327 ---- .../dg_2d_subcell_limiters.jl | 334 ++++ src/solvers/dgsem_structured/indicators_2d.jl | 237 --- .../dgsem_structured/subcell_limiters_2d.jl | 244 +++ src/solvers/dgsem_tree/dg.jl | 5 + src/solvers/dgsem_tree/dg_2d.jl | 1491 ---------------- .../dgsem_tree/dg_2d_subcell_limiters.jl | 1498 +++++++++++++++++ src/solvers/dgsem_tree/indicators.jl | 425 ----- src/solvers/dgsem_tree/indicators_2d.jl | 757 --------- src/solvers/dgsem_tree/subcell_limiters.jl | 432 +++++ src/solvers/dgsem_tree/subcell_limiters_2d.jl | 764 +++++++++ 12 files changed, 3280 insertions(+), 3237 deletions(-) create mode 100644 src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl create mode 100644 src/solvers/dgsem_structured/subcell_limiters_2d.jl create mode 100644 src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl create mode 100644 src/solvers/dgsem_tree/subcell_limiters.jl create mode 100644 src/solvers/dgsem_tree/subcell_limiters_2d.jl diff --git a/src/solvers/dgsem_structured/dg.jl b/src/solvers/dgsem_structured/dg.jl index 5cf4c4ef78..de4601a220 100644 --- a/src/solvers/dgsem_structured/dg.jl +++ b/src/solvers/dgsem_structured/dg.jl @@ -80,6 +80,9 @@ include("indicators_1d.jl") include("indicators_2d.jl") include("indicators_3d.jl") +include("subcell_limiters_2d.jl") +include("dg_2d_subcell_limiters.jl") + # Specialized implementations used to improve performance include("dg_2d_compressible_euler.jl") include("dg_3d_compressible_euler.jl") diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index f674497296..a8e141f562 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -380,333 +380,6 @@ end return nothing end -@inline function calcflux_fhat!(fhat1, fhat2, u, - mesh::StructuredMesh{2}, nonconservative_terms::False, - equations, - volume_flux, dg::DGSEM, element, cache) - @unpack contravariant_vectors = cache.elements - @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded = cache - - flux_temp = flux_temp_threaded[Threads.threadid()] - - # The FV-form fluxes are calculated in a recursive manner, i.e.: - # fhat_(0,1) = w_0 * FVol_0, - # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, - # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). - - # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated - # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` - # and saved in in `flux_temp`. - - # Split form volume flux in orientation 1: x direction - flux_temp .= zero(eltype(flux_temp)) - - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - - # pull the contravariant vectors in each coordinate direction - Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, element) # x direction - - # All diagonal entries of `derivative_split` are zero. Thus, we can skip - # the computation of the diagonal terms. In addition, we use the symmetry - # of the `volume_flux` to save half of the possible two-point flux - # computations. - - # x direction - for ii in (i + 1):nnodes(dg) - u_node_ii = get_node_vars(u, equations, dg, ii, j, element) - # pull the contravariant vectors and compute the average - Ja1_node_ii = get_contravariant_vector(1, contravariant_vectors, ii, j, - element) - Ja1_avg = 0.5 * (Ja1_node + Ja1_node_ii) - - # compute the contravariant sharp flux in the direction of the averaged contravariant vector - fluxtilde1 = volume_flux(u_node, u_node_ii, Ja1_avg, equations) - multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], fluxtilde1, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], fluxtilde1, - equations, dg, ii, j) - end - end - - # FV-form flux `fhat` in x direction - fhat1[:, 1, :] .= zero(eltype(fhat1)) - fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) - - for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) - fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] - end - - # Split form volume flux in orientation 2: y direction - flux_temp .= zero(eltype(flux_temp)) - - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - - # pull the contravariant vectors in each coordinate direction - Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, element) - - # y direction - for jj in (j + 1):nnodes(dg) - u_node_jj = get_node_vars(u, equations, dg, i, jj, element) - # pull the contravariant vectors and compute the average - Ja2_node_jj = get_contravariant_vector(2, contravariant_vectors, i, jj, - element) - Ja2_avg = 0.5 * (Ja2_node + Ja2_node_jj) - # compute the contravariant sharp flux in the direction of the averaged contravariant vector - fluxtilde2 = volume_flux(u_node, u_node_jj, Ja2_avg, equations) - multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], fluxtilde2, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], fluxtilde2, - equations, dg, i, jj) - end - end - - # FV-form flux `fhat` in y direction - fhat2[:, :, 1] .= zero(eltype(fhat2)) - fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) - - for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) - fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] - end - - return nothing -end - -@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, - nonconservative_terms, equations, limiter, - dg, cache, boundary_conditions; - calc_bar_states = true) - if limiter isa SubcellLimiterIDP && !limiter.bar_states - return nothing - end - @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states - @unpack contravariant_vectors = cache.elements - - @unpack normal_direction_xi, normal_direction_eta = limiter.cache.container_bar_states - - # Calc lambdas and bar states inside elements - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i - 1, j, element) - - normal_direction = get_node_coords(normal_direction_xi, equations, dg, - i - 1, j, element) - - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, - normal_direction, equations) - - !calc_bar_states && continue - - flux1 = flux(u_node, normal_direction, equations) - flux1_im1 = flux(u_node_im1, normal_direction, equations) - for v in eachvariable(equations) - bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - - 0.5 * (flux1[v] - flux1_im1[v]) / - lambda1[i, j, element] - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j - 1, element) - - normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, - j - 1, element) - - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, - normal_direction, equations) - - !calc_bar_states && continue - - flux2 = flux(u_node, normal_direction, equations) - flux2_jm1 = flux(u_node_jm1, normal_direction, equations) - for v in eachvariable(equations) - bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - - 0.5 * (flux2[v] - flux2_jm1[v]) / - lambda2[i, j, element] - end - end - end - - # Calc lambdas and bar states at interfaces and periodic boundaries - @threaded for element in eachelement(dg, cache) - # Get neighboring element ids - left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] - - if left != 0 - for i in eachnode(dg) - u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) - u_element = get_node_vars(u, equations, dg, 1, i, element) - - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, i, element) - lambda = max_abs_speed_naive(u_left, u_element, Ja1, equations) - - lambda1[nnodes(dg) + 1, i, left] = lambda - lambda1[1, i, element] = lambda - - !calc_bar_states && continue - - flux_left = flux(u_left, Ja1, equations) - flux_element = flux(u_element, Ja1, equations) - bar_state = 0.5 * (u_element + u_left) - - 0.5 * (flux_element - flux_left) / lambda - for v in eachvariable(equations) - bar_states1[v, nnodes(dg) + 1, i, left] = bar_state[v] - bar_states1[v, 1, i, element] = bar_state[v] - end - end - end - if lower != 0 - for i in eachnode(dg) - u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) - u_element = get_node_vars(u, equations, dg, i, 1, element) - - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - lambda = max_abs_speed_naive(u_lower, u_element, Ja2, equations) - - lambda2[i, nnodes(dg) + 1, lower] = lambda - lambda2[i, 1, element] = lambda - - !calc_bar_states && continue - - flux_lower = flux(u_lower, Ja2, equations) - flux_element = flux(u_element, Ja2, equations) - bar_state = 0.5 * (u_element + u_lower) - - 0.5 * (flux_element - flux_lower) / lambda - for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg) + 1, lower] = bar_state[v] - bar_states2[v, i, 1, element] = bar_state[v] - end - end - end - end - - # Calc lambdas and bar states at physical boundaries - if isperiodic(mesh) - return nothing - end - linear_indices = LinearIndices(size(mesh)) - if !isperiodic(mesh, 1) - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) - lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, Ja1, equations) - flux_outer = flux(u_outer, Ja1, equations) - for v in eachvariable(equations) - bar_states1[v, 1, j, element] = 0.5 * (u_inner[v] + u_outer[v]) - - 0.5 * - (flux_inner[v] - flux_outer[v]) / - lambda1[1, j, element] - end - end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, - element) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) - lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, - u_outer, Ja1, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, Ja1, equations) - flux_outer = flux(u_outer, Ja1, equations) - for v in eachvariable(equations) - bar_states1[v, nnodes(dg) + 1, j, element] = 0.5 * (u_inner[v] + - u_outer[v]) - - 0.5 * - (flux_outer[v] - - flux_inner[v]) / - lambda1[nnodes(dg) + 1, - j, element] - end - end - end - end - if !isperiodic(mesh, 2) - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) - lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, Ja2, equations) - flux_outer = flux(u_outer, Ja2, equations) - for v in eachvariable(equations) - bar_states2[v, i, 1, element] = 0.5 * (u_inner[v] + u_outer[v]) - - 0.5 * - (flux_inner[v] - flux_outer[v]) / - lambda2[i, 1, element] - end - end - end - # + eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), - element) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) - lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, - u_outer, Ja2, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, Ja2, equations) - flux_outer = flux(u_outer, Ja2, equations) - for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg) + 1, element] = 0.5 * (u_outer[v] + - u_inner[v]) - - 0.5 * - (flux_outer[v] - - flux_inner[v]) / - lambda2[i, - nnodes(dg) + 1, - element] - end - end - end - end - - return nothing -end - function calc_interface_flux!(cache, u, mesh::StructuredMesh{2}, nonconservative_terms, # can be True/False diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl new file mode 100644 index 0000000000..6d7c0a740a --- /dev/null +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -0,0 +1,334 @@ +# 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 + +@inline function calcflux_fhat!(fhat1, fhat2, u, + mesh::StructuredMesh{2}, nonconservative_terms::False, + equations, + volume_flux, dg::DGSEM, element, cache) + @unpack contravariant_vectors = cache.elements + @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded = cache + + flux_temp = flux_temp_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fhat_(0,1) = w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # pull the contravariant vectors in each coordinate direction + Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, element) # x direction + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of the `volume_flux` to save half of the possible two-point flux + # computations. + + # x direction + for ii in (i + 1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + # pull the contravariant vectors and compute the average + Ja1_node_ii = get_contravariant_vector(1, contravariant_vectors, ii, j, + element) + Ja1_avg = 0.5 * (Ja1_node + Ja1_node_ii) + + # compute the contravariant sharp flux in the direction of the averaged contravariant vector + fluxtilde1 = volume_flux(u_node, u_node_ii, Ja1_avg, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], fluxtilde1, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], fluxtilde1, + equations, dg, ii, j) + end + end + + # FV-form flux `fhat` in x direction + fhat1[:, 1, :] .= zero(eltype(fhat1)) + fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) + + for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) + fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + end + + # Split form volume flux in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # pull the contravariant vectors in each coordinate direction + Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, element) + + # y direction + for jj in (j + 1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + # pull the contravariant vectors and compute the average + Ja2_node_jj = get_contravariant_vector(2, contravariant_vectors, i, jj, + element) + Ja2_avg = 0.5 * (Ja2_node + Ja2_node_jj) + # compute the contravariant sharp flux in the direction of the averaged contravariant vector + fluxtilde2 = volume_flux(u_node, u_node_jj, Ja2_avg, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], fluxtilde2, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], fluxtilde2, + equations, dg, i, jj) + end + end + + # FV-form flux `fhat` in y direction + fhat2[:, :, 1] .= zero(eltype(fhat2)) + fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) + + for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) + fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + end + + return nothing +end + +@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, + nonconservative_terms, equations, limiter, + dg, cache, boundary_conditions; + calc_bar_states = true) + if limiter isa SubcellLimiterIDP && !limiter.bar_states + return nothing + end + @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states + @unpack contravariant_vectors = cache.elements + + @unpack normal_direction_xi, normal_direction_eta = limiter.cache.container_bar_states + + # Calc lambdas and bar states inside elements + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i - 1, j, element) + + normal_direction = get_node_coords(normal_direction_xi, equations, dg, + i - 1, j, element) + + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, + normal_direction, equations) + + !calc_bar_states && continue + + flux1 = flux(u_node, normal_direction, equations) + flux1_im1 = flux(u_node_im1, normal_direction, equations) + for v in eachvariable(equations) + bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - + 0.5 * (flux1[v] - flux1_im1[v]) / + lambda1[i, j, element] + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j - 1, element) + + normal_direction = get_node_coords(normal_direction_eta, equations, dg, i, + j - 1, element) + + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, + normal_direction, equations) + + !calc_bar_states && continue + + flux2 = flux(u_node, normal_direction, equations) + flux2_jm1 = flux(u_node_jm1, normal_direction, equations) + for v in eachvariable(equations) + bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - + 0.5 * (flux2[v] - flux2_jm1[v]) / + lambda2[i, j, element] + end + end + end + + # Calc lambdas and bar states at interfaces and periodic boundaries + @threaded for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), i, left) + u_element = get_node_vars(u, equations, dg, 1, i, element) + + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, i, element) + lambda = max_abs_speed_naive(u_left, u_element, Ja1, equations) + + lambda1[nnodes(dg) + 1, i, left] = lambda + lambda1[1, i, element] = lambda + + !calc_bar_states && continue + + flux_left = flux(u_left, Ja1, equations) + flux_element = flux(u_element, Ja1, equations) + bar_state = 0.5 * (u_element + u_left) - + 0.5 * (flux_element - flux_left) / lambda + for v in eachvariable(equations) + bar_states1[v, nnodes(dg) + 1, i, left] = bar_state[v] + bar_states1[v, 1, i, element] = bar_state[v] + end + end + end + if lower != 0 + for i in eachnode(dg) + u_lower = get_node_vars(u, equations, dg, i, nnodes(dg), lower) + u_element = get_node_vars(u, equations, dg, i, 1, element) + + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + lambda = max_abs_speed_naive(u_lower, u_element, Ja2, equations) + + lambda2[i, nnodes(dg) + 1, lower] = lambda + lambda2[i, 1, element] = lambda + + !calc_bar_states && continue + + flux_lower = flux(u_lower, Ja2, equations) + flux_element = flux(u_element, Ja2, equations) + bar_state = 0.5 * (u_element + u_lower) - + 0.5 * (flux_element - flux_lower) / lambda + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg) + 1, lower] = bar_state[v] + bar_states2[v, i, 1, element] = bar_state[v] + end + end + end + end + + # Calc lambdas and bar states at physical boundaries + if isperiodic(mesh) + return nothing + end + linear_indices = LinearIndices(size(mesh)) + if !isperiodic(mesh, 1) + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[1], Ja1, 1, + equations, dg, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, Ja1, equations) + flux_outer = flux(u_outer, Ja1, equations) + for v in eachvariable(equations) + bar_states1[v, 1, j, element] = 0.5 * (u_inner[v] + u_outer[v]) - + 0.5 * + (flux_inner[v] - flux_outer[v]) / + lambda1[1, j, element] + end + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, + element) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[2], Ja1, 2, + equations, dg, nnodes(dg), j, + element) + lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, + u_outer, Ja1, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, Ja1, equations) + flux_outer = flux(u_outer, Ja1, equations) + for v in eachvariable(equations) + bar_states1[v, nnodes(dg) + 1, j, element] = 0.5 * (u_inner[v] + + u_outer[v]) - + 0.5 * + (flux_outer[v] - + flux_inner[v]) / + lambda1[nnodes(dg) + 1, + j, element] + end + end + end + end + if !isperiodic(mesh, 2) + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[3], Ja2, 3, + equations, dg, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, Ja2, equations) + flux_outer = flux(u_outer, Ja2, equations) + for v in eachvariable(equations) + bar_states2[v, i, 1, element] = 0.5 * (u_inner[v] + u_outer[v]) - + 0.5 * + (flux_inner[v] - flux_outer[v]) / + lambda2[i, 1, element] + end + end + end + # + eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), + element) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[4], Ja2, 4, + equations, dg, i, nnodes(dg), + element) + lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, + u_outer, Ja2, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, Ja2, equations) + flux_outer = flux(u_outer, Ja2, equations) + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg) + 1, element] = 0.5 * (u_outer[v] + + u_inner[v]) - + 0.5 * + (flux_outer[v] - + flux_inner[v]) / + lambda2[i, + nnodes(dg) + 1, + element] + end + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_structured/indicators_2d.jl b/src/solvers/dgsem_structured/indicators_2d.jl index 8f6b54459e..f4b07b70cb 100644 --- a/src/solvers/dgsem_structured/indicators_2d.jl +++ b/src/solvers/dgsem_structured/indicators_2d.jl @@ -27,241 +27,4 @@ function apply_smoothing!(mesh::StructuredMesh{2}, alpha, alpha_tmp, dg, cache) alpha[element] = max(alpha_tmp[element], 0.5 * alpha_tmp[lower], alpha[element]) end end - -function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, - mesh::StructuredMesh{2}) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack contravariant_vectors = cache.elements - # Calc bounds at interfaces and periodic boundaries - for element in eachelement(dg, cache) - # Get neighboring element ids - left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] - - if left != 0 - for j in eachnode(dg) - var_left = u[variable, nnodes(dg), j, left] - var_element = u[variable, 1, j, element] - - var_min[1, j, element] = min(var_min[1, j, element], var_left) - var_max[1, j, element] = max(var_max[1, j, element], var_left) - - var_min[nnodes(dg), j, left] = min(var_min[nnodes(dg), j, left], - var_element) - var_max[nnodes(dg), j, left] = max(var_max[nnodes(dg), j, left], - var_element) - end - end - if lower != 0 - for i in eachnode(dg) - var_lower = u[variable, i, nnodes(dg), lower] - var_element = u[variable, i, 1, element] - - var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) - var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) - - var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], - var_element) - var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], - var_element) - end - end - end - - # Calc bounds at physical boundaries - if isperiodic(mesh) - return nothing - end - linear_indices = LinearIndices(size(mesh)) - if !isperiodic(mesh, 1) - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) - var_outer = u_outer[variable] - - var_min[1, j, element] = min(var_min[1, j, element], var_outer) - var_max[1, j, element] = max(var_max[1, j, element], var_outer) - end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, - element) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) - var_outer = u_outer[variable] - - var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], - var_outer) - var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], - var_outer) - end - end - end - if !isperiodic(mesh, 2) - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) - var_outer = u_outer[variable] - - var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) - var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) - end - end - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), - element) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) - var_outer = u_outer[variable] - - var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], - var_outer) - var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], - var_outer) - end - end - end - - return nothing -end - -function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, - mesh::StructuredMesh{2}) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack contravariant_vectors = cache.elements - # Calc bounds at interfaces and periodic boundaries - for element in eachelement(dg, cache) - # Get neighboring element ids - left = cache.elements.left_neighbors[1, element] - lower = cache.elements.left_neighbors[2, element] - - if left != 0 - for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, - left), equations) - var_element = variable(get_node_vars(u, equations, dg, 1, j, element), - equations) - - var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_left) - var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, - left], var_element) - end - end - if lower != 0 - for i in eachnode(dg) - var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), - lower), equations) - var_element = variable(get_node_vars(u, equations, dg, i, 1, element), - equations) - - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_lower) - var_minmax[i, nnodes(dg), lower] = minmax(var_minmax[i, nnodes(dg), - lower], - var_element) - end - end - end - - # Calc bounds at physical boundaries - if isperiodic(mesh) - return nothing - end - linear_indices = LinearIndices(size(mesh)) - if !isperiodic(mesh, 1) - # - xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[begin, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) - - var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) - end - end - # + xi direction - for cell_y in axes(mesh, 2) - element = linear_indices[end, cell_y] - for j in eachnode(dg) - Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, - element) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) - var_outer = variable(u_outer, equations) - - var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, - element], - var_outer) - end - end - end - if !isperiodic(mesh, 2) - # - eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, begin] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) - - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) - end - end - # + eta direction - for cell_x in axes(mesh, 1) - element = linear_indices[cell_x, end] - for i in eachnode(dg) - Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), - element) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) - var_outer = variable(u_outer, equations) - - var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), - element], - var_outer) - end - end - end - - return nothing -end end # @muladd diff --git a/src/solvers/dgsem_structured/subcell_limiters_2d.jl b/src/solvers/dgsem_structured/subcell_limiters_2d.jl new file mode 100644 index 0000000000..8faa10cb18 --- /dev/null +++ b/src/solvers/dgsem_structured/subcell_limiters_2d.jl @@ -0,0 +1,244 @@ +# 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 calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, + mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + @unpack contravariant_vectors = cache.elements + # Calc bounds at interfaces and periodic boundaries + for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for j in eachnode(dg) + var_left = u[variable, nnodes(dg), j, left] + var_element = u[variable, 1, j, element] + + var_min[1, j, element] = min(var_min[1, j, element], var_left) + var_max[1, j, element] = max(var_max[1, j, element], var_left) + + var_min[nnodes(dg), j, left] = min(var_min[nnodes(dg), j, left], + var_element) + var_max[nnodes(dg), j, left] = max(var_max[nnodes(dg), j, left], + var_element) + end + end + if lower != 0 + for i in eachnode(dg) + var_lower = u[variable, i, nnodes(dg), lower] + var_element = u[variable, i, 1, element] + + var_min[i, 1, element] = min(var_min[i, 1, element], var_lower) + var_max[i, 1, element] = max(var_max[i, 1, element], var_lower) + + var_min[i, nnodes(dg), lower] = min(var_min[i, nnodes(dg), lower], + var_element) + var_max[i, nnodes(dg), lower] = max(var_max[i, nnodes(dg), lower], + var_element) + end + end + end + + # Calc bounds at physical boundaries + if isperiodic(mesh) + return nothing + end + linear_indices = LinearIndices(size(mesh)) + if !isperiodic(mesh, 1) + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[1], Ja1, 1, + equations, dg, 1, j, element) + var_outer = u_outer[variable] + + var_min[1, j, element] = min(var_min[1, j, element], var_outer) + var_max[1, j, element] = max(var_max[1, j, element], var_outer) + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, + element) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[2], Ja1, 2, + equations, dg, nnodes(dg), j, + element) + var_outer = u_outer[variable] + + var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], + var_outer) + var_max[nnodes(dg), j, element] = max(var_max[nnodes(dg), j, element], + var_outer) + end + end + end + if !isperiodic(mesh, 2) + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[3], Ja2, 3, + equations, dg, i, 1, element) + var_outer = u_outer[variable] + + var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) + var_max[i, 1, element] = max(var_max[i, 1, element], var_outer) + end + end + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), + element) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[4], Ja2, 4, + equations, dg, i, nnodes(dg), + element) + var_outer = u_outer[variable] + + var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], + var_outer) + var_max[i, nnodes(dg), element] = max(var_max[i, nnodes(dg), element], + var_outer) + end + end + end + + return nothing +end + +function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, + mesh::StructuredMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + @unpack contravariant_vectors = cache.elements + # Calc bounds at interfaces and periodic boundaries + for element in eachelement(dg, cache) + # Get neighboring element ids + left = cache.elements.left_neighbors[1, element] + lower = cache.elements.left_neighbors[2, element] + + if left != 0 + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, + left), equations) + var_element = variable(get_node_vars(u, equations, dg, 1, j, element), + equations) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_left) + var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, + left], var_element) + end + end + if lower != 0 + for i in eachnode(dg) + var_lower = variable(get_node_vars(u, equations, dg, i, nnodes(dg), + lower), equations) + var_element = variable(get_node_vars(u, equations, dg, i, 1, element), + equations) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_lower) + var_minmax[i, nnodes(dg), lower] = minmax(var_minmax[i, nnodes(dg), + lower], + var_element) + end + end + end + + # Calc bounds at physical boundaries + if isperiodic(mesh) + return nothing + end + linear_indices = LinearIndices(size(mesh)) + if !isperiodic(mesh, 1) + # - xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[begin, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[1], Ja1, 1, + equations, dg, 1, j, element) + var_outer = variable(u_outer, equations) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) + end + end + # + xi direction + for cell_y in axes(mesh, 2) + element = linear_indices[end, cell_y] + for j in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, + element) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[2], Ja1, 2, + equations, dg, nnodes(dg), j, + element) + var_outer = variable(u_outer, equations) + + var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, + element], + var_outer) + end + end + end + if !isperiodic(mesh, 2) + # - eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, begin] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[3], Ja2, 3, + equations, dg, i, 1, element) + var_outer = variable(u_outer, equations) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) + end + end + # + eta direction + for cell_x in axes(mesh, 1) + element = linear_indices[cell_x, end] + for i in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), + element) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[4], Ja2, 4, + equations, dg, i, nnodes(dg), + element) + var_outer = variable(u_outer, equations) + + var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), + element], + var_outer) + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 2ebefac573..550209833e 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -76,4 +76,9 @@ include("dg_3d_parabolic.jl") # as well as specialized implementations used to improve performance include("dg_2d_compressible_euler.jl") include("dg_3d_compressible_euler.jl") + +# Subcell limiters +include("subcell_limiters.jl") +include("subcell_limiters_2d.jl") +include("dg_2d_subcell_limiters.jl") end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index b6e4a74325..2f7d5122a2 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -568,1497 +568,6 @@ end return nothing end -function calc_volume_integral!(du, u, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, - nonconservative_terms, equations, - volume_integral::VolumeIntegralSubcellLimiting, - dg::DGSEM, cache, t, boundary_conditions) - @unpack limiter = volume_integral - - # Calculate lambdas and bar states - @trixi_timeit timer() "calc_lambdas_bar_states!" calc_lambdas_bar_states!(u, t, - mesh, - nonconservative_terms, - equations, - limiter, - dg, cache, - boundary_conditions) - # Calculate boundaries - @trixi_timeit timer() "calc_variable_bounds!" calc_variable_bounds!(u, mesh, - nonconservative_terms, - equations, - limiter, dg, - cache) - - if limiter.smoothness_indicator - @unpack element_ids_dg, element_ids_dgfv = cache - # Calculate element-wise blending factors α - alpha_element = @trixi_timeit timer() "element-wise blending factors" limiter.IndicatorHG(u, - mesh, - equations, - dg, - cache) - - # Determine element ids for DG-only and subcell-wise blended DG-FV volume integral - pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, - dg, cache) - - # Loop over pure DG elements - @trixi_timeit timer() "pure DG" @threaded for idx_element in eachindex(element_ids_dg) - element = element_ids_dg[idx_element] - flux_differencing_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral.volume_flux_dg, dg, cache) - end - - # Loop over blended DG-FV elements - @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for idx_element in eachindex(element_ids_dgfv) - element = element_ids_dgfv[idx_element] - subcell_limiting_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral, limiter, - dg, cache) - end - else # limiter.smoothness_indicator == false - # Loop over all elements - @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for element in eachelement(dg, - cache) - subcell_limiting_kernel!(du, u, element, mesh, - nonconservative_terms, equations, - volume_integral, limiter, - dg, cache) - end - end -end - -@inline function subcell_limiting_kernel!(du, u, - element, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, - nonconservative_terms::False, equations, - volume_integral, limiter::SubcellLimiterIDP, - dg::DGSEM, cache) - @unpack inverse_weights = dg.basis - @unpack volume_flux_dg, volume_flux_fv = volume_integral - - # high-order DG fluxes - @unpack fhat1_threaded, fhat2_threaded = cache - - fhat1 = fhat1_threaded[Threads.threadid()] - fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - - # low-order FV fluxes - @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache - - fstar1_L = fstar1_L_threaded[Threads.threadid()] - fstar2_L = fstar2_L_threaded[Threads.threadid()] - fstar1_R = fstar1_R_threaded[Threads.threadid()] - fstar2_R = fstar2_R_threaded[Threads.threadid()] - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - - # antidiffusive flux - calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, limiter, dg, element, - cache) - - # Calculate volume integral contribution of low-order FV flux - for j in eachnode(dg), i in eachnode(dg) - for v in eachvariable(equations) - du[v, i, j, element] += inverse_weights[i] * - (fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) + - inverse_weights[j] * - (fstar2_L[v, i, j + 1] - fstar2_R[v, i, j]) - end - end - - return nothing -end - -@inline function subcell_limiting_kernel!(du, u, - element, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, - nonconservative_terms::False, equations, - volume_integral, limiter::SubcellLimiterMCL, - dg::DGSEM, cache) - @unpack inverse_weights = dg.basis - @unpack volume_flux_dg, volume_flux_fv = volume_integral - - # high-order DG fluxes - @unpack fhat1_threaded, fhat2_threaded = cache - fhat1 = fhat1_threaded[Threads.threadid()] - fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - - # low-order FV fluxes - @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache - fstar1_L = fstar1_L_threaded[Threads.threadid()] - fstar2_L = fstar2_L_threaded[Threads.threadid()] - fstar1_R = fstar1_R_threaded[Threads.threadid()] - fstar2_R = fstar2_R_threaded[Threads.threadid()] - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) - - # antidiffusive flux - calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, limiter, dg, - element, cache) - - # limit antidiffusive flux - calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, - limiter, dg, element, cache, - fstar1_L, fstar2_L) - - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - for j in eachnode(dg), i in eachnode(dg) - for v in eachvariable(equations) - du[v, i, j, element] += inverse_weights[i] * - (fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) + - inverse_weights[j] * - (fstar2_L[v, i, j + 1] - fstar2_R[v, i, j]) - - du[v, i, j, element] += inverse_weights[i] * - (-antidiffusive_flux1[v, i + 1, j, element] + - antidiffusive_flux1[v, i, j, element]) + - inverse_weights[j] * - (-antidiffusive_flux2[v, i, j + 1, element] + - antidiffusive_flux2[v, i, j, element]) - end - end - - return nothing -end - -# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element -# (**without non-conservative terms**). -# -# See also `flux_differencing_kernel!`. -@inline function calcflux_fhat!(fhat1, fhat2, u, - mesh::TreeMesh{2}, nonconservative_terms::False, - equations, - volume_flux, dg::DGSEM, element, cache) - @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded = cache - - flux_temp = flux_temp_threaded[Threads.threadid()] - - # The FV-form fluxes are calculated in a recursive manner, i.e.: - # fhat_(0,1) = w_0 * FVol_0, - # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, - # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). - - # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated - # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` - # and saved in in `flux_temp`. - - # Split form volume flux in orientation 1: x direction - flux_temp .= zero(eltype(flux_temp)) - - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - - # All diagonal entries of `derivative_split` are zero. Thus, we can skip - # the computation of the diagonal terms. In addition, we use the symmetry - # of the `volume_flux` to save half of the possible two-point flux - # computations. - for ii in (i + 1):nnodes(dg) - u_node_ii = get_node_vars(u, equations, dg, ii, j, element) - flux1 = volume_flux(u_node, u_node_ii, 1, equations) - multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, - equations, dg, ii, j) - end - end - - # FV-form flux `fhat` in x direction - fhat1[:, 1, :] .= zero(eltype(fhat1)) - fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) - - for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) - fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] - end - - # Split form volume flux in orientation 2: y direction - flux_temp .= zero(eltype(flux_temp)) - - for j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - for jj in (j + 1):nnodes(dg) - u_node_jj = get_node_vars(u, equations, dg, i, jj, element) - flux2 = volume_flux(u_node, u_node_jj, 2, equations) - multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, - equations, dg, i, jj) - end - end - - # FV-form flux `fhat` in y direction - fhat2[:, :, 1] .= zero(eltype(fhat2)) - fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) - - for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) - fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] - end - - return nothing -end - -# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. -@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, - limiter::SubcellLimiterIDP, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - - for j in eachnode(dg), i in 2:nnodes(dg) - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] - end - end - for j in 2:nnodes(dg), i in eachnode(dg) - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] - end - end - - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) - - return nothing -end - -@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, - limiter::SubcellLimiterMCL, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - - for j in eachnode(dg), i in 2:nnodes(dg) - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = -(fhat1[v, i, j] - fstar1[v, i, j]) - end - end - for j in 2:nnodes(dg), i in eachnode(dg) - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = -(fhat2[v, i, j] - fstar2[v, i, j]) - end - end - - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) - - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) - - return nothing -end - -@inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, - nonconservative_terms, equations, limiter, - dg, cache, boundary_conditions; - calc_bar_states = true) - if limiter isa SubcellLimiterIDP && !limiter.bar_states - return nothing - end - @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states - - # Calc lambdas and bar states inside elements - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in 2:nnodes(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_im1 = get_node_vars(u, equations, dg, i - 1, j, element) - lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, - equations) - - !calc_bar_states && continue - - flux1 = flux(u_node, 1, equations) - flux1_im1 = flux(u_node_im1, 1, equations) - for v in eachvariable(equations) - bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - - 0.5 * (flux1[v] - flux1_im1[v]) / - lambda1[i, j, element] - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - u_node = get_node_vars(u, equations, dg, i, j, element) - u_node_jm1 = get_node_vars(u, equations, dg, i, j - 1, element) - lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, - equations) - - !calc_bar_states && continue - - flux2 = flux(u_node, 2, equations) - flux2_jm1 = flux(u_node_jm1, 2, equations) - for v in eachvariable(equations) - bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - - 0.5 * (flux2[v] - flux2_jm1[v]) / - lambda2[i, j, element] - end - end - end - - # Calc lambdas and bar states at interfaces and periodic boundaries - @threaded for interface in eachinterface(dg, cache) - # Get neighboring element ids - left_id = cache.interfaces.neighbor_ids[1, interface] - right_id = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - if orientation == 1 - for j in eachnode(dg) - u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) - u_right = get_node_vars(u, equations, dg, 1, j, right_id) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - - lambda1[nnodes(dg) + 1, j, left_id] = lambda - lambda1[1, j, right_id] = lambda - - !calc_bar_states && continue - - flux_left = flux(u_left, orientation, equations) - flux_right = flux(u_right, orientation, equations) - bar_state = 0.5 * (u_left + u_right) - - 0.5 * (flux_right - flux_left) / lambda - for v in eachvariable(equations) - bar_states1[v, nnodes(dg) + 1, j, left_id] = bar_state[v] - bar_states1[v, 1, j, right_id] = bar_state[v] - end - end - else # orientation == 2 - for i in eachnode(dg) - u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) - u_right = get_node_vars(u, equations, dg, i, 1, right_id) - lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) - - lambda2[i, nnodes(dg) + 1, left_id] = lambda - lambda2[i, 1, right_id] = lambda - - !calc_bar_states && continue - - flux_left = flux(u_left, orientation, equations) - flux_right = flux(u_right, orientation, equations) - bar_state = 0.5 * (u_left + u_right) - - 0.5 * (flux_right - flux_left) / lambda - for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg) + 1, left_id] = bar_state[v] - bar_states2[v, i, 1, right_id] = bar_state[v] - end - end - end - end - - # Calc lambdas and bar states at physical boundaries - @threaded for boundary in eachboundary(dg, cache) - element = cache.boundaries.neighbor_ids[boundary] - orientation = cache.boundaries.orientations[boundary] - neighbor_side = cache.boundaries.neighbor_sides[boundary] - - if orientation == 1 - if neighbor_side == 2 # Element is on the right, boundary on the left - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], - orientation, 1, - equations, dg, 1, j, element) - lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, - orientation, equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, orientation, equations) - flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - - 0.5 * (flux_inner - flux_outer) / lambda1[1, j, element] - for v in eachvariable(equations) - bar_states1[v, 1, j, element] = bar_state[v] - end - end - else # Element is on the left, boundary on the right - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], - orientation, 2, - equations, dg, nnodes(dg), j, - element) - lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, - u_outer, - orientation, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, orientation, equations) - flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - - 0.5 * (flux_outer - flux_inner) / - lambda1[nnodes(dg) + 1, j, element] - for v in eachvariable(equations) - bar_states1[v, nnodes(dg) + 1, j, element] = bar_state[v] - end - end - end - else # orientation == 2 - if neighbor_side == 2 # Element is on the right, boundary on the left - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], - orientation, 3, - equations, dg, i, 1, element) - lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, - orientation, equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, orientation, equations) - flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - - 0.5 * (flux_inner - flux_outer) / lambda2[i, 1, element] - for v in eachvariable(equations) - bar_states2[v, i, 1, element] = bar_state[v] - end - end - else # Element is on the left, boundary on the right - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], - orientation, 4, - equations, dg, i, nnodes(dg), - element) - lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, - u_outer, - orientation, - equations) - - !calc_bar_states && continue - - flux_inner = flux(u_inner, orientation, equations) - flux_outer = flux(u_outer, orientation, equations) - bar_state = 0.5 * (u_inner + u_outer) - - 0.5 * (flux_outer - flux_inner) / - lambda2[i, nnodes(dg) + 1, element] - for v in eachvariable(equations) - bar_states2[v, i, nnodes(dg) + 1, element] = bar_state[v] - end - end - end - end - end - - return nothing -end - -@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, - limiter::SubcellLimiterIDP, dg, cache) - if !limiter.bar_states - return nothing - end - @unpack variable_bounds = limiter.cache.container_subcell_limiter - @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states - - counter = 1 - # state variables - if limiter.local_minmax - for index in limiter.local_minmax_variables_cons - var_min = variable_bounds[counter] - var_max = variable_bounds[counter + 1] - @threaded for element in eachelement(dg, cache) - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) - for j in eachnode(dg), i in eachnode(dg) - var_min[i, j, element] = min(var_min[i, j, element], - u[index, i, j, element]) - var_max[i, j, element] = max(var_max[i, j, element], - u[index, i, j, element]) - # TODO: Add source term! - # - xi direction - var_min[i, j, element] = min(var_min[i, j, element], - bar_states1[index, i, j, element]) - var_max[i, j, element] = max(var_max[i, j, element], - bar_states1[index, i, j, element]) - # + xi direction - var_min[i, j, element] = min(var_min[i, j, element], - bar_states1[index, i + 1, j, element]) - var_max[i, j, element] = max(var_max[i, j, element], - bar_states1[index, i + 1, j, element]) - # - eta direction - var_min[i, j, element] = min(var_min[i, j, element], - bar_states2[index, i, j, element]) - var_max[i, j, element] = max(var_max[i, j, element], - bar_states2[index, i, j, element]) - # + eta direction - var_min[i, j, element] = min(var_min[i, j, element], - bar_states2[index, i, j + 1, element]) - var_max[i, j, element] = max(var_max[i, j, element], - bar_states2[index, i, j + 1, element]) - end - end - counter += 2 - end - end - # Specific Entropy - if limiter.spec_entropy - s_min = variable_bounds[counter] - @threaded for element in eachelement(dg, cache) - s_min[:, :, element] .= typemax(eltype(s_min)) - for j in eachnode(dg), i in eachnode(dg) - s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), - equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # TODO: Add source? - # - xi direction - s = entropy_spec(get_node_vars(bar_states1, equations, dg, i, j, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # + xi direction - s = entropy_spec(get_node_vars(bar_states1, equations, dg, i + 1, j, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # - eta direction - s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # + eta direction - s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j + 1, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - end - end - counter += 1 - end - # Mathematical entropy - if limiter.math_entropy - s_max = variable_bounds[counter] - @threaded for element in eachelement(dg, cache) - s_max[:, :, element] .= typemin(eltype(s_max)) - for j in eachnode(dg), i in eachnode(dg) - s = entropy_math(get_node_vars(u, equations, dg, i, j, element), - equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # - xi direction - s = entropy_math(get_node_vars(bar_states1, equations, dg, i, j, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # + xi direction - s = entropy_math(get_node_vars(bar_states1, equations, dg, i + 1, j, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # - eta direction - s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # + eta direction - s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j + 1, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - end - end - end - - return nothing -end - -@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, - limiter::SubcellLimiterMCL, dg, cache) - @unpack var_min, var_max = limiter.cache.container_subcell_limiter - @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states - - @threaded for element in eachelement(dg, cache) - for v in eachvariable(equations) - var_min[v, :, :, element] .= typemax(eltype(var_min)) - var_max[v, :, :, element] .= typemin(eltype(var_max)) - end - - if limiter.DensityLimiter - for j in eachnode(dg), i in eachnode(dg) - # Previous solution - var_min[1, i, j, element] = min(var_min[1, i, j, element], - u[1, i, j, element]) - var_max[1, i, j, element] = max(var_max[1, i, j, element], - u[1, i, j, element]) - # - xi direction - bar_state_rho = bar_states1[1, i, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], - bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], - bar_state_rho) - # + xi direction - bar_state_rho = bar_states1[1, i + 1, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], - bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], - bar_state_rho) - # - eta direction - bar_state_rho = bar_states2[1, i, j, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], - bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], - bar_state_rho) - # + eta direction - bar_state_rho = bar_states2[1, i, j + 1, element] - var_min[1, i, j, element] = min(var_min[1, i, j, element], - bar_state_rho) - var_max[1, i, j, element] = max(var_max[1, i, j, element], - bar_state_rho) - end - end #limiter.DensityLimiter - - if limiter.SequentialLimiter - for j in eachnode(dg), i in eachnode(dg) - # Previous solution - for v in 2:nvariables(equations) - phi = u[v, i, j, element] / u[1, i, j, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], phi) - end - # - xi direction - bar_state_rho = bar_states1[1, i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_phi) - end - # + xi direction - bar_state_rho = bar_states1[1, i + 1, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i + 1, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_phi) - end - # - eta direction - bar_state_rho = bar_states2[1, i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_phi) - end - # + eta direction - bar_state_rho = bar_states2[1, i, j + 1, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j + 1, element] / bar_state_rho - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_phi) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_phi) - end - end - elseif limiter.ConservativeLimiter - for j in eachnode(dg), i in eachnode(dg) - # Previous solution - for v in 2:nvariables(equations) - var_min[v, i, j, element] = min(var_min[v, i, j, element], - u[v, i, j, element]) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - u[v, i, j, element]) - end - # - xi direction - for v in 2:nvariables(equations) - bar_state_rho = bar_states1[v, i, j, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_rho) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_rho) - end - # + xi direction - for v in 2:nvariables(equations) - bar_state_rho = bar_states1[v, i + 1, j, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_rho) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_rho) - end - # - eta direction - for v in 2:nvariables(equations) - bar_state_rho = bar_states2[v, i, j, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_rho) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_rho) - end - # + eta direction - for v in 2:nvariables(equations) - bar_state_rho = bar_states2[v, i, j + 1, element] - var_min[v, i, j, element] = min(var_min[v, i, j, element], - bar_state_rho) - var_max[v, i, j, element] = max(var_max[v, i, j, element], - bar_state_rho) - end - end - end - end - - return nothing -end - -@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, - equations, limiter, dg, element, - cache, - fstar1, fstar2) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack var_min, var_max = limiter.cache.container_subcell_limiter - @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states - - if limiter.Plotting - @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter - for j in eachnode(dg), i in eachnode(dg) - alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) - alpha[:, i, j, element] .= one(eltype(alpha)) - if limiter.PressurePositivityLimiterKuzmin - alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) - alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) - end - if limiter.SemiDiscEntropyLimiter - alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) - alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) - end - end - end - - # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. - # To avoid further calculations with these values, we replace them by 0. - # It can also happen that the limited flux changes its sign (for instance to -1e-13). - # This does not really make sense in theory and causes problems for the visualization. - # Therefore we make sure that the flux keeps its sign during limiting. - - # Density limiter - if limiter.DensityLimiter - for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - bar_state_rho = bar_states1[1, i, j, element] - - # Limit density - if antidiffusive_flux1[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i - 1, j, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[1, i, j, element], - max(f_max, 0.0)) - else - f_min = lambda * max(var_min[1, i - 1, j, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[1, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = min(1, - (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux1[1, i, j, element] + - sign(flux_limited) * eps())) - end - - if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], - coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - alpha_mean[1, i - 1, j, element] += coefficient - alpha_mean[1, i, j, element] += coefficient - end - end - antidiffusive_flux1[1, i, j, element] = flux_limited - - #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll - for v in 2:nvariables(equations) - antidiffusive_flux1[v, i, j, element] = coefficient * - antidiffusive_flux1[v, i, j, - element] - end - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - bar_state_rho = bar_states2[1, i, j, element] - - # Limit density - if antidiffusive_flux2[1, i, j, element] > 0 - f_max = lambda * min(var_max[1, i, j - 1, element] - bar_state_rho, - bar_state_rho - var_min[1, i, j, element]) - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[1, i, j, element], - max(f_max, 0.0)) - else - f_min = lambda * max(var_min[1, i, j - 1, element] - bar_state_rho, - bar_state_rho - var_max[1, i, j, element]) - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[1, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = min(1, - (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux2[1, i, j, element] + - sign(flux_limited) * eps())) - end - - if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], - coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - alpha_mean[1, i, j - 1, element] += coefficient - alpha_mean[1, i, j, element] += coefficient - end - end - antidiffusive_flux2[1, i, j, element] = flux_limited - - #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll - for v in 2:nvariables(equations) - antidiffusive_flux2[v, i, j, element] = coefficient * - antidiffusive_flux2[v, i, j, - element] - end - end - end - end # if limiter.DensityLimiter - - # Sequential limiter - if limiter.SequentialLimiter - for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - bar_state_rho = bar_states1[1, i, j, element] - - # Limit velocity and total energy - rho_limited_iim1 = lambda * bar_state_rho - - antidiffusive_flux1[1, i, j, element] - rho_limited_im1i = lambda * bar_state_rho + - antidiffusive_flux1[1, i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i, j, element] - - phi = bar_state_phi / bar_state_rho - - g = antidiffusive_flux1[v, i, j, element] + - (lambda * bar_state_phi - rho_limited_im1i * phi) - - if g > 0 - g_max = min(rho_limited_im1i * - (var_max[v, i - 1, j, element] - phi), - rho_limited_iim1 * (phi - var_min[v, i, j, element])) - g_max = isapprox(g_max, 0.0, atol = eps()) ? 0.0 : g_max - g_limited = min(g, max(g_max, 0.0)) - else - g_min = max(rho_limited_im1i * - (var_min[v, i - 1, j, element] - phi), - rho_limited_iim1 * (phi - var_max[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min - g_limited = max(g, min(g_min, 0.0)) - end - if limiter.Plotting - if isapprox(g, 0.0, atol = eps()) - coefficient = 1.0 # g_limited is zero as well - else - coefficient = min(1, - (g_limited + sign(g_limited) * eps()) / - (g + sign(g_limited) * eps())) - end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], - coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - alpha_mean[v, i - 1, j, element] += coefficient - alpha_mean[v, i, j, element] += coefficient - end - antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - - lambda * bar_state_phi) + - g_limited - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - bar_state_rho = bar_states2[1, i, j, element] - - # Limit velocity and total energy - rho_limited_jjm1 = lambda * bar_state_rho - - antidiffusive_flux2[1, i, j, element] - rho_limited_jm1j = lambda * bar_state_rho + - antidiffusive_flux2[1, i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j, element] - - phi = bar_state_phi / bar_state_rho - - g = antidiffusive_flux2[v, i, j, element] + - (lambda * bar_state_phi - rho_limited_jm1j * phi) - - if g > 0 - g_max = min(rho_limited_jm1j * - (var_max[v, i, j - 1, element] - phi), - rho_limited_jjm1 * (phi - var_min[v, i, j, element])) - g_max = isapprox(g_max, 0.0, atol = eps()) ? 0.0 : g_max - g_limited = min(g, max(g_max, 0.0)) - else - g_min = max(rho_limited_jm1j * - (var_min[v, i, j - 1, element] - phi), - rho_limited_jjm1 * (phi - var_max[v, i, j, element])) - g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min - g_limited = max(g, min(g_min, 0.0)) - end - if limiter.Plotting - if isapprox(g, 0.0, atol = eps()) - coefficient = 1.0 # g_limited is zero as well - else - coefficient = min(1, - (g_limited + sign(g_limited) * eps()) / - (g + sign(g_limited) * eps())) - end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], - coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - alpha_mean[v, i, j - 1, element] += coefficient - alpha_mean[v, i, j, element] += coefficient - end - - antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - - lambda * bar_state_phi) + - g_limited - end - end - # Conservative limiter - elseif limiter.ConservativeLimiter - for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states1[v, i, j, element] - # Limit density - if antidiffusive_flux1[v, i, j, element] > 0 - f_max = lambda * min(var_max[v, i - 1, j, element] - bar_state_phi, - bar_state_phi - var_min[v, i, j, element]) - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[v, i, j, element], - max(f_max, 0.0)) - else - f_min = lambda * max(var_min[v, i - 1, j, element] - bar_state_phi, - bar_state_phi - var_max[v, i, j, element]) - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[v, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting - if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, - atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = min(1, - (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux1[v, i, j, element] + - sign(flux_limited) * eps())) - end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], - coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - alpha_mean[v, i - 1, j, element] += coefficient - alpha_mean[v, i, j, element] += coefficient - end - antidiffusive_flux1[v, i, j, element] = flux_limited - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - for v in 2:nvariables(equations) - bar_state_phi = bar_states2[v, i, j, element] - # Limit density - if antidiffusive_flux2[v, i, j, element] > 0 - f_max = lambda * min(var_max[v, i, j - 1, element] - bar_state_phi, - bar_state_phi - var_min[v, i, j, element]) - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[v, i, j, element], - max(f_max, 0.0)) - else - f_min = lambda * max(var_min[v, i, j - 1, element] - bar_state_phi, - bar_state_phi - var_max[v, i, j, element]) - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[v, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting - if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, - atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = min(1, - (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux2[v, i, j, element] + - sign(flux_limited) * eps())) - end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], - coefficient) - alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) - alpha_mean[v, i, j - 1, element] += coefficient - alpha_mean[v, i, j, element] += coefficient - end - antidiffusive_flux2[v, i, j, element] = flux_limited - end - end - end # limiter.SequentialLimiter and limiter.ConservativeLimiter - - # Density positivity limiter - if limiter.DensityPositivityLimiter - beta = limiter.DensityPositivityCorrectionFactor - for j in eachnode(dg), i in 2:nnodes(dg) - lambda = lambda1[i, j, element] - bar_state_rho = bar_states1[1, i, j, element] - # Limit density - if antidiffusive_flux1[1, i, j, element] > 0 - f_max = (1 - beta) * lambda * bar_state_rho - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[1, i, j, element], - max(f_max, 0.0)) - else - f_min = -(1 - beta) * lambda * bar_state_rho - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[1, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] - end - - if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], - coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !limiter.DensityLimiter - alpha_mean[1, i - 1, j, element] += coefficient - alpha_mean[1, i, j, element] += coefficient - end - end - end - antidiffusive_flux1[1, i, j, element] = flux_limited - - #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll - for v in 2:nvariables(equations) - antidiffusive_flux1[v, i, j, element] = coefficient * - antidiffusive_flux1[v, i, j, - element] - end - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - lambda = lambda2[i, j, element] - bar_state_rho = bar_states2[1, i, j, element] - # Limit density - if antidiffusive_flux2[1, i, j, element] > 0 - f_max = (1 - beta) * lambda * bar_state_rho - f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[1, i, j, element], - max(f_max, 0.0)) - else - f_min = -(1 - beta) * lambda * bar_state_rho - f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[1, i, j, element], - min(f_min, 0.0)) - end - - if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) - coefficient = 1.0 # flux_limited is zero as well - else - coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] - end - - if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter - alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], - coefficient) - alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !limiter.DensityLimiter - alpha_mean[1, i, j - 1, element] += coefficient - alpha_mean[1, i, j, element] += coefficient - end - end - end - antidiffusive_flux2[1, i, j, element] = flux_limited - - #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll - for v in 2:nvariables(equations) - antidiffusive_flux2[v, i, j, element] = coefficient * - antidiffusive_flux2[v, i, j, - element] - end - end - end - end #if limiter.DensityPositivityLimiter - - # Divide alpha_mean by number of additions - if limiter.Plotting - @unpack alpha_mean = limiter.cache.container_subcell_limiter - # Interfaces contribute with 1.0 - if limiter.DensityLimiter || limiter.DensityPositivityLimiter - for i in eachnode(dg) - alpha_mean[1, i, 1, element] += 1.0 - alpha_mean[1, i, nnodes(dg), element] += 1.0 - alpha_mean[1, 1, i, element] += 1.0 - alpha_mean[1, nnodes(dg), i, element] += 1.0 - end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean[1, i, j, element] /= 4 - end - end - if limiter.SequentialLimiter || limiter.ConservativeLimiter - for v in 2:nvariables(equations) - for i in eachnode(dg) - alpha_mean[v, i, 1, element] += 1.0 - alpha_mean[v, i, nnodes(dg), element] += 1.0 - alpha_mean[v, 1, i, element] += 1.0 - alpha_mean[v, nnodes(dg), i, element] += 1.0 - end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean[v, i, j, element] /= 4 - end - end - end - end - - # Limit pressure à la Kuzmin - if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.container_subcell_limiter - for j in eachnode(dg), i in 2:nnodes(dg) - bar_state_velocity = bar_states1[2, i, j, element]^2 + - bar_states1[3, i, j, element]^2 - flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + - antidiffusive_flux1[3, i, j, element]^2 - - Q = lambda1[i, j, element]^2 * - (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - - 0.5 * bar_state_velocity) - - if limiter.PressurePositivityLimiterKuzminExact - # exact calculation of max(R_ij, R_ji) - R_max = lambda1[i, j, element] * - abs(bar_states1[2, i, j, element] * - antidiffusive_flux1[2, i, j, element] + - bar_states1[3, i, j, element] * - antidiffusive_flux1[3, i, j, element] - - bar_states1[1, i, j, element] * - antidiffusive_flux1[4, i, j, element] - - bar_states1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) - R_max += max(0, - 0.5 * flux_velocity - - antidiffusive_flux1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) - else - # approximation R_max - R_max = lambda1[i, j, element] * - (sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states1[1, i, j, element] * - antidiffusive_flux1[4, i, j, element]) + - abs(bar_states1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element])) - R_max += max(0, - 0.5 * flux_velocity - - antidiffusive_flux1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) - end - alpha = 1 # Initialize alpha for plotting - if R_max > Q - alpha = Q / R_max - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] *= alpha - end - end - if limiter.Plotting - alpha_pressure[i - 1, j, element] = min(alpha_pressure[i - 1, j, - element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], - alpha) - alpha_mean_pressure[i - 1, j, element] += alpha - alpha_mean_pressure[i, j, element] += alpha - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - bar_state_velocity = bar_states2[2, i, j, element]^2 + - bar_states2[3, i, j, element]^2 - flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + - antidiffusive_flux2[3, i, j, element]^2 - - Q = lambda2[i, j, element]^2 * - (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - - 0.5 * bar_state_velocity) - - if limiter.PressurePositivityLimiterKuzminExact - # exact calculation of max(R_ij, R_ji) - R_max = lambda2[i, j, element] * - abs(bar_states2[2, i, j, element] * - antidiffusive_flux2[2, i, j, element] + - bar_states2[3, i, j, element] * - antidiffusive_flux2[3, i, j, element] - - bar_states2[1, i, j, element] * - antidiffusive_flux2[4, i, j, element] - - bar_states2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) - R_max += max(0, - 0.5 * flux_velocity - - antidiffusive_flux2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) - else - # approximation R_max - R_max = lambda2[i, j, element] * - (sqrt(bar_state_velocity * flux_velocity) + - abs(bar_states2[1, i, j, element] * - antidiffusive_flux2[4, i, j, element]) + - abs(bar_states2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element])) - R_max += max(0, - 0.5 * flux_velocity - - antidiffusive_flux2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) - end - alpha = 1 # Initialize alpha for plotting - if R_max > Q - alpha = Q / R_max - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] *= alpha - end - end - if limiter.Plotting - alpha_pressure[i, j - 1, element] = min(alpha_pressure[i, j - 1, - element], alpha) - alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], - alpha) - alpha_mean_pressure[i, j - 1, element] += alpha - alpha_mean_pressure[i, j, element] += alpha - end - end - if limiter.Plotting - @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter - # Interfaces contribute with 1.0 - for i in eachnode(dg) - alpha_mean_pressure[i, 1, element] += 1.0 - alpha_mean_pressure[i, nnodes(dg), element] += 1.0 - alpha_mean_pressure[1, i, element] += 1.0 - alpha_mean_pressure[nnodes(dg), i, element] += 1.0 - end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean_pressure[i, j, element] /= 4 - end - end - end - - # Limit entropy - # TODO: This is a very inefficient function. We compute the entropy four times at each node. - # TODO: For now, this only works for Cartesian meshes. - if limiter.SemiDiscEntropyLimiter - for j in eachnode(dg), i in 2:nnodes(dg) - antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, - i, j, element) - u_local = get_node_vars(u, equations, dg, i, j, element) - u_local_m1 = get_node_vars(u, equations, dg, i - 1, j, element) - - # Using mathematic entropy - v_local = cons2entropy(u_local, equations) - v_local_m1 = cons2entropy(u_local_m1, equations) - - q_local = u_local[2] / u_local[1] * entropy(u_local, equations) - q_local_m1 = u_local_m1[2] / u_local_m1[1] * entropy(u_local_m1, equations) - - f_local = flux(u_local, 1, equations) - f_local_m1 = flux(u_local_m1, 1, equations) - - psi_local = dot(v_local, f_local) - q_local - psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 - - delta_v = v_local - v_local_m1 - delta_psi = psi_local - psi_local_m1 - - entProd_FV = dot(delta_v, fstar1[:, i, j]) - delta_psi - delta_entProd = dot(delta_v, antidiffusive_flux_local) - - alpha = 1 # Initialize alpha for plotting - if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) - alpha = min(1.0, - (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) - for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = alpha * - antidiffusive_flux1[v, i, j, - element] - end - end - if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter - alpha_entropy[i - 1, j, element] = min(alpha_entropy[i - 1, j, element], - alpha) - alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) - alpha_mean_entropy[i - 1, j, element] += alpha - alpha_mean_entropy[i, j, element] += alpha - end - end - - for j in 2:nnodes(dg), i in eachnode(dg) - antidiffusive_flux_local = get_node_vars(antidiffusive_flux2, equations, dg, - i, j, element) - u_local = get_node_vars(u, equations, dg, i, j, element) - u_local_m1 = get_node_vars(u, equations, dg, i, j - 1, element) - - # Using mathematic entropy - v_local = cons2entropy(u_local, equations) - v_local_m1 = cons2entropy(u_local_m1, equations) - - q_local = u_local[3] / u_local[1] * entropy(u_local, equations) - q_local_m1 = u_local_m1[3] / u_local_m1[1] * entropy(u_local_m1, equations) - - f_local = flux(u_local, 2, equations) - f_local_m1 = flux(u_local_m1, 2, equations) - - psi_local = dot(v_local, f_local) - q_local - psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 - - delta_v = v_local - v_local_m1 - delta_psi = psi_local - psi_local_m1 - - entProd_FV = dot(delta_v, fstar2[:, i, j]) - delta_psi - delta_entProd = dot(delta_v, antidiffusive_flux_local) - - alpha = 1 # Initialize alpha for plotting - if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) - alpha = min(1.0, - (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) - for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = alpha * - antidiffusive_flux2[v, i, j, - element] - end - end - if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter - alpha_entropy[i, j - 1, element] = min(alpha_entropy[i, j - 1, element], - alpha) - alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) - alpha_mean_entropy[i, j - 1, element] += alpha - alpha_mean_entropy[i, j, element] += alpha - end - end - if limiter.Plotting - @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter - # Interfaces contribute with 1.0 - for i in eachnode(dg) - alpha_mean_entropy[i, 1, element] += 1.0 - alpha_mean_entropy[i, nnodes(dg), element] += 1.0 - alpha_mean_entropy[1, i, element] += 1.0 - alpha_mean_entropy[nnodes(dg), i, element] += 1.0 - end - for j in eachnode(dg), i in eachnode(dg) - alpha_mean_entropy[i, j, element] /= 4 - end - end - end - - return nothing -end - -@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, - orientation_or_normal, direction, equations, - dg, indices...) - if boundary_condition == boundary_condition_slip_wall #boundary_condition_reflecting_euler_wall - if orientation_or_normal isa AbstractArray - u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], - u_inner[4]) - else # orientation_or_normal isa Integer - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) - end - elseif boundary_condition == boundary_condition_mixed_dirichlet_wall - x = get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) - if x[1] < 1 / 6 # BoundaryConditionCharacteristic - u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, - u_inner, - orientation_or_normal, - direction, x, t, - equations) - - return u_outer - else # x[1] >= 1 / 6 # boundary_condition_slip_wall - if orientation_or_normal isa AbstractArray - u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], - u_inner[4]) - else # orientation_or_normal isa Integer - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) - end - end - end - - return u_inner -end - -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::BoundaryConditionDirichlet, - orientation_or_normal, direction, equations, - dg, indices...) - @unpack node_coordinates = cache.elements - - x = get_node_coords(node_coordinates, equations, dg, indices...) - u_outer = boundary_condition.boundary_value_function(x, t, equations) - - return u_outer -end - -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::BoundaryConditionCharacteristic, - orientation_or_normal, direction, equations, - dg, indices...) - @unpack node_coordinates = cache.elements - - x = get_node_coords(node_coordinates, equations, dg, indices...) - u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, - u_inner, orientation_or_normal, - direction, x, t, equations) - - return u_outer -end - # We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl new file mode 100644 index 0000000000..064a9b86f9 --- /dev/null +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -0,0 +1,1498 @@ +# 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 calc_volume_integral!(du, u, + mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + nonconservative_terms, equations, + volume_integral::VolumeIntegralSubcellLimiting, + dg::DGSEM, cache, t, boundary_conditions) + @unpack limiter = volume_integral + + # Calculate lambdas and bar states + @trixi_timeit timer() "calc_lambdas_bar_states!" calc_lambdas_bar_states!(u, t, + mesh, + nonconservative_terms, + equations, + limiter, + dg, cache, + boundary_conditions) + # Calculate boundaries + @trixi_timeit timer() "calc_variable_bounds!" calc_variable_bounds!(u, mesh, + nonconservative_terms, + equations, + limiter, dg, + cache) + + if limiter.smoothness_indicator + @unpack element_ids_dg, element_ids_dgfv = cache + # Calculate element-wise blending factors α + alpha_element = @trixi_timeit timer() "element-wise blending factors" limiter.IndicatorHG(u, + mesh, + equations, + dg, + cache) + + # Determine element ids for DG-only and subcell-wise blended DG-FV volume integral + pure_and_blended_element_ids!(element_ids_dg, element_ids_dgfv, alpha_element, + dg, cache) + + # Loop over pure DG elements + @trixi_timeit timer() "pure DG" @threaded for idx_element in eachindex(element_ids_dg) + element = element_ids_dg[idx_element] + flux_differencing_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral.volume_flux_dg, dg, cache) + end + + # Loop over blended DG-FV elements + @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for idx_element in eachindex(element_ids_dgfv) + element = element_ids_dgfv[idx_element] + subcell_limiting_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, limiter, + dg, cache) + end + else # limiter.smoothness_indicator == false + # Loop over all elements + @trixi_timeit timer() "subcell-wise blended DG-FV" @threaded for element in eachelement(dg, + cache) + subcell_limiting_kernel!(du, u, element, mesh, + nonconservative_terms, equations, + volume_integral, limiter, + dg, cache) + end + end +end + +@inline function subcell_limiting_kernel!(du, u, + element, + mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + nonconservative_terms::False, equations, + volume_integral, limiter::SubcellLimiterIDP, + dg::DGSEM, cache) + @unpack inverse_weights = dg.basis + @unpack volume_flux_dg, volume_flux_fv = volume_integral + + # high-order DG fluxes + @unpack fhat1_threaded, fhat2_threaded = cache + + fhat1 = fhat1_threaded[Threads.threadid()] + fhat2 = fhat2_threaded[Threads.threadid()] + calcflux_fhat!(fhat1, fhat2, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + + # low-order FV fluxes + @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache + + fstar1_L = fstar1_L_threaded[Threads.threadid()] + fstar2_L = fstar2_L_threaded[Threads.threadid()] + fstar1_R = fstar1_R_threaded[Threads.threadid()] + fstar2_R = fstar2_R_threaded[Threads.threadid()] + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + + # antidiffusive flux + calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + nonconservative_terms, equations, limiter, dg, element, + cache) + + # Calculate volume integral contribution of low-order FV flux + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + du[v, i, j, element] += inverse_weights[i] * + (fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * + (fstar2_L[v, i, j + 1] - fstar2_R[v, i, j]) + end + end + + return nothing +end + +@inline function subcell_limiting_kernel!(du, u, + element, + mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + nonconservative_terms::False, equations, + volume_integral, limiter::SubcellLimiterMCL, + dg::DGSEM, cache) + @unpack inverse_weights = dg.basis + @unpack volume_flux_dg, volume_flux_fv = volume_integral + + # high-order DG fluxes + @unpack fhat1_threaded, fhat2_threaded = cache + fhat1 = fhat1_threaded[Threads.threadid()] + fhat2 = fhat2_threaded[Threads.threadid()] + calcflux_fhat!(fhat1, fhat2, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + + # low-order FV fluxes + @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache + fstar1_L = fstar1_L_threaded[Threads.threadid()] + fstar2_L = fstar2_L_threaded[Threads.threadid()] + fstar1_R = fstar1_R_threaded[Threads.threadid()] + fstar2_R = fstar2_R_threaded[Threads.threadid()] + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + + # antidiffusive flux + calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) + + # limit antidiffusive flux + calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, + limiter, dg, element, cache, + fstar1_L, fstar2_L) + + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + du[v, i, j, element] += inverse_weights[i] * + (fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) + + inverse_weights[j] * + (fstar2_L[v, i, j + 1] - fstar2_R[v, i, j]) + + du[v, i, j, element] += inverse_weights[i] * + (-antidiffusive_flux1[v, i + 1, j, element] + + antidiffusive_flux1[v, i, j, element]) + + inverse_weights[j] * + (-antidiffusive_flux2[v, i, j + 1, element] + + antidiffusive_flux2[v, i, j, element]) + end + end + + return nothing +end + +# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element +# (**without non-conservative terms**). +# +# See also `flux_differencing_kernel!`. +@inline function calcflux_fhat!(fhat1, fhat2, u, + mesh::TreeMesh{2}, nonconservative_terms::False, + equations, + volume_flux, dg::DGSEM, element, cache) + @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded = cache + + flux_temp = flux_temp_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fhat_(0,1) = w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of the `volume_flux` to save half of the possible two-point flux + # computations. + for ii in (i + 1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + flux1 = volume_flux(u_node, u_node_ii, 1, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, + equations, dg, ii, j) + end + end + + # FV-form flux `fhat` in x direction + fhat1[:, 1, :] .= zero(eltype(fhat1)) + fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) + + for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) + fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + end + + # Split form volume flux in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + for jj in (j + 1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + flux2 = volume_flux(u_node, u_node_jj, 2, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, + equations, dg, i, jj) + end + end + + # FV-form flux `fhat` in y direction + fhat2[:, :, 1] .= zero(eltype(fhat2)) + fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) + + for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) + fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + end + + return nothing +end + +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. +@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, + limiter::SubcellLimiterIDP, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] + end + end + + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) + + return nothing +end + +@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, + nonconservative_terms, equations, + limiter::SubcellLimiterMCL, dg, element, cache) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] = -(fhat1[v, i, j] - fstar1[v, i, j]) + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] = -(fhat2[v, i, j] - fstar2[v, i, j]) + end + end + + antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) + + antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) + + return nothing +end + +@inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, + nonconservative_terms, equations, limiter, + dg, cache, boundary_conditions; + calc_bar_states = true) + if limiter isa SubcellLimiterIDP && !limiter.bar_states + return nothing + end + @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states + + # Calc lambdas and bar states inside elements + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in 2:nnodes(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_im1 = get_node_vars(u, equations, dg, i - 1, j, element) + lambda1[i, j, element] = max_abs_speed_naive(u_node_im1, u_node, 1, + equations) + + !calc_bar_states && continue + + flux1 = flux(u_node, 1, equations) + flux1_im1 = flux(u_node_im1, 1, equations) + for v in eachvariable(equations) + bar_states1[v, i, j, element] = 0.5 * (u_node[v] + u_node_im1[v]) - + 0.5 * (flux1[v] - flux1_im1[v]) / + lambda1[i, j, element] + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + u_node_jm1 = get_node_vars(u, equations, dg, i, j - 1, element) + lambda2[i, j, element] = max_abs_speed_naive(u_node_jm1, u_node, 2, + equations) + + !calc_bar_states && continue + + flux2 = flux(u_node, 2, equations) + flux2_jm1 = flux(u_node_jm1, 2, equations) + for v in eachvariable(equations) + bar_states2[v, i, j, element] = 0.5 * (u_node[v] + u_node_jm1[v]) - + 0.5 * (flux2[v] - flux2_jm1[v]) / + lambda2[i, j, element] + end + end + end + + # Calc lambdas and bar states at interfaces and periodic boundaries + @threaded for interface in eachinterface(dg, cache) + # Get neighboring element ids + left_id = cache.interfaces.neighbor_ids[1, interface] + right_id = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + if orientation == 1 + for j in eachnode(dg) + u_left = get_node_vars(u, equations, dg, nnodes(dg), j, left_id) + u_right = get_node_vars(u, equations, dg, 1, j, right_id) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda1[nnodes(dg) + 1, j, left_id] = lambda + lambda1[1, j, right_id] = lambda + + !calc_bar_states && continue + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + bar_state = 0.5 * (u_left + u_right) - + 0.5 * (flux_right - flux_left) / lambda + for v in eachvariable(equations) + bar_states1[v, nnodes(dg) + 1, j, left_id] = bar_state[v] + bar_states1[v, 1, j, right_id] = bar_state[v] + end + end + else # orientation == 2 + for i in eachnode(dg) + u_left = get_node_vars(u, equations, dg, i, nnodes(dg), left_id) + u_right = get_node_vars(u, equations, dg, i, 1, right_id) + lambda = max_abs_speed_naive(u_left, u_right, orientation, equations) + + lambda2[i, nnodes(dg) + 1, left_id] = lambda + lambda2[i, 1, right_id] = lambda + + !calc_bar_states && continue + + flux_left = flux(u_left, orientation, equations) + flux_right = flux(u_right, orientation, equations) + bar_state = 0.5 * (u_left + u_right) - + 0.5 * (flux_right - flux_left) / lambda + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg) + 1, left_id] = bar_state[v] + bar_states2[v, i, 1, right_id] = bar_state[v] + end + end + end + end + + # Calc lambdas and bar states at physical boundaries + @threaded for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[1], + orientation, 1, + equations, dg, 1, j, element) + lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, + orientation, equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + bar_state = 0.5 * (u_inner + u_outer) - + 0.5 * (flux_inner - flux_outer) / lambda1[1, j, element] + for v in eachvariable(equations) + bar_states1[v, 1, j, element] = bar_state[v] + end + end + else # Element is on the left, boundary on the right + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[2], + orientation, 2, + equations, dg, nnodes(dg), j, + element) + lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, + u_outer, + orientation, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + bar_state = 0.5 * (u_inner + u_outer) - + 0.5 * (flux_outer - flux_inner) / + lambda1[nnodes(dg) + 1, j, element] + for v in eachvariable(equations) + bar_states1[v, nnodes(dg) + 1, j, element] = bar_state[v] + end + end + end + else # orientation == 2 + if neighbor_side == 2 # Element is on the right, boundary on the left + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[3], + orientation, 3, + equations, dg, i, 1, element) + lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, + orientation, equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + bar_state = 0.5 * (u_inner + u_outer) - + 0.5 * (flux_inner - flux_outer) / lambda2[i, 1, element] + for v in eachvariable(equations) + bar_states2[v, i, 1, element] = bar_state[v] + end + end + else # Element is on the left, boundary on the right + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[4], + orientation, 4, + equations, dg, i, nnodes(dg), + element) + lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, + u_outer, + orientation, + equations) + + !calc_bar_states && continue + + flux_inner = flux(u_inner, orientation, equations) + flux_outer = flux(u_outer, orientation, equations) + bar_state = 0.5 * (u_inner + u_outer) - + 0.5 * (flux_outer - flux_inner) / + lambda2[i, nnodes(dg) + 1, element] + for v in eachvariable(equations) + bar_states2[v, i, nnodes(dg) + 1, element] = bar_state[v] + end + end + end + end + end + + return nothing +end + +@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, + limiter::SubcellLimiterIDP, dg, cache) + if !limiter.bar_states + return nothing + end + @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states + + counter = 1 + # state variables + if limiter.local_minmax + for index in limiter.local_minmax_variables_cons + var_min = variable_bounds[counter] + var_max = variable_bounds[counter + 1] + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + for j in eachnode(dg), i in eachnode(dg) + var_min[i, j, element] = min(var_min[i, j, element], + u[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], + u[index, i, j, element]) + # TODO: Add source term! + # - xi direction + var_min[i, j, element] = min(var_min[i, j, element], + bar_states1[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], + bar_states1[index, i, j, element]) + # + xi direction + var_min[i, j, element] = min(var_min[i, j, element], + bar_states1[index, i + 1, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], + bar_states1[index, i + 1, j, element]) + # - eta direction + var_min[i, j, element] = min(var_min[i, j, element], + bar_states2[index, i, j, element]) + var_max[i, j, element] = max(var_max[i, j, element], + bar_states2[index, i, j, element]) + # + eta direction + var_min[i, j, element] = min(var_min[i, j, element], + bar_states2[index, i, j + 1, element]) + var_max[i, j, element] = max(var_max[i, j, element], + bar_states2[index, i, j + 1, element]) + end + end + counter += 2 + end + end + # Specific Entropy + if limiter.spec_entropy + s_min = variable_bounds[counter] + @threaded for element in eachelement(dg, cache) + s_min[:, :, element] .= typemax(eltype(s_min)) + for j in eachnode(dg), i in eachnode(dg) + s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), + equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # TODO: Add source? + # - xi direction + s = entropy_spec(get_node_vars(bar_states1, equations, dg, i, j, + element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # + xi direction + s = entropy_spec(get_node_vars(bar_states1, equations, dg, i + 1, j, + element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # - eta direction + s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j, + element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + # + eta direction + s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j + 1, + element), equations) + s_min[i, j, element] = min(s_min[i, j, element], s) + end + end + counter += 1 + end + # Mathematical entropy + if limiter.math_entropy + s_max = variable_bounds[counter] + @threaded for element in eachelement(dg, cache) + s_max[:, :, element] .= typemin(eltype(s_max)) + for j in eachnode(dg), i in eachnode(dg) + s = entropy_math(get_node_vars(u, equations, dg, i, j, element), + equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # - xi direction + s = entropy_math(get_node_vars(bar_states1, equations, dg, i, j, + element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # + xi direction + s = entropy_math(get_node_vars(bar_states1, equations, dg, i + 1, j, + element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # - eta direction + s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j, + element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + # + eta direction + s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j + 1, + element), equations) + s_max[i, j, element] = max(s_max[i, j, element], s) + end + end + end + + return nothing +end + +@inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, + limiter::SubcellLimiterMCL, dg, cache) + @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states + + @threaded for element in eachelement(dg, cache) + for v in eachvariable(equations) + var_min[v, :, :, element] .= typemax(eltype(var_min)) + var_max[v, :, :, element] .= typemin(eltype(var_max)) + end + + if limiter.DensityLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + var_min[1, i, j, element] = min(var_min[1, i, j, element], + u[1, i, j, element]) + var_max[1, i, j, element] = max(var_max[1, i, j, element], + u[1, i, j, element]) + # - xi direction + bar_state_rho = bar_states1[1, i, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], + bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], + bar_state_rho) + # + xi direction + bar_state_rho = bar_states1[1, i + 1, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], + bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], + bar_state_rho) + # - eta direction + bar_state_rho = bar_states2[1, i, j, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], + bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], + bar_state_rho) + # + eta direction + bar_state_rho = bar_states2[1, i, j + 1, element] + var_min[1, i, j, element] = min(var_min[1, i, j, element], + bar_state_rho) + var_max[1, i, j, element] = max(var_max[1, i, j, element], + bar_state_rho) + end + end #limiter.DensityLimiter + + if limiter.SequentialLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + for v in 2:nvariables(equations) + phi = u[v, i, j, element] / u[1, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], phi) + end + # - xi direction + bar_state_rho = bar_states1[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_phi) + end + # + xi direction + bar_state_rho = bar_states1[1, i + 1, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i + 1, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_phi) + end + # - eta direction + bar_state_rho = bar_states2[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_phi) + end + # + eta direction + bar_state_rho = bar_states2[1, i, j + 1, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j + 1, element] / bar_state_rho + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_phi) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_phi) + end + end + elseif limiter.ConservativeLimiter + for j in eachnode(dg), i in eachnode(dg) + # Previous solution + for v in 2:nvariables(equations) + var_min[v, i, j, element] = min(var_min[v, i, j, element], + u[v, i, j, element]) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + u[v, i, j, element]) + end + # - xi direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states1[v, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_rho) + end + # + xi direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states1[v, i + 1, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_rho) + end + # - eta direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states2[v, i, j, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_rho) + end + # + eta direction + for v in 2:nvariables(equations) + bar_state_rho = bar_states2[v, i, j + 1, element] + var_min[v, i, j, element] = min(var_min[v, i, j, element], + bar_state_rho) + var_max[v, i, j, element] = max(var_max[v, i, j, element], + bar_state_rho) + end + end + end + end + + return nothing +end + +@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, + equations, limiter, dg, element, + cache, + fstar1, fstar2) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states + + if limiter.Plotting + @unpack alpha, alpha_pressure, alpha_entropy, + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) + alpha[:, i, j, element] .= one(eltype(alpha)) + if limiter.PressurePositivityLimiterKuzmin + alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) + alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) + end + if limiter.SemiDiscEntropyLimiter + alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) + alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) + end + end + end + + # The antidiffuse flux can have very small absolute values. This can lead to values of f_min which are zero up to machine accuracy. + # To avoid further calculations with these values, we replace them by 0. + # It can also happen that the limited flux changes its sign (for instance to -1e-13). + # This does not really make sense in theory and causes problems for the visualization. + # Therefore we make sure that the flux keeps its sign during limiting. + + # Density limiter + if limiter.DensityLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] + + # Limit density + if antidiffusive_flux1[1, i, j, element] > 0 + f_max = lambda * min(var_max[1, i - 1, j, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[1, i, j, element], + max(f_max, 0.0)) + else + f_min = lambda * max(var_min[1, i - 1, j, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[1, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting || limiter.DensityAlphaForAll + if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = min(1, + (flux_limited + sign(flux_limited) * eps()) / + (antidiffusive_flux1[1, i, j, element] + + sign(flux_limited) * eps())) + end + + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], + coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + alpha_mean[1, i - 1, j, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end + end + antidiffusive_flux1[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if limiter.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux1[v, i, j, element] = coefficient * + antidiffusive_flux1[v, i, j, + element] + end + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] + + # Limit density + if antidiffusive_flux2[1, i, j, element] > 0 + f_max = lambda * min(var_max[1, i, j - 1, element] - bar_state_rho, + bar_state_rho - var_min[1, i, j, element]) + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[1, i, j, element], + max(f_max, 0.0)) + else + f_min = lambda * max(var_min[1, i, j - 1, element] - bar_state_rho, + bar_state_rho - var_max[1, i, j, element]) + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[1, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting || limiter.DensityAlphaForAll + if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = min(1, + (flux_limited + sign(flux_limited) * eps()) / + (antidiffusive_flux2[1, i, j, element] + + sign(flux_limited) * eps())) + end + + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], + coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + alpha_mean[1, i, j - 1, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end + end + antidiffusive_flux2[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if limiter.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux2[v, i, j, element] = coefficient * + antidiffusive_flux2[v, i, j, + element] + end + end + end + end # if limiter.DensityLimiter + + # Sequential limiter + if limiter.SequentialLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] + + # Limit velocity and total energy + rho_limited_iim1 = lambda * bar_state_rho - + antidiffusive_flux1[1, i, j, element] + rho_limited_im1i = lambda * bar_state_rho + + antidiffusive_flux1[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i, j, element] + + phi = bar_state_phi / bar_state_rho + + g = antidiffusive_flux1[v, i, j, element] + + (lambda * bar_state_phi - rho_limited_im1i * phi) + + if g > 0 + g_max = min(rho_limited_im1i * + (var_max[v, i - 1, j, element] - phi), + rho_limited_iim1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol = eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) + else + g_min = max(rho_limited_im1i * + (var_min[v, i - 1, j, element] - phi), + rho_limited_iim1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min + g_limited = max(g, min(g_min, 0.0)) + end + if limiter.Plotting + if isapprox(g, 0.0, atol = eps()) + coefficient = 1.0 # g_limited is zero as well + else + coefficient = min(1, + (g_limited + sign(g_limited) * eps()) / + (g + sign(g_limited) * eps())) + end + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], + coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i - 1, j, element] += coefficient + alpha_mean[v, i, j, element] += coefficient + end + antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - + lambda * bar_state_phi) + + g_limited + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] + + # Limit velocity and total energy + rho_limited_jjm1 = lambda * bar_state_rho - + antidiffusive_flux2[1, i, j, element] + rho_limited_jm1j = lambda * bar_state_rho + + antidiffusive_flux2[1, i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] + + phi = bar_state_phi / bar_state_rho + + g = antidiffusive_flux2[v, i, j, element] + + (lambda * bar_state_phi - rho_limited_jm1j * phi) + + if g > 0 + g_max = min(rho_limited_jm1j * + (var_max[v, i, j - 1, element] - phi), + rho_limited_jjm1 * (phi - var_min[v, i, j, element])) + g_max = isapprox(g_max, 0.0, atol = eps()) ? 0.0 : g_max + g_limited = min(g, max(g_max, 0.0)) + else + g_min = max(rho_limited_jm1j * + (var_min[v, i, j - 1, element] - phi), + rho_limited_jjm1 * (phi - var_max[v, i, j, element])) + g_min = isapprox(g_min, 0.0, atol = eps()) ? 0.0 : g_min + g_limited = max(g, min(g_min, 0.0)) + end + if limiter.Plotting + if isapprox(g, 0.0, atol = eps()) + coefficient = 1.0 # g_limited is zero as well + else + coefficient = min(1, + (g_limited + sign(g_limited) * eps()) / + (g + sign(g_limited) * eps())) + end + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], + coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i, j - 1, element] += coefficient + alpha_mean[v, i, j, element] += coefficient + end + + antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - + lambda * bar_state_phi) + + g_limited + end + end + # Conservative limiter + elseif limiter.ConservativeLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states1[v, i, j, element] + # Limit density + if antidiffusive_flux1[v, i, j, element] > 0 + f_max = lambda * min(var_max[v, i - 1, j, element] - bar_state_phi, + bar_state_phi - var_min[v, i, j, element]) + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[v, i, j, element], + max(f_max, 0.0)) + else + f_min = lambda * max(var_min[v, i - 1, j, element] - bar_state_phi, + bar_state_phi - var_max[v, i, j, element]) + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[v, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting + if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, + atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = min(1, + (flux_limited + sign(flux_limited) * eps()) / + (antidiffusive_flux1[v, i, j, element] + + sign(flux_limited) * eps())) + end + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], + coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i - 1, j, element] += coefficient + alpha_mean[v, i, j, element] += coefficient + end + antidiffusive_flux1[v, i, j, element] = flux_limited + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + for v in 2:nvariables(equations) + bar_state_phi = bar_states2[v, i, j, element] + # Limit density + if antidiffusive_flux2[v, i, j, element] > 0 + f_max = lambda * min(var_max[v, i, j - 1, element] - bar_state_phi, + bar_state_phi - var_min[v, i, j, element]) + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[v, i, j, element], + max(f_max, 0.0)) + else + f_min = lambda * max(var_min[v, i, j - 1, element] - bar_state_phi, + bar_state_phi - var_max[v, i, j, element]) + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[v, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting + if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, + atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = min(1, + (flux_limited + sign(flux_limited) * eps()) / + (antidiffusive_flux2[v, i, j, element] + + sign(flux_limited) * eps())) + end + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], + coefficient) + alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) + alpha_mean[v, i, j - 1, element] += coefficient + alpha_mean[v, i, j, element] += coefficient + end + antidiffusive_flux2[v, i, j, element] = flux_limited + end + end + end # limiter.SequentialLimiter and limiter.ConservativeLimiter + + # Density positivity limiter + if limiter.DensityPositivityLimiter + beta = limiter.DensityPositivityCorrectionFactor + for j in eachnode(dg), i in 2:nnodes(dg) + lambda = lambda1[i, j, element] + bar_state_rho = bar_states1[1, i, j, element] + # Limit density + if antidiffusive_flux1[1, i, j, element] > 0 + f_max = (1 - beta) * lambda * bar_state_rho + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux1[1, i, j, element], + max(f_max, 0.0)) + else + f_min = -(1 - beta) * lambda * bar_state_rho + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux1[1, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting || limiter.DensityAlphaForAll + if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + end + + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], + coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + if !limiter.DensityLimiter + alpha_mean[1, i - 1, j, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end + end + end + antidiffusive_flux1[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if limiter.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux1[v, i, j, element] = coefficient * + antidiffusive_flux1[v, i, j, + element] + end + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + lambda = lambda2[i, j, element] + bar_state_rho = bar_states2[1, i, j, element] + # Limit density + if antidiffusive_flux2[1, i, j, element] > 0 + f_max = (1 - beta) * lambda * bar_state_rho + f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max + flux_limited = min(antidiffusive_flux2[1, i, j, element], + max(f_max, 0.0)) + else + f_min = -(1 - beta) * lambda * bar_state_rho + f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min + flux_limited = max(antidiffusive_flux2[1, i, j, element], + min(f_min, 0.0)) + end + + if limiter.Plotting || limiter.DensityAlphaForAll + if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) + coefficient = 1.0 # flux_limited is zero as well + else + coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + end + + if limiter.Plotting + @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], + coefficient) + alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) + if !limiter.DensityLimiter + alpha_mean[1, i, j - 1, element] += coefficient + alpha_mean[1, i, j, element] += coefficient + end + end + end + antidiffusive_flux2[1, i, j, element] = flux_limited + + #Limit all quantities with the same alpha + if limiter.DensityAlphaForAll + for v in 2:nvariables(equations) + antidiffusive_flux2[v, i, j, element] = coefficient * + antidiffusive_flux2[v, i, j, + element] + end + end + end + end #if limiter.DensityPositivityLimiter + + # Divide alpha_mean by number of additions + if limiter.Plotting + @unpack alpha_mean = limiter.cache.container_subcell_limiter + # Interfaces contribute with 1.0 + if limiter.DensityLimiter || limiter.DensityPositivityLimiter + for i in eachnode(dg) + alpha_mean[1, i, 1, element] += 1.0 + alpha_mean[1, i, nnodes(dg), element] += 1.0 + alpha_mean[1, 1, i, element] += 1.0 + alpha_mean[1, nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[1, i, j, element] /= 4 + end + end + if limiter.SequentialLimiter || limiter.ConservativeLimiter + for v in 2:nvariables(equations) + for i in eachnode(dg) + alpha_mean[v, i, 1, element] += 1.0 + alpha_mean[v, i, nnodes(dg), element] += 1.0 + alpha_mean[v, 1, i, element] += 1.0 + alpha_mean[v, nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean[v, i, j, element] /= 4 + end + end + end + end + + # Limit pressure à la Kuzmin + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.container_subcell_limiter + for j in eachnode(dg), i in 2:nnodes(dg) + bar_state_velocity = bar_states1[2, i, j, element]^2 + + bar_states1[3, i, j, element]^2 + flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + + antidiffusive_flux1[3, i, j, element]^2 + + Q = lambda1[i, j, element]^2 * + (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - + 0.5 * bar_state_velocity) + + if limiter.PressurePositivityLimiterKuzminExact + # exact calculation of max(R_ij, R_ji) + R_max = lambda1[i, j, element] * + abs(bar_states1[2, i, j, element] * + antidiffusive_flux1[2, i, j, element] + + bar_states1[3, i, j, element] * + antidiffusive_flux1[3, i, j, element] - + bar_states1[1, i, j, element] * + antidiffusive_flux1[4, i, j, element] - + bar_states1[4, i, j, element] * + antidiffusive_flux1[1, i, j, element]) + R_max += max(0, + 0.5 * flux_velocity - + antidiffusive_flux1[4, i, j, element] * + antidiffusive_flux1[1, i, j, element]) + else + # approximation R_max + R_max = lambda1[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states1[1, i, j, element] * + antidiffusive_flux1[4, i, j, element]) + + abs(bar_states1[4, i, j, element] * + antidiffusive_flux1[1, i, j, element])) + R_max += max(0, + 0.5 * flux_velocity - + antidiffusive_flux1[4, i, j, element] * + antidiffusive_flux1[1, i, j, element]) + end + alpha = 1 # Initialize alpha for plotting + if R_max > Q + alpha = Q / R_max + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] *= alpha + end + end + if limiter.Plotting + alpha_pressure[i - 1, j, element] = min(alpha_pressure[i - 1, j, + element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], + alpha) + alpha_mean_pressure[i - 1, j, element] += alpha + alpha_mean_pressure[i, j, element] += alpha + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + bar_state_velocity = bar_states2[2, i, j, element]^2 + + bar_states2[3, i, j, element]^2 + flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + + antidiffusive_flux2[3, i, j, element]^2 + + Q = lambda2[i, j, element]^2 * + (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - + 0.5 * bar_state_velocity) + + if limiter.PressurePositivityLimiterKuzminExact + # exact calculation of max(R_ij, R_ji) + R_max = lambda2[i, j, element] * + abs(bar_states2[2, i, j, element] * + antidiffusive_flux2[2, i, j, element] + + bar_states2[3, i, j, element] * + antidiffusive_flux2[3, i, j, element] - + bar_states2[1, i, j, element] * + antidiffusive_flux2[4, i, j, element] - + bar_states2[4, i, j, element] * + antidiffusive_flux2[1, i, j, element]) + R_max += max(0, + 0.5 * flux_velocity - + antidiffusive_flux2[4, i, j, element] * + antidiffusive_flux2[1, i, j, element]) + else + # approximation R_max + R_max = lambda2[i, j, element] * + (sqrt(bar_state_velocity * flux_velocity) + + abs(bar_states2[1, i, j, element] * + antidiffusive_flux2[4, i, j, element]) + + abs(bar_states2[4, i, j, element] * + antidiffusive_flux2[1, i, j, element])) + R_max += max(0, + 0.5 * flux_velocity - + antidiffusive_flux2[4, i, j, element] * + antidiffusive_flux2[1, i, j, element]) + end + alpha = 1 # Initialize alpha for plotting + if R_max > Q + alpha = Q / R_max + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] *= alpha + end + end + if limiter.Plotting + alpha_pressure[i, j - 1, element] = min(alpha_pressure[i, j - 1, + element], alpha) + alpha_pressure[i, j, element] = min(alpha_pressure[i, j, element], + alpha) + alpha_mean_pressure[i, j - 1, element] += alpha + alpha_mean_pressure[i, j, element] += alpha + end + end + if limiter.Plotting + @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean_pressure[i, 1, element] += 1.0 + alpha_mean_pressure[i, nnodes(dg), element] += 1.0 + alpha_mean_pressure[1, i, element] += 1.0 + alpha_mean_pressure[nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean_pressure[i, j, element] /= 4 + end + end + end + + # Limit entropy + # TODO: This is a very inefficient function. We compute the entropy four times at each node. + # TODO: For now, this only works for Cartesian meshes. + if limiter.SemiDiscEntropyLimiter + for j in eachnode(dg), i in 2:nnodes(dg) + antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, + i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) + u_local_m1 = get_node_vars(u, equations, dg, i - 1, j, element) + + # Using mathematic entropy + v_local = cons2entropy(u_local, equations) + v_local_m1 = cons2entropy(u_local_m1, equations) + + q_local = u_local[2] / u_local[1] * entropy(u_local, equations) + q_local_m1 = u_local_m1[2] / u_local_m1[1] * entropy(u_local_m1, equations) + + f_local = flux(u_local, 1, equations) + f_local_m1 = flux(u_local_m1, 1, equations) + + psi_local = dot(v_local, f_local) - q_local + psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 + + delta_v = v_local - v_local_m1 + delta_psi = psi_local - psi_local_m1 + + entProd_FV = dot(delta_v, fstar1[:, i, j]) - delta_psi + delta_entProd = dot(delta_v, antidiffusive_flux_local) + + alpha = 1 # Initialize alpha for plotting + if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) + alpha = min(1.0, + (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) + for v in eachvariable(equations) + antidiffusive_flux1[v, i, j, element] = alpha * + antidiffusive_flux1[v, i, j, + element] + end + end + if limiter.Plotting + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_entropy[i - 1, j, element] = min(alpha_entropy[i - 1, j, element], + alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i - 1, j, element] += alpha + alpha_mean_entropy[i, j, element] += alpha + end + end + + for j in 2:nnodes(dg), i in eachnode(dg) + antidiffusive_flux_local = get_node_vars(antidiffusive_flux2, equations, dg, + i, j, element) + u_local = get_node_vars(u, equations, dg, i, j, element) + u_local_m1 = get_node_vars(u, equations, dg, i, j - 1, element) + + # Using mathematic entropy + v_local = cons2entropy(u_local, equations) + v_local_m1 = cons2entropy(u_local_m1, equations) + + q_local = u_local[3] / u_local[1] * entropy(u_local, equations) + q_local_m1 = u_local_m1[3] / u_local_m1[1] * entropy(u_local_m1, equations) + + f_local = flux(u_local, 2, equations) + f_local_m1 = flux(u_local_m1, 2, equations) + + psi_local = dot(v_local, f_local) - q_local + psi_local_m1 = dot(v_local_m1, f_local_m1) - q_local_m1 + + delta_v = v_local - v_local_m1 + delta_psi = psi_local - psi_local_m1 + + entProd_FV = dot(delta_v, fstar2[:, i, j]) - delta_psi + delta_entProd = dot(delta_v, antidiffusive_flux_local) + + alpha = 1 # Initialize alpha for plotting + if (entProd_FV + delta_entProd > 0.0) && (delta_entProd != 0.0) + alpha = min(1.0, + (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) + for v in eachvariable(equations) + antidiffusive_flux2[v, i, j, element] = alpha * + antidiffusive_flux2[v, i, j, + element] + end + end + if limiter.Plotting + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_entropy[i, j - 1, element] = min(alpha_entropy[i, j - 1, element], + alpha) + alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) + alpha_mean_entropy[i, j - 1, element] += alpha + alpha_mean_entropy[i, j, element] += alpha + end + end + if limiter.Plotting + @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter + # Interfaces contribute with 1.0 + for i in eachnode(dg) + alpha_mean_entropy[i, 1, element] += 1.0 + alpha_mean_entropy[i, nnodes(dg), element] += 1.0 + alpha_mean_entropy[1, i, element] += 1.0 + alpha_mean_entropy[nnodes(dg), i, element] += 1.0 + end + for j in eachnode(dg), i in eachnode(dg) + alpha_mean_entropy[i, j, element] /= 4 + end + end + end + + return nothing +end + +@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, + orientation_or_normal, direction, equations, + dg, indices...) + if boundary_condition == boundary_condition_slip_wall #boundary_condition_reflecting_euler_wall + if orientation_or_normal isa AbstractArray + u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + else # orientation_or_normal isa Integer + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) + end + elseif boundary_condition == boundary_condition_mixed_dirichlet_wall + x = get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + orientation_or_normal, + direction, x, t, + equations) + + return u_outer + else # x[1] >= 1 / 6 # boundary_condition_slip_wall + if orientation_or_normal isa AbstractArray + u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + else # orientation_or_normal isa Integer + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) + end + end + end + + return u_inner +end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::BoundaryConditionDirichlet, + orientation_or_normal, direction, equations, + dg, indices...) + @unpack node_coordinates = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(x, t, equations) + + return u_outer +end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::BoundaryConditionCharacteristic, + orientation_or_normal, direction, equations, + dg, indices...) + @unpack node_coordinates = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, orientation_or_normal, + direction, x, t, equations) + + return u_outer +end +end # @muladd diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 51d0f6a6f2..2eb0af8714 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -215,431 +215,6 @@ const IndicatorLoehner = IndicatorLöhner return num / den end -abstract type AbstractSubcellLimiter end - -function create_cache(typ::Type{LimiterType}, - semi) where {LimiterType <: AbstractSubcellLimiter} - create_cache(typ, mesh_equations_solver_cache(semi)...) -end - -function get_element_variables!(element_variables, limiter::AbstractSubcellLimiter, - ::VolumeIntegralSubcellLimiting) - element_variables[:smooth_indicator_elementwise] = limiter.IndicatorHG.cache.alpha - return nothing -end - -""" - SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], - positivity_variables_nonlinear = (), - positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, - bar_states = true, - max_iterations_newton = 10, - newton_tolerances = (1.0e-12, 1.0e-14), - gamma_constant_newton = 2 * ndims(equations), - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure) - -Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) -including: -- maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) -- positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) -- one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) - -The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity -limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. -The Newton-bisection method for the limiting of non-linear variables uses maximal `max_iterations_newton` -iterations, tolerances `newton_tolerances` and the gamma constant `gamma_constant_newton` -(gamma_constant_newton>=2*d, where d=#dimensions). - -A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with -`variable_smoothness_indicator`, which disables subcell blending for element-wise -indicator values <= `threshold_smoothness_indicator`. - -!!! note - This limiter and the correction callback [`SubcellLimiterIDPCorrection`](@ref) only work together. - Without the callback, no limiting takes place, leading to a standard flux-differencing DGSEM scheme. - -## References - -- Rueda-Ramírez, Pazner, Gassner (2022) - Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods - [DOI: 10.1016/j.compfluid.2022.105627](https://doi.org/10.1016/j.compfluid.2022.105627) -- Pazner (2020) - Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting - [DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876) - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. -""" -struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, - Cache, Indicator} <: AbstractSubcellLimiter - local_minmax::Bool - local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables - positivity::Bool - positivity_variables_cons::Vector{Int} # Positivity for conservative variables - positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables - positivity_correction_factor::RealT - spec_entropy::Bool - math_entropy::Bool - bar_states::Bool - cache::Cache - max_iterations_newton::Int - newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method - gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints - smoothness_indicator::Bool - threshold_smoothness_indicator::RealT - IndicatorHG::Indicator -end - -# this method is used when the limiter is constructed as for shock-capturing volume integrals -function SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], - positivity_variables_nonlinear = (), - positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, - bar_states = true, - max_iterations_newton = 10, - newton_tolerances = (1.0e-12, 1.0e-14), - gamma_constant_newton = 2 * ndims(equations), - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure) - local_minmax = (length(local_minmax_variables_cons) > 0) - positivity = (length(positivity_variables_cons) + - length(positivity_variables_nonlinear) > 0) - if math_entropy && spec_entropy - error("Only one of the two can be selected: math_entropy/spec_entropy") - end - - number_bounds = 2 * length(local_minmax_variables_cons) + - length(positivity_variables_nonlinear) + - spec_entropy + math_entropy - - for index in positivity_variables_cons - if !(index in local_minmax_variables_cons) - number_bounds += 1 - end - end - - cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds, bar_states) - - if smoothness_indicator - IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max = 1.0, - alpha_smooth = false, - variable = variable_smoothness_indicator) - else - IndicatorHG = nothing - end - SubcellLimiterIDP{typeof(positivity_correction_factor), - typeof(positivity_variables_nonlinear), - typeof(cache), typeof(IndicatorHG)}(local_minmax, - local_minmax_variables_cons, - positivity, - positivity_variables_cons, - positivity_variables_nonlinear, - positivity_correction_factor, - spec_entropy, - math_entropy, - bar_states, - cache, - max_iterations_newton, - newton_tolerances, - gamma_constant_newton, - smoothness_indicator, - threshold_smoothness_indicator, - IndicatorHG) -end - -function Base.show(io::IO, limiter::SubcellLimiterIDP) - @nospecialize limiter # reduce precompilation time - @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter - - print(io, "SubcellLimiterIDP(") - if !(local_minmax || positivity || spec_entropy || math_entropy) - print(io, "No limiter selected => pure DG method") - else - print(io, "limiter=(") - local_minmax && print(io, "min/max limiting, ") - positivity && print(io, "positivity, ") - spec_entropy && print(io, "specific entropy, ") - math_entropy && print(io, "mathematical entropy, ") - print(io, "), ") - end - limiter.smoothness_indicator && - print(io, ", Smoothness indicator: ", limiter.IndicatorHG, - " with threshold ", limiter.threshold_smoothness_indicator, "), ") - print(io, - "Local bounds with $(limiter.bar_states ? "Bar States" : "FV solution")") - print(io, ")") -end - -function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) - @nospecialize limiter # reduce precompilation time - @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter - - if get(io, :compact, false) - show(io, limiter) - else - if !(local_minmax || positivity || spec_entropy || math_entropy) - setup = ["limiter" => "No limiter selected => pure DG method"] - else - setup = ["limiter" => ""] - if local_minmax - setup = [ - setup..., - "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", - ] - end - if positivity - string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" - setup = [setup..., "" => string] - setup = [ - setup..., - "" => " positivity correction factor = $(limiter.positivity_correction_factor)", - ] - end - if spec_entropy - setup = [setup..., "" => "local minimum bound for specific entropy"] - end - if math_entropy - setup = [setup..., "" => "local maximum bound for mathematical entropy"] - end - setup = [ - setup..., - "Local bounds" => (limiter.bar_states ? "Bar States" : "FV solution"), - ] - if limiter.smoothness_indicator - setup = [ - setup..., - "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", - ] - end - summary_box(io, "SubcellLimiterIDP", setup) - end - end -end - -function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, - ::VolumeIntegralSubcellLimiting, equations) - node_variables[:alpha_limiter] = limiter.cache.container_subcell_limiter.alpha - # TODO: alpha is not filled before the first timestep. - return nothing -end - -""" - SubcellLimiterMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure, - Plotting = true) - -Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- local two-sided limiting for `cons(1)` (`DensityLimiter`) -- transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) -- local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) -- local two-sided limiting for conservative variables (`ConservativeLimiter`) -- positivity limiting for `cons(1)` (`DensityPositivityLimiter`) and pressure (`PressurePositivityLimiterKuzmin`) -- semidiscrete entropy fix (`SemiDiscEntropyLimiter`) - -The pressure positivity limiting preserves a sharp version (`PressurePositivityLimiterKuzminExact`) -and a more cautious one. The density positivity limiter uses a `DensityPositivityCorrectionFactor` -such that `u^new >= positivity_correction_factor * u^FV`. All additional analyses for plotting routines -can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). - -A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with -`variable_smoothness_indicator`, which disables subcell blending for element-wise -indicator values <= `threshold_smoothness_indicator`. - -## References - -- Rueda-Ramírez, Bolm, Kuzmin, Gassner (2023) - Monolithic Convex Limiting for Legendre-Gauss-Lobatto Discontinuous Galerkin Spectral Element Methods - [arXiv:2303.00374](https://doi.org/10.48550/arXiv.2303.00374) -- Kuzmin (2020) - Monolithic convex limiting for continuous finite element discretizations of hyperbolic conservation laws - [DOI: 10.1016/j.cma.2019.112804](https://doi.org/10.1016/j.cma.2019.112804) - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. -""" -struct SubcellLimiterMCL{RealT <: Real, Cache, Indicator} <: AbstractSubcellLimiter - cache::Cache - DensityLimiter::Bool # Impose local maximum/minimum for cons(1) based on bar states - DensityAlphaForAll::Bool # Use the cons(1) blending coefficient for all quantities - SequentialLimiter::Bool # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states - ConservativeLimiter::Bool # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states - PressurePositivityLimiterKuzmin::Bool # Impose positivity for pressure â la Kuzmin - PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - DensityPositivityLimiter::Bool # Impose positivity for cons(1) - DensityPositivityCorrectionFactor::RealT # Correction Factor for DensityPositivityLimiter in [0,1) - SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix - smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner - threshold_smoothness_indicator::RealT # threshold for smoothness indicator - IndicatorHG::Indicator - Plotting::Bool -end - -# this method is used when the limiter is constructed as for shock-capturing volume integrals -function SubcellLimiterMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, - smoothness_indicator = false, - threshold_smoothness_indicator = 0.1, - variable_smoothness_indicator = density_pressure, - Plotting = true) - if SequentialLimiter && ConservativeLimiter - error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") - end - cache = create_cache(SubcellLimiterMCL, equations, basis, - PressurePositivityLimiterKuzmin) - if smoothness_indicator - IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth = false, - variable = variable_smoothness_indicator) - else - IndicatorHG = nothing - end - SubcellLimiterMCL{typeof(threshold_smoothness_indicator), typeof(cache), - typeof(IndicatorHG)}(cache, - DensityLimiter, DensityAlphaForAll, - SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, - PressurePositivityLimiterKuzminExact, - DensityPositivityLimiter, - DensityPositivityCorrectionFactor, - SemiDiscEntropyLimiter, - smoothness_indicator, - threshold_smoothness_indicator, IndicatorHG, - Plotting) -end - -function Base.show(io::IO, limiter::SubcellLimiterMCL) - @nospecialize limiter # reduce precompilation time - - print(io, "SubcellLimiterMCL(") - limiter.DensityLimiter && print(io, "; dens") - limiter.DensityAlphaForAll && print(io, "; dens alpha ∀") - limiter.SequentialLimiter && print(io, "; seq") - limiter.ConservativeLimiter && print(io, "; cons") - if limiter.PressurePositivityLimiterKuzmin - print(io, - "; $(limiter.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") - end - limiter.DensityPositivityLimiter && print(io, "; dens pos") - if limiter.DensityPositivityCorrectionFactor != 0 - print(io, - " with correction factor $(limiter.DensityPositivityCorrectionFactor)") - end - limiter.SemiDiscEntropyLimiter && print(io, "; semid. entropy") - limiter.smoothness_indicator && - print(io, "; Smoothness indicator: ", limiter.IndicatorHG, - " with threshold ", limiter.threshold_smoothness_indicator) - print(io, ")") -end - -function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) - @nospecialize limiter # reduce precompilation time - @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = limiter - - if get(io, :compact, false) - show(io, limiter) - else - setup = ["limiter" => ""] - DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) - DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) - SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) - ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) - if limiter.PressurePositivityLimiterKuzmin - setup = [ - setup..., - "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")", - ] - end - if DensityPositivityLimiter - if limiter.DensityPositivityCorrectionFactor != 0.0 - setup = [ - setup..., - "" => "DensityPositivityLimiter with correction factor $(limiter.DensityPositivityCorrectionFactor)", - ] - else - setup = [setup..., "" => "DensityPositivityLimiter"] - end - end - SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) - if limiter.smoothness_indicator - setup = [ - setup..., - "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", - ] - end - summary_box(io, "SubcellLimiterMCL", setup) - end -end - -function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, - ::VolumeIntegralSubcellLimiting, equations) - if !limiter.Plotting - return nothing - end - @unpack alpha = limiter.cache.container_subcell_limiter - variables = varnames(cons2cons, equations) - for v in eachvariable(equations) - s = Symbol("alpha_", variables[v]) - node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] - end - - if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_pressure = limiter.cache.container_subcell_limiter - node_variables[:alpha_pressure] = alpha_pressure - end - - if limiter.SemiDiscEntropyLimiter - @unpack alpha_entropy = limiter.cache.container_subcell_limiter - node_variables[:alpha_entropy] = alpha_entropy - end - - for v in eachvariable(equations) - @unpack alpha_mean = limiter.cache.container_subcell_limiter - s = Symbol("alpha_mean_", variables[v]) - node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) - end - - if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter - node_variables[:alpha_mean_pressure] = alpha_mean_pressure - end - - if limiter.SemiDiscEntropyLimiter - @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter - node_variables[:alpha_mean_entropy] = alpha_mean_entropy - end - - return nothing -end - """ IndicatorMax(equations::AbstractEquations, basis; variable) IndicatorMax(semi::AbstractSemidiscretization; variable) diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 48177fce79..085cb71ad0 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -189,763 +189,6 @@ function (löhner::IndicatorLöhner)(u::AbstractArray{<:Any, 4}, return alpha end -# this method is used when the limiter is constructed as for shock-capturing volume integrals -function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, number_bounds, bar_states) - container_subcell_limiter = Trixi.ContainerSubcellLimiterIDP2D{real(basis) - }(0, - nnodes(basis), - number_bounds) - - cache = (;) - if bar_states - container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, - nvariables(equations), - nnodes(basis)) - cache = (; cache..., container_bar_states) - end - - idp_bounds_delta = zeros(real(basis), number_bounds) - - return (; cache..., container_subcell_limiter, idp_bounds_delta) -end - -function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, - dt; - kwargs...) - @unpack alpha = limiter.cache.container_subcell_limiter - alpha .= zero(eltype(alpha)) - if limiter.smoothness_indicator - elements = semi.cache.element_ids_dgfv - else - elements = eachelement(dg, semi.cache) - end - - if limiter.local_minmax - @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, - limiter, u, - t, dt, - semi, elements) - end - if limiter.positivity - @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, - semi, elements) - end - if limiter.spec_entropy - @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, - dt, - semi, elements) - end - if limiter.math_entropy - @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, - dt, - semi, elements) - end - - # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = limiter.cache.container_subcell_limiter - @threaded for element in elements - for j in eachnode(dg), i in 2:nnodes(dg) - alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) - end - for j in 2:nnodes(dg), i in eachnode(dg) - alpha2[i, j, element] = max(alpha[i, j - 1, element], alpha[i, j, element]) - end - alpha1[1, :, element] .= zero(eltype(alpha1)) - alpha1[nnodes(dg) + 1, :, element] .= zero(eltype(alpha1)) - alpha2[:, 1, element] .= zero(eltype(alpha2)) - alpha2[:, nnodes(dg) + 1, element] .= zero(eltype(alpha2)) - end - - return nothing -end - -@inline function calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - # Calc bounds inside elements - @threaded for element in eachelement(dg, cache) - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) - # Calculate bounds at Gauss-Lobatto nodes using u - for j in eachnode(dg), i in eachnode(dg) - var = u[variable, i, j, element] - var_min[i, j, element] = min(var_min[i, j, element], var) - var_max[i, j, element] = max(var_max[i, j, element], var) - - if i > 1 - var_min[i - 1, j, element] = min(var_min[i - 1, j, element], var) - var_max[i - 1, j, element] = max(var_max[i - 1, j, element], var) - end - if i < nnodes(dg) - var_min[i + 1, j, element] = min(var_min[i + 1, j, element], var) - var_max[i + 1, j, element] = max(var_max[i + 1, j, element], var) - end - if j > 1 - var_min[i, j - 1, element] = min(var_min[i, j - 1, element], var) - var_max[i, j - 1, element] = max(var_max[i, j - 1, element], var) - end - if j < nnodes(dg) - var_min[i, j + 1, element] = min(var_min[i, j + 1, element], var) - var_max[i, j + 1, element] = max(var_max[i, j + 1, element], var) - end - end - end - - # Values at element boundary - calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh) -end - -@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, - mesh::TreeMesh2D) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - # Calc bounds at interfaces and periodic boundaries - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - for i in eachnode(dg) - index_left = (nnodes(dg), i) - index_right = (1, i) - if orientation == 2 - index_left = reverse(index_left) - index_right = reverse(index_right) - end - var_left = u[variable, index_left..., left] - var_right = u[variable, index_right..., right] - - var_min[index_right..., right] = min(var_min[index_right..., right], - var_left) - var_max[index_right..., right] = max(var_max[index_right..., right], - var_left) - - var_min[index_left..., left] = min(var_min[index_left..., left], var_right) - var_max[index_left..., left] = max(var_max[index_left..., left], var_right) - end - end - - # Calc bounds at physical boundaries - for boundary in eachboundary(dg, cache) - element = cache.boundaries.neighbor_ids[boundary] - orientation = cache.boundaries.orientations[boundary] - neighbor_side = cache.boundaries.neighbor_sides[boundary] - - for i in eachnode(dg) - if neighbor_side == 2 # Element is on the right, boundary on the left - index = (1, i) - boundary_index = 1 - else # Element is on the left, boundary on the right - index = (nnodes(dg), i) - boundary_index = 2 - end - if orientation == 2 - index = reverse(index) - boundary_index += 2 - end - u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[boundary_index], - orientation, boundary_index, - equations, dg, index..., element) - var_outer = u_outer[variable] - - var_min[index..., element] = min(var_min[index..., element], var_outer) - var_max[index..., element] = max(var_max[index..., element], var_outer) - end - end - - return nothing -end - -@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, t, - semi) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - # Calc bounds inside elements - @threaded for element in eachelement(dg, cache) - var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) - - # Calculate bounds at Gauss-Lobatto nodes using u - for j in eachnode(dg), i in eachnode(dg) - var = variable(get_node_vars(u, equations, dg, i, j, element), equations) - var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) - - if i > 1 - var_minmax[i - 1, j, element] = minmax(var_minmax[i - 1, j, element], - var) - end - if i < nnodes(dg) - var_minmax[i + 1, j, element] = minmax(var_minmax[i + 1, j, element], - var) - end - if j > 1 - var_minmax[i, j - 1, element] = minmax(var_minmax[i, j - 1, element], - var) - end - if j < nnodes(dg) - var_minmax[i, j + 1, element] = minmax(var_minmax[i, j + 1, element], - var) - end - end - end - - # Values at element boundary - calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) -end - -@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, - mesh::TreeMesh2D) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - # Calc bounds at interfaces and periodic boundaries - for interface in eachinterface(dg, cache) - # Get neighboring element ids - left = cache.interfaces.neighbor_ids[1, interface] - right = cache.interfaces.neighbor_ids[2, interface] - - orientation = cache.interfaces.orientations[interface] - - if orientation == 1 - for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, - left), equations) - var_right = variable(get_node_vars(u, equations, dg, 1, j, right), - equations) - - var_minmax[1, j, right] = minmax(var_minmax[1, j, right], var_left) - var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, - left], var_right) - end - else # orientation == 2 - for i in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), - left), equations) - var_right = variable(get_node_vars(u, equations, dg, i, 1, right), - equations) - - var_minmax[i, 1, right] = minmax(var_minmax[i, 1, right], var_left) - var_minmax[i, nnodes(dg), left] = minmax(var_minmax[i, nnodes(dg), - left], var_right) - end - end - end - - # Calc bounds at physical boundaries - for boundary in eachboundary(dg, cache) - element = cache.boundaries.neighbor_ids[boundary] - orientation = cache.boundaries.orientations[boundary] - neighbor_side = cache.boundaries.neighbor_sides[boundary] - - if orientation == 1 - if neighbor_side == 2 # Element is on the right, boundary on the left - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], - orientation, 1, - equations, dg, 1, j, element) - var_outer = variable(u_outer, equations) - - var_minmax[1, j, element] = minmax(var_minmax[1, j, element], - var_outer) - end - else # Element is on the left, boundary on the right - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], - orientation, 2, - equations, dg, nnodes(dg), j, - element) - var_outer = variable(u_outer, equations) - - var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), - j, element], - var_outer) - end - end - else # orientation == 2 - if neighbor_side == 2 # Element is on the right, boundary on the left - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], - orientation, 3, - equations, dg, i, 1, element) - var_outer = variable(u_outer, equations) - - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], - var_outer) - end - else # Element is on the left, boundary on the right - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], - orientation, 4, - equations, dg, i, nnodes(dg), - element) - var_outer = variable(u_outer, equations) - - var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, - nnodes(dg), - element], - var_outer) - end - end - end - end - - return nothing -end - -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) - for (index, variable) in enumerate(limiter.local_minmax_variables_cons) - idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) - end - - return nothing -end - -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, - index) - mesh, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.container_subcell_limiter - - var_min = variable_bounds[2 * (index - 1) + 1] - var_max = variable_bounds[2 * (index - 1) + 2] - if !limiter.bar_states - calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) - end - - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack inverse_weights = dg.basis - - @threaded for element in elements - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - end - for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end - var = u[variable, i, j, element] - # Real Zalesak type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pp and Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2[variable, i, j + 1, element] - - Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + - max(0, val_flux2_local) + max(0, val_flux2_local_jp1) - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - Pp = inverse_jacobian * Pp - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / - (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) - Qm = abs(Qm) / - (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) - end - end - - return nothing -end - -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.container_subcell_limiter - - s_min = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + 1] - if !limiter.bar_states - calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) - end - - # Perform Newton's bisection method to find new alpha - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, - specEntropy_goal, specEntropy_dGoal_dbeta, - specEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, limiter) - end - end - - return nothing -end - -specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) -function specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) -end -function specEntropy_initialCheck(bound, goal, newton_abstol) - goal <= max(newton_abstol, abs(bound) * newton_abstol) -end - -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy = limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter - - s_max = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + spec_entropy + 1] - if !limiter.bar_states - calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) - end - - # Perform Newton's bisection method to find new alpha - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, - mathEntropy_goal, mathEntropy_dGoal_dbeta, - mathEntropy_initialCheck, standard_finalCheck, - dt, mesh, equations, dg, cache, limiter) - end - end - - return nothing -end - -mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) -function mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(cons2entropy(u, equations), dt * antidiffusive_flux) -end -function mathEntropy_initialCheck(bound, goal, newton_abstol) - goal >= -max(newton_abstol, abs(bound) * newton_abstol) -end - -@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) - # Conservative variables - for (index, variable) in enumerate(limiter.positivity_variables_cons) - idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) - end - - # Nonlinear variables - for (index, variable) in enumerate(limiter.positivity_variables_nonlinear) - idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, variable, index) - end - - return nothing -end - -@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, - index) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack inverse_weights = dg.basis - @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = limiter - - @unpack variable_bounds = limiter.cache.container_subcell_limiter - - counter = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + - math_entropy - if local_minmax - if variable in limiter.local_minmax_variables_cons - for (index_, variable_) in enumerate(limiter.local_minmax_variables_cons) - if variable == variable_ - var_min = variable_bounds[2 * (index_ - 1) + 1] - break - end - end - else - for variable_ in limiter.positivity_variables_cons[1:index] - if !(variable_ in limiter.local_minmax_variables_cons) - counter += 1 - end - end - var_min = variable_bounds[counter] - end - else - var_min = variable_bounds[counter + index] - end - - @threaded for element in elements - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - end - for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end - - var = u[variable, i, j, element] - if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") - end - - # Compute bound - if limiter.local_minmax - var_min[i, j, element] = max(var_min[i, j, element], - positivity_correction_factor * var) - else - var_min[i, j, element] = positivity_correction_factor * var - end - - # Real one-sided Zalesak-type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2[variable, i, j + 1, element] - - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) - - # Calculate alpha - alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) - end - end - - return nothing -end - -@inline function idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, - variable, index) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter - - index_ = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + - math_entropy + index - for variable_ in limiter.positivity_variables_cons - if !(variable_ in limiter.local_minmax_variables_cons) - index_ += 1 - end - end - var_min = variable_bounds[index_] - - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - # Compute bound - u_local = get_node_vars(u, equations, dg, i, j, element) - var = variable(u_local, equations) - if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") - end - var_min[i, j, element] = positivity_correction_factor * var - - # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, - pressure_goal, pressure_dgoal_dbeta, - pressure_initialCheck, pressure_finalCheck, - dt, mesh, equations, dg, cache, limiter) - end - end - - return nothing -end - -pressure_goal(bound, u, equations) = bound - pressure(u, equations) -function pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(dpdu(u, equations), dt * antidiffusive_flux) -end -pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0 -function pressure_finalCheck(bound, goal, newton_abstol) - (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) -end - -@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, - goal_fct, dgoal_fct, initialCheck, finalCheck, - dt, mesh, equations, dg, cache, limiter) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - else # mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end - - @unpack gamma_constant_newton = limiter - - # negative xi direction - antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * - get_node_vars(antidiffusive_flux1, equations, dg, i, j, - element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) - - # positive xi direction - antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * - inverse_weights[i] * - get_node_vars(antidiffusive_flux1, equations, dg, i + 1, j, - element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) - - # negative eta direction - antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * - get_node_vars(antidiffusive_flux2, equations, dg, i, j, - element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) - - # positive eta direction - antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * - inverse_weights[j] * - get_node_vars(antidiffusive_flux2, equations, dg, i, j + 1, - element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) - - return nothing -end - -@inline function newton_loop!(alpha, bound, u, i, j, element, - goal_fct, dgoal_fct, initialCheck, finalCheck, - equations, dt, limiter, antidiffusive_flux) - newton_reltol, newton_abstol = limiter.newton_tolerances - - beta = 1 - alpha[i, j, element] - - beta_L = 0 # alpha = 1 - beta_R = beta # No higher beta (lower alpha) than the current one - - u_curr = u + beta * dt * antidiffusive_flux - - # If state is valid, perform initial check and return if correction is not needed - if isValidState(u_curr, equations) - as = goal_fct(bound, u_curr, equations) - - initialCheck(bound, as, newton_abstol) && return nothing - end - - # Newton iterations - for iter in 1:(limiter.max_iterations_newton) - beta_old = beta - - # If the state is valid, evaluate d(goal)/d(beta) - if isValidState(u_curr, equations) - dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) - else # Otherwise, perform a bisection step - dSdbeta = 0 - end - - if dSdbeta != 0 - # Update beta with Newton's method - beta = beta - as / dSdbeta - end - - # Check bounds - if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0) || isnan(beta) - # Out of bounds, do a bisection step - beta = 0.5 * (beta_L + beta_R) - # Get new u - u_curr = u + beta * dt * antidiffusive_flux - - # If the state is invalid, finish bisection step without checking tolerance and iterate further - if !isValidState(u_curr, equations) - beta_R = beta - continue - end - - # Check new beta for condition and update bounds - as = goal_fct(bound, u_curr, equations) - if initialCheck(bound, as, newton_abstol) - # New beta fulfills condition - beta_L = beta - else - # New beta does not fulfill condition - beta_R = beta - end - else - # Get new u - u_curr = u + beta * dt * antidiffusive_flux - - # If the state is invalid, redefine right bound without checking tolerance and iterate further - if !isValidState(u_curr, equations) - beta_R = beta - continue - end - - # Evaluate goal function - as = goal_fct(bound, u_curr, equations) - end - - # Check relative tolerance - if abs(beta_old - beta) <= newton_reltol - break - end - - # Check absolute tolerance - if finalCheck(bound, as, newton_abstol) - break - end - end - - new_alpha = 1 - beta - if alpha[i, j, element] > new_alpha + newton_abstol - error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") - else - alpha[i, j, element] = new_alpha - end - - return nothing -end - -function standard_finalCheck(bound, goal, newton_abstol) - abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) -end - -# this method is used when the limiter is constructed as for shock-capturing volume integrals -function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) - container_subcell_limiter = Trixi.ContainerSubcellLimiterMCL2D{real(basis) - }(0, - nvariables(equations), - nnodes(basis)) - container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, - nvariables(equations), - nnodes(basis)) - - idp_bounds_delta = zeros(real(basis), 2, - nvariables(equations) + PressurePositivityLimiterKuzmin) - - return (; container_subcell_limiter, container_bar_states, idp_bounds_delta) -end - # this method is used when the indicator is constructed as for shock-capturing volume integrals function create_cache(::Type{IndicatorMax}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl new file mode 100644 index 0000000000..a953180352 --- /dev/null +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -0,0 +1,432 @@ +# 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 + +abstract type AbstractSubcellLimiter end + +function create_cache(typ::Type{LimiterType}, + semi) where {LimiterType <: AbstractSubcellLimiter} + create_cache(typ, mesh_equations_solver_cache(semi)...) +end + +function get_element_variables!(element_variables, limiter::AbstractSubcellLimiter, + ::VolumeIntegralSubcellLimiting) + element_variables[:smooth_indicator_elementwise] = limiter.IndicatorHG.cache.alpha + return nothing +end + +""" + SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, + bar_states = true, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations), + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure) + +Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) +including: +- maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) +- positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) +- one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) + +The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity +limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. +The Newton-bisection method for the limiting of non-linear variables uses maximal `max_iterations_newton` +iterations, tolerances `newton_tolerances` and the gamma constant `gamma_constant_newton` +(gamma_constant_newton>=2*d, where d=#dimensions). + +A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with +`variable_smoothness_indicator`, which disables subcell blending for element-wise +indicator values <= `threshold_smoothness_indicator`. + +!!! note + This limiter and the correction callback [`SubcellLimiterIDPCorrection`](@ref) only work together. + Without the callback, no limiting takes place, leading to a standard flux-differencing DGSEM scheme. + +## References + +- Rueda-Ramírez, Pazner, Gassner (2022) + Subcell Limiting Strategies for Discontinuous Galerkin Spectral Element Methods + [DOI: 10.1016/j.compfluid.2022.105627](https://doi.org/10.1016/j.compfluid.2022.105627) +- Pazner (2020) + Sparse invariant domain preserving discontinuous Galerkin methods with subcell convex limiting + [DOI: 10.1016/j.cma.2021.113876](https://doi.org/10.1016/j.cma.2021.113876) + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, + Cache, Indicator} <: AbstractSubcellLimiter + local_minmax::Bool + local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables + positivity::Bool + positivity_variables_cons::Vector{Int} # Positivity for conservative variables + positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables + positivity_correction_factor::RealT + spec_entropy::Bool + math_entropy::Bool + bar_states::Bool + cache::Cache + max_iterations_newton::Int + newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method + gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints + smoothness_indicator::Bool + threshold_smoothness_indicator::RealT + IndicatorHG::Indicator +end + +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], + positivity_variables_cons = [], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, + bar_states = true, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations), + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure) + local_minmax = (length(local_minmax_variables_cons) > 0) + positivity = (length(positivity_variables_cons) + + length(positivity_variables_nonlinear) > 0) + if math_entropy && spec_entropy + error("Only one of the two can be selected: math_entropy/spec_entropy") + end + + number_bounds = 2 * length(local_minmax_variables_cons) + + length(positivity_variables_nonlinear) + + spec_entropy + math_entropy + + for index in positivity_variables_cons + if !(index in local_minmax_variables_cons) + number_bounds += 1 + end + end + + cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds, bar_states) + + if smoothness_indicator + IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max = 1.0, + alpha_smooth = false, + variable = variable_smoothness_indicator) + else + IndicatorHG = nothing + end + SubcellLimiterIDP{typeof(positivity_correction_factor), + typeof(positivity_variables_nonlinear), + typeof(cache), typeof(IndicatorHG)}(local_minmax, + local_minmax_variables_cons, + positivity, + positivity_variables_cons, + positivity_variables_nonlinear, + positivity_correction_factor, + spec_entropy, + math_entropy, + bar_states, + cache, + max_iterations_newton, + newton_tolerances, + gamma_constant_newton, + smoothness_indicator, + threshold_smoothness_indicator, + IndicatorHG) +end + +function Base.show(io::IO, limiter::SubcellLimiterIDP) + @nospecialize limiter # reduce precompilation time + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter + + print(io, "SubcellLimiterIDP(") + if !(local_minmax || positivity || spec_entropy || math_entropy) + print(io, "No limiter selected => pure DG method") + else + print(io, "limiter=(") + local_minmax && print(io, "min/max limiting, ") + positivity && print(io, "positivity, ") + spec_entropy && print(io, "specific entropy, ") + math_entropy && print(io, "mathematical entropy, ") + print(io, "), ") + end + limiter.smoothness_indicator && + print(io, ", Smoothness indicator: ", limiter.IndicatorHG, + " with threshold ", limiter.threshold_smoothness_indicator, "), ") + print(io, + "Local bounds with $(limiter.bar_states ? "Bar States" : "FV solution")") + print(io, ")") +end + +function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) + @nospecialize limiter # reduce precompilation time + @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter + + if get(io, :compact, false) + show(io, limiter) + else + if !(local_minmax || positivity || spec_entropy || math_entropy) + setup = ["limiter" => "No limiter selected => pure DG method"] + else + setup = ["limiter" => ""] + if local_minmax + setup = [ + setup..., + "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", + ] + end + if positivity + string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" + setup = [setup..., "" => string] + setup = [ + setup..., + "" => " positivity correction factor = $(limiter.positivity_correction_factor)", + ] + end + if spec_entropy + setup = [setup..., "" => "local minimum bound for specific entropy"] + end + if math_entropy + setup = [setup..., "" => "local maximum bound for mathematical entropy"] + end + setup = [ + setup..., + "Local bounds" => (limiter.bar_states ? "Bar States" : "FV solution"), + ] + if limiter.smoothness_indicator + setup = [ + setup..., + "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", + ] + end + summary_box(io, "SubcellLimiterIDP", setup) + end + end +end + +function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, + ::VolumeIntegralSubcellLimiting, equations) + node_variables[:alpha_limiter] = limiter.cache.container_subcell_limiter.alpha + # TODO: alpha is not filled before the first timestep. + return nothing +end + +""" + SubcellLimiterMCL(equations::AbstractEquations, basis; + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = false, + DensityPositivityCorrectionFactor = 0.0, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure, + Plotting = true) + +Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: +- local two-sided limiting for `cons(1)` (`DensityLimiter`) +- transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) +- local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) +- local two-sided limiting for conservative variables (`ConservativeLimiter`) +- positivity limiting for `cons(1)` (`DensityPositivityLimiter`) and pressure (`PressurePositivityLimiterKuzmin`) +- semidiscrete entropy fix (`SemiDiscEntropyLimiter`) + +The pressure positivity limiting preserves a sharp version (`PressurePositivityLimiterKuzminExact`) +and a more cautious one. The density positivity limiter uses a `DensityPositivityCorrectionFactor` +such that `u^new >= positivity_correction_factor * u^FV`. All additional analyses for plotting routines +can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). + +A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with +`variable_smoothness_indicator`, which disables subcell blending for element-wise +indicator values <= `threshold_smoothness_indicator`. + +## References + +- Rueda-Ramírez, Bolm, Kuzmin, Gassner (2023) + Monolithic Convex Limiting for Legendre-Gauss-Lobatto Discontinuous Galerkin Spectral Element Methods + [arXiv:2303.00374](https://doi.org/10.48550/arXiv.2303.00374) +- Kuzmin (2020) + Monolithic convex limiting for continuous finite element discretizations of hyperbolic conservation laws + [DOI: 10.1016/j.cma.2019.112804](https://doi.org/10.1016/j.cma.2019.112804) + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +struct SubcellLimiterMCL{RealT <: Real, Cache, Indicator} <: AbstractSubcellLimiter + cache::Cache + DensityLimiter::Bool # Impose local maximum/minimum for cons(1) based on bar states + DensityAlphaForAll::Bool # Use the cons(1) blending coefficient for all quantities + SequentialLimiter::Bool # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states + ConservativeLimiter::Bool # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states + PressurePositivityLimiterKuzmin::Bool # Impose positivity for pressure â la Kuzmin + PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha + DensityPositivityLimiter::Bool # Impose positivity for cons(1) + DensityPositivityCorrectionFactor::RealT # Correction Factor for DensityPositivityLimiter in [0,1) + SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix + smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner + threshold_smoothness_indicator::RealT # threshold for smoothness indicator + IndicatorHG::Indicator + Plotting::Bool +end + +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function SubcellLimiterMCL(equations::AbstractEquations, basis; + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = false, + DensityPositivityCorrectionFactor = 0.0, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + threshold_smoothness_indicator = 0.1, + variable_smoothness_indicator = density_pressure, + Plotting = true) + if SequentialLimiter && ConservativeLimiter + error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") + end + cache = create_cache(SubcellLimiterMCL, equations, basis, + PressurePositivityLimiterKuzmin) + if smoothness_indicator + IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth = false, + variable = variable_smoothness_indicator) + else + IndicatorHG = nothing + end + SubcellLimiterMCL{typeof(threshold_smoothness_indicator), typeof(cache), + typeof(IndicatorHG)}(cache, + DensityLimiter, DensityAlphaForAll, + SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzmin, + PressurePositivityLimiterKuzminExact, + DensityPositivityLimiter, + DensityPositivityCorrectionFactor, + SemiDiscEntropyLimiter, + smoothness_indicator, + threshold_smoothness_indicator, IndicatorHG, + Plotting) +end + +function Base.show(io::IO, limiter::SubcellLimiterMCL) + @nospecialize limiter # reduce precompilation time + + print(io, "SubcellLimiterMCL(") + limiter.DensityLimiter && print(io, "; dens") + limiter.DensityAlphaForAll && print(io, "; dens alpha ∀") + limiter.SequentialLimiter && print(io, "; seq") + limiter.ConservativeLimiter && print(io, "; cons") + if limiter.PressurePositivityLimiterKuzmin + print(io, + "; $(limiter.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") + end + limiter.DensityPositivityLimiter && print(io, "; dens pos") + if limiter.DensityPositivityCorrectionFactor != 0 + print(io, + " with correction factor $(limiter.DensityPositivityCorrectionFactor)") + end + limiter.SemiDiscEntropyLimiter && print(io, "; semid. entropy") + limiter.smoothness_indicator && + print(io, "; Smoothness indicator: ", limiter.IndicatorHG, + " with threshold ", limiter.threshold_smoothness_indicator) + print(io, ")") +end + +function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) + @nospecialize limiter # reduce precompilation time + @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, + PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = limiter + + if get(io, :compact, false) + show(io, limiter) + else + setup = ["limiter" => ""] + DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) + DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) + SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) + ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) + if limiter.PressurePositivityLimiterKuzmin + setup = [ + setup..., + "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")", + ] + end + if DensityPositivityLimiter + if limiter.DensityPositivityCorrectionFactor != 0.0 + setup = [ + setup..., + "" => "DensityPositivityLimiter with correction factor $(limiter.DensityPositivityCorrectionFactor)", + ] + else + setup = [setup..., "" => "DensityPositivityLimiter"] + end + end + SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) + if limiter.smoothness_indicator + setup = [ + setup..., + "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", + ] + end + summary_box(io, "SubcellLimiterMCL", setup) + end +end + +function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, + ::VolumeIntegralSubcellLimiting, equations) + if !limiter.Plotting + return nothing + end + @unpack alpha = limiter.cache.container_subcell_limiter + variables = varnames(cons2cons, equations) + for v in eachvariable(equations) + s = Symbol("alpha_", variables[v]) + node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] + end + + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_pressure = limiter.cache.container_subcell_limiter + node_variables[:alpha_pressure] = alpha_pressure + end + + if limiter.SemiDiscEntropyLimiter + @unpack alpha_entropy = limiter.cache.container_subcell_limiter + node_variables[:alpha_entropy] = alpha_entropy + end + + for v in eachvariable(equations) + @unpack alpha_mean = limiter.cache.container_subcell_limiter + s = Symbol("alpha_mean_", variables[v]) + node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) + end + + if limiter.PressurePositivityLimiterKuzmin + @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter + node_variables[:alpha_mean_pressure] = alpha_mean_pressure + end + + if limiter.SemiDiscEntropyLimiter + @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter + node_variables[:alpha_mean_entropy] = alpha_mean_entropy + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl new file mode 100644 index 0000000000..f66321e393 --- /dev/null +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -0,0 +1,764 @@ +# 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 method is used when the limiter is constructed as for shock-capturing volume integrals +function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, + basis::LobattoLegendreBasis, number_bounds, bar_states) + container_subcell_limiter = Trixi.ContainerSubcellLimiterIDP2D{real(basis) + }(0, + nnodes(basis), + number_bounds) + + cache = (;) + if bar_states + container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, + nvariables(equations), + nnodes(basis)) + cache = (; cache..., container_bar_states) + end + + idp_bounds_delta = zeros(real(basis), number_bounds) + + return (; cache..., container_subcell_limiter, idp_bounds_delta) +end + +function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, + dt; + kwargs...) + @unpack alpha = limiter.cache.container_subcell_limiter + alpha .= zero(eltype(alpha)) + if limiter.smoothness_indicator + elements = semi.cache.element_ids_dgfv + else + elements = eachelement(dg, semi.cache) + end + + if limiter.local_minmax + @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, + limiter, u, + t, dt, + semi, elements) + end + if limiter.positivity + @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, + semi, elements) + end + if limiter.spec_entropy + @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, + dt, + semi, elements) + end + if limiter.math_entropy + @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, + dt, + semi, elements) + end + + # Calculate alpha1 and alpha2 + @unpack alpha1, alpha2 = limiter.cache.container_subcell_limiter + @threaded for element in elements + for j in eachnode(dg), i in 2:nnodes(dg) + alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) + end + for j in 2:nnodes(dg), i in eachnode(dg) + alpha2[i, j, element] = max(alpha[i, j - 1, element], alpha[i, j, element]) + end + alpha1[1, :, element] .= zero(eltype(alpha1)) + alpha1[nnodes(dg) + 1, :, element] .= zero(eltype(alpha1)) + alpha2[:, 1, element] .= zero(eltype(alpha2)) + alpha2[:, nnodes(dg) + 1, element] .= zero(eltype(alpha2)) + end + + return nothing +end + +@inline function calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + # Calculate bounds at Gauss-Lobatto nodes using u + for j in eachnode(dg), i in eachnode(dg) + var = u[variable, i, j, element] + var_min[i, j, element] = min(var_min[i, j, element], var) + var_max[i, j, element] = max(var_max[i, j, element], var) + + if i > 1 + var_min[i - 1, j, element] = min(var_min[i - 1, j, element], var) + var_max[i - 1, j, element] = max(var_max[i - 1, j, element], var) + end + if i < nnodes(dg) + var_min[i + 1, j, element] = min(var_min[i + 1, j, element], var) + var_max[i + 1, j, element] = max(var_max[i + 1, j, element], var) + end + if j > 1 + var_min[i, j - 1, element] = min(var_min[i, j - 1, element], var) + var_max[i, j - 1, element] = max(var_max[i, j - 1, element], var) + end + if j < nnodes(dg) + var_min[i, j + 1, element] = min(var_min[i, j + 1, element], var) + var_max[i, j + 1, element] = max(var_max[i, j + 1, element], var) + end + end + end + + # Values at element boundary + calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh) +end + +@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, + mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) + end + var_left = u[variable, index_left..., left] + var_right = u[variable, index_right..., right] + + var_min[index_right..., right] = min(var_min[index_right..., right], + var_left) + var_max[index_right..., right] = max(var_max[index_right..., right], + var_left) + + var_min[index_left..., left] = min(var_min[index_left..., left], var_right) + var_max[index_left..., left] = max(var_max[index_left..., left], var_right) + end + end + + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + for i in eachnode(dg) + if neighbor_side == 2 # Element is on the right, boundary on the left + index = (1, i) + boundary_index = 1 + else # Element is on the left, boundary on the right + index = (nnodes(dg), i) + boundary_index = 2 + end + if orientation == 2 + index = reverse(index) + boundary_index += 2 + end + u_inner = get_node_vars(u, equations, dg, index..., element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[boundary_index], + orientation, boundary_index, + equations, dg, index..., element) + var_outer = u_outer[variable] + + var_min[index..., element] = min(var_min[index..., element], var_outer) + var_max[index..., element] = max(var_max[index..., element], var_outer) + end + end + + return nothing +end + +@inline function calc_bounds_1sided!(var_minmax, minmax, typeminmax, variable, u, t, + semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements + @threaded for element in eachelement(dg, cache) + var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) + + # Calculate bounds at Gauss-Lobatto nodes using u + for j in eachnode(dg), i in eachnode(dg) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) + + if i > 1 + var_minmax[i - 1, j, element] = minmax(var_minmax[i - 1, j, element], + var) + end + if i < nnodes(dg) + var_minmax[i + 1, j, element] = minmax(var_minmax[i + 1, j, element], + var) + end + if j > 1 + var_minmax[i, j - 1, element] = minmax(var_minmax[i, j - 1, element], + var) + end + if j < nnodes(dg) + var_minmax[i, j + 1, element] = minmax(var_minmax[i, j + 1, element], + var) + end + end + end + + # Values at element boundary + calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) +end + +@inline function calc_bounds_1sided_interface!(var_minmax, minmax, variable, u, t, semi, + mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + if orientation == 1 + for j in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, + left), equations) + var_right = variable(get_node_vars(u, equations, dg, 1, j, right), + equations) + + var_minmax[1, j, right] = minmax(var_minmax[1, j, right], var_left) + var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, + left], var_right) + end + else # orientation == 2 + for i in eachnode(dg) + var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), + left), equations) + var_right = variable(get_node_vars(u, equations, dg, i, 1, right), + equations) + + var_minmax[i, 1, right] = minmax(var_minmax[i, 1, right], var_left) + var_minmax[i, nnodes(dg), left] = minmax(var_minmax[i, nnodes(dg), + left], var_right) + end + end + end + + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + if orientation == 1 + if neighbor_side == 2 # Element is on the right, boundary on the left + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, 1, j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[1], + orientation, 1, + equations, dg, 1, j, element) + var_outer = variable(u_outer, equations) + + var_minmax[1, j, element] = minmax(var_minmax[1, j, element], + var_outer) + end + else # Element is on the left, boundary on the right + for j in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[2], + orientation, 2, + equations, dg, nnodes(dg), j, + element) + var_outer = variable(u_outer, equations) + + var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), + j, element], + var_outer) + end + end + else # orientation == 2 + if neighbor_side == 2 # Element is on the right, boundary on the left + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, 1, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[3], + orientation, 3, + equations, dg, i, 1, element) + var_outer = variable(u_outer, equations) + + var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], + var_outer) + end + else # Element is on the left, boundary on the right + for i in eachnode(dg) + u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[4], + orientation, 4, + equations, dg, i, nnodes(dg), + element) + var_outer = variable(u_outer, equations) + + var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, + nnodes(dg), + element], + var_outer) + end + end + end + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) + for (index, variable) in enumerate(limiter.local_minmax_variables_cons) + idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, + index) + mesh, _, dg, cache = mesh_equations_solver_cache(semi) + @unpack variable_bounds = limiter.cache.container_subcell_limiter + + var_min = variable_bounds[2 * (index - 1) + 1] + var_max = variable_bounds[2 * (index - 1) + 2] + if !limiter.bar_states + calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + end + + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack inverse_weights = dg.basis + + @threaded for element in elements + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + end + for j in eachnode(dg), i in eachnode(dg) + if mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end + var = u[variable, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pp and Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2[variable, i, j + 1, element] + + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / + (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / + (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) + end + end + + return nothing +end + +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack variable_bounds = limiter.cache.container_subcell_limiter + + s_min = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + 1] + if !limiter.bar_states + calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) + end + + # Perform Newton's bisection method to find new alpha + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, + specEntropy_goal, specEntropy_dGoal_dbeta, + specEntropy_initialCheck, standard_finalCheck, + dt, mesh, equations, dg, cache, limiter) + end + end + + return nothing +end + +specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) +function specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) + -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) +end +function specEntropy_initialCheck(bound, goal, newton_abstol) + goal <= max(newton_abstol, abs(bound) * newton_abstol) +end + +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack spec_entropy = limiter + @unpack variable_bounds = limiter.cache.container_subcell_limiter + + s_max = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + spec_entropy + 1] + if !limiter.bar_states + calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) + end + + # Perform Newton's bisection method to find new alpha + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, + mathEntropy_goal, mathEntropy_dGoal_dbeta, + mathEntropy_initialCheck, standard_finalCheck, + dt, mesh, equations, dg, cache, limiter) + end + end + + return nothing +end + +mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) +function mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) + -dot(cons2entropy(u, equations), dt * antidiffusive_flux) +end +function mathEntropy_initialCheck(bound, goal, newton_abstol) + goal >= -max(newton_abstol, abs(bound) * newton_abstol) +end + +@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) + # Conservative variables + for (index, variable) in enumerate(limiter.positivity_variables_cons) + idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) + end + + # Nonlinear variables + for (index, variable) in enumerate(limiter.positivity_variables_nonlinear) + idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, variable, index) + end + + return nothing +end + +@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, + index) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack inverse_weights = dg.basis + @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = limiter + + @unpack variable_bounds = limiter.cache.container_subcell_limiter + + counter = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + + math_entropy + if local_minmax + if variable in limiter.local_minmax_variables_cons + for (index_, variable_) in enumerate(limiter.local_minmax_variables_cons) + if variable == variable_ + var_min = variable_bounds[2 * (index_ - 1) + 1] + break + end + end + else + for variable_ in limiter.positivity_variables_cons[1:index] + if !(variable_ in limiter.local_minmax_variables_cons) + counter += 1 + end + end + var_min = variable_bounds[counter] + end + else + var_min = variable_bounds[counter + index] + end + + @threaded for element in elements + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + end + for j in eachnode(dg), i in eachnode(dg) + if mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end + + var = u[variable, i, j, element] + if var < 0 + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + end + + # Compute bound + if limiter.local_minmax + var_min[i, j, element] = max(var_min[i, j, element], + positivity_correction_factor * var) + else + var_min[i, j, element] = positivity_correction_factor * var + end + + # Real one-sided Zalesak-type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2[variable, i, j + 1, element] + + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) + + # Calculate alpha + alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) + end + end + + return nothing +end + +@inline function idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, + variable, index) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = limiter + @unpack variable_bounds = limiter.cache.container_subcell_limiter + + index_ = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + + math_entropy + index + for variable_ in limiter.positivity_variables_cons + if !(variable_ in limiter.local_minmax_variables_cons) + index_ += 1 + end + end + var_min = variable_bounds[index_] + + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + # Compute bound + u_local = get_node_vars(u, equations, dg, i, j, element) + var = variable(u_local, equations) + if var < 0 + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + end + var_min[i, j, element] = positivity_correction_factor * var + + # Perform Newton's bisection method to find new alpha + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, + pressure_goal, pressure_dgoal_dbeta, + pressure_initialCheck, pressure_finalCheck, + dt, mesh, equations, dg, cache, limiter) + end + end + + return nothing +end + +pressure_goal(bound, u, equations) = bound - pressure(u, equations) +function pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) + -dot(dpdu(u, equations), dt * antidiffusive_flux) +end +pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0 +function pressure_finalCheck(bound, goal, newton_abstol) + (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) +end + +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, + goal_fct, dgoal_fct, initialCheck, finalCheck, + dt, mesh, equations, dg, cache, limiter) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + if mesh isa TreeMesh + inverse_jacobian = cache.elements.inverse_jacobian[element] + else # mesh isa StructuredMesh + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + end + + @unpack gamma_constant_newton = limiter + + # negative xi direction + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * + get_node_vars(antidiffusive_flux1, equations, dg, i, j, + element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, + finalCheck, equations, dt, limiter, antidiffusive_flux) + + # positive xi direction + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * + inverse_weights[i] * + get_node_vars(antidiffusive_flux1, equations, dg, i + 1, j, + element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, + finalCheck, equations, dt, limiter, antidiffusive_flux) + + # negative eta direction + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * + get_node_vars(antidiffusive_flux2, equations, dg, i, j, + element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, + finalCheck, equations, dt, limiter, antidiffusive_flux) + + # positive eta direction + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * + inverse_weights[j] * + get_node_vars(antidiffusive_flux2, equations, dg, i, j + 1, + element) + newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, + finalCheck, equations, dt, limiter, antidiffusive_flux) + + return nothing +end + +@inline function newton_loop!(alpha, bound, u, i, j, element, + goal_fct, dgoal_fct, initialCheck, finalCheck, + equations, dt, limiter, antidiffusive_flux) + newton_reltol, newton_abstol = limiter.newton_tolerances + + beta = 1 - alpha[i, j, element] + + beta_L = 0 # alpha = 1 + beta_R = beta # No higher beta (lower alpha) than the current one + + u_curr = u + beta * dt * antidiffusive_flux + + # If state is valid, perform initial check and return if correction is not needed + if isValidState(u_curr, equations) + as = goal_fct(bound, u_curr, equations) + + initialCheck(bound, as, newton_abstol) && return nothing + end + + # Newton iterations + for iter in 1:(limiter.max_iterations_newton) + beta_old = beta + + # If the state is valid, evaluate d(goal)/d(beta) + if isValidState(u_curr, equations) + dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + else # Otherwise, perform a bisection step + dSdbeta = 0 + end + + if dSdbeta != 0 + # Update beta with Newton's method + beta = beta - as / dSdbeta + end + + # Check bounds + if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0) || isnan(beta) + # Out of bounds, do a bisection step + beta = 0.5 * (beta_L + beta_R) + # Get new u + u_curr = u + beta * dt * antidiffusive_flux + + # If the state is invalid, finish bisection step without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + + # Check new beta for condition and update bounds + as = goal_fct(bound, u_curr, equations) + if initialCheck(bound, as, newton_abstol) + # New beta fulfills condition + beta_L = beta + else + # New beta does not fulfill condition + beta_R = beta + end + else + # Get new u + u_curr = u + beta * dt * antidiffusive_flux + + # If the state is invalid, redefine right bound without checking tolerance and iterate further + if !isValidState(u_curr, equations) + beta_R = beta + continue + end + + # Evaluate goal function + as = goal_fct(bound, u_curr, equations) + end + + # Check relative tolerance + if abs(beta_old - beta) <= newton_reltol + break + end + + # Check absolute tolerance + if finalCheck(bound, as, newton_abstol) + break + end + end + + new_alpha = 1 - beta + if alpha[i, j, element] > new_alpha + newton_abstol + error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") + else + alpha[i, j, element] = new_alpha + end + + return nothing +end + +function standard_finalCheck(bound, goal, newton_abstol) + abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) +end + +# this method is used when the limiter is constructed as for shock-capturing volume integrals +function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, + basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) + container_subcell_limiter = Trixi.ContainerSubcellLimiterMCL2D{real(basis) + }(0, + nvariables(equations), + nnodes(basis)) + container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, + nvariables(equations), + nnodes(basis)) + + idp_bounds_delta = zeros(real(basis), 2, + nvariables(equations) + PressurePositivityLimiterKuzmin) + + return (; container_subcell_limiter, container_bar_states, idp_bounds_delta) +end +end # @muladd From 98d8d67b29a053faa7494bf1b62ddca277b89e80 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 10 Jul 2023 09:52:30 +0200 Subject: [PATCH 251/423] Move create_cache routine to specific file --- src/solvers/dgsem_tree/dg_2d.jl | 30 ------------------ .../dgsem_tree/dg_2d_subcell_limiters.jl | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 2f7d5122a2..370d69746e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -89,36 +89,6 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMe fstar2_R_threaded) end -function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, - volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) - cache = create_cache(mesh, equations, - VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), - dg, uEltype) - if volume_integral.limiter.smoothness_indicator - element_ids_dg = Int[] - element_ids_dgfv = Int[] - cache = (; cache..., element_ids_dg, element_ids_dgfv) - end - - A3dp1_x = Array{uEltype, 3} - A3dp1_y = Array{uEltype, 3} - A3d = Array{uEltype, 3} - - fhat1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, - nnodes(dg)) for _ in 1:Threads.nthreads()] - fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), - nnodes(dg) + 1) for _ in 1:Threads.nthreads()] - flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) - for _ in 1:Threads.nthreads()] - - container_antidiffusive_flux = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, - nvariables(equations), - nnodes(dg)) - - return (; cache..., container_antidiffusive_flux, fhat1_threaded, fhat2_threaded, - flux_temp_threaded) -end - # The methods below are specialized on the mortar type # and called from the basic `create_cache` method at the top. function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMesh2D, diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 064a9b86f9..9a41a4f23f 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -5,6 +5,37 @@ @muladd begin #! format: noindent + +function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, + volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) + cache = create_cache(mesh, equations, + VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), + dg, uEltype) + if volume_integral.limiter.smoothness_indicator + element_ids_dg = Int[] + element_ids_dgfv = Int[] + cache = (; cache..., element_ids_dg, element_ids_dgfv) + end + + A3dp1_x = Array{uEltype, 3} + A3dp1_y = Array{uEltype, 3} + A3d = Array{uEltype, 3} + + fhat1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, + nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + + container_antidiffusive_flux = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, + nvariables(equations), + nnodes(dg)) + + return (; cache..., container_antidiffusive_flux, fhat1_threaded, fhat2_threaded, + flux_temp_threaded) +end + function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, From c32d490e97e1830b3b1f13be029e58cbeabf39e4 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Mon, 10 Jul 2023 09:59:07 +0200 Subject: [PATCH 252/423] Fix format --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 9a41a4f23f..60a4ebfd21 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -5,7 +5,6 @@ @muladd begin #! format: noindent - function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) cache = create_cache(mesh, equations, From 84b72e4439fd3cdb2c28d15a440c0ed9fca107e0 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 9 Aug 2023 11:40:56 +0200 Subject: [PATCH 253/423] Implement suggestions --- src/Trixi.jl | 7 +++++-- src/callbacks_stage/subcell_limiter_idp_correction.jl | 5 +++-- src/callbacks_stage/subcell_limiter_idp_correction_2d.jl | 5 ++--- src/callbacks_step/limiting_analysis_2d.jl | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index 3b5a094f2a..c710408f80 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -217,12 +217,15 @@ export DG, VolumeIntegralFluxDifferencing, VolumeIntegralPureLGLFiniteVolume, VolumeIntegralShockCapturingHG, IndicatorHennemannGassner, - VolumeIntegralSubcellLimiting, SubcellLimiterIDP, SubcellLimiterMCL, VolumeIntegralUpwind, SurfaceIntegralWeakForm, SurfaceIntegralStrongForm, SurfaceIntegralUpwind, MortarL2 +export VolumeIntegralSubcellLimiting, BoundsCheckCallback, + SubcellLimiterIDP, SubcellLimiterIDPCorrection, + SubcellLimiterMCL + export nelements, nnodes, nvariables, eachelement, eachnode, eachvariable @@ -251,7 +254,7 @@ export ControllerThreeLevel, ControllerThreeLevelCombined, IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, NeuralNetworkCNN -export PositivityPreservingLimiterZhangShu, SubcellLimiterIDPCorrection, BoundsCheckCallback +export PositivityPreservingLimiterZhangShu export trixi_include, examples_dir, get_examples, default_example, default_example_unstructured, ode_default_options diff --git a/src/callbacks_stage/subcell_limiter_idp_correction.jl b/src/callbacks_stage/subcell_limiter_idp_correction.jl index f7c3aacc7e..69125ebecd 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction.jl @@ -32,8 +32,9 @@ struct SubcellLimiterIDPCorrection end function (limiter!::SubcellLimiterIDPCorrection)(u_ode, integrator::Trixi.SimpleIntegratorSSP, stage) - limiter!(u_ode, integrator.p, integrator.t, integrator.dt, - integrator.p.solver.volume_integral) + semi = integrator.p + limiter!(u_ode, semi, integrator.t, integrator.dt, + semi.solver.volume_integral) end function (limiter!::SubcellLimiterIDPCorrection)(u_ode, semi, t, dt, diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index a3c7f6c047..23eb6c7b64 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -5,7 +5,7 @@ @muladd begin #! format: noindent -@inline function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) +function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter @@ -48,8 +48,7 @@ return nothing end -@inline function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, - cache) +function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index 4ef4a29531..3ed78ee6db 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -5,7 +5,7 @@ @muladd begin #! format: noindent -@inline function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, +function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha = limiter.cache.container_subcell_limiter @@ -23,7 +23,7 @@ return alpha_avg / total_volume end -@inline function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, +function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha = limiter.cache.container_subcell_limiter From d01353b55d42030d8afa8f3a8f7c182fd137760d Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 9 Aug 2023 11:47:09 +0200 Subject: [PATCH 254/423] Remove outdated code --- src/callbacks_step/limiting_analysis_2d.jl | 6 ++---- src/time_integration/methods_SSP.jl | 7 ------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index 3ed78ee6db..1d56d7b58a 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -5,8 +5,7 @@ @muladd begin #! format: noindent -function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, - limiter) +function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha = limiter.cache.container_subcell_limiter @@ -23,8 +22,7 @@ function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, return alpha_avg / total_volume end -function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, - limiter) +function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha = limiter.cache.container_subcell_limiter diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 87275bcdfb..f3a9edb8e4 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -139,13 +139,6 @@ function solve!(integrator::SimpleIntegratorSSP) t_end = last(prob.tspan) callbacks = integrator.opts.callback - # WARNING: Only works if the last callback got a variable `output_directory`. - if callbacks.discrete_callbacks[end].condition isa SaveSolutionCallback - output_directory = callbacks.discrete_callbacks[end].condition.output_directory - else - output_directory = "out" - end - integrator.finalstep = false while !integrator.finalstep if isnan(integrator.dt) From 438e5dbd4b11385abb30df1a410e765d755a571c Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 21 Aug 2023 10:17:48 +0200 Subject: [PATCH 255/423] Merge branch 'main' into subcell-limiting --- .github/dependabot.yml | 2 +- .github/workflows/SpellCheck.yml | 2 +- AUTHORS.md | 1 + NEWS.md | 2 + Project.toml | 2 +- ...lixir_navierstokes_convergence_periodic.jl | 136 ++++++ .../elixir_navierstokes_convergence_walls.jl | 160 +++++++ src/Trixi.jl | 3 +- src/callbacks_stage/bounds_check_2d.jl | 6 +- .../subcell_limiter_idp_correction_2d.jl | 8 +- src/callbacks_step/limiting_analysis.jl | 4 +- src/callbacks_step/limiting_analysis_2d.jl | 8 +- src/equations/compressible_euler_1d.jl | 51 +++ src/equations/compressible_navier_stokes.jl | 70 +++ .../compressible_navier_stokes_1d.jl | 403 ++++++++++++++++++ .../compressible_navier_stokes_2d.jl | 77 +--- .../compressible_navier_stokes_3d.jl | 6 +- src/equations/equations_parabolic.jl | 2 + src/equations/shallow_water_1d.jl | 2 +- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 91 ++++ src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 99 +++++ src/solvers/dgsem_tree/containers_2d.jl | 3 + src/solvers/dgsem_tree/dg_2d_parabolic.jl | 252 ++++++++++- .../dgsem_tree/dg_2d_subcell_limiters.jl | 52 +-- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 323 +++++++++++++- src/solvers/dgsem_tree/subcell_limiters.jl | 14 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 40 +- src/time_integration/methods_SSP.jl | 8 +- test/runtests.jl | 4 +- test/test_parabolic_1d.jl | 35 +- test/test_parabolic_2d.jl | 54 +++ test/test_parabolic_3d.jl | 58 ++- 32 files changed, 1814 insertions(+), 164 deletions(-) create mode 100644 examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl create mode 100644 examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl create mode 100644 src/equations/compressible_navier_stokes.jl create mode 100644 src/equations/compressible_navier_stokes_1d.jl diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 700707ced3..d60f0707fc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,4 +4,4 @@ updates: - package-ecosystem: "github-actions" directory: "/" # Location of package manifests schedule: - interval: "weekly" + interval: "monthly" diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml index a1a429cad9..6ebb288ea3 100644 --- a/.github/workflows/SpellCheck.yml +++ b/.github/workflows/SpellCheck.yml @@ -10,4 +10,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v3 - name: Check spelling - uses: crate-ci/typos@v1.16.2 + uses: crate-ci/typos@v1.16.5 diff --git a/AUTHORS.md b/AUTHORS.md index abaa3e7e03..74bfaa9c85 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -28,6 +28,7 @@ are listed in alphabetical order: * Jesse Chan * Lars Christmann * Christof Czernik +* Daniel Doehring * Patrick Ersing * Erik Faulhaber * Gregor Gassner diff --git a/NEWS.md b/NEWS.md index 8e374d9ce9..4b96e1e283 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,8 +9,10 @@ for human readability. #### Added - Experimental support for 3D parabolic diffusion terms has been added. +- Non-uniform `TreeMesh` available for hyperbolic-parabolic equations. - Capability to set truly discontinuous initial conditions in 1D. - Wetting and drying feature and examples for 1D and 2D shallow water equations +- Subcell positivity limiting support for conservative variables in 2D for `TreeMesh` #### Changed diff --git a/Project.toml b/Project.toml index c22d4b9064..dd937ed213 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.5.38-pre" +version = "0.5.39-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl new file mode 100644 index 0000000000..3f72d319b0 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl @@ -0,0 +1,136 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 6.25e-4 # equivalent to Re = 1600 + +equations = CompressibleEulerEquations1D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), + Prandtl=prandtl_number()) + +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +# (Simplified version of the 2D) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + rho = c + A * sin(pi_x) * cos(pi_t) + v1 = sin(pi_x) * cos(pi_t) + p = rho^2 + + return prim2cons(SVector(rho, v1, p), equations) +end +initial_condition = initial_condition_navier_stokes_convergence_test + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_t) + + v1 = sin(pi_x) * cos(pi_t) + v1_t = -pi * sin(pi_x) * sin(pi_t) + v1_x = pi * cos(pi_x) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * cos(pi_t) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # x-momentum equation + du2 = ( rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + # stress tensor from x-direction + - v1_xx * mu_) + + # total energy equation + du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) + # stress tensor and temperature gradient terms from x-direction + - v1_xx * v1 * mu_ + - v1_x * v1_x * mu_ + - T_const * inv_rho_cubed * ( p_xx * rho * rho + - 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x + - p * rho * rho_xx ) * mu_) + + return SVector(du1, du2, du3) +end + +volume_flux = flux_ranocha +solver = DGSEM(polydeg=3, surface_flux=flux_hllc, + volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = -1.0 +coordinates_max = 1.0 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + n_cells_max=100_000) + + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver, + source_terms = source_terms_navier_stokes_convergence_test) + +############################################################################### +# 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) + +alive_callback = AliveCallback(analysis_interval=analysis_interval,) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-9 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl new file mode 100644 index 0000000000..181a2cb209 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl @@ -0,0 +1,160 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations1D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), Prandtl=prandtl_number(), + gradient_variables=GradientVariablesPrimitive()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, + volume_integral=VolumeIntegralWeakForm()) + +coordinates_min = -1.0 +coordinates_max = 1.0 + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + periodicity=false, + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) +# and by the initial condition (which passes in `CompressibleEulerEquations1D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0)) ) * cos(pi_t) + p = rho^2 + + return prim2cons(SVector(rho, v1, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = (( 2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) + - A * A * log(x + 2.0) * exp(-A * (x - 1.0)) + - (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = ( rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + # stress tensor from y-direction + - v1_xx * mu_) + + # total energy equation + du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) + # stress tensor and temperature gradient terms from x-direction + - v1_xx * v1 * mu_ + - v1_x * v1_x * mu_ + - T_const * inv_rho_cubed * ( p_xx * rho * rho + - 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x + - p * rho * rho_xx ) * mu_ ) + + return SVector(du1, du2, du3) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> + Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), + equations_parabolic)) +heat_bc_right = Adiabatic((x, t, equations) -> 0.0) + +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_right) + +# define inviscid boundary conditions +boundary_conditions = (; x_neg = boundary_condition_slip_wall, + x_pos = boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; x_neg = boundary_condition_left, + x_pos = boundary_condition_right) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary \ No newline at end of file diff --git a/src/Trixi.jl b/src/Trixi.jl index d63be5573f..1c15436713 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -152,7 +152,8 @@ export AcousticPerturbationEquations2D, LinearizedEulerEquations2D export LaplaceDiffusion1D, LaplaceDiffusion2D, - CompressibleNavierStokesDiffusion2D, CompressibleNavierStokesDiffusion3D + CompressibleNavierStokesDiffusion1D, CompressibleNavierStokesDiffusion2D, + CompressibleNavierStokesDiffusion3D export GradientVariablesPrimitive, GradientVariablesEntropy diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 600ff07751..a5e146f555 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -9,7 +9,7 @@ limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors, interval) @unpack local_minmax, positivity, spec_entropy, math_entropy = solver.volume_integral.limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients @unpack idp_bounds_delta = limiter.cache save_errors_ = save_errors && (iter % interval == 0) @@ -138,10 +138,10 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterMCL, time, iter, output_directory, save_errors, interval) - @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @unpack idp_bounds_delta = limiter.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes n_vars = nvariables(equations) diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index 23eb6c7b64..fffb743993 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -7,8 +7,8 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else @@ -50,8 +50,8 @@ end function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.container_subcell_limiter + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index 65d280f33d..55e48cbaf8 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -143,7 +143,7 @@ end limiter::SubcellLimiterIDP, time, iter) @unpack output_directory = limiting_analysis_callback - @unpack alpha = limiter.cache.container_subcell_limiter + @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha_avg = analyze_coefficient_IDP(mesh, equations, dg, cache, limiter) @@ -159,7 +159,7 @@ end @unpack output_directory = limiting_analysis_callback @unpack weights = dg.basis @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients n_vars = nvariables(equations) diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index 1d56d7b58a..a6b5c498c3 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -7,7 +7,7 @@ function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, limiter) @unpack weights = dg.basis - @unpack alpha = limiter.cache.container_subcell_limiter + @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) @@ -24,7 +24,7 @@ end function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, limiter) @unpack weights = dg.basis - @unpack alpha = limiter.cache.container_subcell_limiter + @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha_avg = zero(eltype(alpha)) total_volume = zero(eltype(alpha)) @@ -42,7 +42,7 @@ end function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, - alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients n_vars = nvariables(equations) @@ -87,7 +87,7 @@ function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, limiter) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, - alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients n_vars = nvariables(equations) diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index e4fd0997ea..9204989e8b 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -198,6 +198,57 @@ function initial_condition_eoc_test_coupled_euler_gravity(x, t, return prim2cons(SVector(rho, v1, p), equations) end +""" + boundary_condition_slip_wall(u_inner, orientation, direction, x, t, + surface_flux_function, equations::CompressibleEulerEquations1D) +Determine the boundary numerical surface flux for a slip wall condition. +Imposes a zero normal velocity at the wall. +Density is taken from the internal solution state and pressure is computed as an +exact solution of a 1D Riemann problem. Further details about this boundary state +are available in the paper: +- J. J. W. van der Vegt and H. van der Ven (2002) + Slip flow boundary conditions in discontinuous Galerkin discretizations of + the Euler equations of gas dynamics + [PDF](https://reports.nlr.nl/bitstream/handle/10921/692/TP-2002-300.pdf?sequence=1) + + Should be used together with [`TreeMesh`](@ref). +""" +@inline function boundary_condition_slip_wall(u_inner, orientation, + direction, x, t, + surface_flux_function, + equations::CompressibleEulerEquations1D) + # compute the primitive variables + rho_local, v_normal, p_local = cons2prim(u_inner, equations) + + if isodd(direction) # flip sign of normal to make it outward pointing + v_normal *= -1 + end + + # Get the solution of the pressure Riemann problem + # See Section 6.3.3 of + # Eleuterio F. Toro (2009) + # Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction + # [DOI: 10.1007/b79761](https://doi.org/10.1007/b79761) + if v_normal <= 0.0 + sound_speed = sqrt(equations.gamma * p_local / rho_local) # local sound speed + p_star = p_local * + (1 + 0.5 * (equations.gamma - 1) * v_normal / sound_speed)^(2 * + equations.gamma * + equations.inv_gamma_minus_one) + else # v_normal > 0.0 + A = 2 / ((equations.gamma + 1) * rho_local) + B = p_local * (equations.gamma - 1) / (equations.gamma + 1) + p_star = p_local + + 0.5 * v_normal / A * + (v_normal + sqrt(v_normal^2 + 4 * A * (p_local + B))) + end + + # For the slip wall we directly set the flux as the normal velocity is zero + return SVector(zero(eltype(u_inner)), + p_star, + zero(eltype(u_inner))) +end + # Calculate 1D flux for a single point @inline function flux(u, orientation::Integer, equations::CompressibleEulerEquations1D) rho, rho_v1, rho_e = u diff --git a/src/equations/compressible_navier_stokes.jl b/src/equations/compressible_navier_stokes.jl new file mode 100644 index 0000000000..af7897d458 --- /dev/null +++ b/src/equations/compressible_navier_stokes.jl @@ -0,0 +1,70 @@ +# TODO: can we generalize this to MHD? +""" + struct BoundaryConditionNavierStokesWall + +Creates a wall-type boundary conditions for the compressible Navier-Stokes equations. +The fields `boundary_condition_velocity` and `boundary_condition_heat_flux` are intended +to be boundary condition types such as the `NoSlip` velocity boundary condition and the +`Adiabatic` or `Isothermal` heat boundary condition. + +!!! warning "Experimental feature" + This is an experimental feature and may change in future releases. +""" +struct BoundaryConditionNavierStokesWall{V, H} + boundary_condition_velocity::V + boundary_condition_heat_flux::H +end + +""" + struct NoSlip + +Use to create a no-slip boundary condition with `BoundaryConditionNavierStokesWall`. The field `boundary_value_function` +should be a function with signature `boundary_value_function(x, t, equations)` +and should return a `SVector{NDIMS}` whose entries are the velocity vector at a +point `x` and time `t`. +""" +struct NoSlip{F} + boundary_value_function::F # value of the velocity vector on the boundary +end + +""" + struct Isothermal + +Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). +The field `boundary_value_function` should be a function with signature +`boundary_value_function(x, t, equations)` and return a scalar value for the +temperature at point `x` and time `t`. +""" +struct Isothermal{F} + boundary_value_function::F # value of the temperature on the boundary +end + +""" + struct Adiabatic + +Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). +The field `boundary_value_normal_flux_function` should be a function with signature +`boundary_value_normal_flux_function(x, t, equations)` and return a scalar value for the +normal heat flux at point `x` and time `t`. +""" +struct Adiabatic{F} + boundary_value_normal_flux_function::F # scaled heat flux 1/T * kappa * dT/dn +end + +""" +!!! warning "Experimental code" + This code is experimental and may be changed or removed in any future release. + +`GradientVariablesPrimitive` and `GradientVariablesEntropy` are gradient variable type parameters +for `CompressibleNavierStokesDiffusion1D`. By default, the gradient variables are set to be +`GradientVariablesPrimitive`. Specifying `GradientVariablesEntropy` instead uses the entropy variable +formulation from +- Hughes, Mallet, Franca (1986) + A new finite element formulation for computational fluid dynamics: I. Symmetric forms of the + compressible Euler and Navier-Stokes equations and the second law of thermodynamics. + [https://doi.org/10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) + +Under `GradientVariablesEntropy`, the Navier-Stokes discretization is provably entropy stable. +""" +struct GradientVariablesPrimitive end +struct GradientVariablesEntropy end diff --git a/src/equations/compressible_navier_stokes_1d.jl b/src/equations/compressible_navier_stokes_1d.jl new file mode 100644 index 0000000000..dca846cac1 --- /dev/null +++ b/src/equations/compressible_navier_stokes_1d.jl @@ -0,0 +1,403 @@ +@doc raw""" + CompressibleNavierStokesDiffusion1D(equations; mu, Pr, + gradient_variables=GradientVariablesPrimitive()) + +Contains the diffusion (i.e. parabolic) terms applied +to mass, momenta, and total energy together with the advective terms from +the [`CompressibleEulerEquations1D`](@ref). + +- `equations`: instance of the [`CompressibleEulerEquations1D`](@ref) +- `mu`: dynamic viscosity, +- `Pr`: Prandtl number, +- `gradient_variables`: which variables the gradients are taken with respect to. + Defaults to `GradientVariablesPrimitive()`. + +Fluid properties such as the dynamic viscosity ``\mu`` can be provided in any consistent unit system, e.g., +[``\mu``] = kg m⁻¹ s⁻¹. + +The particular form of the compressible Navier-Stokes implemented is +```math +\frac{\partial}{\partial t} +\begin{pmatrix} +\rho \\ \rho v \\ \rho e +\end{pmatrix} ++ +\frac{\partial}{\partial x} +\begin{pmatrix} + \rho v \\ \rho v^2 + p \\ (\rho e + p) v +\end{pmatrix} += +\frac{\partial}{\partial x} +\begin{pmatrix} +0 \\ \tau \\ \tau v - q +\end{pmatrix} +``` +where the system is closed with the ideal gas assumption giving +```math +p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v^2 \right) +``` +as the pressure. The value of the adiabatic constant `gamma` is taken from the [`CompressibleEulerEquations1D`](@ref). +The terms on the right hand side of the system above +are built from the viscous stress +```math +\tau = \mu \frac{\partial}{\partial x} v +``` +where the heat flux is +```math +q = -\kappa \frac{\partial}{\partial x} \left(T\right),\quad T = \frac{p}{R\rho} +``` +where ``T`` is the temperature and ``\kappa`` is the thermal conductivity for Fick's law. +Under the assumption that the gas has a constant Prandtl number, +the thermal conductivity is +```math +\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}. +``` +From this combination of temperature ``T`` and thermal conductivity ``\kappa`` we see +that the gas constant `R` cancels and the heat flux becomes +```math +q = -\kappa \frac{\partial}{\partial x} \left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}} \frac{\partial}{\partial x} \left(\frac{p}{\rho}\right) +``` +which is the form implemented below in the [`flux`](@ref) function. + +In one spatial dimensions we require gradients for two quantities, e.g., +primitive quantities +```math +\frac{\partial}{\partial x} v,\, \frac{\partial}{\partial x} T +``` +or the entropy variables +```math +\frac{\partial}{\partial x} w_2,\, \frac{\partial}{\partial x} w_3 +``` +where +```math +w_2 = \frac{\rho v1}{p},\, w_3 = -\frac{\rho}{p} +``` + +!!! warning "Experimental code" + This code is experimental and may be changed or removed in any future release. +""" +struct CompressibleNavierStokesDiffusion1D{GradientVariables, RealT <: Real, + E <: AbstractCompressibleEulerEquations{1}} <: + AbstractCompressibleNavierStokesDiffusion{1, 3} + # TODO: parabolic + # 1) For now save gamma and inv(gamma-1) again, but could potentially reuse them from the Euler equations + # 2) Add NGRADS as a type parameter here and in AbstractEquationsParabolic, add `ngradients(...)` accessor function + gamma::RealT # ratio of specific heats + inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications + + mu::RealT # viscosity + Pr::RealT # Prandtl number + kappa::RealT # thermal diffusivity for Fick's law + + equations_hyperbolic::E # CompressibleEulerEquations1D + gradient_variables::GradientVariables # GradientVariablesPrimitive or GradientVariablesEntropy +end + +# default to primitive gradient variables +function CompressibleNavierStokesDiffusion1D(equations::CompressibleEulerEquations1D; + mu, Prandtl, + gradient_variables = GradientVariablesPrimitive()) + gamma = equations.gamma + inv_gamma_minus_one = equations.inv_gamma_minus_one + μ, Pr = promote(mu, Prandtl) + + # Under the assumption of constant Prandtl number the thermal conductivity + # constant is kappa = gamma μ / ((gamma-1) Pr). + # Important note! Factor of μ is accounted for later in `flux`. + kappa = gamma * inv_gamma_minus_one / Pr + + CompressibleNavierStokesDiffusion1D{typeof(gradient_variables), typeof(gamma), + typeof(equations)}(gamma, inv_gamma_minus_one, + μ, Pr, kappa, + equations, gradient_variables) +end + +# TODO: parabolic +# This is the flexibility a user should have to select the different gradient variable types +# varnames(::typeof(cons2prim) , ::CompressibleNavierStokesDiffusion1D) = ("v1", "v2", "T") +# varnames(::typeof(cons2entropy), ::CompressibleNavierStokesDiffusion1D) = ("w2", "w3", "w4") + +function varnames(variable_mapping, + equations_parabolic::CompressibleNavierStokesDiffusion1D) + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) +end + +# we specialize this function to compute gradients of primitive variables instead of +# conservative variables. +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + cons2prim +end +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + cons2entropy +end + +# Explicit formulas for the diffusive Navier-Stokes fluxes are available, e.g., in Section 2 +# of the paper by Rueda-Ramírez, Hennemann, Hindenlang, Winters, and Gassner +# "An Entropy Stable Nodal Discontinuous Galerkin Method for the resistive +# MHD Equations. Part II: Subcell Finite Volume Shock Capturing" +# where one sets the magnetic field components equal to 0. +function flux(u, gradients, orientation::Integer, + equations::CompressibleNavierStokesDiffusion1D) + # Here, `u` is assumed to be the "transformed" variables specified by `gradient_variable_transformation`. + rho, v1, _ = convert_transformed_to_primitive(u, equations) + # Here `gradients` is assumed to contain the gradients of the primitive variables (rho, v1, v2, T) + # either computed directly or reverse engineered from the gradient of the entropy variables + # by way of the `convert_gradient_variables` function. + _, dv1dx, dTdx = convert_derivative_to_primitive(u, gradients, equations) + + # Viscous stress (tensor) + tau_11 = dv1dx + + # Fick's law q = -kappa * grad(T) = -kappa * grad(p / (R rho)) + # with thermal diffusivity constant kappa = gamma μ R / ((gamma-1) Pr) + # Note, the gas constant cancels under this formulation, so it is not present + # in the implementation + q1 = equations.kappa * dTdx + + # Constant dynamic viscosity is copied to a variable for readability. + # Offers flexibility for dynamic viscosity via Sutherland's law where it depends + # on temperature and reference values, Ts and Tref such that mu(T) + mu = equations.mu + + # viscous flux components in the x-direction + f1 = zero(rho) + f2 = tau_11 * mu + f3 = (v1 * tau_11 + q1) * mu + + return SVector(f1, f2, f3) +end + +# Convert conservative variables to primitive +@inline function cons2prim(u, equations::CompressibleNavierStokesDiffusion1D) + rho, rho_v1, _ = u + + v1 = rho_v1 / rho + T = temperature(u, equations) + + return SVector(rho, v1, T) +end + +# Convert conservative variables to entropy +# TODO: parabolic. We can improve efficiency by not computing w_1, which involves logarithms +# This can be done by specializing `cons2entropy` and `entropy2cons` to `CompressibleNavierStokesDiffusion1D`, +# but this may be confusing to new users. +function cons2entropy(u, equations::CompressibleNavierStokesDiffusion1D) + cons2entropy(u, equations.equations_hyperbolic) +end +function entropy2cons(w, equations::CompressibleNavierStokesDiffusion1D) + entropy2cons(w, equations.equations_hyperbolic) +end + +# the `flux` function takes in transformed variables `u` which depend on the type of the gradient variables. +# For CNS, it is simplest to formulate the viscous terms in primitive variables, so we transform the transformed +# variables into primitive variables. +@inline function convert_transformed_to_primitive(u_transformed, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + return u_transformed +end + +# TODO: parabolic. Make this more efficient! +@inline function convert_transformed_to_primitive(u_transformed, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + # note: this uses CompressibleNavierStokesDiffusion1D versions of cons2prim and entropy2cons + return cons2prim(entropy2cons(u_transformed, equations), equations) +end + +# Takes the solution values `u` and gradient of the entropy variables (w_2, w_3, w_4) and +# reverse engineers the gradients to be terms of the primitive variables (v1, v2, T). +# Helpful because then the diffusive fluxes have the same form as on paper. +# Note, the first component of `gradient_entropy_vars` contains gradient(rho) which is unused. +# TODO: parabolic; entropy stable viscous terms +@inline function convert_derivative_to_primitive(u, gradient, + ::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + return gradient +end + +# the first argument is always the "transformed" variables. +@inline function convert_derivative_to_primitive(w, gradient_entropy_vars, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + + # TODO: parabolic. This is inefficient to pass in transformed variables but then transform them back. + # We can fix this if we directly compute v1, v2, T from the entropy variables + u = entropy2cons(w, equations) # calls a "modified" entropy2cons defined for CompressibleNavierStokesDiffusion1D + rho, rho_v1, _ = u + + v1 = rho_v1 / rho + T = temperature(u, equations) + + return SVector(gradient_entropy_vars[1], + T * (gradient_entropy_vars[2] + v1 * gradient_entropy_vars[3]), # grad(u) = T*(grad(w_2)+v1*grad(w_3)) + T * T * gradient_entropy_vars[3]) +end + +# This routine is required because `prim2cons` is called in `initial_condition`, which +# is called with `equations::CompressibleEulerEquations1D`. This means it is inconsistent +# with `cons2prim(..., ::CompressibleNavierStokesDiffusion1D)` as defined above. +# TODO: parabolic. Is there a way to clean this up? +@inline function prim2cons(u, equations::CompressibleNavierStokesDiffusion1D) + prim2cons(u, equations.equations_hyperbolic) +end + +@inline function temperature(u, equations::CompressibleNavierStokesDiffusion1D) + rho, rho_v1, rho_e = u + + p = (equations.gamma - 1) * (rho_e - 0.5 * rho_v1^2 / rho) + T = p / rho + return T +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Adiabatic})(flux_inner, + u_inner, + orientation::Integer, + direction, + x, t, + operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + return SVector(u_inner[1], v1, u_inner[3]) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Adiabatic})(flux_inner, + u_inner, + orientation::Integer, + direction, + x, t, + operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + # rho, v1, v2, _ = u_inner + normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, + t, + equations) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + _, tau_1n, _ = flux_inner # extract fluxes for 2nd equation + normal_energy_flux = v1 * tau_1n + normal_heat_flux + return SVector(flux_inner[1], flux_inner[2], normal_energy_flux) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Isothermal})(flux_inner, + u_inner, + orientation::Integer, + direction, + x, t, + operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, + equations) + return SVector(u_inner[1], v1, T) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Isothermal})(flux_inner, + u_inner, + orientation::Integer, + direction, + x, t, + operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesPrimitive + }) + return flux_inner +end + +# specialized BC impositions for GradientVariablesEntropy. + +# This should return a SVector containing the boundary values of entropy variables. +# Here, `w_inner` are the transformed variables (e.g., entropy variables). +# +# Taken from "Entropy stable modal discontinuous Galerkin schemes and wall boundary conditions +# for the compressible Navier-Stokes equations" by Chan, Lin, Warburton 2022. +# DOI: 10.1016/j.jcp.2021.110723 +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Adiabatic})(flux_inner, + w_inner, + orientation::Integer, + direction, + x, t, + operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + negative_rho_inv_p = w_inner[3] # w_3 = -rho / p + return SVector(w_inner[1], -v1 * negative_rho_inv_p, negative_rho_inv_p) +end + +# this is actually identical to the specialization for GradientVariablesPrimitive, but included for completeness. +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Adiabatic})(flux_inner, + w_inner, + orientation::Integer, + direction, + x, t, + operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, + t, + equations) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + _, tau_1n, _ = flux_inner # extract fluxes for 2nd equation + normal_energy_flux = v1 * tau_1n + normal_heat_flux + return SVector(flux_inner[1], flux_inner[2], normal_energy_flux) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Isothermal})(flux_inner, + w_inner, + orientation::Integer, + direction, + x, t, + operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations) + T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, + equations) + + # the entropy variables w2 = rho * v1 / p = v1 / T = -v1 * w3. + w3 = -1 / T + return SVector(w_inner[1], -v1 * w3, w3) +end + +@inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, + <:Isothermal})(flux_inner, + w_inner, + orientation::Integer, + direction, + x, t, + operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion1D{ + GradientVariablesEntropy + }) + return SVector(flux_inner[1], flux_inner[2], flux_inner[3]) +end diff --git a/src/equations/compressible_navier_stokes_2d.jl b/src/equations/compressible_navier_stokes_2d.jl index a1f11717e6..f762fe5d5e 100644 --- a/src/equations/compressible_navier_stokes_2d.jl +++ b/src/equations/compressible_navier_stokes_2d.jl @@ -29,7 +29,7 @@ The particular form of the compressible Navier-Stokes implemented is = \nabla \cdot \begin{pmatrix} -0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \nabla q +0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \mathbf{q} \end{pmatrix} ``` where the system is closed with the ideal gas assumption giving @@ -44,7 +44,7 @@ are built from the viscous stress tensor ``` where ``\underline{I}`` is the ``2\times 2`` identity matrix and the heat flux is ```math -\nabla q = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho} +\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho} ``` where ``T`` is the temperature and ``\kappa`` is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, @@ -55,7 +55,7 @@ the thermal conductivity is From this combination of temperature ``T`` and thermal conductivity ``\kappa`` we see that the gas constant `R` cancels and the heat flux becomes ```math -\nabla q = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right) +\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right) ``` which is the form implemented below in the [`flux`](@ref) function. @@ -93,24 +93,6 @@ struct CompressibleNavierStokesDiffusion2D{GradientVariables, RealT <: Real, gradient_variables::GradientVariables # GradientVariablesPrimitive or GradientVariablesEntropy end -""" -!!! warning "Experimental code" - This code is experimental and may be changed or removed in any future release. - -`GradientVariablesPrimitive` and `GradientVariablesEntropy` are gradient variable type parameters -for `CompressibleNavierStokesDiffusion2D`. By default, the gradient variables are set to be -`GradientVariablesPrimitive`. Specifying `GradientVariablesEntropy` instead uses the entropy variable -formulation from -- Hughes, Mallet, Franca (1986) - A new finite element formulation for computational fluid dynamics: I. Symmetric forms of the - compressible Euler and Navier-Stokes equations and the second law of thermodynamics. - [https://doi.org/10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) - -Under `GradientVariablesEntropy`, the Navier-Stokes discretization is provably entropy stable. -""" -struct GradientVariablesPrimitive end -struct GradientVariablesEntropy end - # default to primitive gradient variables function CompressibleNavierStokesDiffusion2D(equations::CompressibleEulerEquations2D; mu, Prandtl, @@ -315,59 +297,6 @@ end return dv2dx - dv1dy end -# TODO: can we generalize this to MHD? -""" - struct BoundaryConditionNavierStokesWall - -Creates a wall-type boundary conditions for the compressible Navier-Stokes equations. -The fields `boundary_condition_velocity` and `boundary_condition_heat_flux` are intended -to be boundary condition types such as the `NoSlip` velocity boundary condition and the -`Adiabatic` or `Isothermal` heat boundary condition. - -!!! warning "Experimental feature" - This is an experimental feature and may change in future releases. -""" -struct BoundaryConditionNavierStokesWall{V, H} - boundary_condition_velocity::V - boundary_condition_heat_flux::H -end - -""" - struct NoSlip - -Use to create a no-slip boundary condition with `BoundaryConditionNavierStokesWall`. The field `boundary_value_function` -should be a function with signature `boundary_value_function(x, t, equations)` -and should return a `SVector{NDIMS}` whose entries are the velocity vector at a -point `x` and time `t`. -""" -struct NoSlip{F} - boundary_value_function::F # value of the velocity vector on the boundary -end - -""" - struct Isothermal - -Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). -The field `boundary_value_function` should be a function with signature -`boundary_value_function(x, t, equations)` and return a scalar value for the -temperature at point `x` and time `t`. -""" -struct Isothermal{F} - boundary_value_function::F # value of the temperature on the boundary -end - -""" - struct Adiabatic - -Used to create a no-slip boundary condition with [`BoundaryConditionNavierStokesWall`](@ref). -The field `boundary_value_normal_flux_function` should be a function with signature -`boundary_value_normal_flux_function(x, t, equations)` and return a scalar value for the -normal heat flux at point `x` and time `t`. -""" -struct Adiabatic{F} - boundary_value_normal_flux_function::F # scaled heat flux 1/T * kappa * dT/dn -end - @inline function (boundary_condition::BoundaryConditionNavierStokesWall{<:NoSlip, <:Adiabatic})(flux_inner, u_inner, diff --git a/src/equations/compressible_navier_stokes_3d.jl b/src/equations/compressible_navier_stokes_3d.jl index 0b770dff1c..166b53bf61 100644 --- a/src/equations/compressible_navier_stokes_3d.jl +++ b/src/equations/compressible_navier_stokes_3d.jl @@ -29,7 +29,7 @@ The particular form of the compressible Navier-Stokes implemented is = \nabla \cdot \begin{pmatrix} -0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \nabla q +0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \mathbf{q} \end{pmatrix} ``` where the system is closed with the ideal gas assumption giving @@ -44,7 +44,7 @@ are built from the viscous stress tensor ``` where ``\underline{I}`` is the ``3\times 3`` identity matrix and the heat flux is ```math -\nabla q = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho} +\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho} ``` where ``T`` is the temperature and ``\kappa`` is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, @@ -55,7 +55,7 @@ the thermal conductivity is From this combination of temperature ``T`` and thermal conductivity ``\kappa`` we see that the gas constant `R` cancels and the heat flux becomes ```math -\nabla q = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right) +\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right) ``` which is the form implemented below in the [`flux`](@ref) function. diff --git a/src/equations/equations_parabolic.jl b/src/equations/equations_parabolic.jl index 6c0be43798..6621402504 100644 --- a/src/equations/equations_parabolic.jl +++ b/src/equations/equations_parabolic.jl @@ -11,5 +11,7 @@ include("laplace_diffusion_2d.jl") # Compressible Navier-Stokes equations abstract type AbstractCompressibleNavierStokesDiffusion{NDIMS, NVARS} <: AbstractEquationsParabolic{NDIMS, NVARS} end +include("compressible_navier_stokes.jl") +include("compressible_navier_stokes_1d.jl") include("compressible_navier_stokes_2d.jl") include("compressible_navier_stokes_3d.jl") diff --git a/src/equations/shallow_water_1d.jl b/src/equations/shallow_water_1d.jl index 57bcb1212e..32782d5478 100644 --- a/src/equations/shallow_water_1d.jl +++ b/src/equations/shallow_water_1d.jl @@ -653,7 +653,7 @@ end c_rr = sqrt(equations.gravity * h_rr) λ_min = min(v_ll - c_ll, v_rr - c_rr) - λ_max = max(v_rr + c_rr, v_rr + c_rr) + λ_max = max(v_ll + c_ll, v_rr + c_rr) return λ_min, λ_max end diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 7e90a83a9c..a04523d2fb 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -22,6 +22,97 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra return cache end +# TODO: Remove in favor of the implementation for the TreeMesh +# once the P4estMesh can handle mortars as well +function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + initial_condition, boundary_conditions_parabolic, source_terms, + dg::DG, parabolic_scheme, cache, cache_parabolic) + (; u_transformed, gradients, flux_viscous) = cache_parabolic + + # Convert conservative variables to a form more suitable for viscous flux calculations + @trixi_timeit timer() "transform variables" begin + transform_variables!(u_transformed, u, mesh, equations_parabolic, + dg, parabolic_scheme, cache, cache_parabolic) + end + + # Compute the gradients of the transformed variables + @trixi_timeit timer() "calculate gradient" begin + calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, + boundary_conditions_parabolic, dg, cache, cache_parabolic) + end + + # Compute and store the viscous fluxes + @trixi_timeit timer() "calculate viscous fluxes" begin + calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh, + equations_parabolic, dg, cache, cache_parabolic) + end + + # The remainder of this function is essentially a regular rhs! for parabolic + # equations (i.e., it computes the divergence of the viscous fluxes) + # + # OBS! In `calc_viscous_fluxes!`, the viscous flux values at the volume nodes of each element have + # been computed and stored in `fluxes_viscous`. In the following, we *reuse* (abuse) the + # `interfaces` and `boundaries` containers in `cache_parabolic` to interpolate and store the + # *fluxes* at the element surfaces, as opposed to interpolating and storing the *solution* (as it + # is done in the hyperbolic operator). That is, `interfaces.u`/`boundaries.u` store *viscous flux values* + # and *not the solution*. The advantage is that a) we do not need to allocate more storage, b) we + # do not need to recreate the existing data structure only with a different name, and c) we do not + # need to interpolate solutions *and* gradients to the surfaces. + + # TODO: parabolic; reconsider current data structure reuse strategy + + # Reset du + @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) + + # Calculate volume integral + @trixi_timeit timer() "volume integral" begin + calc_volume_integral!(du, flux_viscous, mesh, equations_parabolic, dg, cache) + end + + # Prolong solution to interfaces + @trixi_timeit timer() "prolong2interfaces" begin + prolong2interfaces!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) + end + + # Calculate interface fluxes + @trixi_timeit timer() "interface flux" begin + calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, dg, cache_parabolic) + end + + # Prolong solution to boundaries + @trixi_timeit timer() "prolong2boundaries" begin + prolong2boundaries!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) + end + + # Calculate boundary fluxes + @trixi_timeit timer() "boundary flux" begin + calc_boundary_flux_divergence!(cache_parabolic, t, + boundary_conditions_parabolic, mesh, + equations_parabolic, + dg.surface_integral, dg) + end + + # TODO: parabolic; extend to mortars + @assert nmortars(dg, cache) == 0 + + # Calculate surface integrals + @trixi_timeit timer() "surface integral" begin + calc_surface_integral!(du, u, mesh, equations_parabolic, + dg.surface_integral, dg, cache_parabolic) + end + + # Apply Jacobian from mapping to reference element + @trixi_timeit timer() "Jacobian" begin + apply_jacobian_parabolic!(du, mesh, equations_parabolic, dg, cache_parabolic) + end + + return nothing +end + function calc_gradient!(gradients, u_transformed, t, mesh::P4estMesh{2}, equations_parabolic, boundary_conditions_parabolic, dg::DG, diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 6439cad69b..2d26c1aff5 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -22,6 +22,105 @@ function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::Abstra return cache end +# This file collects all methods that have been updated to work with parabolic systems of equations +# +# assumptions: parabolic terms are of the form div(f(u, grad(u))) and +# will be discretized first order form as follows: +# 1. compute grad(u) +# 2. compute f(u, grad(u)) +# 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) +# boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). +# TODO: Remove in favor of the implementation for the TreeMesh +# once the P4estMesh can handle mortars as well +function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + initial_condition, boundary_conditions_parabolic, source_terms, + dg::DG, parabolic_scheme, cache, cache_parabolic) + @unpack u_transformed, gradients, flux_viscous = cache_parabolic + + # Convert conservative variables to a form more suitable for viscous flux calculations + @trixi_timeit timer() "transform variables" begin + transform_variables!(u_transformed, u, mesh, equations_parabolic, + dg, parabolic_scheme, cache, cache_parabolic) + end + + # Compute the gradients of the transformed variables + @trixi_timeit timer() "calculate gradient" begin + calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, + boundary_conditions_parabolic, dg, cache, cache_parabolic) + end + + # Compute and store the viscous fluxes + @trixi_timeit timer() "calculate viscous fluxes" begin + calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh, + equations_parabolic, dg, cache, cache_parabolic) + end + + # The remainder of this function is essentially a regular rhs! for parabolic + # equations (i.e., it computes the divergence of the viscous fluxes) + # + # OBS! In `calc_viscous_fluxes!`, the viscous flux values at the volume nodes of each element have + # been computed and stored in `fluxes_viscous`. In the following, we *reuse* (abuse) the + # `interfaces` and `boundaries` containers in `cache_parabolic` to interpolate and store the + # *fluxes* at the element surfaces, as opposed to interpolating and storing the *solution* (as it + # is done in the hyperbolic operator). That is, `interfaces.u`/`boundaries.u` store *viscous flux values* + # and *not the solution*. The advantage is that a) we do not need to allocate more storage, b) we + # do not need to recreate the existing data structure only with a different name, and c) we do not + # need to interpolate solutions *and* gradients to the surfaces. + + # TODO: parabolic; reconsider current data structure reuse strategy + + # Reset du + @trixi_timeit timer() "reset ∂u/∂t" reset_du!(du, dg, cache) + + # Calculate volume integral + @trixi_timeit timer() "volume integral" begin + calc_volume_integral!(du, flux_viscous, mesh, equations_parabolic, dg, cache) + end + + # Prolong solution to interfaces + @trixi_timeit timer() "prolong2interfaces" begin + prolong2interfaces!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) + end + + # Calculate interface fluxes + @trixi_timeit timer() "interface flux" begin + calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, dg, cache_parabolic) + end + + # Prolong solution to boundaries + @trixi_timeit timer() "prolong2boundaries" begin + prolong2boundaries!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) + end + + # Calculate boundary fluxes + @trixi_timeit timer() "boundary flux" begin + calc_boundary_flux_divergence!(cache_parabolic, t, + boundary_conditions_parabolic, + mesh, equations_parabolic, + dg.surface_integral, dg) + end + + # TODO: parabolic; extend to mortars + @assert nmortars(dg, cache) == 0 + + # Calculate surface integrals + @trixi_timeit timer() "surface integral" begin + calc_surface_integral!(du, u, mesh, equations_parabolic, + dg.surface_integral, dg, cache_parabolic) + end + + # Apply Jacobian from mapping to reference element + @trixi_timeit timer() "Jacobian" begin + apply_jacobian_parabolic!(du, mesh, equations_parabolic, dg, cache_parabolic) + end + + return nothing +end + function calc_gradient!(gradients, u_transformed, t, mesh::P4estMesh{3}, equations_parabolic, boundary_conditions_parabolic, dg::DG, diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index d79ddcbc51..8ab174d20b 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1320,6 +1320,7 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) return nothing end +# Container data structure (structure-of-arrays style) for variables used for IDP limiting mutable struct ContainerSubcellLimiterIDP2D{uEltype <: Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} @@ -1388,6 +1389,7 @@ function Base.resize!(container::ContainerSubcellLimiterIDP2D, capacity) return nothing end +# Container data structure (structure-of-arrays style) for variables used for MCL limiting mutable struct ContainerSubcellLimiterMCL2D{uEltype <: Real} var_min::Array{uEltype, 4} # [variable, i, j, element] var_max::Array{uEltype, 4} # [variable, i, j, element] @@ -1512,6 +1514,7 @@ function Base.resize!(container::ContainerSubcellLimiterMCL2D, capacity) return nothing end +# Container data structure (structure-of-arrays style) for variables used for subcell limiting useing bar states mutable struct ContainerBarStates{uEltype <: Real} bar_states1::Array{uEltype, 4} # [variable, i, j, element] bar_states2::Array{uEltype, 4} # [variable, i, j, element] diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index c586257999..0da2523038 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -13,7 +13,7 @@ # 2. compute f(u, grad(u)) # 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) # boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). -function rhs_parabolic!(du, u, t, mesh::Union{TreeMesh{2}, P4estMesh{2}}, +function rhs_parabolic!(du, u, t, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) @@ -85,8 +85,18 @@ function rhs_parabolic!(du, u, t, mesh::Union{TreeMesh{2}, P4estMesh{2}}, dg.surface_integral, dg) end - # TODO: parabolic; extend to mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -500,6 +510,227 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end +function prolong2mortars!(cache, flux_viscous::Tuple{AbstractArray, AbstractArray}, + mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, surface_integral, + dg::DGSEM) + flux_viscous_x, flux_viscous_y = flux_viscous + @threaded for mortar in eachmortar(dg, cache) + large_element = cache.mortars.neighbor_ids[3, mortar] + upper_element = cache.mortars.neighbor_ids[2, mortar] + lower_element = cache.mortars.neighbor_ids[1, mortar] + + # Copy solution small to small + if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + for l in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper[2, v, l, mortar] = flux_viscous_x[v, 1, l, + upper_element] + cache.mortars.u_lower[2, v, l, mortar] = flux_viscous_x[v, 1, l, + lower_element] + end + end + else + # L2 mortars in y-direction + for l in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper[2, v, l, mortar] = flux_viscous_y[v, l, 1, + upper_element] + cache.mortars.u_lower[2, v, l, mortar] = flux_viscous_y[v, l, 1, + lower_element] + end + end + end + else # large_sides[mortar] == 2 -> small elements on left side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + for l in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper[1, v, l, mortar] = flux_viscous_x[v, + nnodes(dg), + l, + upper_element] + cache.mortars.u_lower[1, v, l, mortar] = flux_viscous_x[v, + nnodes(dg), + l, + lower_element] + end + end + else + # L2 mortars in y-direction + for l in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper[1, v, l, mortar] = flux_viscous_y[v, l, + nnodes(dg), + upper_element] + cache.mortars.u_lower[1, v, l, mortar] = flux_viscous_y[v, l, + nnodes(dg), + lower_element] + end + end + end + end + + # Interpolate large element face data to small interface locations + if cache.mortars.large_sides[mortar] == 1 # -> large element on left side + leftright = 1 + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(flux_viscous_x, :, nnodes(dg), :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large) + else + # L2 mortars in y-direction + u_large = view(flux_viscous_y, :, :, nnodes(dg), large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large) + end + else # large_sides[mortar] == 2 -> large element on right side + leftright = 2 + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(flux_viscous_x, :, 1, :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large) + else + # L2 mortars in y-direction + u_large = view(flux_viscous_y, :, :, 1, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large) + end + end + end + + return nothing +end + +# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +function calc_mortar_flux!(surface_flux_values, + mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) + @unpack surface_flux = surface_integral + @unpack u_lower, u_upper, orientations = cache.mortars + @unpack fstar_upper_threaded, fstar_lower_threaded = cache + + @threaded for mortar in eachmortar(dg, cache) + # Choose thread-specific pre-allocated container + fstar_upper = fstar_upper_threaded[Threads.threadid()] + fstar_lower = fstar_lower_threaded[Threads.threadid()] + + # Calculate fluxes + orientation = orientations[mortar] + calc_fstar!(fstar_upper, equations_parabolic, surface_flux, dg, u_upper, mortar, + orientation) + calc_fstar!(fstar_lower, equations_parabolic, surface_flux, dg, u_lower, mortar, + orientation) + + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations_parabolic, mortar_l2, dg, cache, + mortar, fstar_upper, fstar_lower) + end + + return nothing +end + +@inline function calc_fstar!(destination::AbstractArray{<:Any, 2}, + equations_parabolic::AbstractEquationsParabolic, + surface_flux, dg::DGSEM, + u_interfaces, interface, orientation) + for i in eachnode(dg) + # Call pointwise two-point numerical flux function + u_ll, u_rr = get_surface_node_vars(u_interfaces, equations_parabolic, dg, i, + interface) + # TODO: parabolic; only BR1 at the moment + flux = 0.5 * (u_ll + u_rr) + + # Copy flux to left and right element storage + set_node_vars!(destination, flux, equations_parabolic, dg, i) + end + + return nothing +end + +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, + mortar, fstar_upper, fstar_lower) + large_element = cache.mortars.neighbor_ids[3, mortar] + upper_element = cache.mortars.neighbor_ids[2, mortar] + lower_element = cache.mortars.neighbor_ids[1, mortar] + + # Copy flux small to small + if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + direction = 1 + else + # L2 mortars in y-direction + direction = 3 + end + else # large_sides[mortar] == 2 -> small elements on left side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + direction = 2 + else + # L2 mortars in y-direction + direction = 4 + end + end + surface_flux_values[:, :, direction, upper_element] .= fstar_upper + surface_flux_values[:, :, direction, lower_element] .= fstar_lower + + # Project small fluxes to large element + if cache.mortars.large_sides[mortar] == 1 # -> large element on left side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + direction = 2 + else + # L2 mortars in y-direction + direction = 4 + end + else # large_sides[mortar] == 2 -> large element on right side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + direction = 1 + else + # L2 mortars in y-direction + direction = 3 + end + end + + # TODO: Taal performance + # for v in eachvariable(equations) + # # The code below is semantically equivalent to + # # surface_flux_values[v, :, direction, large_element] .= + # # (mortar_l2.reverse_upper * fstar_upper[v, :] + mortar_l2.reverse_lower * fstar_lower[v, :]) + # # but faster and does not allocate. + # # Note that `true * some_float == some_float` in Julia, i.e. `true` acts as + # # a universal `one`. Hence, the second `mul!` means "add the matrix-vector + # # product to the current value of the destination". + # @views mul!(surface_flux_values[v, :, direction, large_element], + # mortar_l2.reverse_upper, fstar_upper[v, :]) + # @views mul!(surface_flux_values[v, :, direction, large_element], + # mortar_l2.reverse_lower, fstar_lower[v, :], true, true) + # end + # The code above could be replaced by the following code. However, the relative efficiency + # depends on the types of fstar_upper/fstar_lower and dg.l2mortar_reverse_upper. + # Using StaticArrays for both makes the code above faster for common test cases. + multiply_dimensionwise!(view(surface_flux_values, :, :, direction, large_element), + mortar_l2.reverse_upper, fstar_upper, + mortar_l2.reverse_lower, fstar_lower) + + return nothing +end + # Calculate the gradient of the transformed variables function calc_gradient!(gradients, u_transformed, t, mesh::TreeMesh{2}, equations_parabolic, @@ -589,7 +820,20 @@ function calc_gradient!(gradients, u_transformed, t, dg.surface_integral, dg) end - # TODO: parabolic; mortars + # Prolong solution to mortars + # NOTE: This re-uses the implementation for hyperbolic terms in "dg_2d.jl" + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(surface_flux_values, + mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 60a4ebfd21..0f0fb1a4b7 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -27,11 +27,11 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - container_antidiffusive_flux = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, - nvariables(equations), - nnodes(dg)) + antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, + nvariables(equations), + nnodes(dg)) - return (; cache..., container_antidiffusive_flux, fhat1_threaded, fhat2_threaded, + return (; cache..., antidiffusive_fluxes, fhat1_threaded, fhat2_threaded, flux_temp_threaded) end @@ -178,7 +178,7 @@ end limiter, dg, element, cache, fstar1_L, fstar2_L) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * @@ -278,7 +278,7 @@ end @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, limiter::SubcellLimiterIDP, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -303,7 +303,7 @@ end @inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, nonconservative_terms, equations, limiter::SubcellLimiterMCL, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -531,7 +531,7 @@ end if !limiter.bar_states return nothing end - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states counter = 1 @@ -638,7 +638,7 @@ end @inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, limiter::SubcellLimiterMCL, dg, cache) - @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @threaded for element in eachelement(dg, cache) @@ -778,13 +778,13 @@ end equations, limiter, dg, element, cache, fstar1, fstar2) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux - @unpack var_min, var_max = limiter.cache.container_subcell_limiter + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states if limiter.Plotting @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.container_subcell_limiter + alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha[:, i, j, element] .= one(eltype(alpha)) @@ -837,7 +837,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -887,7 +887,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -948,7 +948,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -999,7 +999,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1043,7 +1043,7 @@ end (antidiffusive_flux1[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1083,7 +1083,7 @@ end (antidiffusive_flux2[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1122,7 +1122,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1168,7 +1168,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1193,7 +1193,7 @@ end # Divide alpha_mean by number of additions if limiter.Plotting - @unpack alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha_mean = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 if limiter.DensityLimiter || limiter.DensityPositivityLimiter for i in eachnode(dg) @@ -1223,7 +1223,7 @@ end # Limit pressure à la Kuzmin if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.container_subcell_limiter + @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 @@ -1334,7 +1334,7 @@ end end end if limiter.Plotting - @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter + @unpack alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_pressure[i, 1, element] += 1.0 @@ -1388,7 +1388,7 @@ end end end if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients alpha_entropy[i - 1, j, element] = min(alpha_entropy[i - 1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1433,7 +1433,7 @@ end end end if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.container_subcell_limiter + @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients alpha_entropy[i, j - 1, element] = min(alpha_entropy[i, j - 1, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1442,7 +1442,7 @@ end end end if limiter.Plotting - @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter + @unpack alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_entropy[i, 1, element] += 1.0 diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 5b63b971cd..2745d312b3 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -13,7 +13,7 @@ # 2. compute f(u, grad(u)) # 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) # boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). -function rhs_parabolic!(du, u, t, mesh::Union{TreeMesh{3}, P4estMesh{3}}, +function rhs_parabolic!(du, u, t, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) @@ -85,8 +85,18 @@ function rhs_parabolic!(du, u, t, mesh::Union{TreeMesh{3}, P4estMesh{3}}, dg.surface_integral, dg) end - # TODO: parabolic; extend to mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -583,6 +593,298 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end +function prolong2mortars!(cache, + flux_viscous::Tuple{AbstractArray, AbstractArray, + AbstractArray}, + mesh::TreeMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) + # temporary buffer for projections + @unpack fstar_tmp1_threaded = cache + + flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous + @threaded for mortar in eachmortar(dg, cache) + fstar_tmp1 = fstar_tmp1_threaded[Threads.threadid()] + + lower_left_element = cache.mortars.neighbor_ids[1, mortar] + lower_right_element = cache.mortars.neighbor_ids[2, mortar] + upper_left_element = cache.mortars.neighbor_ids[3, mortar] + upper_right_element = cache.mortars.neighbor_ids[4, mortar] + large_element = cache.mortars.neighbor_ids[5, mortar] + + # Copy solution small to small + if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + for k in eachnode(dg), j in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[2, v, j, k, mortar] = flux_viscous_x[v, + 1, + j, + k, + upper_left_element] + cache.mortars.u_upper_right[2, v, j, k, mortar] = flux_viscous_x[v, + 1, + j, + k, + upper_right_element] + cache.mortars.u_lower_left[2, v, j, k, mortar] = flux_viscous_x[v, + 1, + j, + k, + lower_left_element] + cache.mortars.u_lower_right[2, v, j, k, mortar] = flux_viscous_x[v, + 1, + j, + k, + lower_right_element] + end + end + elseif cache.mortars.orientations[mortar] == 2 + # L2 mortars in y-direction + for k in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[2, v, i, k, mortar] = flux_viscous_y[v, + i, + 1, + k, + upper_left_element] + cache.mortars.u_upper_right[2, v, i, k, mortar] = flux_viscous_y[v, + i, + 1, + k, + upper_right_element] + cache.mortars.u_lower_left[2, v, i, k, mortar] = flux_viscous_y[v, + i, + 1, + k, + lower_left_element] + cache.mortars.u_lower_right[2, v, i, k, mortar] = flux_viscous_y[v, + i, + 1, + k, + lower_right_element] + end + end + else # orientations[mortar] == 3 + # L2 mortars in z-direction + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[2, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + 1, + upper_left_element] + cache.mortars.u_upper_right[2, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + 1, + upper_right_element] + cache.mortars.u_lower_left[2, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + 1, + lower_left_element] + cache.mortars.u_lower_right[2, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + 1, + lower_right_element] + end + end + end + else # large_sides[mortar] == 2 -> small elements on left side + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + for k in eachnode(dg), j in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[1, v, j, k, mortar] = flux_viscous_x[v, + nnodes(dg), + j, + k, + upper_left_element] + cache.mortars.u_upper_right[1, v, j, k, mortar] = flux_viscous_x[v, + nnodes(dg), + j, + k, + upper_right_element] + cache.mortars.u_lower_left[1, v, j, k, mortar] = flux_viscous_x[v, + nnodes(dg), + j, + k, + lower_left_element] + cache.mortars.u_lower_right[1, v, j, k, mortar] = flux_viscous_x[v, + nnodes(dg), + j, + k, + lower_right_element] + end + end + elseif cache.mortars.orientations[mortar] == 2 + # L2 mortars in y-direction + for k in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[1, v, i, k, mortar] = flux_viscous_y[v, + i, + nnodes(dg), + k, + upper_left_element] + cache.mortars.u_upper_right[1, v, i, k, mortar] = flux_viscous_y[v, + i, + nnodes(dg), + k, + upper_right_element] + cache.mortars.u_lower_left[1, v, i, k, mortar] = flux_viscous_y[v, + i, + nnodes(dg), + k, + lower_left_element] + cache.mortars.u_lower_right[1, v, i, k, mortar] = flux_viscous_y[v, + i, + nnodes(dg), + k, + lower_right_element] + end + end + else # if cache.mortars.orientations[mortar] == 3 + # L2 mortars in z-direction + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations_parabolic) + cache.mortars.u_upper_left[1, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + nnodes(dg), + upper_left_element] + cache.mortars.u_upper_right[1, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + nnodes(dg), + upper_right_element] + cache.mortars.u_lower_left[1, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + nnodes(dg), + lower_left_element] + cache.mortars.u_lower_right[1, v, i, j, mortar] = flux_viscous_z[v, + i, + j, + nnodes(dg), + lower_right_element] + end + end + end + end + + # Interpolate large element face data to small interface locations + if cache.mortars.large_sides[mortar] == 1 # -> large element on left side + leftright = 1 + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(flux_viscous_x, :, nnodes(dg), :, :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + elseif cache.mortars.orientations[mortar] == 2 + # L2 mortars in y-direction + u_large = view(flux_viscous_y, :, :, nnodes(dg), :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + else # cache.mortars.orientations[mortar] == 3 + # L2 mortars in z-direction + u_large = view(flux_viscous_z, :, :, :, nnodes(dg), large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + end + else # large_sides[mortar] == 2 -> large element on right side + leftright = 2 + if cache.mortars.orientations[mortar] == 1 + # L2 mortars in x-direction + u_large = view(flux_viscous_x, :, 1, :, :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + elseif cache.mortars.orientations[mortar] == 2 + # L2 mortars in y-direction + u_large = view(flux_viscous_y, :, :, 1, :, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + else # cache.mortars.orientations[mortar] == 3 + # L2 mortars in z-direction + u_large = view(flux_viscous_z, :, :, :, 1, large_element) + element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright, + mortar, u_large, fstar_tmp1) + end + end + end + + return nothing +end + +# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +function calc_mortar_flux!(surface_flux_values, + mesh::TreeMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) + @unpack surface_flux = surface_integral + @unpack u_lower_left, u_lower_right, u_upper_left, u_upper_right, orientations = cache.mortars + @unpack (fstar_upper_left_threaded, fstar_upper_right_threaded, + fstar_lower_left_threaded, fstar_lower_right_threaded, + fstar_tmp1_threaded) = cache + + @threaded for mortar in eachmortar(dg, cache) + # Choose thread-specific pre-allocated container + fstar_upper_left = fstar_upper_left_threaded[Threads.threadid()] + fstar_upper_right = fstar_upper_right_threaded[Threads.threadid()] + fstar_lower_left = fstar_lower_left_threaded[Threads.threadid()] + fstar_lower_right = fstar_lower_right_threaded[Threads.threadid()] + fstar_tmp1 = fstar_tmp1_threaded[Threads.threadid()] + + # Calculate fluxes + orientation = orientations[mortar] + calc_fstar!(fstar_upper_left, equations_parabolic, surface_flux, dg, + u_upper_left, mortar, + orientation) + calc_fstar!(fstar_upper_right, equations_parabolic, surface_flux, dg, + u_upper_right, + mortar, orientation) + calc_fstar!(fstar_lower_left, equations_parabolic, surface_flux, dg, + u_lower_left, mortar, + orientation) + calc_fstar!(fstar_lower_right, equations_parabolic, surface_flux, dg, + u_lower_right, + mortar, orientation) + + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations_parabolic, mortar_l2, dg, cache, + mortar, + fstar_upper_left, fstar_upper_right, + fstar_lower_left, fstar_lower_right, + fstar_tmp1) + end + + return nothing +end + +@inline function calc_fstar!(destination::AbstractArray{<:Any, 3}, + equations_parabolic::AbstractEquationsParabolic, + surface_flux, dg::DGSEM, + u_interfaces, interface, orientation) + for j in eachnode(dg), i in eachnode(dg) + # Call pointwise two-point numerical flux function + u_ll, u_rr = get_surface_node_vars(u_interfaces, equations_parabolic, dg, i, j, + interface) + # TODO: parabolic; only BR1 at the moment + flux = 0.5 * (u_ll + u_rr) + + # Copy flux to left and right element storage + set_node_vars!(destination, flux, equations_parabolic, dg, i, j) + end + + return nothing +end + # Calculate the gradient of the transformed variables function calc_gradient!(gradients, u_transformed, t, mesh::TreeMesh{3}, equations_parabolic, @@ -679,7 +981,20 @@ function calc_gradient!(gradients, u_transformed, t, dg.surface_integral, dg) end - # TODO: parabolic; mortars + # Prolong solution to mortars + # NOTE: This re-uses the implementation for hyperbolic terms in "dg_3d.jl" + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(surface_flux_values, + mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index a953180352..8dd17c2d6a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -218,7 +218,7 @@ end function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, ::VolumeIntegralSubcellLimiting, equations) - node_variables[:alpha_limiter] = limiter.cache.container_subcell_limiter.alpha + node_variables[:alpha_limiter] = limiter.cache.subcell_limiter_coefficients.alpha # TODO: alpha is not filled before the first timestep. return nothing end @@ -394,7 +394,7 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, if !limiter.Plotting return nothing end - @unpack alpha = limiter.cache.container_subcell_limiter + @unpack alpha = limiter.cache.subcell_limiter_coefficients variables = varnames(cons2cons, equations) for v in eachvariable(equations) s = Symbol("alpha_", variables[v]) @@ -402,28 +402,28 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, end if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_pressure = limiter.cache.container_subcell_limiter + @unpack alpha_pressure = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_pressure] = alpha_pressure end if limiter.SemiDiscEntropyLimiter - @unpack alpha_entropy = limiter.cache.container_subcell_limiter + @unpack alpha_entropy = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_entropy] = alpha_entropy end for v in eachvariable(equations) - @unpack alpha_mean = limiter.cache.container_subcell_limiter + @unpack alpha_mean = limiter.cache.subcell_limiter_coefficients s = Symbol("alpha_mean_", variables[v]) node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) end if limiter.PressurePositivityLimiterKuzmin - @unpack alpha_mean_pressure = limiter.cache.container_subcell_limiter + @unpack alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_mean_pressure] = alpha_mean_pressure end if limiter.SemiDiscEntropyLimiter - @unpack alpha_mean_entropy = limiter.cache.container_subcell_limiter + @unpack alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_mean_entropy] = alpha_mean_entropy end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index f66321e393..7db04ca83f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -8,10 +8,10 @@ # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds, bar_states) - container_subcell_limiter = Trixi.ContainerSubcellLimiterIDP2D{real(basis) - }(0, - nnodes(basis), - number_bounds) + subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis) + }(0, + nnodes(basis), + number_bounds) cache = (;) if bar_states @@ -23,13 +23,13 @@ function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquat idp_bounds_delta = zeros(real(basis), number_bounds) - return (; cache..., container_subcell_limiter, idp_bounds_delta) + return (; cache..., subcell_limiter_coefficients, idp_bounds_delta) end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; kwargs...) - @unpack alpha = limiter.cache.container_subcell_limiter + @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha .= zero(eltype(alpha)) if limiter.smoothness_indicator elements = semi.cache.element_ids_dgfv @@ -59,7 +59,7 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE end # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = limiter.cache.container_subcell_limiter + @unpack alpha1, alpha2 = limiter.cache.subcell_limiter_coefficients @threaded for element in elements for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) @@ -328,7 +328,7 @@ end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) mesh, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[2 * (index - 1) + 1] var_max = variable_bounds[2 * (index - 1) + 2] @@ -336,7 +336,7 @@ end calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) end - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes @unpack inverse_weights = dg.basis @threaded for element in elements @@ -396,7 +396,7 @@ end @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients s_min = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + 1] if !limiter.bar_states @@ -428,7 +428,7 @@ end @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack spec_entropy = limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients s_max = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + spec_entropy + 1] if !limiter.bar_states @@ -474,11 +474,11 @@ end @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes @unpack inverse_weights = dg.basis @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients counter = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + math_entropy @@ -562,7 +562,7 @@ end variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = limiter - @unpack variable_bounds = limiter.cache.container_subcell_limiter + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients index_ = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + math_entropy + index @@ -607,7 +607,7 @@ end goal_fct, dgoal_fct, initialCheck, finalCheck, dt, mesh, equations, dg, cache, limiter) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.container_antidiffusive_flux + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes if mesh isa TreeMesh inverse_jacobian = cache.elements.inverse_jacobian[element] else # mesh isa StructuredMesh @@ -748,10 +748,10 @@ end # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) - container_subcell_limiter = Trixi.ContainerSubcellLimiterMCL2D{real(basis) - }(0, - nvariables(equations), - nnodes(basis)) + subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterMCL2D{real(basis) + }(0, + nvariables(equations), + nnodes(basis)) container_bar_states = Trixi.ContainerBarStates{real(basis)}(0, nvariables(equations), nnodes(basis)) @@ -759,6 +759,6 @@ function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquat idp_bounds_delta = zeros(real(basis), 2, nvariables(equations) + PressurePositivityLimiterKuzmin) - return (; container_subcell_limiter, container_bar_states, idp_bounds_delta) + return (; subcell_limiter_coefficients, container_bar_states, idp_bounds_delta) end end # @muladd diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index f3a9edb8e4..6dcfe93d7c 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -231,12 +231,12 @@ end Base.resize!(semi, volume_integral::AbstractVolumeIntegral, new_size) = nothing function Base.resize!(semi, volume_integral::VolumeIntegralSubcellLimiting, new_size) - # Resize container_antidiffusive_flux - resize!(semi.cache.container_antidiffusive_flux, new_size) + # Resize container antidiffusive_fluxes + resize!(semi.cache.antidiffusive_fluxes, new_size) - # Resize container_subcell_limiter + # Resize container subcell_limiter_coefficients @unpack limiter = volume_integral - resize!(limiter.cache.container_subcell_limiter, new_size) + resize!(limiter.cache.subcell_limiter_coefficients, new_size) # Calc subcell normal directions before StepsizeCallback if limiter isa SubcellLimiterMCL || diff --git a/test/runtests.jl b/test/runtests.jl index 1b0c745dbf..f1adbaaf1d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,10 +28,10 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) cmd = string(Base.julia_cmd()) coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", cmd) - if !(coverage && Sys.iswindows()) && !(coverage && Sys.islinux()) + if !(coverage && Sys.iswindows()) && !(coverage && Sys.isapple()) # We provide a `--heap-size-hint` to avoid/reduce out-of-memory errors during CI testing mpiexec() do cmd - run(`$cmd -n $TRIXI_MPI_NPROCS $(Base.julia_cmd()) --threads=1 --check-bounds=yes --heap-size-hint=1G $(abspath("test_mpi.jl"))`) + run(`$cmd -n $TRIXI_MPI_NPROCS $(Base.julia_cmd()) --threads=1 --check-bounds=yes --heap-size-hint=0.5G $(abspath("test_mpi.jl"))`) end end end diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 1aaf23d576..06a55100d6 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -19,7 +19,40 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [2.847421658558336e-05] ) end - + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_periodic.jl"), + l2 = [0.0001133835907077494, 6.226282245610444e-5, 0.0002820171699999139], + linf = [0.0006255102377159538, 0.00036195501456059986, 0.0016147729485886941] + ) + end + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_periodic.jl"), + equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), + Prandtl=prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2 = [0.00011310615871043463, 6.216495207074201e-5, 0.00028195843110817814], + linf = [0.0006240837363233886, 0.0003616694320713876, 0.0016147339542413874] + ) + end + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls.jl"), + l2 = [0.00047023310868269237, 0.00032181736027057234, 0.0014966266486095025], + linf = [0.002996375101363302, 0.002863904256059634, 0.012691132946258676] + ) + end + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls.jl"), + equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), + Prandtl=prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2 = [0.0004608500483647771, 0.00032431091222851285, 0.0015159733360626845], + linf = [0.002754803146635787, 0.0028567714697580906, 0.012941794048176192] + ) + end end # Clean up afterwards: delete Trixi output directory diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index e3bb1ed9fb..1564a33dc4 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -125,6 +125,39 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 8 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/8)]) + tspan=(0.0, 1.5) + semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) + ac_sol = analysis_callback(sol) + @test ac_sol.l2[1] ≈ 1.67452550744728e-6 + @test ac_sol.linf[1] ≈ 7.905059166368744e-6 + + # 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)) < 100 + @test (@allocated Trixi.rhs_parabolic!(du_ode, u_ode, semi, t)) < 100 + end + end + @trixi_testset "TreeMesh2D: elixir_advection_diffusion_nonperiodic.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), initial_refinement_level = 2, tspan=(0.0, 0.1), @@ -180,6 +213,27 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), + tspan=(0.0, 0.0), initial_refinement_level=3) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 4 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/4)]) + tspan=(0.0, 0.5) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, + ode_default_options()..., callback=callbacks) + ac_sol = analysis_callback(sol) + @test ac_sol.l2 ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] + @test ac_sol.linf ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] + end + @trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_lid_driven_cavity.jl"), initial_refinement_level = 2, tspan=(0.0, 0.5), diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 67a2723896..d607962afa 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -78,6 +78,27 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 16 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/16)]) + tspan=(0.0, 1.0) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, + ode_default_options()..., callback=callbacks) + ac_sol = analysis_callback(sol) + @test ac_sol.l2 ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] + @test ac_sol.linf ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] + end + @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), initial_refinement_level = 2, tspan=(0.0, 0.25), @@ -86,6 +107,41 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 32 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/32)]) + tspan=(0.0, 10.0) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, + extra_analysis_integrals=(energy_kinetic, + energy_internal, + enstrophy)) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + # Use CarpenterKennedy2N54 since `RDPK3SpFSAL49` gives slightly different results on different machines + sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), + dt=5e-3, + save_everystep=false, callback=callbacks); + ac_sol = analysis_callback(sol) + @test ac_sol.l2 ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] + @test ac_sol.linf ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] + + # 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)) < 100 + @test (@allocated Trixi.rhs_parabolic!(du_ode, u_ode, semi, t)) < 100 + end + end + @trixi_testset "P4estMesh3D: elixir_navierstokes_convergence.jl" begin @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_convergence.jl"), initial_refinement_level = 2, tspan=(0.0, 0.1), @@ -101,8 +157,8 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.0006696415247340326, 0.03442565722527785, 0.03442565722577423, 0.06295407168705314, 0.032857472756916195] ) end - end + # Clean up afterwards: delete Trixi.jl output directory @test_nowarn isdir(outdir) && rm(outdir, recursive=true) From 010e18854d72dd99f3d04ebf3ee9dcb3b548afa8 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 21 Aug 2023 12:11:30 +0200 Subject: [PATCH 256/423] Fix typo --- src/solvers/dgsem_tree/containers_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 8ab174d20b..b1bd509fc7 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1514,7 +1514,7 @@ function Base.resize!(container::ContainerSubcellLimiterMCL2D, capacity) return nothing end -# Container data structure (structure-of-arrays style) for variables used for subcell limiting useing bar states +# Container data structure (structure-of-arrays style) for variables used for subcell limiting using bar states mutable struct ContainerBarStates{uEltype <: Real} bar_states1::Array{uEltype, 4} # [variable, i, j, element] bar_states2::Array{uEltype, 4} # [variable, i, j, element] From ef4c2f27adce61d7cb33555c10666860e8a11f8e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 21 Aug 2023 13:00:06 +0200 Subject: [PATCH 257/423] Fix tests --- test/test_structured_2d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 742160b35f..8e2d00fa68 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -245,15 +245,15 @@ isdir(outdir) && rm(outdir, recursive=true) tspan = (0.0, 0.05)) end - @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin # TODO test. Zahlen ändern + @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2 = [1.2351468819080416, 1.1269856297330367, 1.7239124305681928, 11.715260007491556], - linf = [5.385494274885787, 6.575446482687761, 10.065233650013157, 51.00907987260031], + linf = [5.385492227740844, 6.575446131488329, 10.065232894750887, 51.00900038590831], cells_per_dimension = (8, 12), tspan = (0.0, 0.5)) end - @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin # TODO test. Zahlen ändern + @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), l2 = [1.2607430289877726, 1.1565837325291355, 1.7791790302458714, 11.891223800389232], linf = [5.68876088477983, 8.165554425950146, 10.859100194836538, 50.25822408989214], From 1a2eb003869d3e0baafe68e463868433617b37a9 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 26 Sep 2023 12:31:14 +0200 Subject: [PATCH 258/423] Add two-sided limiting for conservative variables --- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 93 ++++++++ ...ck_bubble_shockcapturing_subcell_minmax.jl | 139 ++++++++++++ src/callbacks_step/save_solution.jl | 11 +- src/callbacks_step/save_solution_dg.jl | 18 +- src/semidiscretization/semidiscretization.jl | 4 + src/solvers/dgsem_tree/subcell_limiters.jl | 54 ++++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 210 +++++++++++++++++- test/test_tree_2d_euler.jl | 9 + test/test_tree_2d_eulermulti.jl | 8 + test/test_unit.jl | 2 +- utils/trixi2txt.jl | 13 +- 11 files changed, 536 insertions(+), 25 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl create mode 100644 examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..ac99c35cdb --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,93 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_chandrashekar +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + 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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + n_cells_max=100_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +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, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); + 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_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl new file mode 100644 index 0000000000..08460eea5a --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -0,0 +1,139 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler multicomponent equations + +# 1) Dry Air 2) Helium + 28% Air +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), + gas_constants = (0.287, 1.578)) + +""" + initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + +A shock-bubble testcase for multicomponent Euler equations +- Ayoub Gouasmi, Karthik Duraisamy, Scott Murman + Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations + [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) +""" +function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225-delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +end +initial_condition = initial_condition_shock_bubble + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[(i+3 for i in eachcomponent(equations))...]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.25, -2.225) +coordinates_max = ( 2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + n_cells_max=1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(Trixi.density,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=600, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); + 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 \ No newline at end of file diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 14ea33368f..31fe0e87c7 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -222,21 +222,28 @@ end end end + node_variables = Dict{Symbol, Any}() + @trixi_timeit timer() "get node variables" get_node_variables!(node_variables, + semi) + @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, element_variables, + node_variables, system = system) end @inline function save_solution_file(u_ode, t, dt, iter, semi::AbstractSemidiscretization, solution_callback, - element_variables = Dict{Symbol, Any}(); + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array_native(u_ode, mesh, equations, solver, cache) save_solution_file(u, t, dt, iter, mesh, equations, solver, cache, solution_callback, - element_variables; system = system) + element_variables, + node_variables; system = system) end # TODO: Taal refactor, move save_mesh_file? diff --git a/src/callbacks_step/save_solution_dg.jl b/src/callbacks_step/save_solution_dg.jl index 6d5004ff65..7c01599903 100644 --- a/src/callbacks_step/save_solution_dg.jl +++ b/src/callbacks_step/save_solution_dg.jl @@ -10,7 +10,9 @@ function save_solution_file(u, time, dt, timestep, UnstructuredMesh2D, SerialP4estMesh, SerialT8codeMesh}, equations, dg::DG, cache, - solution_callback, element_variables = Dict{Symbol, Any}(); + solution_callback, + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback @@ -73,6 +75,16 @@ function save_solution_file(u, time, dt, timestep, var = file["element_variables_$v"] attributes(var)["name"] = string(key) end + + # Store node variables + for (v, (key, node_variable)) in enumerate(node_variables) + # Add to file + file["node_variables_$v"] = node_variable + + # Add variable name as attribute + var = file["node_variables_$v"] + attributes(var)["name"] = string(key) + end end return filename @@ -81,7 +93,9 @@ end function save_solution_file(u, time, dt, timestep, mesh::Union{ParallelTreeMesh, ParallelP4estMesh}, equations, dg::DG, cache, - solution_callback, element_variables = Dict{Symbol, Any}(); + solution_callback, + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback diff --git a/src/semidiscretization/semidiscretization.jl b/src/semidiscretization/semidiscretization.jl index c784f71642..fe7858e31e 100644 --- a/src/semidiscretization/semidiscretization.jl +++ b/src/semidiscretization/semidiscretization.jl @@ -335,6 +335,10 @@ function get_element_variables!(element_variables, u_ode, get_element_variables!(element_variables, u, mesh_equations_solver_cache(semi)...) end +function get_node_variables!(node_variables, semi::AbstractSemidiscretization) + get_node_variables!(node_variables, mesh_equations_solver_cache(semi)...) +end + # To implement AMR and use OrdinaryDiffEq.jl etc., we have to be a bit creative. # Since the caches of the SciML ecosystem are immutable structs, we cannot simply # change the underlying arrays therein. Hence, to support changing the number of diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 3a707de3bc..538e7785db 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -14,11 +14,13 @@ end """ SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], positivity_variables_cons = [], positivity_correction_factor = 0.1) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: +- maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) - positivity limiting for conservative variables (`positivity_variables_cons`) The bounds are calculated using the low-order FV solution. The positivity limiter uses @@ -41,63 +43,93 @@ The bounds are calculated using the low-order FV solution. The positivity limite This is an experimental feature and may change in future releases. """ struct SubcellLimiterIDP{RealT <: Real, Cache} <: AbstractSubcellLimiter + local_minmax::Bool + local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_correction_factor::RealT cache::Cache end -# this method is used when the indicator is constructed as for shock-capturing volume integrals +# this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; + local_minmax_variables_cons = [], positivity_variables_cons = [], positivity_correction_factor = 0.1) + local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) > 0) - number_bounds = length(positivity_variables_cons) + + number_bounds = 2 * length(local_minmax_variables_cons) + + for index in positivity_variables_cons + if !(index in local_minmax_variables_cons) + number_bounds += 1 + end + end cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds) - SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(cache)}(positivity, - positivity_variables_cons, - positivity_correction_factor, - cache) + SubcellLimiterIDP{typeof(positivity_correction_factor), + typeof(cache)}(local_minmax, local_minmax_variables_cons, + positivity, positivity_variables_cons, + positivity_correction_factor, cache) end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - @unpack positivity = limiter + (; local_minmax, positivity) = limiter print(io, "SubcellLimiterIDP(") - if !(positivity) + if !(local_minmax || positivity) print(io, "No limiter selected => pure DG method") else print(io, "limiter=(") + local_minmax && print(io, "min/max limiting, ") positivity && print(io, "positivity") print(io, "), ") end + print(io, "Local bounds with FV solution") print(io, ")") end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - @unpack positivity = limiter + (; local_minmax, positivity) = limiter if get(io, :compact, false) show(io, limiter) else - if !(positivity) + if !(local_minmax || positivity) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] + if local_minmax + setup = [ + setup..., + "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", + ] + end if positivity - string = "positivity with conservative variables $(limiter.positivity_variables_cons)" + string = "positivity for conservative variables $(limiter.positivity_variables_cons)" setup = [setup..., "" => string] setup = [ setup..., "" => " positivity correction factor = $(limiter.positivity_correction_factor)", ] end + setup = [ + setup..., + "Local bounds" => "FV solution", + ] end summary_box(io, "SubcellLimiterIDP", setup) end end + +function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, + ::VolumeIntegralSubcellLimiting, equations) + node_variables[:alpha_limiter] = limiter.cache.subcell_limiter_coefficients.alpha + # TODO: alpha is not filled before the first timestep. + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 09ab84ed11..2df7d8d97f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -6,17 +6,16 @@ #! format: noindent # this method is used when the limiter is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{SubcellLimiterIDP}, - equations::AbstractEquations{2}, +function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, number_bounds) subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis) }(0, nnodes(basis), number_bounds) - cache = (; subcell_limiter_coefficients) + idp_bounds_delta = zeros(real(basis), number_bounds) - return cache + return (; subcell_limiter_coefficients, idp_bounds_delta) end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, @@ -25,6 +24,10 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha .= zero(eltype(alpha)) + if limiter.local_minmax + @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, limiter, + u, t, dt, semi) + end if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) @@ -48,6 +51,175 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE return nothing end +@inline function calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + # Calculate bounds at Gauss-Lobatto nodes using u + for j in eachnode(dg), i in eachnode(dg) + var = u[variable, i, j, element] + var_min[i, j, element] = min(var_min[i, j, element], var) + var_max[i, j, element] = max(var_max[i, j, element], var) + + if i > 1 + var_min[i - 1, j, element] = min(var_min[i - 1, j, element], var) + var_max[i - 1, j, element] = max(var_max[i - 1, j, element], var) + end + if i < nnodes(dg) + var_min[i + 1, j, element] = min(var_min[i + 1, j, element], var) + var_max[i + 1, j, element] = max(var_max[i + 1, j, element], var) + end + if j > 1 + var_min[i, j - 1, element] = min(var_min[i, j - 1, element], var) + var_max[i, j - 1, element] = max(var_max[i, j - 1, element], var) + end + if j < nnodes(dg) + var_min[i, j + 1, element] = min(var_min[i, j + 1, element], var) + var_max[i, j + 1, element] = max(var_max[i, j + 1, element], var) + end + end + end + + # Values at element boundary + calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh) +end + +@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, + mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + @unpack boundary_conditions = semi + # Calc bounds at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) + end + var_left = u[variable, index_left..., left] + var_right = u[variable, index_right..., right] + + var_min[index_right..., right] = min(var_min[index_right..., right], + var_left) + var_max[index_right..., right] = max(var_max[index_right..., right], + var_left) + + var_min[index_left..., left] = min(var_min[index_left..., left], var_right) + var_max[index_left..., left] = max(var_max[index_left..., left], var_right) + end + end + + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + for i in eachnode(dg) + if neighbor_side == 2 # Element is on the right, boundary on the left + index = (1, i) + boundary_index = 1 + else # Element is on the left, boundary on the right + index = (nnodes(dg), i) + boundary_index = 2 + end + if orientation == 2 + index = reverse(index) + boundary_index += 2 + end + u_inner = get_node_vars(u, equations, dg, index..., element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[boundary_index], + orientation, boundary_index, + equations, dg, index..., element) + var_outer = u_outer[variable] + + var_min[index..., element] = min(var_min[index..., element], var_outer) + var_max[index..., element] = max(var_max[index..., element], var_outer) + end + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi) + for (index, variable) in enumerate(limiter.local_minmax_variables_cons) + idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable, index) + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable, index) + mesh, _, dg, cache = mesh_equations_solver_cache(semi) + @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients + + var_min = variable_bounds[2 * (index - 1) + 1] + var_max = variable_bounds[2 * (index - 1) + 2] + calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + + @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack inverse_weights = dg.basis + + @threaded for element in eachelement(dg, semi.cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + var = u[variable, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pp and Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2[variable, i, j + 1, element] + + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / + (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / + (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) + end + end + + return nothing +end + @inline function idp_positivity!(alpha, limiter, u, dt, semi) # Conservative variables for (index, variable) in enumerate(limiter.positivity_variables_cons) @@ -61,11 +233,30 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes @unpack inverse_weights = dg.basis - @unpack positivity_correction_factor = limiter + @unpack local_minmax, positivity_correction_factor = limiter @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[index] + counter = 2 * length(limiter.local_minmax_variables_cons) + if local_minmax + if variable in limiter.local_minmax_variables_cons + for (index_, variable_) in enumerate(limiter.local_minmax_variables_cons) + if variable == variable_ + var_min = variable_bounds[2 * (index_ - 1) + 1] + break + end + end + else + for variable_ in limiter.positivity_variables_cons[1:index] + if !(variable_ in limiter.local_minmax_variables_cons) + counter += 1 + end + end + var_min = variable_bounds[counter] + end + else + var_min = variable_bounds[counter + index] + end @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -76,7 +267,12 @@ end end # Compute bound - var_min[i, j, element] = positivity_correction_factor * var + if limiter.local_minmax + var_min[i, j, element] = max(var_min[i, j, element], + positivity_correction_factor * var) + else + var_min[i, j, element] = positivity_correction_factor * var + end # Real one-sided Zalesak-type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 1b8a261a60..8e3229cb22 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -137,6 +137,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2 = [0.4328635350273501, 0.15011135840723572, 0.15011135840723572, 0.616129927549474], + linf = [1.6145297181778906, 0.8614006163026988, 0.8614006163026972, 6.450225090647602], + tspan = (0.0, 1.0), + initial_refinement_level=4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), l2 = [0.0845430093623868, 0.09271459184623232, 0.09271459184623232, 0.4377291875101709], diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 606afca103..7fae165eaa 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -27,6 +27,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.001)) end + @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), + l2 = [73.01077148870725, 1.4204348924380372, 57122.13972973074, 0.17836374322229048, 0.010313997110520876], + linf = [213.72967389135226, 23.288296880180273, 152494.3261214191, 0.5238498635237653, 0.09157532953441563], + initial_refinement_level = 3, + tspan = (0.0, 0.001)) + end + @trixi_testset "elixir_eulermulti_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), l2 = [0.050182236154087095, 0.050189894464434635, 0.2258715597305131, 0.06175171559771687], diff --git a/test/test_unit.jl b/test/test_unit.jl index 5c5291c243..52cdd8a9ac 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -402,7 +402,7 @@ isdir(outdir) && rm(outdir, recursive=true) indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], 0.1, "cache") + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], 0.1, "cache") @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index b386f150da..12a3d46760 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -70,7 +70,7 @@ function trixi2txt(filename::AbstractString...; center_level_0, length_level_0, leaf_cells, coordinates, levels = read_meshfile(meshfile) # Read data - labels, data, n_elements, n_nodes, element_variables, time = read_datafile(filename) + labels, data, n_elements, n_nodes, element_variables, node_variables, time = read_datafile(filename) # Check if dimensions match if length(leaf_cells) != n_elements @@ -263,7 +263,16 @@ function read_datafile(filename::String) index += 1 end - return labels, data, n_elements, n_nodes, element_variables, time + # Extract node variable arrays + node_variables = Dict{String, Union{Vector{Float64}, Vector{Int}}}() + index = 1 + while haskey(file, "node_variables_$index") + varname = read(attributes(file["node_variables_$index"])["name"]) + node_variables[varname] = read(file["node_variables_$index"]) + index += 1 + end + + return labels, data, n_elements, n_nodes, element_variables, node_variables, time end end From ab9e5d943c55fb874fffacbfb90376a33e66b64f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 26 Sep 2023 12:33:00 +0200 Subject: [PATCH 259/423] Fix visualization routines --- src/solvers/dg.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 36bbc6de36..bc0ee12301 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -12,6 +12,11 @@ function get_element_variables!(element_variables, u, mesh, equations, nothing end +function get_node_variables!(node_variables, mesh, equations, + volume_integral::AbstractVolumeIntegral, dg, cache) + nothing +end + """ VolumeIntegralStrongForm() @@ -214,6 +219,12 @@ function Base.show(io::IO, mime::MIME"text/plain", end end +function get_node_variables!(node_variables, mesh, equations, + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) + get_node_variables!(node_variables, volume_integral.limiter, volume_integral, + equations) +end + # TODO: FD. Should this definition live in a different file because it is # not strictly a DG method? """ @@ -403,6 +414,10 @@ function get_element_variables!(element_variables, u, mesh, equations, dg::DG, c dg, cache) end +function get_node_variables!(node_variables, mesh, equations, dg::DG, cache) + get_node_variables!(node_variables, mesh, equations, dg.volume_integral, dg, cache) +end + const MeshesDGSEM = Union{TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, T8codeMesh} From 534f148e5a4dd2c04416c4e43c74c42391c62174 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 26 Sep 2023 13:01:18 +0200 Subject: [PATCH 260/423] Add bounds calculation for BoundaryConditionDirichlet --- .../elixir_euler_blast_wave_sc_subcell.jl | 96 +++++++++++++++++++ .../dgsem_tree/dg_2d_subcell_limiters.jl | 12 +++ test/test_tree_2d_euler.jl | 9 ++ 3 files changed, 117 insertions(+) create mode 100644 examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..dfd99f5baa --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -0,0 +1,96 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +A medium blast wave taken from +- Sebastian Hennemann, Gregor J. 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) +""" +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave + +boundary_condition = BoundaryConditionDirichlet(initial_condition) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons=[1]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + 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) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=6, + n_cells_max=10_000, + periodicity=false) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions=boundary_condition) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +stepsize_callback = StepsizeCallback(cfl=0.3) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); + 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 \ No newline at end of file diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 70ff346740..b947d06934 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -190,4 +190,16 @@ end return nothing end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::BoundaryConditionDirichlet, + orientation_or_normal, direction, equations, + dg, indices...) + (; node_coordinates) = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(x, t, equations) + + return u_outer +end end # @muladd diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 8e3229cb22..905572ee95 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -129,6 +129,15 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") coverage_override = (maxiters=6,)) end + @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), + l2 = [0.3517507570120483, 0.19252291020146015, 0.19249751956580294, 0.618717827188004], + linf = [1.6699566795772216, 1.3608007992899402, 1.361864507190922, 2.44022884092527], + tspan = (0.0, 0.5), + initial_refinement_level = 4, + coverage_override = (maxiters=6,)) + end + @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), l2 = [0.4866953770742574, 0.1673477470091984, 0.16734774700934, 0.6184367248923149], From 9b0eee9c932ec57354b2cc3cb3ec0589389e1c6e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 26 Sep 2023 14:50:51 +0200 Subject: [PATCH 261/423] Reduce cfl in elixir --- ...r_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl | 2 +- test/test_tree_2d_eulermulti.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 08460eea5a..0a9cc2921b 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -119,7 +119,7 @@ save_solution = SaveSolutionCallback(interval=600, save_final_solution=true, solution_variables=cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl=0.5) callbacks = CallbackSet(summary_callback, analysis_callback, diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 7fae165eaa..76ba39061c 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -29,8 +29,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), - l2 = [73.01077148870725, 1.4204348924380372, 57122.13972973074, 0.17836374322229048, 0.010313997110520876], - linf = [213.72967389135226, 23.288296880180273, 152494.3261214191, 0.5238498635237653, 0.09157532953441563], + l2 = [73.10862636389842, 1.4599061192346743, 57176.25279239441, 0.1781291550432081, 0.010123079839772913], + linf = [214.50568817511956, 25.40392579616452, 152862.41011222568, 0.564195553101797, 0.0956331651771212], initial_refinement_level = 3, tspan = (0.0, 0.001)) end From 3e6f7f877009e86399940f9ef18527d87c6ce2d1 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 26 Sep 2023 16:13:50 +0200 Subject: [PATCH 262/423] Fix test --- test/test_tree_2d_eulermulti.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 76ba39061c..83c02d0b50 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -29,7 +29,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), - l2 = [73.10862636389842, 1.4599061192346743, 57176.25279239441, 0.1781291550432081, 0.010123079839772913], + l2 = [73.10832638093902, 1.4599215762968585, 57176.014861335476, 0.17812843581838675, 0.010123079422717837], linf = [214.50568817511956, 25.40392579616452, 152862.41011222568, 0.564195553101797, 0.0956331651771212], initial_refinement_level = 3, tspan = (0.0, 0.001)) From 6c095a8c0be411274b90d6b151fc969356bb714f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 27 Sep 2023 12:02:53 +0200 Subject: [PATCH 263/423] Fix bounds check routine --- src/callbacks_stage/bounds_check_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index a5e146f555..7b2740ff18 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -103,8 +103,8 @@ open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) end - counter += 1 end + counter += 1 end for variable in limiter.positivity_variables_nonlinear deviation_min = zero(eltype(u)) From 3bf461f718f9ae17f7b335c9bcdf3f1884c48bcf Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 28 Sep 2023 15:50:15 +0200 Subject: [PATCH 264/423] Update tests after fixing conservation in main --- test/test_structured_2d.jl | 12 ++++++------ test/test_tree_2d_euler.jl | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 8e2d00fa68..be1a1d3138 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -187,8 +187,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [0.008160130056105786, 0.008658251740761163, 0.009351904344378272, 0.027757009375556807], - linf = [0.027225634762642947, 0.040734047009665986, 0.03819407519909657, 0.08080651960614205], + l2 = [0.008160127272557726, 0.008658253869683077, 0.009351900401871649, 0.02775701488343099], + linf = [0.027225608222781528, 0.0407340321806311, 0.0381940733564341, 0.08080650914262844], tspan = (0.0, 0.5)) end @@ -208,7 +208,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_free_stream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_sc_subcell.jl"), l2 = [2.6224749465938795e-14, 1.6175366858083413e-14, 2.358782725951525e-14, 5.910156539173304e-14], - linf = [1.1945999744966684e-13, 1.084687895058778e-13, 1.7050250100680842e-13, 2.0250467969162855e-13], + linf = [1.1546319456101628e-14, 1.084687895058778e-13, 1.7050250100680842e-13, 2.0250467969162855e-13], atol = 1.0e-13, cells_per_dimension = (8, 8)) end @@ -216,7 +216,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_free_stream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_MCL.jl"), l2 = [3.532639560334565e-14, 1.4787576718355913e-14, 2.109573923923632e-14, 2.54649935281524e-14], - linf = [1.3955503419538218e-13, 1.1611545058798356e-13, 1.7619239400801234e-13, 2.007283228522283e-13], + linf = [7.993605777301127e-15, 1.1611545058798356e-13, 1.7619239400801234e-13, 2.007283228522283e-13], atol = 1.0e-13, cells_per_dimension = (8, 8)) end @@ -247,8 +247,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), - l2 = [1.2351468819080416, 1.1269856297330367, 1.7239124305681928, 11.715260007491556], - linf = [5.385492227740844, 6.575446131488329, 10.065232894750887, 51.00900038590831], + l2 = [1.2351468819080416, 1.1269856120551724, 1.7239124305681928, 11.715260007491556], + linf = [5.385491808683259, 6.575446013701839, 10.065227889186632, 51.008985921289565], cells_per_dimension = (8, 12), tspan = (0.0, 0.5)) end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 8896b4a234..5cfd7a446c 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -143,8 +143,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.3078500396564997, 0.1759956708830148, 0.1759417699101888, 0.6141202024471839], - linf = [1.297180993766177, 1.105746322133501, 1.1057676530433822, 2.4364099721878776], + l2 = [0.30785094769124677, 0.30785094769124677, 0.17594201496603085, 0.6141202024471839], + linf = [1.2971828380703805, 1.1057475500114755, 1.105770653844522, 2.4364101844067916], tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) From e16154803d3c59e875d68d7ec13f97bd2a035cb1 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 28 Sep 2023 16:31:54 +0200 Subject: [PATCH 265/423] Fix copy error --- test/test_tree_2d_euler.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 5cfd7a446c..f48386aa8a 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -143,7 +143,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.30785094769124677, 0.30785094769124677, 0.17594201496603085, 0.6141202024471839], + l2 = [0.30785094769124677, 0.17599603017990473, 0.17594201496603085, 0.6141202024471839], linf = [1.2971828380703805, 1.1057475500114755, 1.105770653844522, 2.4364101844067916], tspan = (0.0, 0.5), initial_refinement_level = 4, From 2e251852d79c98e2328d0b97e79ad6cf9052f4a5 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 28 Sep 2023 17:53:38 +0200 Subject: [PATCH 266/423] Implement variable_bounds as Dict with Symbols --- src/callbacks_stage/bounds_check.jl | 28 +++--- src/callbacks_stage/bounds_check_2d.jl | 51 +++++----- src/solvers/dgsem_tree/containers_2d.jl | 27 +++--- .../dgsem_tree/dg_2d_subcell_limiters.jl | 11 +-- src/solvers/dgsem_tree/subcell_limiters.jl | 27 ++++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 93 +++++++------------ 6 files changed, 106 insertions(+), 131 deletions(-) diff --git a/src/callbacks_stage/bounds_check.jl b/src/callbacks_stage/bounds_check.jl index 1d56d725c8..600c11d925 100644 --- a/src/callbacks_stage/bounds_check.jl +++ b/src/callbacks_stage/bounds_check.jl @@ -145,34 +145,30 @@ end println("─"^100) println("Maximum deviation from bounds:") println("─"^100) - counter = 1 if local_minmax - for index in limiter.local_minmax_variables_cons - println("$(variables[index]):") - println("-lower bound: ", idp_bounds_delta[counter]) - println("-upper bound: ", idp_bounds_delta[counter + 1]) - counter += 2 + for v in limiter.local_minmax_variables_cons + println("$(variables[v]):") + println("-lower bound: ", idp_bounds_delta[Symbol("$(v)_min")]) + println("-upper bound: ", idp_bounds_delta[Symbol("$(v)_max")]) end end if spec_entropy - println("spec. entropy:\n- lower bound: ", idp_bounds_delta[counter]) - counter += 1 + println("spec. entropy:\n- lower bound: ", idp_bounds_delta[:spec_entropy_min]) end if math_entropy - println("math. entropy:\n- upper bound: ", idp_bounds_delta[counter]) - counter += 1 + println("math. entropy:\n- upper bound: ", idp_bounds_delta[:math_entropy_max]) end if positivity - for index in limiter.positivity_variables_cons - if index in limiter.local_minmax_variables_cons + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons continue end - println("$(variables[index]):\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 + println("$(variables[v]):\n- positivity: ", + idp_bounds_delta[Symbol("$(v)_min")]) end for variable in limiter.positivity_variables_nonlinear - println("$(variable):\n- positivity: ", idp_bounds_delta[counter]) - counter += 1 + println("$(variable):\n- positivity: ", + idp_bounds_delta[Symbol("$(variable)_min")]) end end println("─"^100 * "\n") diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index 7b2740ff18..f66f8b8b3a 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -13,29 +13,31 @@ @unpack idp_bounds_delta = limiter.cache save_errors_ = save_errors && (iter % interval == 0) - counter = 1 if save_errors_ open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) end end if local_minmax - for index in limiter.local_minmax_variables_cons + for v in limiter.local_minmax_variables_cons + key_min = Symbol("$(v)_min") + key_max = Symbol("$(v)_max") deviation_min = zero(eltype(u)) deviation_max = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) deviation_min = max(deviation_min, - variable_bounds[counter][i, j, element] - - u[index, i, j, element]) + variable_bounds[key_min][i, j, element] - + u[v, i, j, element]) deviation_max = max(deviation_max, - u[index, i, j, element] - - variable_bounds[counter + 1][i, j, element]) + u[v, i, j, element] - + variable_bounds[key_max][i, j, element]) end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) - idp_bounds_delta[counter + 1] = max(idp_bounds_delta[counter + 1], - deviation_max) + idp_bounds_delta[key_min] = max(idp_bounds_delta[key_min], + deviation_min) + idp_bounds_delta[key_max] = max(idp_bounds_delta[key_max], + deviation_max) if save_errors_ deviation_min_ = deviation_min deviation_max_ = deviation_max @@ -43,10 +45,10 @@ print(f, ", ", deviation_min_, ", ", deviation_max_) end end - counter += 2 end end if spec_entropy + key = :spec_entropy_min deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -54,18 +56,18 @@ s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) deviation_min = max(deviation_min, - variable_bounds[counter][i, j, element] - s) + variable_bounds[key][i, j, element] - s) end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) if save_errors_ deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) end end - counter += 1 end if math_entropy + key = :math_entropy_max deviation_max = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -73,40 +75,40 @@ s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) deviation_max = max(deviation_max, - s - variable_bounds[counter][i, j, element]) + s - variable_bounds[key][i, j, element]) end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_max) + idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_max) if save_errors_ deviation_max_ = deviation_max open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_max_) end end - counter += 1 end if positivity - for index in limiter.positivity_variables_cons - if index in limiter.local_minmax_variables_cons + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons continue end + key = Symbol("$(v)_min") deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - var = u[index, i, j, element] + var = u[v, i, j, element] deviation_min = max(deviation_min, - variable_bounds[counter][i, j, element] - var) + variable_bounds[key][i, j, element] - var) end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) if save_errors_ deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) end end - counter += 1 end for variable in limiter.positivity_variables_nonlinear + key = Symbol("$(variable)_min") deviation_min = zero(eltype(u)) for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) @@ -114,16 +116,15 @@ var = variable(get_node_vars(u, equations, solver, i, j, element), equations) deviation_min = max(deviation_min, - variable_bounds[counter][i, j, element] - var) + variable_bounds[key][i, j, element] - var) end - idp_bounds_delta[counter] = max(idp_bounds_delta[counter], deviation_min) + idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) if save_errors_ deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) end end - counter += 1 end end if save_errors_ diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index b1bd509fc7..a6d9f57758 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1325,16 +1325,16 @@ mutable struct ContainerSubcellLimiterIDP2D{uEltype <: Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} - variable_bounds::Vector{Array{uEltype, 3}} + variable_bounds::Dict{Symbol, Array{uEltype, 3}} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} - _variable_bounds::Vector{Vector{uEltype}} + _variable_bounds::Dict{Symbol, Vector{uEltype}} end function ContainerSubcellLimiterIDP2D{uEltype}(capacity::Integer, n_nodes, - length) where {uEltype <: Real} + bound_keys) where {uEltype <: Real} nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1345,12 +1345,12 @@ function ContainerSubcellLimiterIDP2D{uEltype}(capacity::Integer, n_nodes, _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes + 1) * capacity) alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - _variable_bounds = Vector{Vector{uEltype}}(undef, length) - variable_bounds = Vector{Array{uEltype, 3}}(undef, length) - for i in 1:length - _variable_bounds[i] = fill(nan_uEltype, n_nodes * n_nodes * capacity) - variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), - (n_nodes, n_nodes, capacity)) + _variable_bounds = Dict{Symbol, Vector{uEltype}}() + variable_bounds = Dict{Symbol, Array{uEltype, 3}}() + for key in bound_keys + _variable_bounds[key] = fill(nan_uEltype, n_nodes * n_nodes * capacity) + variable_bounds[key] = unsafe_wrap(Array, pointer(_variable_bounds[key]), + (n_nodes, n_nodes, capacity)) end return ContainerSubcellLimiterIDP2D{uEltype}(alpha, alpha1, alpha2, @@ -1380,10 +1380,11 @@ function Base.resize!(container::ContainerSubcellLimiterIDP2D, capacity) (n_nodes, n_nodes + 1, capacity)) @unpack _variable_bounds = container - for i in 1:length(_variable_bounds) - resize!(_variable_bounds[i], n_nodes * n_nodes * capacity) - container.variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), - (n_nodes, n_nodes, capacity)) + for (key, _) in _variable_bounds + resize!(_variable_bounds[key], n_nodes * n_nodes * capacity) + container.variable_bounds[key] = unsafe_wrap(Array, + pointer(_variable_bounds[key]), + (n_nodes, n_nodes, capacity)) end return nothing diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 0f0fb1a4b7..e165308967 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -534,12 +534,11 @@ end @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states - counter = 1 # state variables if limiter.local_minmax for index in limiter.local_minmax_variables_cons - var_min = variable_bounds[counter] - var_max = variable_bounds[counter + 1] + var_min = variable_bounds[Symbol("$(index)_min")] + var_max = variable_bounds[Symbol("$(index)_max")] @threaded for element in eachelement(dg, cache) var_min[:, :, element] .= typemax(eltype(var_min)) var_max[:, :, element] .= typemin(eltype(var_max)) @@ -571,12 +570,11 @@ end bar_states2[index, i, j + 1, element]) end end - counter += 2 end end # Specific Entropy if limiter.spec_entropy - s_min = variable_bounds[counter] + s_min = variable_bounds[:spec_entropy_min] @threaded for element in eachelement(dg, cache) s_min[:, :, element] .= typemax(eltype(s_min)) for j in eachnode(dg), i in eachnode(dg) @@ -602,11 +600,10 @@ end s_min[i, j, element] = min(s_min[i, j, element], s) end end - counter += 1 end # Mathematical entropy if limiter.math_entropy - s_max = variable_bounds[counter] + s_max = variable_bounds[:math_entropy_max] @threaded for element in eachelement(dg, cache) s_max[:, :, element] .= typemin(eltype(s_max)) for j in eachnode(dg), i in eachnode(dg) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 8dd17c2d6a..86d88c827f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -108,17 +108,28 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: math_entropy/spec_entropy") end - number_bounds = 2 * length(local_minmax_variables_cons) + - length(positivity_variables_nonlinear) + - spec_entropy + math_entropy - - for index in positivity_variables_cons - if !(index in local_minmax_variables_cons) - number_bounds += 1 + bound_keys = () + if local_minmax + for i in local_minmax_variables_cons + bound_keys = (bound_keys..., Symbol("$(i)_min"), Symbol("$(i)_max")) + end + end + if spec_entropy + bound_keys = (bound_keys..., :spec_entropy_min) + end + if math_entropy + bound_keys = (bound_keys..., :math_entropy_max) + end + for i in positivity_variables_cons + if !(i in local_minmax_variables_cons) + bound_keys = (bound_keys..., Symbol("$(i)_min")) end end + for variable in positivity_variables_nonlinear + bound_keys = (bound_keys..., Symbol("$(variable)_min")) + end - cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds, bar_states) + cache = create_cache(SubcellLimiterIDP, equations, basis, bound_keys, bar_states) if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_max = 1.0, diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 7db04ca83f..a8fcc42c06 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -7,11 +7,11 @@ # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, number_bounds, bar_states) + basis::LobattoLegendreBasis, bound_keys, bar_states) subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis) }(0, nnodes(basis), - number_bounds) + bound_keys) cache = (;) if bar_states @@ -21,7 +21,10 @@ function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquat cache = (; cache..., container_bar_states) end - idp_bounds_delta = zeros(real(basis), number_bounds) + idp_bounds_delta = Dict{Symbol, real(basis)}() + for key in bound_keys + idp_bounds_delta[key] = zero(real(basis)) + end return (; cache..., subcell_limiter_coefficients, idp_bounds_delta) end @@ -318,20 +321,18 @@ end end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) - for (index, variable) in enumerate(limiter.local_minmax_variables_cons) - idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, index) + for variable in limiter.local_minmax_variables_cons + idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable) end return nothing end -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable, - index) +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable) mesh, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - var_min = variable_bounds[2 * (index - 1) + 1] - var_max = variable_bounds[2 * (index - 1) + 2] + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol("$(variable)_min")] + var_max = variable_bounds[Symbol("$(variable)_max")] if !limiter.bar_states calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) end @@ -396,9 +397,8 @@ end @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - s_min = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + 1] + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_min = variable_bounds[:spec_entropy_min] if !limiter.bar_states calc_bounds_1sided!(s_min, min, typemax, entropy_spec, u, t, semi) end @@ -427,10 +427,8 @@ end @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy = limiter - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - s_max = variable_bounds[2 * length(limiter.local_minmax_variables_cons) + spec_entropy + 1] + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_max = variable_bounds[:math_entropy_max] if !limiter.bar_states calc_bounds_1sided!(s_max, max, typemin, entropy_math, u, t, semi) end @@ -459,48 +457,26 @@ end @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) # Conservative variables - for (index, variable) in enumerate(limiter.positivity_variables_cons) - idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, index) + for variable in limiter.positivity_variables_cons + idp_positivity!(alpha, limiter, u, dt, semi, elements, variable) end # Nonlinear variables - for (index, variable) in enumerate(limiter.positivity_variables_nonlinear) - idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, variable, index) + for variable in limiter.positivity_variables_nonlinear + idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, variable) end return nothing end -@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable, - index) +@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes @unpack inverse_weights = dg.basis - @unpack local_minmax, spec_entropy, math_entropy, positivity_correction_factor = limiter - - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - counter = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + - math_entropy - if local_minmax - if variable in limiter.local_minmax_variables_cons - for (index_, variable_) in enumerate(limiter.local_minmax_variables_cons) - if variable == variable_ - var_min = variable_bounds[2 * (index_ - 1) + 1] - break - end - end - else - for variable_ in limiter.positivity_variables_cons[1:index] - if !(variable_ in limiter.local_minmax_variables_cons) - counter += 1 - end - end - var_min = variable_bounds[counter] - end - else - var_min = variable_bounds[counter + index] - end + @unpack local_minmax, positivity_correction_factor = limiter + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol("$(variable)_min")] @threaded for element in elements if mesh isa TreeMesh @@ -558,20 +534,13 @@ end return nothing end -@inline function idp_positivity_newton!(alpha, limiter, u, dt, semi, elements, - variable, index) +@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, + variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack spec_entropy, math_entropy, positivity_correction_factor, positivity_variables_cons = limiter - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - index_ = 2 * length(limiter.local_minmax_variables_cons) + spec_entropy + - math_entropy + index - for variable_ in limiter.positivity_variables_cons - if !(variable_ in limiter.local_minmax_variables_cons) - index_ += 1 - end - end - var_min = variable_bounds[index_] + (; positivity_correction_factor) = limiter + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol("$(variable)_min")] @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) From 99c17828996e95c7de9309efb67a5f5f0bd26056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 5 Oct 2023 17:47:09 +0200 Subject: [PATCH 267/423] Added first (ugly) implementation of subcell limiting for non-conservative systems -> A working version of this implementation is added for the GLM-MHD system -> The flux-differencing formula requires non-conservative terms of the form (local * symmetric)... I modified equations/ideal_glm_mhd_2d.jl and solvers/dgsem_tree/dg_2d.jl to make it work -> In this first implementation, we only use the Powell term and deactivate the GLM term --- .../elixir_mhd_shockcapturing_subcell.jl | 108 ++++++++ .../subcell_limiter_idp_correction_2d.jl | 10 +- src/equations/ideal_glm_mhd_2d.jl | 124 ++++++++- src/solvers/dgsem_tree/containers_2d.jl | 62 +++-- src/solvers/dgsem_tree/dg_2d.jl | 16 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 245 +++++++++++++++--- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 10 +- src/time_integration/methods_SSP.jl | 5 + 8 files changed, 508 insertions(+), 72 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl new file mode 100644 index 0000000000..3729497331 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -0,0 +1,108 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible ideal GLM-MHD equations + +equations = IdealGlmMhdEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) + +An MHD blast wave taken from +- Dominik Derigs, Gregor J. Gassner, Stefanie Walch & Andrew R. Winters (2018) + Entropy Stable Finite Volume Approximations for Ideal Magnetohydrodynamics + [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) +""" +function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 + r = sqrt(x[1]^2 + x[2]^2) + pmax = 10.0 + pmin = 10.0 + + rhomin = 0.5 + rhomax = 1.0 + if r <= 0.09 + p = pmax + rho = rhomax + elseif r >= 0.1 + p = pmin + rho = rhomin + else + p = pmin + (0.1 - r) * (pmax - pmin) / 0.01 + rho = rhomin + (0.1 - r) * (rhomax - rhomin) / 0.01 + end + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + B1 = 1.0/sqrt(4.0*pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) +end +initial_condition = initial_condition_blast_wave + +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) +volume_flux = (flux_derigs_etal, flux_nonconservative_powell) #central +basis = LobattoLegendreBasis(3) + +#volume_integral=VolumeIntegralFluxDifferencing(volume_flux) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_correction_factor=0.8) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-0.5, -0.5) +coordinates_max = ( 0.5, 0.5) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + n_cells_max=10_000) + + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 30 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=10) #analysis_interval + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +cfl = 0.3 +stepsize_callback = StepsizeCallback(cfl=cfl) + +glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback, + glm_speed_callback) + +############################################################################### +# run the simulation +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); # + 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/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index f6b9144457..6f1723e2a9 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -7,7 +7,7 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients @threaded for element in eachelement(dg, cache) @@ -17,16 +17,16 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) for j in eachnode(dg), i in eachnode(dg) # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i, j, + get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i + 1, + get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, j, + get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, + get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) for v in eachvariable(equations) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 8fef1ee22c..82d4844b16 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -23,12 +23,17 @@ mutable struct IdealGlmMhdEquations2D{RealT <: Real} <: end end +struct NonConservativeLocal end +struct NonConservativeSymmetric end + function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN)) # Use `promote` to ensure that `gamma` and `initial_c_h` have the same type IdealGlmMhdEquations2D(promote(gamma, initial_c_h)...) end have_nonconservative_terms(::IdealGlmMhdEquations2D) = True() +nnoncons(::IdealGlmMhdEquations2D) = 2 + function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations2D) ("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3", "psi") end @@ -128,10 +133,10 @@ end f4 = rho_v1 * v3 - B1 * B3 f5 = (kin_en + equations.gamma * p_over_gamma_minus_one + 2 * mag_en) * v1 - B1 * (v1 * B1 + v2 * B2 + v3 * B3) + equations.c_h * psi * B1 - f6 = equations.c_h * psi + f6 = 0#equations.c_h * psi f7 = v1 * B2 - v2 * B1 f8 = v1 * B3 - v3 * B1 - f9 = equations.c_h * B1 + f9 = 0#equations.c_h * B1 else #if orientation == 2 f1 = rho_v2 f2 = rho_v2 * v1 - B2 * B1 @@ -140,9 +145,9 @@ end f5 = (kin_en + equations.gamma * p_over_gamma_minus_one + 2 * mag_en) * v2 - B2 * (v1 * B1 + v2 * B2 + v3 * B3) + equations.c_h * psi * B2 f6 = v2 * B1 - v1 * B2 - f7 = equations.c_h * psi + f7 = 0#equations.c_h * psi f8 = v2 * B3 - v3 * B2 - f9 = equations.c_h * B2 + f9 = 0#equations.c_h * B2 end return SVector(f1, f2, f3, f4, f5, f6, f7, f8, f9) @@ -206,7 +211,7 @@ terms. equations. Part I: Theory and numerical verification [DOI: 10.1016/j.jcp.2018.06.027](https://doi.org/10.1016/j.jcp.2018.06.027) """ -@inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, +#= @inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr @@ -240,6 +245,115 @@ terms. v2_ll * psi_rr) end + return f +end =# +@inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + psi_avg = 0.5 * (psi_ll + psi_rr) + if orientation == 1 + B1_avg = 0.5 * (B1_ll + B1_rr) + f = SVector(0, + B1_ll * B1_avg, + B2_ll * B1_avg, + B3_ll * B1_avg, + v_dot_B_ll * B1_avg, # + v1_ll * psi_ll * psi_rr, + v1_ll * B1_avg, + v2_ll * B1_avg, + v3_ll * B1_avg, + 0)#v1_ll * psi_avg) + else # orientation == 2 + B2_avg = 0.5 * (B2_ll + B2_rr) + f = SVector(0, + B1_ll * B2_avg, + B2_ll * B2_avg, + B3_ll * B2_avg, + v_dot_B_ll * B2_avg, # + v2_ll * psi_ll * psi_rr, + v1_ll * B2_avg, + v2_ll * B2_avg, + v3_ll * B2_avg, + 0)#v2_ll * psi_avg) + end + + return f +end +""" + +""" +@inline function flux_nonconservative_powell(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + f = SVector(0, + B1_ll, + B2_ll, + B3_ll, + v_dot_B_ll, # The term (v1_ll * psi_ll) is missing because we need to define several non-conservative terms + v1_ll, + v2_ll, + v3_ll, + 0)#v1_ll) + + return f +end +""" + +""" +@inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + psi_avg = 0.5 * (psi_ll + psi_rr) + if orientation == 1 + B1_avg = 0.5 * (B1_ll + B1_rr) + f = SVector(0, + B1_avg, + B1_avg, + B1_avg, + B1_avg, # The term (psi_avg) is missing because we need to define several non-conservative terms + B1_avg, + B1_avg, + B1_avg, + 0)#psi_avg) + else # orientation == 2 + B2_avg = 0.5 * (B2_ll + B2_rr) + f = SVector(0, + B2_avg, + B2_avg, + B2_avg, + B2_avg, # The term (psi_avg) is missing because we need to define several non-conservative terms + B2_avg, + B2_avg, + B2_avg, + 0)#psi_avg) + end + return f end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 9148b93631..576732b921 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1266,11 +1266,15 @@ end # | # (i, j-1) mutable struct ContainerAntidiffusiveFlux2D{uEltype <: Real} - antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] - antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux1_L::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux1_R::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2_L::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2_R::Array{uEltype, 4} # [variables, i, j, elements] # internal `resize!`able storage - _antidiffusive_flux1::Vector{uEltype} - _antidiffusive_flux2::Vector{uEltype} + _antidiffusive_flux1_L::Vector{uEltype} + _antidiffusive_flux1_R::Vector{uEltype} + _antidiffusive_flux2_L::Vector{uEltype} + _antidiffusive_flux2_R::Vector{uEltype} end function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, @@ -1278,24 +1282,36 @@ function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults - _antidiffusive_flux1 = fill(nan_uEltype, + _antidiffusive_flux1_L = fill(nan_uEltype, n_variables * (n_nodes + 1) * n_nodes * capacity) - antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), + antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), + (n_variables, n_nodes + 1, n_nodes, capacity)) + _antidiffusive_flux1_R = fill(nan_uEltype, + n_variables * (n_nodes + 1) * n_nodes * capacity) + antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), (n_variables, n_nodes + 1, n_nodes, capacity)) - _antidiffusive_flux2 = fill(nan_uEltype, + _antidiffusive_flux2_L = fill(nan_uEltype, + n_variables * n_nodes * (n_nodes + 1) * capacity) + antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), + (n_variables, n_nodes, n_nodes + 1, capacity)) + _antidiffusive_flux2_R = fill(nan_uEltype, n_variables * n_nodes * (n_nodes + 1) * capacity) - antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), + antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), (n_variables, n_nodes, n_nodes + 1, capacity)) - return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1, - antidiffusive_flux2, - _antidiffusive_flux1, - _antidiffusive_flux2) + return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1_L, + antidiffusive_flux1_R, + antidiffusive_flux2_L, + antidiffusive_flux2_R, + _antidiffusive_flux1_L, + _antidiffusive_flux1_R, + _antidiffusive_flux2_L, + _antidiffusive_flux2_R) end -nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 1) -nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 3) +nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1_L, 1) +nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1_L, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` @@ -1306,14 +1322,22 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) n_nodes = nnodes(fluxes) n_variables = nvariables(fluxes) - @unpack _antidiffusive_flux1, _antidiffusive_flux2 = fluxes + @unpack _antidiffusive_flux1_L, _antidiffusive_flux2_L, _antidiffusive_flux1_R, _antidiffusive_flux2_R = fluxes - resize!(_antidiffusive_flux1, n_variables * (n_nodes + 1) * n_nodes * capacity) - fluxes.antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), + resize!(_antidiffusive_flux1_L, n_variables * (n_nodes + 1) * n_nodes * capacity) + fluxes.antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), (n_variables, n_nodes + 1, n_nodes, capacity)) - resize!(_antidiffusive_flux2, n_variables * n_nodes * (n_nodes + 1) * capacity) - fluxes.antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), + resize!(_antidiffusive_flux1_R, n_variables * (n_nodes + 1) * n_nodes * capacity) + fluxes.antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), + (n_variables, n_nodes + 1, n_nodes, + capacity)) + resize!(_antidiffusive_flux2_L, n_variables * n_nodes * (n_nodes + 1) * capacity) + fluxes.antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), + (n_variables, n_nodes, n_nodes + 1, + capacity)) + resize!(_antidiffusive_flux2_R, n_variables * n_nodes * (n_nodes + 1) * capacity) + fluxes.antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), (n_variables, n_nodes, n_nodes + 1, capacity)) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c30d0a8e01..679b6b33f2 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -316,7 +316,7 @@ end end # The factor 0.5 cancels the factor 2 in the flux differencing form - multiply_add_to_node_vars!(du, alpha * 0.5, integral_contribution, equations, + multiply_add_to_node_vars!(du, alpha, integral_contribution, equations, dg, i, j, element) end end @@ -493,8 +493,8 @@ end # Note the factor 0.5 necessary for the nonconservative fluxes based on # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs - f1_L = f1 + 0.5 * nonconservative_flux(u_ll, u_rr, 1, equations) - f1_R = f1 + 0.5 * nonconservative_flux(u_rr, u_ll, 1, equations) + f1_L = f1 + nonconservative_flux(u_ll, u_rr, 1, equations) + f1_R = f1 + nonconservative_flux(u_rr, u_ll, 1, equations) # Copy to temporary storage set_node_vars!(fstar1_L, f1_L, equations, dg, i, j) @@ -519,8 +519,8 @@ end # Note the factor 0.5 necessary for the nonconservative fluxes based on # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs - f2_L = f2 + 0.5 * nonconservative_flux(u_ll, u_rr, 2, equations) - f2_R = f2 + 0.5 * nonconservative_flux(u_rr, u_ll, 2, equations) + f2_L = f2 + nonconservative_flux(u_ll, u_rr, 2, equations) + f2_R = f2 + nonconservative_flux(u_rr, u_ll, 2, equations) # Copy to temporary storage set_node_vars!(fstar2_L, f2_L, equations, dg, i, j) @@ -626,10 +626,10 @@ function calc_interface_flux!(surface_flux_values, # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs surface_flux_values[v, i, left_direction, left_id] = flux[v] + - 0.5 * + #0.5 * noncons_left[v] surface_flux_values[v, i, right_direction, right_id] = flux[v] + - 0.5 * + #0.5 * noncons_right[v] end end @@ -779,7 +779,7 @@ function calc_boundary_flux_by_direction!(surface_flux_values::AbstractArray{<:A # Copy flux to left and right element storage for v in eachvariable(equations) surface_flux_values[v, i, direction, neighbor] = flux[v] + - 0.5 * noncons_flux[v] + noncons_flux[v] end end end diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 70ff346740..57053f97e0 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -15,19 +15,24 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_y = Array{uEltype, 3} A3d = Array{uEltype, 3} - fhat1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, + fhat1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, nnodes(dg)) for _ in 1:Threads.nthreads()] - fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), + fhat2_L_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + fhat1_R_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, + nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat2_R_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - + flux_temp_nonconservative_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) #nnoncons(equations) + for _ in 1:Threads.nthreads()] antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - - return (; cache..., antidiffusive_fluxes, fhat1_threaded, fhat2_threaded, - flux_temp_threaded) + return (; cache..., antidiffusive_fluxes, + fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, + flux_temp_threaded, flux_temp_nonconservative_threaded) end function calc_volume_integral!(du, u, @@ -47,18 +52,20 @@ end @inline function subcell_limiting_kernel!(du, u, element, mesh::TreeMesh{2}, - nonconservative_terms::False, equations, + nonconservative_terms, equations, volume_integral, limiter::SubcellLimiterIDP, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv = volume_integral # high-order DG fluxes - @unpack fhat1_threaded, fhat2_threaded = cache + @unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache - fhat1 = fhat1_threaded[Threads.threadid()] - fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, + fhat1_L = fhat1_L_threaded[Threads.threadid()] + fhat1_R = fhat1_R_threaded[Threads.threadid()] + fhat2_L = fhat2_L_threaded[Threads.threadid()] + fhat2_R = fhat2_R_threaded[Threads.threadid()] + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # low-order FV fluxes @@ -72,7 +79,9 @@ end nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # antidiffusive flux - calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, element, cache) @@ -93,7 +102,7 @@ end # (**without non-conservative terms**). # # See also `flux_differencing_kernel!`. -@inline function calcflux_fhat!(fhat1, fhat2, u, +@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::TreeMesh{2}, nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) @@ -101,7 +110,7 @@ end @unpack flux_temp_threaded = cache flux_temp = flux_temp_threaded[Threads.threadid()] - + # The FV-form fluxes are calculated in a recursive manner, i.e.: # fhat_(0,1) = w_0 * FVol_0, # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, @@ -132,11 +141,14 @@ end end # FV-form flux `fhat` in x direction - fhat1[:, 1, :] .= zero(eltype(fhat1)) - fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) + fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) + fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) + fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) + fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) - fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat1_L[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_R[v, i + 1, j] = fhat1_L[v, i + 1, j] end # Split form volume flux in orientation 2: y direction @@ -155,38 +167,211 @@ end end # FV-form flux `fhat` in y direction - fhat2[:, :, 1] .= zero(eltype(fhat2)) - fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) + fhat2_L[:, :, 1] .= zero(eltype(fhat2_L)) + fhat2_L[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_L)) + fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) + fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) - fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat2_L[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_R[v, i, j + 1] = fhat2_L[v, i, j + 1] + end + + return nothing +end +# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element +# (**with non-conservative terms**). +# +# See also `flux_differencing_kernel!`. +@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, + mesh::TreeMesh{2}, nonconservative_terms::True, + equations, + volume_flux, dg::DGSEM, element, cache) + @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache + + volume_flux_cons, volume_flux_noncons = volume_flux + + flux_temp = flux_temp_threaded[Threads.threadid()] + flux_temp_noncons = flux_temp_nonconservative_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fhat_(0,1) = w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + flux_temp_noncons .= zero(eltype(flux_temp_noncons)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of `volume_flux_cons` and `volume_flux_noncons` to save half of the possible two-point flux + # computations. + for ii in (i + 1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, + equations, dg, ii, j) + flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric()) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], flux1_noncons, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], flux1_noncons, + equations, dg, ii, j) + end + end + + # FV-form flux `fhat` in x direction + fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) + fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) + fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) + fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) + + fhat_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) + fhat_noncons_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) + + for j in eachnode(dg) + fhat_temp .= zero(eltype(fhat1_L)) + fhat_noncons_temp .= zero(eltype(fhat1_L)) + for i in 1:(nnodes(dg) - 1) + # Get the local contribution to the nonconservative flux + u_node_L = get_node_vars(u, equations, dg, i, j, element) + phi_L = volume_flux_noncons(u_node_L, 1, equations, NonConservativeLocal()) + + u_node_R = get_node_vars(u, equations, dg, i + 1, j, element) + phi_R = volume_flux_noncons(u_node_R, 1, equations, NonConservativeLocal()) + for v in eachvariable(equations) + fhat_temp[v] = fhat_temp[v] + weights[i] * flux_temp[v, i, j] + fhat_noncons_temp[v] = fhat_noncons_temp[v] + weights[i] * flux_temp_noncons[v, i, j] + + fhat1_L[v, i + 1, j] = fhat_temp[v] + phi_L[v] * fhat_noncons_temp[v] + fhat1_R[v, i + 1, j] = fhat_temp[v] + phi_R[v] * fhat_noncons_temp[v] + end + end + end + + # Split form volume flux in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) + flux_temp_noncons .= zero(eltype(flux_temp_noncons)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + for jj in (j + 1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, + equations, dg, i, jj) + flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric()) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], flux2_noncons, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], flux2_noncons, + equations, dg, i, jj) + end + end + + # FV-form flux `fhat` in y direction + fhat2_L[:, :, 1] .= zero(eltype(fhat2_L)) + fhat2_L[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_L)) + fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) + fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) + + for i in eachnode(dg) + fhat_temp .= zero(eltype(fhat1_L)) + fhat_noncons_temp .= zero(eltype(fhat1_L)) + for j in 1:(nnodes(dg) - 1) + # Get the local contribution to the nonconservative flux + u_node_L = get_node_vars(u, equations, dg, i, j, element) + phi_L = volume_flux_noncons(u_node_L, 2, equations, NonConservativeLocal()) + + u_node_R = get_node_vars(u, equations, dg, i, j + 1, element) + phi_R = volume_flux_noncons(u_node_R, 2, equations, NonConservativeLocal()) + for v in eachvariable(equations) + fhat_temp[v] = fhat_temp[v] + weights[j] * flux_temp[v, i, j] + fhat_noncons_temp[v] = fhat_noncons_temp[v] + weights[j] * flux_temp_noncons[v, i, j] + + fhat2_L[v, i, j + 1] = fhat_temp[v] + phi_L[v] * fhat_noncons_temp[v] + fhat2_R[v, i, j + 1] = fhat_temp[v] + phi_R[v] * fhat_noncons_temp[v] + end + end end return nothing end -# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. -@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::False, equations, + limiter::SubcellLimiterIDP, dg, element, cache) + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, element] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, element] + end + end + + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) + + return nothing +end +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::True, equations, limiter::SubcellLimiterIDP, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] - fstar1_R[v, i, j] end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] - fstar2_R[v, i, j] end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) return nothing end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 09ab84ed11..07736c6bfa 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -59,7 +59,7 @@ end @inline function idp_positivity!(alpha, limiter, u, dt, semi, variable, index) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @unpack inverse_weights = dg.basis @unpack positivity_correction_factor = limiter @@ -88,13 +88,13 @@ end # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = inverse_weights[i] * - antidiffusive_flux1[variable, i, j, element] + antidiffusive_flux1_R[variable, i, j, element] val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1[variable, i + 1, j, element] + antidiffusive_flux1_L[variable, i + 1, j, element] val_flux2_local = inverse_weights[j] * - antidiffusive_flux2[variable, i, j, element] + antidiffusive_flux2_R[variable, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2[variable, i, j + 1, element] + antidiffusive_flux2_L[variable, i, j + 1, element] Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index a0ed889968..fed3fb70dd 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -213,6 +213,11 @@ function set_proposed_dt!(integrator::SimpleIntegratorSSP, dt) integrator.dt = dt end +# used by adaptive timestepping algorithms in DiffEq +function get_proposed_dt(integrator::SimpleIntegratorSSP) + return integrator.dt +end + # stop the time integration function terminate!(integrator::SimpleIntegratorSSP) integrator.finalstep = true From 67e379ff17af6a84cbddfeb63b712528434bedf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 6 Oct 2023 15:03:56 +0200 Subject: [PATCH 268/423] Modified non-conservative fluxes to revert src/solvers/dgsem_tree/dg_2d.jl back to its original state --- src/equations/ideal_glm_mhd_2d.jl | 12 ++++++------ src/solvers/dgsem_tree/dg_2d.jl | 16 ++++++++-------- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 6 ++++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 82d4844b16..c032a778c3 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -259,9 +259,9 @@ end =# # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - psi_avg = 0.5 * (psi_ll + psi_rr) + psi_avg = (psi_ll + psi_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 if orientation == 1 - B1_avg = 0.5 * (B1_ll + B1_rr) + B1_avg = (B1_ll + B1_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, B1_ll * B1_avg, B2_ll * B1_avg, @@ -272,7 +272,7 @@ end =# v3_ll * B1_avg, 0)#v1_ll * psi_avg) else # orientation == 2 - B2_avg = 0.5 * (B2_ll + B2_rr) + B2_avg = (B2_ll + B2_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, B1_ll * B2_avg, B2_ll * B2_avg, @@ -329,9 +329,9 @@ end # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - psi_avg = 0.5 * (psi_ll + psi_rr) + psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 if orientation == 1 - B1_avg = 0.5 * (B1_ll + B1_rr) + B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, B1_avg, B1_avg, @@ -342,7 +342,7 @@ end B1_avg, 0)#psi_avg) else # orientation == 2 - B2_avg = 0.5 * (B2_ll + B2_rr) + B2_avg = (B2_ll + B2_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, B2_avg, B2_avg, diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index 679b6b33f2..c30d0a8e01 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -316,7 +316,7 @@ end end # The factor 0.5 cancels the factor 2 in the flux differencing form - multiply_add_to_node_vars!(du, alpha, integral_contribution, equations, + multiply_add_to_node_vars!(du, alpha * 0.5, integral_contribution, equations, dg, i, j, element) end end @@ -493,8 +493,8 @@ end # Note the factor 0.5 necessary for the nonconservative fluxes based on # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs - f1_L = f1 + nonconservative_flux(u_ll, u_rr, 1, equations) - f1_R = f1 + nonconservative_flux(u_rr, u_ll, 1, equations) + f1_L = f1 + 0.5 * nonconservative_flux(u_ll, u_rr, 1, equations) + f1_R = f1 + 0.5 * nonconservative_flux(u_rr, u_ll, 1, equations) # Copy to temporary storage set_node_vars!(fstar1_L, f1_L, equations, dg, i, j) @@ -519,8 +519,8 @@ end # Note the factor 0.5 necessary for the nonconservative fluxes based on # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs - f2_L = f2 + nonconservative_flux(u_ll, u_rr, 2, equations) - f2_R = f2 + nonconservative_flux(u_rr, u_ll, 2, equations) + f2_L = f2 + 0.5 * nonconservative_flux(u_ll, u_rr, 2, equations) + f2_R = f2 + 0.5 * nonconservative_flux(u_rr, u_ll, 2, equations) # Copy to temporary storage set_node_vars!(fstar2_L, f2_L, equations, dg, i, j) @@ -626,10 +626,10 @@ function calc_interface_flux!(surface_flux_values, # the interpretation of global SBP operators coupled discontinuously via # central fluxes/SATs surface_flux_values[v, i, left_direction, left_id] = flux[v] + - #0.5 * + 0.5 * noncons_left[v] surface_flux_values[v, i, right_direction, right_id] = flux[v] + - #0.5 * + 0.5 * noncons_right[v] end end @@ -779,7 +779,7 @@ function calc_boundary_flux_by_direction!(surface_flux_values::AbstractArray{<:A # Copy flux to left and right element storage for v in eachvariable(equations) surface_flux_values[v, i, direction, neighbor] = flux[v] + - noncons_flux[v] + 0.5 * noncons_flux[v] end end end diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 57053f97e0..7c8bdff4b0 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -222,7 +222,8 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, equations, dg, ii, j) - flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric()) + # We multiply by 0.5 because that is done in other parts of Trixi + flux1_noncons = 0.5 * volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric()) multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], flux1_noncons, equations, dg, i, j) multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], flux1_noncons, @@ -272,7 +273,8 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, equations, dg, i, jj) - flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric()) + # We multiply by 0.5 because that is done in other parts of Trixi + flux2_noncons = 0.5 * volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric()) multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], flux2_noncons, equations, dg, i, j) multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], flux2_noncons, From 12c6c1d56dc9780839a92e6c8adfcd64a37da89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 11:51:12 +0200 Subject: [PATCH 269/423] Subcell limiting: Added the possibility to use multiple nonconservative terms --- .../elixir_mhd_shockcapturing_subcell.jl | 17 +- src/Trixi.jl | 2 +- src/equations/equations.jl | 6 + src/equations/ideal_glm_mhd_2d.jl | 165 +++++++++--------- .../dgsem_tree/dg_2d_subcell_limiters.jl | 91 ++++++---- 5 files changed, 153 insertions(+), 128 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 3729497331..db362b74cd 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -19,11 +19,11 @@ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) # setup taken from Derigs et al. DMV article (2018) # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 r = sqrt(x[1]^2 + x[2]^2) + pmax = 10.0 - pmin = 10.0 - - rhomin = 0.5 + pmin = 1.0 rhomax = 1.0 + rhomin = 0.01 if r <= 0.09 p = pmax rho = rhomax @@ -46,13 +46,12 @@ end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_derigs_etal, flux_nonconservative_powell) #central +volume_flux = (flux_derigs_etal, flux_nonconservative_powell) basis = LobattoLegendreBasis(3) -#volume_integral=VolumeIntegralFluxDifferencing(volume_flux) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons=[1], - positivity_correction_factor=0.8) + positivity_correction_factor=0.5) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) @@ -76,10 +75,10 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 30 +analysis_interval = 100 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=10) #analysis_interval +alive_callback = AliveCallback(analysis_interval=analysis_interval) save_solution = SaveSolutionCallback(interval=100, save_initial_solution=true, @@ -102,7 +101,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation stage_callbacks = (SubcellLimiterIDPCorrection(),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); # +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback save_everystep=false, callback=callbacks); summary_callback() # print the timer summary diff --git a/src/Trixi.jl b/src/Trixi.jl index b65d03e797..b448521741 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -60,7 +60,7 @@ using RecipesBase: RecipesBase using Requires: @require using Static: Static, One, True, False @reexport using StaticArrays: SVector -using StaticArrays: StaticArrays, MVector, MArray, SMatrix, @SMatrix +using StaticArrays: StaticArrays, MVector, MArray, SMatrix, @SMatrix, MMatrix using StrideArrays: PtrArray, StrideArray, StaticInt @reexport using StructArrays: StructArrays, StructArray using TimerOutputs: TimerOutputs, @notimeit, TimerOutput, print_timer, reset_timer! diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 9bae563d85..a941f750a6 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -220,6 +220,12 @@ example of equations with nonconservative terms. The return value will be `True()` or `False()` to allow dispatching on the return type. """ have_nonconservative_terms(::AbstractEquations) = False() +""" + nnoncons(equations) +Number of nonconservative terms for a particular equation. The default is 0 and +it must be defined for each nonconservative equation independently. +""" +nnoncons(::AbstractEquations) = 0 have_constant_speed(::AbstractEquations) = False() default_analysis_errors(::AbstractEquations) = (:l2_error, :linf_error) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index c032a778c3..9a26503397 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -133,10 +133,10 @@ end f4 = rho_v1 * v3 - B1 * B3 f5 = (kin_en + equations.gamma * p_over_gamma_minus_one + 2 * mag_en) * v1 - B1 * (v1 * B1 + v2 * B2 + v3 * B3) + equations.c_h * psi * B1 - f6 = 0#equations.c_h * psi + f6 = equations.c_h * psi f7 = v1 * B2 - v2 * B1 f8 = v1 * B3 - v3 * B1 - f9 = 0#equations.c_h * B1 + f9 = equations.c_h * B1 else #if orientation == 2 f1 = rho_v2 f2 = rho_v2 * v1 - B2 * B1 @@ -145,9 +145,9 @@ end f5 = (kin_en + equations.gamma * p_over_gamma_minus_one + 2 * mag_en) * v2 - B2 * (v1 * B1 + v2 * B2 + v3 * B3) + equations.c_h * psi * B2 f6 = v2 * B1 - v1 * B2 - f7 = 0#equations.c_h * psi + f7 = equations.c_h * psi f8 = v2 * B3 - v3 * B2 - f9 = 0#equations.c_h * B2 + f9 = equations.c_h * B2 end return SVector(f1, f2, f3, f4, f5, f6, f7, f8, f9) @@ -211,42 +211,6 @@ terms. equations. Part I: Theory and numerical verification [DOI: 10.1016/j.jcp.2018.06.027](https://doi.org/10.1016/j.jcp.2018.06.027) """ -#= @inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D) - rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll - rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr - - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - - # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) - # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - if orientation == 1 - f = SVector(0, - B1_ll * B1_rr, - B2_ll * B1_rr, - B3_ll * B1_rr, - v_dot_B_ll * B1_rr + v1_ll * psi_ll * psi_rr, - v1_ll * B1_rr, - v2_ll * B1_rr, - v3_ll * B1_rr, - v1_ll * psi_rr) - else # orientation == 2 - f = SVector(0, - B1_ll * B2_rr, - B2_ll * B2_rr, - B3_ll * B2_rr, - v_dot_B_ll * B2_rr + v2_ll * psi_ll * psi_rr, - v1_ll * B2_rr, - v2_ll * B2_rr, - v3_ll * B2_rr, - v2_ll * psi_rr) - end - - return f -end =# @inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll @@ -266,22 +230,22 @@ end =# B1_ll * B1_avg, B2_ll * B1_avg, B3_ll * B1_avg, - v_dot_B_ll * B1_avg, # + v1_ll * psi_ll * psi_rr, + v_dot_B_ll * B1_avg + v1_ll * psi_ll * psi_avg, v1_ll * B1_avg, v2_ll * B1_avg, v3_ll * B1_avg, - 0)#v1_ll * psi_avg) + v1_ll * psi_avg) else # orientation == 2 B2_avg = (B2_ll + B2_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, B1_ll * B2_avg, B2_ll * B2_avg, B3_ll * B2_avg, - v_dot_B_ll * B2_avg, # + v2_ll * psi_ll * psi_rr, + v_dot_B_ll * B2_avg + v2_ll * psi_ll * psi_avg, v1_ll * B2_avg, v2_ll * B2_avg, v3_ll * B2_avg, - 0)#v2_ll * psi_avg) + v2_ll * psi_avg) end return f @@ -291,7 +255,8 @@ end """ @inline function flux_nonconservative_powell(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeLocal) + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll v1_ll = rho_v1_ll / rho_ll @@ -299,18 +264,41 @@ end v3_ll = rho_v3_ll / rho_ll v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) - # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - f = SVector(0, - B1_ll, - B2_ll, - B3_ll, - v_dot_B_ll, # The term (v1_ll * psi_ll) is missing because we need to define several non-conservative terms - v1_ll, - v2_ll, - v3_ll, - 0)#v1_ll) - + if noncons_term ==1 + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + f = SVector(0, + B1_ll, + B2_ll, + B3_ll, + v_dot_B_ll, + v1_ll, + v2_ll, + v3_ll, + 0) + else #noncons_term ==2 + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + if orientation == 1 + f = SVector(0, + 0, + 0, + 0, + v1_ll * psi_ll, + 0, + 0, + 0, + v1_ll) + else #orientation == 2 + f = SVector(0, + 0, + 0, + 0, + v2_ll * psi_ll, + 0, + 0, + 0, + v2_ll) + end + end return f end """ @@ -318,7 +306,8 @@ end """ @inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeSymmetric) + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr @@ -327,31 +316,43 @@ end v3_ll = rho_v3_ll / rho_ll v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) - # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 - if orientation == 1 - B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 - f = SVector(0, - B1_avg, - B1_avg, - B1_avg, - B1_avg, # The term (psi_avg) is missing because we need to define several non-conservative terms - B1_avg, - B1_avg, - B1_avg, - 0)#psi_avg) - else # orientation == 2 - B2_avg = (B2_ll + B2_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + if noncons_term ==1 + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + if orientation == 1 + B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + f = SVector(0, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + 0) + else # orientation == 2 + B2_avg = (B2_ll + B2_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + f = SVector(0, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + 0) + end + else #noncons_term == 2 + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, - B2_avg, - B2_avg, - B2_avg, - B2_avg, # The term (psi_avg) is missing because we need to define several non-conservative terms - B2_avg, - B2_avg, - B2_avg, - 0)#psi_avg) + 0, + 0, + 0, + psi_avg, + 0, + 0, + 0, + psi_avg) end return f diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 7c8bdff4b0..f658f00fcf 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -14,6 +14,7 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} A3d = Array{uEltype, 3} + A4d = Array{uEltype, 4} fhat1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, nnodes(dg)) for _ in 1:Threads.nthreads()] @@ -25,8 +26,8 @@ function create_cache(mesh::TreeMesh{2}, equations, nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - flux_temp_nonconservative_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) #nnoncons(equations) - for _ in 1:Threads.nthreads()] + flux_temp_nonconservative_threaded = A4d[A4d(undef, nvariables(equations), nnoncons(equations), + nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) @@ -222,12 +223,14 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, equations, dg, ii, j) - # We multiply by 0.5 because that is done in other parts of Trixi - flux1_noncons = 0.5 * volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric()) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], flux1_noncons, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], flux1_noncons, - equations, dg, ii, j) + for noncons in 1:nnoncons(equations) + # We multiply by 0.5 because that is done in other parts of Trixi + flux1_noncons = 0.5 * volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], flux1_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], flux1_noncons, + equations, dg, noncons, ii, j) + end end end @@ -238,24 +241,31 @@ end fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) fhat_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) - fhat_noncons_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) + fhat_noncons_temp = zero(MMatrix{nvariables(equations), nnoncons(equations), eltype(fhat1_L)}) for j in eachnode(dg) fhat_temp .= zero(eltype(fhat1_L)) fhat_noncons_temp .= zero(eltype(fhat1_L)) for i in 1:(nnodes(dg) - 1) - # Get the local contribution to the nonconservative flux + # Conservative part + for v in eachvariable(equations) + fhat_temp[v] += weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat_temp[v] + fhat1_R[v, i + 1, j] = fhat_temp[v] + end + # Nonconservative part u_node_L = get_node_vars(u, equations, dg, i, j, element) - phi_L = volume_flux_noncons(u_node_L, 1, equations, NonConservativeLocal()) - u_node_R = get_node_vars(u, equations, dg, i + 1, j, element) - phi_R = volume_flux_noncons(u_node_R, 1, equations, NonConservativeLocal()) - for v in eachvariable(equations) - fhat_temp[v] = fhat_temp[v] + weights[i] * flux_temp[v, i, j] - fhat_noncons_temp[v] = fhat_noncons_temp[v] + weights[i] * flux_temp_noncons[v, i, j] - - fhat1_L[v, i + 1, j] = fhat_temp[v] + phi_L[v] * fhat_noncons_temp[v] - fhat1_R[v, i + 1, j] = fhat_temp[v] + phi_R[v] * fhat_noncons_temp[v] + for noncons in 1:nnoncons(equations) + # Get the local contribution to the nonconservative flux + phi_L = volume_flux_noncons(u_node_L, 1, equations, NonConservativeLocal(), noncons) + phi_R = volume_flux_noncons(u_node_R, 1, equations, NonConservativeLocal(), noncons) + for v in eachvariable(equations) + fhat_noncons_temp[v, noncons] += weights[i] * flux_temp_noncons[v, noncons, i, j] + + fhat1_L[v, i + 1, j] += phi_L[v] * fhat_noncons_temp[v, noncons] + fhat1_R[v, i + 1, j] += phi_R[v] * fhat_noncons_temp[v, noncons] + end end end end @@ -273,12 +283,14 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, equations, dg, i, jj) - # We multiply by 0.5 because that is done in other parts of Trixi - flux2_noncons = 0.5 * volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric()) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], flux2_noncons, - equations, dg, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], flux2_noncons, - equations, dg, i, jj) + for noncons in 1:nnoncons(equations) + # We multiply by 0.5 because that is done in other parts of Trixi + flux2_noncons = 0.5 * volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], flux2_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], flux2_noncons, + equations, dg, noncons, i, jj) + end end end @@ -291,19 +303,26 @@ end for i in eachnode(dg) fhat_temp .= zero(eltype(fhat1_L)) fhat_noncons_temp .= zero(eltype(fhat1_L)) - for j in 1:(nnodes(dg) - 1) - # Get the local contribution to the nonconservative flux + for j in 1:(nnodes(dg) - 1) + # Conservative part + for v in eachvariable(equations) + fhat_temp[v] += weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat_temp[v] + fhat2_R[v, i, j + 1] = fhat_temp[v] + end + # Nonconservative part u_node_L = get_node_vars(u, equations, dg, i, j, element) - phi_L = volume_flux_noncons(u_node_L, 2, equations, NonConservativeLocal()) - u_node_R = get_node_vars(u, equations, dg, i, j + 1, element) - phi_R = volume_flux_noncons(u_node_R, 2, equations, NonConservativeLocal()) - for v in eachvariable(equations) - fhat_temp[v] = fhat_temp[v] + weights[j] * flux_temp[v, i, j] - fhat_noncons_temp[v] = fhat_noncons_temp[v] + weights[j] * flux_temp_noncons[v, i, j] - - fhat2_L[v, i, j + 1] = fhat_temp[v] + phi_L[v] * fhat_noncons_temp[v] - fhat2_R[v, i, j + 1] = fhat_temp[v] + phi_R[v] * fhat_noncons_temp[v] + for noncons in 1:nnoncons(equations) + # Get the local contribution to the nonconservative flux + phi_L = volume_flux_noncons(u_node_L, 2, equations, NonConservativeLocal(), noncons) + phi_R = volume_flux_noncons(u_node_R, 2, equations, NonConservativeLocal(), noncons) + for v in eachvariable(equations) + fhat_noncons_temp[v, noncons] += weights[j] * flux_temp_noncons[v, noncons, i, j] + + fhat2_L[v, i, j + 1] += phi_L[v] * fhat_noncons_temp[v, noncons] + fhat2_R[v, i, j + 1] += phi_R[v] * fhat_noncons_temp[v, noncons] + end end end end From 7017914a1ff465c6d75095397d0e375c8e2e6f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 12:09:30 +0200 Subject: [PATCH 270/423] Added some comments and improved formatting --- .../elixir_mhd_shockcapturing_subcell.jl | 5 +- src/equations/ideal_glm_mhd_2d.jl | 28 ++++- src/solvers/dgsem_tree/containers_2d.jl | 32 +++--- .../dgsem_tree/dg_2d_subcell_limiters.jl | 108 ++++++++++++------ 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index db362b74cd..3185544905 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -10,10 +10,11 @@ equations = IdealGlmMhdEquations2D(1.4) """ initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) -An MHD blast wave taken from +An MHD blast wave modified from: - Dominik Derigs, Gregor J. Gassner, Stefanie Walch & Andrew R. Winters (2018) Entropy Stable Finite Volume Approximations for Ideal Magnetohydrodynamics [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) +This setup needs a positivity limiter for the density. """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) # setup taken from Derigs et al. DMV article (2018) @@ -85,7 +86,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -cfl = 0.3 +cfl = 0.5 stepsize_callback = StepsizeCallback(cfl=cfl) glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 9a26503397..f9290539e7 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -251,10 +251,18 @@ terms. return f end """ - + flux_nonconservative_powell(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) + +Local part of the Powell and GLM non-conservative terms. Needed for the calculation of +the non-conservative staggered "fluxes" for subcell limiting. See, e.g., +- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts + Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ @inline function flux_nonconservative_powell(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, + equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeLocal, noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll @@ -264,7 +272,7 @@ end v3_ll = rho_v3_ll / rho_ll v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - if noncons_term ==1 + if noncons_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) f = SVector(0, B1_ll, @@ -302,10 +310,18 @@ end return f end """ - + flux_nonconservative_powell(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) + +Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of +the non-conservative staggered "fluxes" for subcell limiting. See, e.g., +- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts + Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ @inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D, + equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeSymmetric, noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll @@ -316,7 +332,7 @@ end v3_ll = rho_v3_ll / rho_ll v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - if noncons_term ==1 + if noncons_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) if orientation == 1 B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 576732b921..0784a83403 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1283,22 +1283,22 @@ function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, # Initialize fields with defaults _antidiffusive_flux1_L = fill(nan_uEltype, - n_variables * (n_nodes + 1) * n_nodes * capacity) + n_variables * (n_nodes + 1) * n_nodes * capacity) antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), - (n_variables, n_nodes + 1, n_nodes, capacity)) + (n_variables, n_nodes + 1, n_nodes, capacity)) _antidiffusive_flux1_R = fill(nan_uEltype, - n_variables * (n_nodes + 1) * n_nodes * capacity) + n_variables * (n_nodes + 1) * n_nodes * capacity) antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), - (n_variables, n_nodes + 1, n_nodes, capacity)) + (n_variables, n_nodes + 1, n_nodes, capacity)) _antidiffusive_flux2_L = fill(nan_uEltype, - n_variables * n_nodes * (n_nodes + 1) * capacity) + n_variables * n_nodes * (n_nodes + 1) * capacity) antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), - (n_variables, n_nodes, n_nodes + 1, capacity)) + (n_variables, n_nodes, n_nodes + 1, capacity)) _antidiffusive_flux2_R = fill(nan_uEltype, - n_variables * n_nodes * (n_nodes + 1) * capacity) + n_variables * n_nodes * (n_nodes + 1) * capacity) antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), - (n_variables, n_nodes, n_nodes + 1, capacity)) + (n_variables, n_nodes, n_nodes + 1, capacity)) return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1_L, antidiffusive_flux1_R, @@ -1326,20 +1326,20 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) resize!(_antidiffusive_flux1_L, n_variables * (n_nodes + 1) * n_nodes * capacity) fluxes.antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), - (n_variables, n_nodes + 1, n_nodes, - capacity)) + (n_variables, n_nodes + 1, n_nodes, + capacity)) resize!(_antidiffusive_flux1_R, n_variables * (n_nodes + 1) * n_nodes * capacity) fluxes.antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), - (n_variables, n_nodes + 1, n_nodes, - capacity)) + (n_variables, n_nodes + 1, n_nodes, + capacity)) resize!(_antidiffusive_flux2_L, n_variables * n_nodes * (n_nodes + 1) * capacity) fluxes.antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), - (n_variables, n_nodes, n_nodes + 1, - capacity)) + (n_variables, n_nodes, n_nodes + 1, + capacity)) resize!(_antidiffusive_flux2_R, n_variables * n_nodes * (n_nodes + 1) * capacity) fluxes.antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), - (n_variables, n_nodes, n_nodes + 1, - capacity)) + (n_variables, n_nodes, n_nodes + 1, + capacity)) return nothing end diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index f658f00fcf..4af22c2f0e 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -17,21 +17,23 @@ function create_cache(mesh::TreeMesh{2}, equations, A4d = Array{uEltype, 4} fhat1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, - nnodes(dg)) for _ in 1:Threads.nthreads()] + nnodes(dg)) for _ in 1:Threads.nthreads()] fhat2_L_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), - nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] fhat1_R_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, - nnodes(dg)) for _ in 1:Threads.nthreads()] + nnodes(dg)) for _ in 1:Threads.nthreads()] fhat2_R_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), - nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - flux_temp_nonconservative_threaded = A4d[A4d(undef, nvariables(equations), nnoncons(equations), - nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] + flux_temp_nonconservative_threaded = A4d[A4d(undef, nvariables(equations), + nnoncons(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., antidiffusive_fluxes, + return (; cache..., antidiffusive_fluxes, fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, flux_temp_threaded, flux_temp_nonconservative_threaded) end @@ -80,8 +82,8 @@ end nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # antidiffusive flux - calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, limiter, dg, element, cache) @@ -111,7 +113,7 @@ end @unpack flux_temp_threaded = cache flux_temp = flux_temp_threaded[Threads.threadid()] - + # The FV-form fluxes are calculated in a recursive manner, i.e.: # fhat_(0,1) = w_0 * FVol_0, # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, @@ -184,6 +186,13 @@ end # (**with non-conservative terms**). # # See also `flux_differencing_kernel!`. +# +# The calculation of the non-conservative staggered "fluxes" requires non-conservative +# terms that can be written as a product of local and a symmetric contributions. See, e.g., +# +# - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts +# Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. +# @inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::TreeMesh{2}, nonconservative_terms::True, equations, @@ -225,11 +234,15 @@ end equations, dg, ii, j) for noncons in 1:nnoncons(equations) # We multiply by 0.5 because that is done in other parts of Trixi - flux1_noncons = 0.5 * volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], flux1_noncons, - equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], flux1_noncons, - equations, dg, noncons, ii, j) + flux1_noncons = 0.5 * + volume_flux_noncons(u_node, u_node_ii, 1, equations, + NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], + flux1_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], + flux1_noncons, + equations, dg, noncons, ii, j) end end end @@ -241,7 +254,8 @@ end fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) fhat_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) - fhat_noncons_temp = zero(MMatrix{nvariables(equations), nnoncons(equations), eltype(fhat1_L)}) + fhat_noncons_temp = zero(MMatrix{nvariables(equations), nnoncons(equations), + eltype(fhat1_L)}) for j in eachnode(dg) fhat_temp .= zero(eltype(fhat1_L)) @@ -258,11 +272,14 @@ end u_node_R = get_node_vars(u, equations, dg, i + 1, j, element) for noncons in 1:nnoncons(equations) # Get the local contribution to the nonconservative flux - phi_L = volume_flux_noncons(u_node_L, 1, equations, NonConservativeLocal(), noncons) - phi_R = volume_flux_noncons(u_node_R, 1, equations, NonConservativeLocal(), noncons) + phi_L = volume_flux_noncons(u_node_L, 1, equations, + NonConservativeLocal(), noncons) + phi_R = volume_flux_noncons(u_node_R, 1, equations, + NonConservativeLocal(), noncons) for v in eachvariable(equations) - fhat_noncons_temp[v, noncons] += weights[i] * flux_temp_noncons[v, noncons, i, j] - + fhat_noncons_temp[v, noncons] += weights[i] * + flux_temp_noncons[v, noncons, i, j] + fhat1_L[v, i + 1, j] += phi_L[v] * fhat_noncons_temp[v, noncons] fhat1_R[v, i + 1, j] += phi_R[v] * fhat_noncons_temp[v, noncons] end @@ -285,11 +302,15 @@ end equations, dg, i, jj) for noncons in 1:nnoncons(equations) # We multiply by 0.5 because that is done in other parts of Trixi - flux2_noncons = 0.5 * volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], flux2_noncons, - equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], flux2_noncons, - equations, dg, noncons, i, jj) + flux2_noncons = 0.5 * + volume_flux_noncons(u_node, u_node_jj, 2, equations, + NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], + flux2_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], + flux2_noncons, + equations, dg, noncons, i, jj) end end end @@ -315,10 +336,13 @@ end u_node_R = get_node_vars(u, equations, dg, i, j + 1, element) for noncons in 1:nnoncons(equations) # Get the local contribution to the nonconservative flux - phi_L = volume_flux_noncons(u_node_L, 2, equations, NonConservativeLocal(), noncons) - phi_R = volume_flux_noncons(u_node_R, 2, equations, NonConservativeLocal(), noncons) + phi_L = volume_flux_noncons(u_node_L, 2, equations, + NonConservativeLocal(), noncons) + phi_R = volume_flux_noncons(u_node_R, 2, equations, + NonConservativeLocal(), noncons) for v in eachvariable(equations) - fhat_noncons_temp[v, noncons] += weights[j] * flux_temp_noncons[v, noncons, i, j] + fhat_noncons_temp[v, noncons] += weights[j] * + flux_temp_noncons[v, noncons, i, j] fhat2_L[v, i, j + 1] += phi_L[v] * fhat_noncons_temp[v, noncons] fhat2_R[v, i, j + 1] += phi_R[v] * fhat_noncons_temp[v, noncons] @@ -331,8 +355,8 @@ end end # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. -@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms::False, equations, limiter::SubcellLimiterIDP, dg, element, cache) @@ -340,14 +364,18 @@ end for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - fstar1_L[v, i, j] - antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, element] + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - + fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, + element] end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - fstar2_L[v, i, j] - antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, element] + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - + fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, + element] end end @@ -373,14 +401,18 @@ end for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - fstar1_L[v, i, j] - antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] - fstar1_R[v, i, j] + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - + fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] - + fstar1_R[v, i, j] end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - fstar2_L[v, i, j] - antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] - fstar2_R[v, i, j] + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - + fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] - + fstar2_R[v, i, j] end end From 5119d97c85bea9e0b89c49cda6d32c5365663768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 12:25:30 +0200 Subject: [PATCH 271/423] Added expected results for MHD subcell limiting test --- test/test_tree_2d_mhd.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index 3e104da3e9..da9d34ef74 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -73,6 +73,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") # of this IC to have negative density/pressure values, crashing the simulation. coverage_override = (maxiters=9,)) end + + @trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), + l2 = [1.72786992e-01, 6.33650587e-02, 6.86872255e-02, 0.00000000e+00, 4.31337885e+00, 1.67036008e-01, 1.06316839e-01, 0.00000000e+00, 4.67098356e-03], + linf = [9.80256401e-01, 9.20713091e-01, 5.55986508e-01, 0.00000000e+00, 2.49132899e+01, 6.39041960e-01, 6.08144670e-01, 0.00000000e+00, 5.83546136e-02]) + end end end # module From ad6177e64cda4ff04b457757ee43aef48565662b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 16:52:03 +0200 Subject: [PATCH 272/423] Restored old Powell source term and created a new function name for the modified Powell source term. This was needed due to incompatibility on non-conforming meshes. --- .../elixir_mhd_shockcapturing_subcell.jl | 4 +- src/Trixi.jl | 2 +- src/equations/ideal_glm_mhd_2d.jl | 141 ++++++++++++------ 3 files changed, 100 insertions(+), 47 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 3185544905..d7ef23332f 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -46,8 +46,8 @@ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) end initial_condition = initial_condition_blast_wave -surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_derigs_etal, flux_nonconservative_powell) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) +volume_flux = (flux_derigs_etal, flux_nonconservative_powell2) basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; diff --git a/src/Trixi.jl b/src/Trixi.jl index b448521741..1346d8ff7a 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -161,7 +161,7 @@ export GradientVariablesPrimitive, GradientVariablesEntropy export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_godunov, flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner, - flux_nonconservative_powell, + flux_nonconservative_powell, flux_nonconservative_powell2 flux_kennedy_gruber, flux_shima_etal, flux_ec, flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_es_fjordholm_etal, flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal, diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index f9290539e7..76cfc7b433 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -221,6 +221,95 @@ terms. v3_ll = rho_v3_ll / rho_ll v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + if orientation == 1 + f = SVector(0, + B1_ll * B1_rr, + B2_ll * B1_rr, + B3_ll * B1_rr, + v_dot_B_ll * B1_rr + v1_ll * psi_ll * psi_rr, + v1_ll * B1_rr, + v2_ll * B1_rr, + v3_ll * B1_B1_rravg, + v1_ll * psi_rr) + else # orientation == 2 + f = SVector(0, + B1_ll * B2_rr, + B2_ll * B2_rr, + B3_ll * B2_rr, + v_dot_B_ll * B2_rr + v2_ll * psi_ll * psi_rr, + v1_ll * B2_rr, + v2_ll * B2_rr, + v3_ll * B2_rr, + v2_ll * psi_rr) + end + + return f +end + +@inline function flux_nonconservative_powell(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + + # Note that `v_dot_n_ll` uses the `normal_direction_ll` (contravariant vector + # at the same node location) while `B_dot_n_rr` uses the averaged normal + # direction. The reason for this is that `v_dot_n_ll` depends only on the left + # state and multiplies some gradient while `B_dot_n_rr` is used to compute + # the divergence of B. + v_dot_n_ll = v1_ll * normal_direction_ll[1] + v2_ll * normal_direction_ll[2] + B_dot_n_rr = B1_rr * normal_direction_average[1] + + B2_rr * normal_direction_average[2] + + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + f = SVector(0, + B1_ll * B_dot_n_rr, + B2_ll * B_dot_n_rr, + B3_ll * B_dot_n_rr, + v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr, + v1_ll * B_dot_n_rr, + v2_ll * B_dot_n_rr, + v3_ll * B_dot_n_rr, + v_dot_n_ll * psi_rr) + + return f +end + +""" + flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D) + +Non-symmetric two-point flux discretizing the nonconservative (source) term of +Powell and the Galilean nonconservative term associated with the GLM multiplier +of the [`IdealGlmMhdEquations2D`](@ref). + +This implementation uses a non-conservative term that can be written as the product +of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm +et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different +results on non-conforming meshes(!). +## References +- Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts + Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. +""" +@inline function flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) psi_avg = (psi_ll + psi_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 @@ -261,10 +350,10 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ -@inline function flux_nonconservative_powell(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeLocal, - noncons_term::Integer) +@inline function flux_nonconservative_powell2(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll v1_ll = rho_v1_ll / rho_ll @@ -320,10 +409,10 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ -@inline function flux_nonconservative_powell(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) +@inline function flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr @@ -374,42 +463,6 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., return f end -@inline function flux_nonconservative_powell(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::IdealGlmMhdEquations2D) - rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll - rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr - - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - - # Note that `v_dot_n_ll` uses the `normal_direction_ll` (contravariant vector - # at the same node location) while `B_dot_n_rr` uses the averaged normal - # direction. The reason for this is that `v_dot_n_ll` depends only on the left - # state and multiplies some gradient while `B_dot_n_rr` is used to compute - # the divergence of B. - v_dot_n_ll = v1_ll * normal_direction_ll[1] + v2_ll * normal_direction_ll[2] - B_dot_n_rr = B1_rr * normal_direction_average[1] + - B2_rr * normal_direction_average[2] - - # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) - # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - f = SVector(0, - B1_ll * B_dot_n_rr, - B2_ll * B_dot_n_rr, - B3_ll * B_dot_n_rr, - v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr, - v1_ll * B_dot_n_rr, - v2_ll * B_dot_n_rr, - v3_ll * B_dot_n_rr, - v_dot_n_ll * psi_rr) - - return f -end - """ flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations2D) From 91580938ef79ce9783d4bfb17aff034ecb04d537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 16:54:00 +0200 Subject: [PATCH 273/423] Fixed bug --- src/equations/ideal_glm_mhd_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 76cfc7b433..fcd337d646 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -231,7 +231,7 @@ terms. v_dot_B_ll * B1_rr + v1_ll * psi_ll * psi_rr, v1_ll * B1_rr, v2_ll * B1_rr, - v3_ll * B1_B1_rravg, + v3_ll * B1_rr, v1_ll * psi_rr) else # orientation == 2 f = SVector(0, From 3dcccc40d97857cb29a1d96aca97b3277409824c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 10 Oct 2023 16:58:53 +0200 Subject: [PATCH 274/423] Fixed bug --- src/Trixi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index 1346d8ff7a..14687cbb99 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -161,7 +161,7 @@ export GradientVariablesPrimitive, GradientVariablesEntropy export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_godunov, flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner, - flux_nonconservative_powell, flux_nonconservative_powell2 + flux_nonconservative_powell, flux_nonconservative_powell2, flux_kennedy_gruber, flux_shima_etal, flux_ec, flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_es_fjordholm_etal, flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal, From adb930e08f2bf5902f24ee20c3cefd8e54a28f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 11 Oct 2023 11:30:20 +0200 Subject: [PATCH 275/423] Moved new multiple-dispatch structs for to equations.jl --- src/equations/equations.jl | 13 +++++++++++++ src/equations/ideal_glm_mhd_2d.jl | 3 --- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index a941f750a6..ac232a8bb3 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -207,7 +207,20 @@ where `x` specifies the coordinates, `t` is the current time, and `equation` is struct BoundaryConditionNeumann{B} boundary_normal_flux_function::B end +""" + NonConservativeLocal +Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". +When the argument nonconservative_type is of type `NonConservativeLocal`, the function returns the local part of the non-conservative term. +""" +struct NonConservativeLocal end +""" + NonConservativeSymmetric + +Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". +When the argument nonconservative_type is of type `NonConservativeSymmetric`, the function returns the symmetric part of the non-conservative term. +""" +struct NonConservativeSymmetric end # set sensible default values that may be overwritten by specific equations """ have_nonconservative_terms(equations) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index fcd337d646..09b1788ed8 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -23,9 +23,6 @@ mutable struct IdealGlmMhdEquations2D{RealT <: Real} <: end end -struct NonConservativeLocal end -struct NonConservativeSymmetric end - function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN)) # Use `promote` to ensure that `gamma` and `initial_c_h` have the same type IdealGlmMhdEquations2D(promote(gamma, initial_c_h)...) From b0e3aad73c8162287f5049e7be000ee9c742418b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 11 Oct 2023 12:48:41 +0200 Subject: [PATCH 276/423] Improved allocations --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 80 ++++++++++++------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 4af22c2f0e..adcb06837b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -30,12 +30,20 @@ function create_cache(mesh::TreeMesh{2}, equations, nnoncons(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), + nnodes(dg)) + for _ in 1:Threads.nthreads()] + fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), + nnoncons(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) return (; cache..., antidiffusive_fluxes, fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, - flux_temp_threaded, flux_temp_nonconservative_threaded) + flux_temp_threaded, flux_temp_nonconservative_threaded, fhat_temp_threaded, + fhat_nonconservative_temp_threaded) end function calc_volume_integral!(du, u, @@ -198,13 +206,16 @@ end equations, volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache + @unpack flux_temp_threaded, flux_temp_nonconservative_threaded, fhat_temp_threaded, fhat_nonconservative_temp_threaded = cache volume_flux_cons, volume_flux_noncons = volume_flux flux_temp = flux_temp_threaded[Threads.threadid()] flux_temp_noncons = flux_temp_nonconservative_threaded[Threads.threadid()] + fhat_temp = fhat_temp_threaded[Threads.threadid()] + fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()] + # The FV-form fluxes are calculated in a recursive manner, i.e.: # fhat_(0,1) = w_0 * FVol_0, # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, @@ -253,19 +264,17 @@ end fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) - fhat_temp = zero(MVector{nvariables(equations), eltype(fhat1_L)}) - fhat_noncons_temp = zero(MMatrix{nvariables(equations), nnoncons(equations), - eltype(fhat1_L)}) + fhat_temp .= zero(eltype(fhat1_L)) + fhat_noncons_temp .= zero(eltype(fhat1_L)) - for j in eachnode(dg) - fhat_temp .= zero(eltype(fhat1_L)) - fhat_noncons_temp .= zero(eltype(fhat1_L)) + @trixi_timeit timer() "subcell volume integral (x)" for j in eachnode(dg) for i in 1:(nnodes(dg) - 1) # Conservative part for v in eachvariable(equations) - fhat_temp[v] += weights[i] * flux_temp[v, i, j] - fhat1_L[v, i + 1, j] = fhat_temp[v] - fhat1_R[v, i + 1, j] = fhat_temp[v] + fhat_temp[v, i + 1, j] = fhat_temp[v, i, j] + + weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat_temp[v, i + 1, j] + fhat1_R[v, i + 1, j] = fhat_temp[v, i + 1, j] end # Nonconservative part u_node_L = get_node_vars(u, equations, dg, i, j, element) @@ -277,11 +286,18 @@ end phi_R = volume_flux_noncons(u_node_R, 1, equations, NonConservativeLocal(), noncons) for v in eachvariable(equations) - fhat_noncons_temp[v, noncons] += weights[i] * - flux_temp_noncons[v, noncons, i, j] - - fhat1_L[v, i + 1, j] += phi_L[v] * fhat_noncons_temp[v, noncons] - fhat1_R[v, i + 1, j] += phi_R[v] * fhat_noncons_temp[v, noncons] + fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, + noncons, + i, j] + + weights[i] * + flux_temp_noncons[v, + noncons, + i, j] + + fhat1_L[v, i + 1, j] += phi_L[v] * + fhat_noncons_temp[v, noncons, i + 1, j] + fhat1_R[v, i + 1, j] += phi_R[v] * + fhat_noncons_temp[v, noncons, i + 1, j] end end end @@ -321,15 +337,17 @@ end fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) - for i in eachnode(dg) - fhat_temp .= zero(eltype(fhat1_L)) - fhat_noncons_temp .= zero(eltype(fhat1_L)) + fhat_temp .= zero(eltype(fhat1_L)) + fhat_noncons_temp .= zero(eltype(fhat1_L)) + + @trixi_timeit timer() "subcell volume integral (y)" for i in eachnode(dg) for j in 1:(nnodes(dg) - 1) # Conservative part for v in eachvariable(equations) - fhat_temp[v] += weights[j] * flux_temp[v, i, j] - fhat2_L[v, i, j + 1] = fhat_temp[v] - fhat2_R[v, i, j + 1] = fhat_temp[v] + fhat_temp[v, i, j + 1] = fhat_temp[v, i, j] + + weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat_temp[v, i, j + 1] + fhat2_R[v, i, j + 1] = fhat_temp[v, i, j + 1] end # Nonconservative part u_node_L = get_node_vars(u, equations, dg, i, j, element) @@ -341,16 +359,22 @@ end phi_R = volume_flux_noncons(u_node_R, 2, equations, NonConservativeLocal(), noncons) for v in eachvariable(equations) - fhat_noncons_temp[v, noncons] += weights[j] * - flux_temp_noncons[v, noncons, i, j] - - fhat2_L[v, i, j + 1] += phi_L[v] * fhat_noncons_temp[v, noncons] - fhat2_R[v, i, j + 1] += phi_R[v] * fhat_noncons_temp[v, noncons] + fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, + noncons, + i, j] + + weights[j] * + flux_temp_noncons[v, + noncons, + i, j] + + fhat2_L[v, i, j + 1] += phi_L[v] * + fhat_noncons_temp[v, noncons, i, j + 1] + fhat2_R[v, i, j + 1] += phi_R[v] * + fhat_noncons_temp[v, noncons, i, j + 1] end end end end - return nothing end From e0a3fdfcb577683ebcf57eafce65539f67cab8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 11 Oct 2023 16:55:30 +0200 Subject: [PATCH 277/423] Avoid double computation of local part of non-conservative flux --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index adcb06837b..da5b438e42 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -37,13 +37,19 @@ function create_cache(mesh::TreeMesh{2}, equations, nnoncons(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] + + phi_threaded = A4d[A4d(undef, nvariables(equations), + nnoncons(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) return (; cache..., antidiffusive_fluxes, fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, flux_temp_threaded, flux_temp_nonconservative_threaded, fhat_temp_threaded, - fhat_nonconservative_temp_threaded) + fhat_nonconservative_temp_threaded, phi_threaded) end function calc_volume_integral!(du, u, @@ -206,7 +212,8 @@ end equations, volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded, flux_temp_nonconservative_threaded, fhat_temp_threaded, fhat_nonconservative_temp_threaded = cache + @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache + @unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache volume_flux_cons, volume_flux_noncons = volume_flux @@ -215,6 +222,7 @@ end fhat_temp = fhat_temp_threaded[Threads.threadid()] fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()] + phi = phi_threaded[Threads.threadid()] # The FV-form fluxes are calculated in a recursive manner, i.e.: # fhat_(0,1) = w_0 * FVol_0, @@ -267,6 +275,15 @@ end fhat_temp .= zero(eltype(fhat1_L)) fhat_noncons_temp .= zero(eltype(fhat1_L)) + # Compute local contribution to non-conservative flux + for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) + u_local = get_node_vars(u, equations, dg, i, j, element) + set_node_vars!(phi, + volume_flux_noncons(u_local, 1, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end + @trixi_timeit timer() "subcell volume integral (x)" for j in eachnode(dg) for i in 1:(nnodes(dg) - 1) # Conservative part @@ -277,14 +294,7 @@ end fhat1_R[v, i + 1, j] = fhat_temp[v, i + 1, j] end # Nonconservative part - u_node_L = get_node_vars(u, equations, dg, i, j, element) - u_node_R = get_node_vars(u, equations, dg, i + 1, j, element) for noncons in 1:nnoncons(equations) - # Get the local contribution to the nonconservative flux - phi_L = volume_flux_noncons(u_node_L, 1, equations, - NonConservativeLocal(), noncons) - phi_R = volume_flux_noncons(u_node_R, 1, equations, - NonConservativeLocal(), noncons) for v in eachvariable(equations) fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, noncons, @@ -294,9 +304,9 @@ end noncons, i, j] - fhat1_L[v, i + 1, j] += phi_L[v] * + fhat1_L[v, i + 1, j] += phi[v, noncons, i, j] * fhat_noncons_temp[v, noncons, i + 1, j] - fhat1_R[v, i + 1, j] += phi_R[v] * + fhat1_R[v, i + 1, j] += phi[v, noncons, i + 1, j] * fhat_noncons_temp[v, noncons, i + 1, j] end end @@ -340,6 +350,15 @@ end fhat_temp .= zero(eltype(fhat1_L)) fhat_noncons_temp .= zero(eltype(fhat1_L)) + # Compute local contribution to non-conservative flux + for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) + u_local = get_node_vars(u, equations, dg, i, j, element) + set_node_vars!(phi, + volume_flux_noncons(u_local, 2, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end + @trixi_timeit timer() "subcell volume integral (y)" for i in eachnode(dg) for j in 1:(nnodes(dg) - 1) # Conservative part @@ -350,14 +369,7 @@ end fhat2_R[v, i, j + 1] = fhat_temp[v, i, j + 1] end # Nonconservative part - u_node_L = get_node_vars(u, equations, dg, i, j, element) - u_node_R = get_node_vars(u, equations, dg, i, j + 1, element) for noncons in 1:nnoncons(equations) - # Get the local contribution to the nonconservative flux - phi_L = volume_flux_noncons(u_node_L, 2, equations, - NonConservativeLocal(), noncons) - phi_R = volume_flux_noncons(u_node_R, 2, equations, - NonConservativeLocal(), noncons) for v in eachvariable(equations) fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, noncons, @@ -367,9 +379,9 @@ end noncons, i, j] - fhat2_L[v, i, j + 1] += phi_L[v] * + fhat2_L[v, i, j + 1] += phi[v, noncons, i, j] * fhat_noncons_temp[v, noncons, i, j + 1] - fhat2_R[v, i, j + 1] += phi_R[v] * + fhat2_R[v, i, j + 1] += phi[v, noncons, i, j + 1] * fhat_noncons_temp[v, noncons, i, j + 1] end end From 86884e81e7cfbe18d6f7390fc64d8d14f21bd574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Wed, 11 Oct 2023 17:15:20 +0200 Subject: [PATCH 278/423] Improved subcell volume integral in y direction and formatting --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 100 ++++++++---------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index da5b438e42..3a9d898bc4 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -272,8 +272,8 @@ end fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) - fhat_temp .= zero(eltype(fhat1_L)) - fhat_noncons_temp .= zero(eltype(fhat1_L)) + fhat_temp[:, 1, :] .= zero(eltype(fhat1_L)) + fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L)) # Compute local contribution to non-conservative flux for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) @@ -284,32 +284,26 @@ end equations, dg, noncons, i, j) end - @trixi_timeit timer() "subcell volume integral (x)" for j in eachnode(dg) - for i in 1:(nnodes(dg) - 1) - # Conservative part - for v in eachvariable(equations) - fhat_temp[v, i + 1, j] = fhat_temp[v, i, j] + - weights[i] * flux_temp[v, i, j] - fhat1_L[v, i + 1, j] = fhat_temp[v, i + 1, j] - fhat1_R[v, i + 1, j] = fhat_temp[v, i + 1, j] - end - # Nonconservative part - for noncons in 1:nnoncons(equations) - for v in eachvariable(equations) - fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, - noncons, - i, j] + - weights[i] * - flux_temp_noncons[v, - noncons, - i, j] - - fhat1_L[v, i + 1, j] += phi[v, noncons, i, j] * - fhat_noncons_temp[v, noncons, i + 1, j] - fhat1_R[v, i + 1, j] += phi[v, noncons, i + 1, j] * - fhat_noncons_temp[v, noncons, i + 1, j] - end - end + for j in eachnode(dg), i in 1:(nnodes(dg) - 1) + # Conservative part + for v in eachvariable(equations) + fhat_temp[v, i + 1, j] = fhat_temp[v, i, j] + + weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat_temp[v, i + 1, j] + fhat1_R[v, i + 1, j] = fhat_temp[v, i + 1, j] + end + # Nonconservative part + for noncons in 1:nnoncons(equations), v in eachvariable(equations) + fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, noncons, i, + j] + + weights[i] * + flux_temp_noncons[v, noncons, i, + j] + + fhat1_L[v, i + 1, j] += phi[v, noncons, i, j] * + fhat_noncons_temp[v, noncons, i + 1, j] + fhat1_R[v, i + 1, j] += phi[v, noncons, i + 1, j] * + fhat_noncons_temp[v, noncons, i + 1, j] end end @@ -347,8 +341,8 @@ end fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) - fhat_temp .= zero(eltype(fhat1_L)) - fhat_noncons_temp .= zero(eltype(fhat1_L)) + fhat_temp[:, :, 1] .= zero(eltype(fhat1_L)) + fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L)) # Compute local contribution to non-conservative flux for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) @@ -359,32 +353,26 @@ end equations, dg, noncons, i, j) end - @trixi_timeit timer() "subcell volume integral (y)" for i in eachnode(dg) - for j in 1:(nnodes(dg) - 1) - # Conservative part - for v in eachvariable(equations) - fhat_temp[v, i, j + 1] = fhat_temp[v, i, j] + - weights[j] * flux_temp[v, i, j] - fhat2_L[v, i, j + 1] = fhat_temp[v, i, j + 1] - fhat2_R[v, i, j + 1] = fhat_temp[v, i, j + 1] - end - # Nonconservative part - for noncons in 1:nnoncons(equations) - for v in eachvariable(equations) - fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, - noncons, - i, j] + - weights[j] * - flux_temp_noncons[v, - noncons, - i, j] - - fhat2_L[v, i, j + 1] += phi[v, noncons, i, j] * - fhat_noncons_temp[v, noncons, i, j + 1] - fhat2_R[v, i, j + 1] += phi[v, noncons, i, j + 1] * - fhat_noncons_temp[v, noncons, i, j + 1] - end - end + for j in 1:(nnodes(dg) - 1), i in eachnode(dg) + # Conservative part + for v in eachvariable(equations) + fhat_temp[v, i, j + 1] = fhat_temp[v, i, j] + + weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat_temp[v, i, j + 1] + fhat2_R[v, i, j + 1] = fhat_temp[v, i, j + 1] + end + # Nonconservative part + for noncons in 1:nnoncons(equations), v in eachvariable(equations) + fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, noncons, i, + j] + + weights[j] * + flux_temp_noncons[v, noncons, i, + j] + + fhat2_L[v, i, j + 1] += phi[v, noncons, i, j] * + fhat_noncons_temp[v, noncons, i, j + 1] + fhat2_R[v, i, j + 1] += phi[v, noncons, i, j + 1] * + fhat_noncons_temp[v, noncons, i, j + 1] end end return nothing From 0d61cfdb64e7eb97046f87898ff6c0beecb7b51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 10:22:10 +0200 Subject: [PATCH 279/423] Apply suggestions from code review Co-authored-by: Hendrik Ranocha --- src/equations/equations.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index ac232a8bb3..63151f5dff 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -208,17 +208,19 @@ struct BoundaryConditionNeumann{B} boundary_normal_flux_function::B end """ - NonConservativeLocal + NonConservativeLocal() Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". -When the argument nonconservative_type is of type `NonConservativeLocal`, the function returns the local part of the non-conservative term. +When the argument `nonconservative_type` is of type `NonConservativeLocal`, +the function returns the local part of the non-conservative term. """ struct NonConservativeLocal end """ - NonConservativeSymmetric + NonConservativeSymmetric() Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". -When the argument nonconservative_type is of type `NonConservativeSymmetric`, the function returns the symmetric part of the non-conservative term. +When the argument `nonconservative_type` is of type `NonConservativeSymmetric`, +the function returns the symmetric part of the non-conservative term. """ struct NonConservativeSymmetric end # set sensible default values that may be overwritten by specific equations From b0caf8eedd81ee1fe3558535560f1e08c365a45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 10:25:10 +0200 Subject: [PATCH 280/423] Added timers and corrected docstrings --- src/equations/ideal_glm_mhd_2d.jl | 4 ++-- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 09b1788ed8..45aeba3ac2 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -337,7 +337,7 @@ results on non-conforming meshes(!). return f end """ - flux_nonconservative_powell(u_ll, orientation::Integer, + flux_nonconservative_powell2(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeLocal, noncons_term::Integer) @@ -396,7 +396,7 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., return f end """ - flux_nonconservative_powell(u_ll, orientation::Integer, + flux_nonconservative_powell2(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeSymmetric, noncons_term::Integer) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 3a9d898bc4..17354cd27b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -82,7 +82,7 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] - calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + @trixi_timeit timer() "calcflux_fhat!" calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, nonconservative_terms, equations, volume_flux_dg, dg, element, cache) # low-order FV fluxes @@ -92,11 +92,11 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + @trixi_timeit timer() "calcflux_fv!" calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, volume_flux_fv, dg, element, cache) # antidiffusive flux - calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + @trixi_timeit timer() "calcflux_antidiffusive!" calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, nonconservative_terms, equations, limiter, dg, element, @@ -214,7 +214,7 @@ end @unpack weights, derivative_split = dg.basis @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache @unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache - + volume_flux_cons, volume_flux_noncons = volume_flux flux_temp = flux_temp_threaded[Threads.threadid()] From 6dae80a214fbbae1f0506043f9caadc60557f6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 10:32:09 +0200 Subject: [PATCH 281/423] Improved formatting --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 17354cd27b..3731f322ee 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -82,9 +82,11 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fhat!" calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) - + @trixi_timeit timer() "calcflux_fhat!" begin + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) + end # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -92,15 +94,19 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fv!" calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + @trixi_timeit timer() "calcflux_fv!" begin + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) + end # antidiffusive flux - @trixi_timeit timer() "calcflux_antidiffusive!" calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, - nonconservative_terms, equations, limiter, dg, element, - cache) + @trixi_timeit timer() "calcflux_antidiffusive!" begin + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) + end # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -214,7 +220,7 @@ end @unpack weights, derivative_split = dg.basis @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache @unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache - + volume_flux_cons, volume_flux_noncons = volume_flux flux_temp = flux_temp_threaded[Threads.threadid()] From 0c2e24e4d0e7f4a36a6cc412e666301f3fc7bd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 10:50:59 +0200 Subject: [PATCH 282/423] Reduced testing time --- test/test_tree_2d_mhd.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index da9d34ef74..c3911a741c 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -76,8 +76,9 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), - l2 = [1.72786992e-01, 6.33650587e-02, 6.86872255e-02, 0.00000000e+00, 4.31337885e+00, 1.67036008e-01, 1.06316839e-01, 0.00000000e+00, 4.67098356e-03], - linf = [9.80256401e-01, 9.20713091e-01, 5.55986508e-01, 0.00000000e+00, 2.49132899e+01, 6.39041960e-01, 6.08144670e-01, 0.00000000e+00, 5.83546136e-02]) + l2 = [2.9974425783503109e-02, 7.2849646345685956e-02, 7.2488477174662239e-02, 0.0000000000000000e+00, 1.2507971380965512e+00, 1.8929505145499678e-02, 1.2218606317164420e-02, 0.0000000000000000e+00, 3.0154796910479838e-03], + linf = [3.2147382412340830e-01, 1.3709471664007811e+00, 1.3465154685288383e+00, 0.0000000000000000e+00, 1.6051257523415284e+01, 3.0564266749926644e-01, 2.3908016329805595e-01, 0.0000000000000000e+00, 1.3711262178549158e-01], + tspan = (0.0, 0.003)) end end From 9c73f4c3c90a643ec50886da74ad4d677775ad39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 14:25:05 +0200 Subject: [PATCH 283/423] Deactivate bar states for subcell positivity MHD test --- examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index d7ef23332f..10e0620462 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -52,7 +52,8 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons=[1], - positivity_correction_factor=0.5) + positivity_correction_factor=0.5, + bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) From 4e6681c52b5a29f33eec113044f35890c37a943f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 15:01:44 +0200 Subject: [PATCH 284/423] The pressure positivity limiter works for MHD --- .../elixir_mhd_shockcapturing_subcell.jl | 7 ++++--- src/equations/ideal_glm_mhd_2d.jl | 20 +++++++++++++++++++ test/test_tree_2d_mhd.jl | 4 ++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 10e0620462..8ee8177949 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -22,7 +22,7 @@ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) r = sqrt(x[1]^2 + x[2]^2) pmax = 10.0 - pmin = 1.0 + pmin = 0.01 rhomax = 1.0 rhomin = 0.01 if r <= 0.09 @@ -52,7 +52,8 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons=[1], - positivity_correction_factor=0.5, + positivity_variables_nonlinear = [pressure], + positivity_correction_factor=0.1, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, @@ -87,7 +88,7 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -cfl = 0.5 +cfl = 0.4 stepsize_callback = StepsizeCallback(cfl=cfl) glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 45aeba3ac2..1e03aa451c 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1003,6 +1003,18 @@ end return SVector(w1, w2, w3, w4, w5, w6, w7, w8, w9) end +# Transformation from conservative variables u to d(p)/d(u) +@inline function dpdu(u, equations::IdealGlmMhdEquations2D) + rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_square = v1^2 + v2^2 + v3^2 + + return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) +end + # Convert entropy variables to conservative variables @inline function entropy2cons(w, equations::IdealGlmMhdEquations2D) w1, w2, w3, w4, w5, w6, w7, w8, w9 = w @@ -1030,6 +1042,14 @@ end return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end +@inline function isValidState(cons, equations::IdealGlmMhdEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end + # Convert primitive to conservative variables @inline function prim2cons(prim, equations::IdealGlmMhdEquations2D) rho, v1, v2, v3, p, B1, B2, B3, psi = prim diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index c3911a741c..42edabed8a 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -76,8 +76,8 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), - l2 = [2.9974425783503109e-02, 7.2849646345685956e-02, 7.2488477174662239e-02, 0.0000000000000000e+00, 1.2507971380965512e+00, 1.8929505145499678e-02, 1.2218606317164420e-02, 0.0000000000000000e+00, 3.0154796910479838e-03], - linf = [3.2147382412340830e-01, 1.3709471664007811e+00, 1.3465154685288383e+00, 0.0000000000000000e+00, 1.6051257523415284e+01, 3.0564266749926644e-01, 2.3908016329805595e-01, 0.0000000000000000e+00, 1.3711262178549158e-01], + l2 = [3.2064026219236076e-02, 7.2461094392606618e-02, 7.2380202888062711e-02, 0.0000000000000000e+00, 8.6293936673145932e-01, 8.4091669534557805e-03, 5.2156364913231732e-03, 0.0000000000000000e+00, 2.0786952301129021e-04], + linf = [3.8778760255775635e-01, 9.4666683953698927e-01, 9.4618924645661928e-01, 0.0000000000000000e+00, 1.0980297261521951e+01, 1.0264404591009069e-01, 1.0655686942176350e-01, 0.0000000000000000e+00, 6.1013422157115546e-03], tspan = (0.0, 0.003)) end end From a4a1fe80279c20e53dedeea567fa8f1b9f33f9ad Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 12 Oct 2023 15:30:48 +0200 Subject: [PATCH 285/423] Allow arbitrary nonlinear positivity limiting --- src/equations/compressible_euler_2d.jl | 5 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 46 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index d95fbdbcfc..782c8f253a 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1572,7 +1572,7 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function dpdu(u, equations::CompressibleEulerEquations2D) +@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1581,6 +1581,9 @@ end return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) end +@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::False) + return pressure(u, equations) +end @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index a8fcc42c06..c71b343674 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -554,27 +554,25 @@ end # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, - pressure_goal, pressure_dgoal_dbeta, - pressure_initialCheck, pressure_finalCheck, - dt, mesh, equations, dg, cache, limiter) + variable, dt, mesh, equations, dg, cache, limiter) end end return nothing end -pressure_goal(bound, u, equations) = bound - pressure(u, equations) -function pressure_dgoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(dpdu(u, equations), dt * antidiffusive_flux) +goal_function(variable, bound, u, equations) = bound - variable(u, equations) +function dgoal_function(variable, u, dt, antidiffusive_flux, equations) + -dot(variable(u, equations, true), dt * antidiffusive_flux) end -pressure_initialCheck(bound, goal, newton_abstol) = goal <= 0 -function pressure_finalCheck(bound, goal, newton_abstol) + +initialCheck(bound, goal, newton_abstol) = goal <= 0 +function finalCheck(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, - goal_fct, dgoal_fct, initialCheck, finalCheck, - dt, mesh, equations, dg, cache, limiter) + variable, dt, mesh, equations, dg, cache, limiter) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes if mesh isa TreeMesh @@ -589,37 +587,36 @@ end antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, + antidiffusive_flux) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, + antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, + antidiffusive_flux) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, goal_fct, dgoal_fct, initialCheck, - finalCheck, equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, + antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, - goal_fct, dgoal_fct, initialCheck, finalCheck, +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, antidiffusive_flux) newton_reltol, newton_abstol = limiter.newton_tolerances @@ -632,7 +629,7 @@ end # If state is valid, perform initial check and return if correction is not needed if isValidState(u_curr, equations) - as = goal_fct(bound, u_curr, equations) + as = goal_function(variable, bound, u_curr, equations) initialCheck(bound, as, newton_abstol) && return nothing end @@ -643,7 +640,8 @@ end # If the state is valid, evaluate d(goal)/d(beta) if isValidState(u_curr, equations) - dSdbeta = dgoal_fct(u_curr, dt, antidiffusive_flux, equations) + dSdbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, + equations) else # Otherwise, perform a bisection step dSdbeta = 0 end @@ -667,7 +665,7 @@ end end # Check new beta for condition and update bounds - as = goal_fct(bound, u_curr, equations) + as = goal_function(variable, bound, u_curr, equations) if initialCheck(bound, as, newton_abstol) # New beta fulfills condition beta_L = beta @@ -686,7 +684,7 @@ end end # Evaluate goal function - as = goal_fct(bound, u_curr, equations) + as = goal_function(variable, bound, u_curr, equations) end # Check relative tolerance From 2eac4cf7444d9b5da4786ac24b6670ef7ed96b03 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 12 Oct 2023 16:13:54 +0200 Subject: [PATCH 286/423] Implement changes for limiting of entropys --- src/equations/compressible_euler_2d.jl | 2 + src/solvers/dgsem_tree/subcell_limiters_2d.jl | 63 +++++++++---------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 782c8f253a..ddf769049c 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1544,6 +1544,7 @@ end return SVector(w1, w2, w3, w4) end +entropy_math(u, equations, derivative::True) = cons2entropy(u, equations) # Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) @inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) @@ -1570,6 +1571,7 @@ end return SVector(w1, w2, w3, w4) end +entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) # Transformation from conservative variables u to d(p)/d(u) @inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index c71b343674..9e120db4e3 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -408,8 +408,8 @@ end for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, - specEntropy_goal, specEntropy_dGoal_dbeta, - specEntropy_initialCheck, standard_finalCheck, + entropy_spec, initial_check_entropy_spec, + final_check_standard, dt, mesh, equations, dg, cache, limiter) end end @@ -417,11 +417,7 @@ end return nothing end -specEntropy_goal(bound, u, equations) = bound - entropy_spec(u, equations) -function specEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(cons2entropy_spec(u, equations), dt * antidiffusive_flux) -end -function specEntropy_initialCheck(bound, goal, newton_abstol) +function initial_check_entropy_spec(bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end @@ -438,8 +434,8 @@ end for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, - mathEntropy_goal, mathEntropy_dGoal_dbeta, - mathEntropy_initialCheck, standard_finalCheck, + entropy_math, initial_check_entropy_math, + final_check_standard, dt, mesh, equations, dg, cache, limiter) end end @@ -447,11 +443,7 @@ end return nothing end -mathEntropy_goal(bound, u, equations) = bound - entropy_math(u, equations) -function mathEntropy_dGoal_dbeta(u, dt, antidiffusive_flux, equations) - -dot(cons2entropy(u, equations), dt * antidiffusive_flux) -end -function mathEntropy_initialCheck(bound, goal, newton_abstol) +function initial_check_entropy_math(bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end @@ -554,7 +546,9 @@ end # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, - variable, dt, mesh, equations, dg, cache, limiter) + variable, initial_check_nonnegative, + final_check_nonnegative, + dt, mesh, equations, dg, cache, limiter) end end @@ -563,16 +557,17 @@ end goal_function(variable, bound, u, equations) = bound - variable(u, equations) function dgoal_function(variable, u, dt, antidiffusive_flux, equations) - -dot(variable(u, equations, true), dt * antidiffusive_flux) + -dot(variable(u, equations, True()), dt * antidiffusive_flux) end -initialCheck(bound, goal, newton_abstol) = goal <= 0 -function finalCheck(bound, goal, newton_abstol) +initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 +function final_check_nonnegative(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end -@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, - variable, dt, mesh, equations, dg, cache, limiter) +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, + initial_check, final_check, dt, mesh, equations, + dg, cache, limiter) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes if mesh isa TreeMesh @@ -587,37 +582,37 @@ end antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, - antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, - antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, - antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, variable, equations, dt, limiter, - antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, variable, - equations, dt, limiter, antidiffusive_flux) +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) newton_reltol, newton_abstol = limiter.newton_tolerances beta = 1 - alpha[i, j, element] @@ -631,7 +626,7 @@ end if isValidState(u_curr, equations) as = goal_function(variable, bound, u_curr, equations) - initialCheck(bound, as, newton_abstol) && return nothing + initial_check(bound, as, newton_abstol) && return nothing end # Newton iterations @@ -666,7 +661,7 @@ end # Check new beta for condition and update bounds as = goal_function(variable, bound, u_curr, equations) - if initialCheck(bound, as, newton_abstol) + if initial_check(bound, as, newton_abstol) # New beta fulfills condition beta_L = beta else @@ -693,7 +688,7 @@ end end # Check absolute tolerance - if finalCheck(bound, as, newton_abstol) + if final_check(bound, as, newton_abstol) break end end @@ -708,7 +703,7 @@ end return nothing end -function standard_finalCheck(bound, goal, newton_abstol) +function final_check_standard(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end From 651b7169d6d882f052b45eda7eedfd023d286667 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 12 Oct 2023 16:23:17 +0200 Subject: [PATCH 287/423] Relocate checks and goal functions --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9e120db4e3..14ffef07fe 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -417,10 +417,6 @@ end return nothing end -function initial_check_entropy_spec(bound, goal, newton_abstol) - goal <= max(newton_abstol, abs(bound) * newton_abstol) -end - @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -443,10 +439,6 @@ end return nothing end -function initial_check_entropy_math(bound, goal, newton_abstol) - goal >= -max(newton_abstol, abs(bound) * newton_abstol) -end - @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) # Conservative variables for variable in limiter.positivity_variables_cons @@ -555,16 +547,6 @@ end return nothing end -goal_function(variable, bound, u, equations) = bound - variable(u, equations) -function dgoal_function(variable, u, dt, antidiffusive_flux, equations) - -dot(variable(u, equations, True()), dt * antidiffusive_flux) -end - -initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 -function final_check_nonnegative(bound, goal, newton_abstol) - (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) -end - @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, initial_check, final_check, dt, mesh, equations, dg, cache, limiter) @@ -703,6 +685,27 @@ end return nothing end +# Initial checks +function initial_check_entropy_spec(bound, goal, newton_abstol) + goal <= max(newton_abstol, abs(bound) * newton_abstol) +end + +function initial_check_entropy_math(bound, goal, newton_abstol) + goal >= -max(newton_abstol, abs(bound) * newton_abstol) +end + +initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 +function final_check_nonnegative(bound, goal, newton_abstol) + (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) +end + +# Goal and d(Goal)d(u) function +goal_function(variable, bound, u, equations) = bound - variable(u, equations) +function dgoal_function(variable, u, dt, antidiffusive_flux, equations) + -dot(variable(u, equations, True()), dt * antidiffusive_flux) +end + +# Final check function final_check_standard(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end From 70b4fd846a1bde1ce596acf2d8161a5ed087baef Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 12 Oct 2023 16:58:49 +0200 Subject: [PATCH 288/423] Rename functions --- src/equations/compressible_euler_2d.jl | 8 ++++---- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index ddf769049c..cc7b86ef67 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1574,7 +1574,7 @@ end entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) # Transformation from conservative variables u to d(p)/d(u) -@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) +@inline function dpdu(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1583,8 +1583,8 @@ entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) end -@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::False) - return pressure(u, equations) +@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) + return dpdu(u, equations) end @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) @@ -1611,7 +1611,7 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end -@inline function isValidState(cons, equations::CompressibleEulerEquations2D) +@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) p = pressure(cons, equations) if cons[1] <= 0.0 || p <= 0.0 return false diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 14ffef07fe..00a5996ef6 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -605,7 +605,7 @@ end u_curr = u + beta * dt * antidiffusive_flux # If state is valid, perform initial check and return if correction is not needed - if isValidState(u_curr, equations) + if is_valid_state(u_curr, equations) as = goal_function(variable, bound, u_curr, equations) initial_check(bound, as, newton_abstol) && return nothing @@ -616,7 +616,7 @@ end beta_old = beta # If the state is valid, evaluate d(goal)/d(beta) - if isValidState(u_curr, equations) + if is_valid_state(u_curr, equations) dSdbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, equations) else # Otherwise, perform a bisection step @@ -636,7 +636,7 @@ end u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, finish bisection step without checking tolerance and iterate further - if !isValidState(u_curr, equations) + if !is_valid_state(u_curr, equations) beta_R = beta continue end @@ -655,7 +655,7 @@ end u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, redefine right bound without checking tolerance and iterate further - if !isValidState(u_curr, equations) + if !is_valid_state(u_curr, equations) beta_R = beta continue end From 82c9a2f44f28e045370d291121ffee63fc9db4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 12 Oct 2023 18:06:58 +0200 Subject: [PATCH 289/423] MCL works again FOR CONSERVATIVE SYSTEMS --- src/callbacks_stage/bounds_check_2d.jl | 84 ++--- src/equations/ideal_glm_mhd_2d.jl | 3 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 324 +++++++++++------- 3 files changed, 248 insertions(+), 163 deletions(-) diff --git a/src/callbacks_stage/bounds_check_2d.jl b/src/callbacks_stage/bounds_check_2d.jl index f66f8b8b3a..6d2c7a7413 100644 --- a/src/callbacks_stage/bounds_check_2d.jl +++ b/src/callbacks_stage/bounds_check_2d.jl @@ -138,11 +138,11 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterMCL, - time, iter, output_directory, save_errors, interval) + time, iter, output_directory, save_errors, interval) # TODO: nonconservative_terms::False @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @unpack idp_bounds_delta = limiter.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L = cache.antidiffusive_fluxes n_vars = nvariables(equations) @@ -168,7 +168,7 @@ end for j in eachnode(solver), i in eachnode(solver) # -x rho_limited = bar_states1[1, i, j, element] - - antidiffusive_flux1[1, i, j, element] / + antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) @@ -176,7 +176,7 @@ end rho_limited - var_max[1, i, j, element]) # +x rho_limited = bar_states1[1, i + 1, j, element] + - antidiffusive_flux1[1, i + 1, j, element] / + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) @@ -184,7 +184,7 @@ end rho_limited - var_max[1, i, j, element]) # -y rho_limited = bar_states2[1, i, j, element] - - antidiffusive_flux2[1, i, j, element] / + antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) @@ -192,7 +192,7 @@ end rho_limited - var_max[1, i, j, element]) # +y rho_limited = bar_states2[1, i, j + 1, element] + - antidiffusive_flux2[1, i, j + 1, element] / + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] deviation_min[1] = max(deviation_min[1], var_min[1, i, j, element] - rho_limited) @@ -235,11 +235,11 @@ end for j in eachnode(solver), i in eachnode(solver) # -x rho_limited = bar_states1[1, i, j, element] - - antidiffusive_flux1[1, i, j, element] / + antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - - antidiffusive_flux1[v, i, j, element] / + antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - @@ -259,11 +259,11 @@ end end # +x rho_limited = bar_states1[1, i + 1, j, element] + - antidiffusive_flux1[1, i + 1, j, element] / + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] for v in 2:n_vars var_limited = bar_states1[v, i + 1, j, element] + - antidiffusive_flux1[v, i + 1, j, element] / + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - @@ -283,11 +283,11 @@ end end # -y rho_limited = bar_states2[1, i, j, element] - - antidiffusive_flux2[1, i, j, element] / + antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - - antidiffusive_flux2[v, i, j, element] / + antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - @@ -307,11 +307,11 @@ end end # +y rho_limited = bar_states2[1, i, j + 1, element] + - antidiffusive_flux2[1, i, j + 1, element] / + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] for v in 2:n_vars var_limited = bar_states2[v, i, j + 1, element] + - antidiffusive_flux2[v, i, j + 1, element] / + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - @@ -365,11 +365,11 @@ end for j in eachnode(solver), i in eachnode(solver) # -x rho_limited = bar_states1[1, i, j, element] - - antidiffusive_flux1[1, i, j, element] / + antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - - antidiffusive_flux1[v, i, j, element] / + antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) @@ -387,11 +387,11 @@ end end # +x rho_limited = bar_states1[1, i + 1, j, element] + - antidiffusive_flux1[1, i + 1, j, element] / + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] for v in 2:n_vars var_limited = bar_states1[v, i + 1, j, element] + - antidiffusive_flux1[v, i + 1, j, element] / + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) @@ -409,11 +409,11 @@ end end # -y rho_limited = bar_states2[1, i, j, element] - - antidiffusive_flux2[1, i, j, element] / + antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - - antidiffusive_flux2[v, i, j, element] / + antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) @@ -431,11 +431,11 @@ end end # +y rho_limited = bar_states2[1, i, j + 1, element] + - antidiffusive_flux2[1, i, j + 1, element] / + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] for v in 2:n_vars var_limited = bar_states2[v, i, j + 1, element] + - antidiffusive_flux2[v, i, j + 1, element] / + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] deviation_min[v] = max(deviation_min[v], var_min[v, i, j, element] - var_limited) @@ -472,69 +472,69 @@ end for j in eachnode(solver), i in eachnode(solver) # -x rho_limited = bar_states1[1, i, j, element] - - antidiffusive_flux1[1, i, j, element] / + antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] error_pressure = 0.5 * (bar_states1[2, i, j, element] - - antidiffusive_flux1[2, i, j, element] / + antidiffusive_flux1_L[2, i, j, element] / lambda1[i, j, element])^2 + 0.5 * (bar_states1[3, i, j, element] - - antidiffusive_flux1[3, i, j, element] / + antidiffusive_flux1_L[3, i, j, element] / lambda1[i, j, element])^2 - (bar_states1[4, i, j, element] - - antidiffusive_flux1[4, i, j, element] / + antidiffusive_flux1_L[4, i, j, element] / lambda1[i, j, element]) * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) # +x rho_limited = bar_states1[1, i + 1, j, element] + - antidiffusive_flux1[1, i + 1, j, element] / + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] error_pressure = 0.5 * (bar_states1[2, i + 1, j, element] + - antidiffusive_flux1[2, i + 1, j, element] / + antidiffusive_flux1_L[2, i + 1, j, element] / lambda1[i + 1, j, element])^2 + 0.5 * (bar_states1[3, i + 1, j, element] + - antidiffusive_flux1[3, i + 1, j, element] / + antidiffusive_flux1_L[3, i + 1, j, element] / lambda1[i + 1, j, element])^2 - (bar_states1[4, i + 1, j, element] + - antidiffusive_flux1[4, i + 1, j, element] / + antidiffusive_flux1_L[4, i + 1, j, element] / lambda1[i + 1, j, element]) * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) # -y rho_limited = bar_states2[1, i, j, element] - - antidiffusive_flux2[1, i, j, element] / + antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] error_pressure = 0.5 * (bar_states2[2, i, j, element] - - antidiffusive_flux2[2, i, j, element] / + antidiffusive_flux2_L[2, i, j, element] / lambda2[i, j, element])^2 + 0.5 * (bar_states2[3, i, j, element] - - antidiffusive_flux2[3, i, j, element] / + antidiffusive_flux2_L[3, i, j, element] / lambda2[i, j, element])^2 - (bar_states2[4, i, j, element] - - antidiffusive_flux2[4, i, j, element] / + antidiffusive_flux2_L[4, i, j, element] / lambda2[i, j, element]) * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) # +y rho_limited = bar_states2[1, i, j + 1, element] + - antidiffusive_flux2[1, i, j + 1, element] / + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] error_pressure = 0.5 * (bar_states2[2, i, j + 1, element] + - antidiffusive_flux2[2, i, j + 1, element] / + antidiffusive_flux2_L[2, i, j + 1, element] / lambda2[i, j + 1, element])^2 + 0.5 * (bar_states2[3, i, j + 1, element] + - antidiffusive_flux2[3, i, j + 1, element] / + antidiffusive_flux2_L[3, i, j + 1, element] / lambda2[i, j + 1, element])^2 - (bar_states2[4, i, j + 1, element] + - antidiffusive_flux2[4, i, j + 1, element] / + antidiffusive_flux2_L[4, i, j + 1, element] / lambda2[i, j + 1, element]) * rho_limited deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], error_pressure) @@ -559,22 +559,22 @@ end for j in eachnode(solver), i in eachnode(solver) # -x rho_limited = (1 - beta) * bar_states1[1, i, j, element] - - antidiffusive_flux1[1, i, j, element] / + antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # +x rho_limited = (1 - beta) * bar_states1[1, i + 1, j, element] + - antidiffusive_flux1[1, i + 1, j, element] / + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # -y rho_limited = (1 - beta) * bar_states2[1, i, j, element] - - antidiffusive_flux2[1, i, j, element] / + antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] deviation_min[1] = max(deviation_min[1], -rho_limited) # +y rho_limited = (1 - beta) * bar_states2[1, i, j + 1, element] + - antidiffusive_flux2[1, i, j + 1, element] / + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] deviation_min[1] = max(deviation_min[1], -rho_limited) end diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 1e03aa451c..64172db379 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1012,7 +1012,8 @@ end v3 = rho_v3 / rho v_square = v1^2 + v2^2 + v3^2 - return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) + return (equations.gamma - 1.0) * + SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) end # Convert entropy variables to conservative variables diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 0c9e1e7b4f..5e2999054c 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -185,11 +185,16 @@ end @unpack volume_flux_dg, volume_flux_fv = volume_integral # high-order DG fluxes - @unpack fhat1_threaded, fhat2_threaded = cache - fhat1 = fhat1_threaded[Threads.threadid()] - fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + @unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache + fhat1_L = fhat1_L_threaded[Threads.threadid()] + fhat1_R = fhat1_R_threaded[Threads.threadid()] + fhat2_L = fhat2_L_threaded[Threads.threadid()] + fhat2_R = fhat2_R_threaded[Threads.threadid()] + @trixi_timeit timer() "calcflux_fhat!" begin + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) + end # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -197,20 +202,26 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + @trixi_timeit timer() "calcflux_fv!" begin + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) + end # antidiffusive flux - calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, - u, mesh, nonconservative_terms, equations, limiter, dg, - element, cache) + @trixi_timeit timer() "calcflux_antidiffusive!" begin + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) + end # limit antidiffusive flux calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, limiter, dg, element, cache, fstar1_L, fstar2_L) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * @@ -219,11 +230,11 @@ end (fstar2_L[v, i, j + 1] - fstar2_R[v, i, j]) du[v, i, j, element] += inverse_weights[i] * - (-antidiffusive_flux1[v, i + 1, j, element] + - antidiffusive_flux1[v, i, j, element]) + + (-antidiffusive_flux1_L[v, i + 1, j, element] + + antidiffusive_flux1_R[v, i, j, element]) + inverse_weights[j] * - (-antidiffusive_flux2[v, i, j + 1, element] + - antidiffusive_flux2[v, i, j, element]) + (-antidiffusive_flux2_L[v, i, j + 1, element] + + antidiffusive_flux2_R[v, i, j, element]) end end @@ -568,27 +579,76 @@ end return nothing end -@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::False, equations, + limiter::SubcellLimiterMCL, dg, element, cache) + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1_L[v, i, j, element] = -(fhat1_L[v, i, j] - + fstar1_L[v, i, j]) + antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, + element] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2_L[v, i, j, element] = -(fhat2_L[v, i, j] - + fstar2_L[v, i, j]) + antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, + element] + end + end + + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) + + return nothing +end + +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::True, equations, limiter::SubcellLimiterMCL, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = -(fhat1[v, i, j] - fstar1[v, i, j]) + antidiffusive_flux1_L[v, i, j, element] = -(fhat1_L[v, i, j] - + fstar1_L[v, i, j]) + antidiffusive_flux1_R[v, i, j, element] = -(fhat1_R[v, i, j] - + fstar1_R[v, i, j]) end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = -(fhat2[v, i, j] - fstar2[v, i, j]) + antidiffusive_flux2_L[v, i, j, element] = -(fhat2_L[v, i, j] - + fstar2_L[v, i, j]) + antidiffusive_flux2_R[v, i, j, element] = -(fhat2_R[v, i, j] - + fstar2_R[v, i, j]) end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) return nothing end @@ -1039,11 +1099,11 @@ end return nothing end -@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, +@inline function calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms::False, equations, limiter, dg, element, cache, fstar1, fstar2) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @@ -1077,27 +1137,27 @@ end bar_state_rho = bar_states1[1, i, j, element] # Limit density - if antidiffusive_flux1[1, i, j, element] > 0 + if antidiffusive_flux1_L[1, i, j, element] > 0 f_max = lambda * min(var_max[1, i - 1, j, element] - bar_state_rho, bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[1, i, j, element], + flux_limited = min(antidiffusive_flux1_L[1, i, j, element], max(f_max, 0.0)) else f_min = lambda * max(var_min[1, i - 1, j, element] - bar_state_rho, bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[1, i, j, element], + flux_limited = max(antidiffusive_flux1_L[1, i, j, element], min(f_min, 0.0)) end if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) + if isapprox(antidiffusive_flux1_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux1[1, i, j, element] + + (antidiffusive_flux1_L[1, i, j, element] + sign(flux_limited) * eps())) end @@ -1110,14 +1170,16 @@ end alpha_mean[1, i, j, element] += coefficient end end - antidiffusive_flux1[1, i, j, element] = flux_limited + antidiffusive_flux1_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha if limiter.DensityAlphaForAll for v in 2:nvariables(equations) - antidiffusive_flux1[v, i, j, element] = coefficient * - antidiffusive_flux1[v, i, j, - element] + antidiffusive_flux1_L[v, i, j, element] = coefficient * + antidiffusive_flux1_L[v, + i, + j, + element] end end end @@ -1127,27 +1189,27 @@ end bar_state_rho = bar_states2[1, i, j, element] # Limit density - if antidiffusive_flux2[1, i, j, element] > 0 + if antidiffusive_flux2_L[1, i, j, element] > 0 f_max = lambda * min(var_max[1, i, j - 1, element] - bar_state_rho, bar_state_rho - var_min[1, i, j, element]) f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[1, i, j, element], + flux_limited = min(antidiffusive_flux2_L[1, i, j, element], max(f_max, 0.0)) else f_min = lambda * max(var_min[1, i, j - 1, element] - bar_state_rho, bar_state_rho - var_max[1, i, j, element]) f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[1, i, j, element], + flux_limited = max(antidiffusive_flux2_L[1, i, j, element], min(f_min, 0.0)) end if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) + if isapprox(antidiffusive_flux2_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux2[1, i, j, element] + + (antidiffusive_flux2_L[1, i, j, element] + sign(flux_limited) * eps())) end @@ -1160,14 +1222,16 @@ end alpha_mean[1, i, j, element] += coefficient end end - antidiffusive_flux2[1, i, j, element] = flux_limited + antidiffusive_flux2_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha if limiter.DensityAlphaForAll for v in 2:nvariables(equations) - antidiffusive_flux2[v, i, j, element] = coefficient * - antidiffusive_flux2[v, i, j, - element] + antidiffusive_flux2_L[v, i, j, element] = coefficient * + antidiffusive_flux2_L[v, + i, + j, + element] end end end @@ -1181,15 +1245,15 @@ end # Limit velocity and total energy rho_limited_iim1 = lambda * bar_state_rho - - antidiffusive_flux1[1, i, j, element] + antidiffusive_flux1_L[1, i, j, element] rho_limited_im1i = lambda * bar_state_rho + - antidiffusive_flux1[1, i, j, element] + antidiffusive_flux1_L[1, i, j, element] for v in 2:nvariables(equations) bar_state_phi = bar_states1[v, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux1[v, i, j, element] + + g = antidiffusive_flux1_L[v, i, j, element] + (lambda * bar_state_phi - rho_limited_im1i * phi) if g > 0 @@ -1220,9 +1284,9 @@ end alpha_mean[v, i - 1, j, element] += coefficient alpha_mean[v, i, j, element] += coefficient end - antidiffusive_flux1[v, i, j, element] = (rho_limited_im1i * phi - - lambda * bar_state_phi) + - g_limited + antidiffusive_flux1_L[v, i, j, element] = (rho_limited_im1i * phi - + lambda * bar_state_phi) + + g_limited end end @@ -1232,15 +1296,15 @@ end # Limit velocity and total energy rho_limited_jjm1 = lambda * bar_state_rho - - antidiffusive_flux2[1, i, j, element] + antidiffusive_flux2_L[1, i, j, element] rho_limited_jm1j = lambda * bar_state_rho + - antidiffusive_flux2[1, i, j, element] + antidiffusive_flux2_L[1, i, j, element] for v in 2:nvariables(equations) bar_state_phi = bar_states2[v, i, j, element] phi = bar_state_phi / bar_state_rho - g = antidiffusive_flux2[v, i, j, element] + + g = antidiffusive_flux2_L[v, i, j, element] + (lambda * bar_state_phi - rho_limited_jm1j * phi) if g > 0 @@ -1272,9 +1336,9 @@ end alpha_mean[v, i, j, element] += coefficient end - antidiffusive_flux2[v, i, j, element] = (rho_limited_jm1j * phi - - lambda * bar_state_phi) + - g_limited + antidiffusive_flux2_L[v, i, j, element] = (rho_limited_jm1j * phi - + lambda * bar_state_phi) + + g_limited end end # Conservative limiter @@ -1284,28 +1348,28 @@ end for v in 2:nvariables(equations) bar_state_phi = bar_states1[v, i, j, element] # Limit density - if antidiffusive_flux1[v, i, j, element] > 0 + if antidiffusive_flux1_L[v, i, j, element] > 0 f_max = lambda * min(var_max[v, i - 1, j, element] - bar_state_phi, bar_state_phi - var_min[v, i, j, element]) f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[v, i, j, element], + flux_limited = min(antidiffusive_flux1_L[v, i, j, element], max(f_max, 0.0)) else f_min = lambda * max(var_min[v, i - 1, j, element] - bar_state_phi, bar_state_phi - var_max[v, i, j, element]) f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[v, i, j, element], + flux_limited = max(antidiffusive_flux1_L[v, i, j, element], min(f_min, 0.0)) end if limiter.Plotting - if isapprox(antidiffusive_flux1[v, i, j, element], 0.0, + if isapprox(antidiffusive_flux1_L[v, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux1[v, i, j, element] + + (antidiffusive_flux1_L[v, i, j, element] + sign(flux_limited) * eps())) end @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients @@ -1315,7 +1379,7 @@ end alpha_mean[v, i - 1, j, element] += coefficient alpha_mean[v, i, j, element] += coefficient end - antidiffusive_flux1[v, i, j, element] = flux_limited + antidiffusive_flux1_L[v, i, j, element] = flux_limited end end @@ -1324,28 +1388,28 @@ end for v in 2:nvariables(equations) bar_state_phi = bar_states2[v, i, j, element] # Limit density - if antidiffusive_flux2[v, i, j, element] > 0 + if antidiffusive_flux2_L[v, i, j, element] > 0 f_max = lambda * min(var_max[v, i, j - 1, element] - bar_state_phi, bar_state_phi - var_min[v, i, j, element]) f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[v, i, j, element], + flux_limited = min(antidiffusive_flux2_L[v, i, j, element], max(f_max, 0.0)) else f_min = lambda * max(var_min[v, i, j - 1, element] - bar_state_phi, bar_state_phi - var_max[v, i, j, element]) f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[v, i, j, element], + flux_limited = max(antidiffusive_flux2_L[v, i, j, element], min(f_min, 0.0)) end if limiter.Plotting - if isapprox(antidiffusive_flux2[v, i, j, element], 0.0, + if isapprox(antidiffusive_flux2_L[v, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else coefficient = min(1, (flux_limited + sign(flux_limited) * eps()) / - (antidiffusive_flux2[v, i, j, element] + + (antidiffusive_flux2_L[v, i, j, element] + sign(flux_limited) * eps())) end @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients @@ -1355,7 +1419,7 @@ end alpha_mean[v, i, j - 1, element] += coefficient alpha_mean[v, i, j, element] += coefficient end - antidiffusive_flux2[v, i, j, element] = flux_limited + antidiffusive_flux2_L[v, i, j, element] = flux_limited end end end # limiter.SequentialLimiter and limiter.ConservativeLimiter @@ -1367,23 +1431,23 @@ end lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] # Limit density - if antidiffusive_flux1[1, i, j, element] > 0 + if antidiffusive_flux1_L[1, i, j, element] > 0 f_max = (1 - beta) * lambda * bar_state_rho f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux1[1, i, j, element], + flux_limited = min(antidiffusive_flux1_L[1, i, j, element], max(f_max, 0.0)) else f_min = -(1 - beta) * lambda * bar_state_rho f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux1[1, i, j, element], + flux_limited = max(antidiffusive_flux1_L[1, i, j, element], min(f_min, 0.0)) end if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux1[1, i, j, element], 0.0, atol = eps()) + if isapprox(antidiffusive_flux1_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux1[1, i, j, element] + coefficient = flux_limited / antidiffusive_flux1_L[1, i, j, element] end if limiter.Plotting @@ -1397,14 +1461,16 @@ end end end end - antidiffusive_flux1[1, i, j, element] = flux_limited + antidiffusive_flux1_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha if limiter.DensityAlphaForAll for v in 2:nvariables(equations) - antidiffusive_flux1[v, i, j, element] = coefficient * - antidiffusive_flux1[v, i, j, - element] + antidiffusive_flux1_L[v, i, j, element] = coefficient * + antidiffusive_flux1_L[v, + i, + j, + element] end end end @@ -1413,23 +1479,23 @@ end lambda = lambda2[i, j, element] bar_state_rho = bar_states2[1, i, j, element] # Limit density - if antidiffusive_flux2[1, i, j, element] > 0 + if antidiffusive_flux2_L[1, i, j, element] > 0 f_max = (1 - beta) * lambda * bar_state_rho f_max = isapprox(f_max, 0.0, atol = eps()) ? 0.0 : f_max - flux_limited = min(antidiffusive_flux2[1, i, j, element], + flux_limited = min(antidiffusive_flux2_L[1, i, j, element], max(f_max, 0.0)) else f_min = -(1 - beta) * lambda * bar_state_rho f_min = isapprox(f_min, 0.0, atol = eps()) ? 0.0 : f_min - flux_limited = max(antidiffusive_flux2[1, i, j, element], + flux_limited = max(antidiffusive_flux2_L[1, i, j, element], min(f_min, 0.0)) end if limiter.Plotting || limiter.DensityAlphaForAll - if isapprox(antidiffusive_flux2[1, i, j, element], 0.0, atol = eps()) + if isapprox(antidiffusive_flux2_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else - coefficient = flux_limited / antidiffusive_flux2[1, i, j, element] + coefficient = flux_limited / antidiffusive_flux2_L[1, i, j, element] end if limiter.Plotting @@ -1443,14 +1509,16 @@ end end end end - antidiffusive_flux2[1, i, j, element] = flux_limited + antidiffusive_flux2_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha if limiter.DensityAlphaForAll for v in 2:nvariables(equations) - antidiffusive_flux2[v, i, j, element] = coefficient * - antidiffusive_flux2[v, i, j, - element] + antidiffusive_flux2_L[v, i, j, element] = coefficient * + antidiffusive_flux2_L[v, + i, + j, + element] end end end @@ -1492,8 +1560,8 @@ end for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 - flux_velocity = antidiffusive_flux1[2, i, j, element]^2 + - antidiffusive_flux1[3, i, j, element]^2 + flux_velocity = antidiffusive_flux1_L[2, i, j, element]^2 + + antidiffusive_flux1_L[3, i, j, element]^2 Q = lambda1[i, j, element]^2 * (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - @@ -1503,35 +1571,35 @@ end # exact calculation of max(R_ij, R_ji) R_max = lambda1[i, j, element] * abs(bar_states1[2, i, j, element] * - antidiffusive_flux1[2, i, j, element] + + antidiffusive_flux1_L[2, i, j, element] + bar_states1[3, i, j, element] * - antidiffusive_flux1[3, i, j, element] - + antidiffusive_flux1_L[3, i, j, element] - bar_states1[1, i, j, element] * - antidiffusive_flux1[4, i, j, element] - + antidiffusive_flux1_L[4, i, j, element] - bar_states1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) + antidiffusive_flux1_L[1, i, j, element]) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) + antidiffusive_flux1_L[4, i, j, element] * + antidiffusive_flux1_L[1, i, j, element]) else # approximation R_max R_max = lambda1[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + abs(bar_states1[1, i, j, element] * - antidiffusive_flux1[4, i, j, element]) + + antidiffusive_flux1_L[4, i, j, element]) + abs(bar_states1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element])) + antidiffusive_flux1_L[1, i, j, element])) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux1[4, i, j, element] * - antidiffusive_flux1[1, i, j, element]) + antidiffusive_flux1_L[4, i, j, element] * + antidiffusive_flux1_L[1, i, j, element]) end alpha = 1 # Initialize alpha for plotting if R_max > Q alpha = Q / R_max for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] *= alpha + antidiffusive_flux1_L[v, i, j, element] *= alpha end end if limiter.Plotting @@ -1547,8 +1615,8 @@ end for j in 2:nnodes(dg), i in eachnode(dg) bar_state_velocity = bar_states2[2, i, j, element]^2 + bar_states2[3, i, j, element]^2 - flux_velocity = antidiffusive_flux2[2, i, j, element]^2 + - antidiffusive_flux2[3, i, j, element]^2 + flux_velocity = antidiffusive_flux2_L[2, i, j, element]^2 + + antidiffusive_flux2_L[3, i, j, element]^2 Q = lambda2[i, j, element]^2 * (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - @@ -1558,35 +1626,35 @@ end # exact calculation of max(R_ij, R_ji) R_max = lambda2[i, j, element] * abs(bar_states2[2, i, j, element] * - antidiffusive_flux2[2, i, j, element] + + antidiffusive_flux2_L[2, i, j, element] + bar_states2[3, i, j, element] * - antidiffusive_flux2[3, i, j, element] - + antidiffusive_flux2_L[3, i, j, element] - bar_states2[1, i, j, element] * - antidiffusive_flux2[4, i, j, element] - + antidiffusive_flux2_L[4, i, j, element] - bar_states2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) + antidiffusive_flux2_L[1, i, j, element]) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) + antidiffusive_flux2_L[4, i, j, element] * + antidiffusive_flux2_L[1, i, j, element]) else # approximation R_max R_max = lambda2[i, j, element] * (sqrt(bar_state_velocity * flux_velocity) + abs(bar_states2[1, i, j, element] * - antidiffusive_flux2[4, i, j, element]) + + antidiffusive_flux2_L[4, i, j, element]) + abs(bar_states2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element])) + antidiffusive_flux2_L[1, i, j, element])) R_max += max(0, 0.5 * flux_velocity - - antidiffusive_flux2[4, i, j, element] * - antidiffusive_flux2[1, i, j, element]) + antidiffusive_flux2_L[4, i, j, element] * + antidiffusive_flux2_L[1, i, j, element]) end alpha = 1 # Initialize alpha for plotting if R_max > Q alpha = Q / R_max for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] *= alpha + antidiffusive_flux2_L[v, i, j, element] *= alpha end end if limiter.Plotting @@ -1618,7 +1686,8 @@ end # TODO: For now, this only works for Cartesian meshes. if limiter.SemiDiscEntropyLimiter for j in eachnode(dg), i in 2:nnodes(dg) - antidiffusive_flux_local = get_node_vars(antidiffusive_flux1, equations, dg, + antidiffusive_flux_local = get_node_vars(antidiffusive_flux1_L, equations, + dg, i, j, element) u_local = get_node_vars(u, equations, dg, i, j, element) u_local_m1 = get_node_vars(u, equations, dg, i - 1, j, element) @@ -1647,9 +1716,11 @@ end alpha = min(1.0, (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = alpha * - antidiffusive_flux1[v, i, j, - element] + antidiffusive_flux1_L[v, i, j, element] = alpha * + antidiffusive_flux1_L[v, + i, + j, + element] end end if limiter.Plotting @@ -1663,7 +1734,8 @@ end end for j in 2:nnodes(dg), i in eachnode(dg) - antidiffusive_flux_local = get_node_vars(antidiffusive_flux2, equations, dg, + antidiffusive_flux_local = get_node_vars(antidiffusive_flux2_L, equations, + dg, i, j, element) u_local = get_node_vars(u, equations, dg, i, j, element) u_local_m1 = get_node_vars(u, equations, dg, i, j - 1, element) @@ -1692,9 +1764,11 @@ end alpha = min(1.0, (abs(entProd_FV) + eps()) / (abs(delta_entProd) + eps())) for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = alpha * - antidiffusive_flux2[v, i, j, - element] + antidiffusive_flux2_L[v, i, j, element] = alpha * + antidiffusive_flux2_L[v, + i, + j, + element] end end if limiter.Plotting @@ -1721,6 +1795,16 @@ end end end + # Copy antidiffusive fluxes left to antidifussive fluxes right + for j in eachnode(dg), i in 2:nnodes(dg), v in eachvariable(equations) + antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, + element] + end + for j in 2:nnodes(dg), i in eachnode(dg), v in eachvariable(equations) + antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, + element] + end + return nothing end From 463de3abccbe605612758e8b11254f3a36c72a74 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 13 Oct 2023 13:27:31 +0200 Subject: [PATCH 290/423] Add @inline --- src/equations/compressible_euler_2d.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index cc7b86ef67..8fd99bbfc6 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1544,7 +1544,7 @@ end return SVector(w1, w2, w3, w4) end -entropy_math(u, equations, derivative::True) = cons2entropy(u, equations) +@inline entropy_math(u, equations, derivative::True) = cons2entropy(u, equations) # Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) @inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) @@ -1571,7 +1571,7 @@ entropy_math(u, equations, derivative::True) = cons2entropy(u, equations) return SVector(w1, w2, w3, w4) end -entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) +@inline entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) # Transformation from conservative variables u to d(p)/d(u) @inline function dpdu(u, equations::CompressibleEulerEquations2D) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 00a5996ef6..0a778aa881 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -695,9 +695,6 @@ function initial_check_entropy_math(bound, goal, newton_abstol) end initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 -function final_check_nonnegative(bound, goal, newton_abstol) - (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) -end # Goal and d(Goal)d(u) function goal_function(variable, bound, u, equations) = bound - variable(u, equations) @@ -710,6 +707,10 @@ function final_check_standard(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end +function final_check_nonnegative(bound, goal, newton_abstol) + (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) +end + # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) From e4d3a9d6b573908769db0e6c2ed6614a46d3e1d4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 13 Oct 2023 13:39:17 +0200 Subject: [PATCH 291/423] Add @inline to checks and goal functions; Update test required --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 0a778aa881..0055b2181b 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -686,28 +686,28 @@ end end # Initial checks -function initial_check_entropy_spec(bound, goal, newton_abstol) +@inline function initial_check_entropy_spec(bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -function initial_check_entropy_math(bound, goal, newton_abstol) +@inline function initial_check_entropy_math(bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 +@inline initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 # Goal and d(Goal)d(u) function -goal_function(variable, bound, u, equations) = bound - variable(u, equations) -function dgoal_function(variable, u, dt, antidiffusive_flux, equations) +@inline goal_function(variable, bound, u, equations) = bound - variable(u, equations) +@inline function dgoal_function(variable, u, dt, antidiffusive_flux, equations) -dot(variable(u, equations, True()), dt * antidiffusive_flux) end # Final check -function final_check_standard(bound, goal, newton_abstol) +@inline function final_check_standard(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end -function final_check_nonnegative(bound, goal, newton_abstol) +@inline function final_check_nonnegative(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end From d04afadf3d80938dc25c17ba1d7741e81f8ee167 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 13 Oct 2023 15:25:38 +0200 Subject: [PATCH 292/423] Update tests --- test/test_structured_2d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index be1a1d3138..f776de954b 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -187,8 +187,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [0.008160127272557726, 0.008658253869683077, 0.009351900401871649, 0.02775701488343099], - linf = [0.027225608222781528, 0.0407340321806311, 0.0381940733564341, 0.08080650914262844], + l2 = [0.00816013114351954, 0.008658251709937477, 0.009351905651482216, 0.027757012781694318], + linf = [0.027225615981281148, 0.040734036539016305, 0.0381940733564341, 0.08080650914262844], tspan = (0.0, 0.5)) end @@ -248,7 +248,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2 = [1.2351468819080416, 1.1269856120551724, 1.7239124305681928, 11.715260007491556], - linf = [5.385491808683259, 6.575446013701839, 10.065227889186632, 51.008985921289565], + linf = [5.385492532917423, 6.575446146030286, 10.0652310822613, 51.00901293102744], cells_per_dimension = (8, 12), tspan = (0.0, 0.5)) end From de23b5889177c23632155d2a05d74c0e7685c6e2 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 13 Oct 2023 15:39:20 +0200 Subject: [PATCH 293/423] Add comment about subcell limiting with non-conforming meshes --- src/solvers/dg.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index bc0ee12301..e16fb1421c 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -186,6 +186,12 @@ end A subcell limiting volume integral type for DG methods based on subcell blending approaches with a low-order FV method. Used with limiter [`SubcellLimiterIDP`](@ref). +!!! note + Subcell limiting methods are not fully functional on non-conforming meshes. This is + mainly because the implementation assumes that low- and high-order schemes have the same + surface terms, which is not guaranteed for non-conforming meshes. The low-order scheme + with a high-order mortar is not invariant domain preserving. + !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ From 48bd943b779473af6220fb9d7a11ff575007de8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 13 Oct 2023 18:23:52 +0200 Subject: [PATCH 294/423] Subcell limiting is working with StructuredMesh again --- .../subcell_limiter_idp_correction_2d.jl | 10 +++++----- .../dg_2d_subcell_limiters.jl | 20 ++++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index e63c288f12..95a841b406 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -50,7 +50,7 @@ end function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients if dg.volume_integral.limiter.smoothness_indicator @@ -66,16 +66,16 @@ function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i, j, + get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i + 1, + get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, j, + get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, + get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) for v in eachvariable(equations) diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 6d7c0a740a..8d0894f251 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -5,7 +5,7 @@ @muladd begin #! format: noindent -@inline function calcflux_fhat!(fhat1, fhat2, u, +@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::StructuredMesh{2}, nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) @@ -56,11 +56,14 @@ end # FV-form flux `fhat` in x direction - fhat1[:, 1, :] .= zero(eltype(fhat1)) - fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) + fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) + fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) + fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) + fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) - fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat1_L[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_R[v, i + 1, j] = fhat1_L[v, i + 1, j] end # Split form volume flux in orientation 2: y direction @@ -89,11 +92,14 @@ end # FV-form flux `fhat` in y direction - fhat2[:, :, 1] .= zero(eltype(fhat2)) - fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) + fhat2_L[:, :, 1] .= zero(eltype(fhat2_L)) + fhat2_L[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_L)) + fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) + fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) - fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat2_L[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_R[v, i, j + 1] = fhat2_L[v, i, j + 1] end return nothing From 20abe7bf6dbae3a49f03b74ff6e2fe915978e142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 16 Oct 2023 09:42:31 +0200 Subject: [PATCH 295/423] Renamed variables for consistency --- src/Trixi.jl | 2 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index 14687cbb99..542342503d 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -60,7 +60,7 @@ using RecipesBase: RecipesBase using Requires: @require using Static: Static, One, True, False @reexport using StaticArrays: SVector -using StaticArrays: StaticArrays, MVector, MArray, SMatrix, @SMatrix, MMatrix +using StaticArrays: StaticArrays, MVector, MArray, SMatrix, @SMatrix using StrideArrays: PtrArray, StrideArray, StaticInt @reexport using StructArrays: StructArrays, StructArray using TimerOutputs: TimerOutputs, @notimeit, TimerOutput, print_timer, reset_timer! diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 3731f322ee..1bb9171486 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -26,7 +26,7 @@ function create_cache(mesh::TreeMesh{2}, equations, nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - flux_temp_nonconservative_threaded = A4d[A4d(undef, nvariables(equations), + flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), nnoncons(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] @@ -48,7 +48,7 @@ function create_cache(mesh::TreeMesh{2}, equations, nnodes(dg)) return (; cache..., antidiffusive_fluxes, fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, - flux_temp_threaded, flux_temp_nonconservative_threaded, fhat_temp_threaded, + flux_temp_threaded, flux_nonconservative_temp_threaded, fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded) end @@ -218,13 +218,13 @@ end equations, volume_flux, dg::DGSEM, element, cache) @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded, flux_temp_nonconservative_threaded = cache + @unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache @unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache volume_flux_cons, volume_flux_noncons = volume_flux flux_temp = flux_temp_threaded[Threads.threadid()] - flux_temp_noncons = flux_temp_nonconservative_threaded[Threads.threadid()] + flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()] fhat_temp = fhat_temp_threaded[Threads.threadid()] fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()] @@ -241,7 +241,7 @@ end # Split form volume flux in orientation 1: x direction flux_temp .= zero(eltype(flux_temp)) - flux_temp_noncons .= zero(eltype(flux_temp_noncons)) + flux_noncons_temp .= zero(eltype(flux_noncons_temp)) for j in eachnode(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) @@ -262,10 +262,10 @@ end flux1_noncons = 0.5 * volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[i, ii], + multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[i, ii], flux1_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[ii, i], + multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[ii, i], flux1_noncons, equations, dg, noncons, ii, j) end @@ -303,7 +303,7 @@ end fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, noncons, i, j] + weights[i] * - flux_temp_noncons[v, noncons, i, + flux_noncons_temp[v, noncons, i, j] fhat1_L[v, i + 1, j] += phi[v, noncons, i, j] * @@ -315,7 +315,7 @@ end # Split form volume flux in orientation 2: y direction flux_temp .= zero(eltype(flux_temp)) - flux_temp_noncons .= zero(eltype(flux_temp_noncons)) + flux_noncons_temp .= zero(eltype(flux_noncons_temp)) for j in eachnode(dg), i in eachnode(dg) u_node = get_node_vars(u, equations, dg, i, j, element) @@ -331,10 +331,10 @@ end flux2_noncons = 0.5 * volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[j, jj], + multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[j, jj], flux2_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_temp_noncons, derivative_split[jj, j], + multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[jj, j], flux2_noncons, equations, dg, noncons, i, jj) end @@ -372,7 +372,7 @@ end fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, noncons, i, j] + weights[j] * - flux_temp_noncons[v, noncons, i, + flux_noncons_temp[v, noncons, i, j] fhat2_L[v, i, j + 1] += phi[v, noncons, i, j] * From 96be07072a269a9bf4ddb5345520b1502ebfa550 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 16 Oct 2023 13:42:54 +0200 Subject: [PATCH 296/423] Remove subcell visualization --- src/callbacks_step/save_solution.jl | 12 ++---------- src/callbacks_step/save_solution_dg.jl | 18 ++---------------- src/semidiscretization/semidiscretization.jl | 4 ---- src/solvers/dg.jl | 15 --------------- src/solvers/dgsem_tree/subcell_limiters.jl | 7 ------- utils/trixi2txt.jl | 13 ++----------- 6 files changed, 6 insertions(+), 63 deletions(-) diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 31fe0e87c7..9e47a50818 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -222,28 +222,20 @@ end end end - node_variables = Dict{Symbol, Any}() - @trixi_timeit timer() "get node variables" get_node_variables!(node_variables, - semi) - @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, - element_variables, - node_variables, system = system) end @inline function save_solution_file(u_ode, t, dt, iter, semi::AbstractSemidiscretization, solution_callback, - element_variables = Dict{Symbol, Any}(), - node_variables = Dict{Symbol, Any}(); + element_variables = Dict{Symbol, Any}(); system = "") mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array_native(u_ode, mesh, equations, solver, cache) save_solution_file(u, t, dt, iter, mesh, equations, solver, cache, solution_callback, - element_variables, - node_variables; system = system) + element_variables; system = system) end # TODO: Taal refactor, move save_mesh_file? diff --git a/src/callbacks_step/save_solution_dg.jl b/src/callbacks_step/save_solution_dg.jl index 7c01599903..6d5004ff65 100644 --- a/src/callbacks_step/save_solution_dg.jl +++ b/src/callbacks_step/save_solution_dg.jl @@ -10,9 +10,7 @@ function save_solution_file(u, time, dt, timestep, UnstructuredMesh2D, SerialP4estMesh, SerialT8codeMesh}, equations, dg::DG, cache, - solution_callback, - element_variables = Dict{Symbol, Any}(), - node_variables = Dict{Symbol, Any}(); + solution_callback, element_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback @@ -75,16 +73,6 @@ function save_solution_file(u, time, dt, timestep, var = file["element_variables_$v"] attributes(var)["name"] = string(key) end - - # Store node variables - for (v, (key, node_variable)) in enumerate(node_variables) - # Add to file - file["node_variables_$v"] = node_variable - - # Add variable name as attribute - var = file["node_variables_$v"] - attributes(var)["name"] = string(key) - end end return filename @@ -93,9 +81,7 @@ end function save_solution_file(u, time, dt, timestep, mesh::Union{ParallelTreeMesh, ParallelP4estMesh}, equations, dg::DG, cache, - solution_callback, - element_variables = Dict{Symbol, Any}(), - node_variables = Dict{Symbol, Any}(); + solution_callback, element_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback diff --git a/src/semidiscretization/semidiscretization.jl b/src/semidiscretization/semidiscretization.jl index fe7858e31e..c784f71642 100644 --- a/src/semidiscretization/semidiscretization.jl +++ b/src/semidiscretization/semidiscretization.jl @@ -335,10 +335,6 @@ function get_element_variables!(element_variables, u_ode, get_element_variables!(element_variables, u, mesh_equations_solver_cache(semi)...) end -function get_node_variables!(node_variables, semi::AbstractSemidiscretization) - get_node_variables!(node_variables, mesh_equations_solver_cache(semi)...) -end - # To implement AMR and use OrdinaryDiffEq.jl etc., we have to be a bit creative. # Since the caches of the SciML ecosystem are immutable structs, we cannot simply # change the underlying arrays therein. Hence, to support changing the number of diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index e16fb1421c..9dc485c9c9 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -12,11 +12,6 @@ function get_element_variables!(element_variables, u, mesh, equations, nothing end -function get_node_variables!(node_variables, mesh, equations, - volume_integral::AbstractVolumeIntegral, dg, cache) - nothing -end - """ VolumeIntegralStrongForm() @@ -225,12 +220,6 @@ function Base.show(io::IO, mime::MIME"text/plain", end end -function get_node_variables!(node_variables, mesh, equations, - volume_integral::VolumeIntegralSubcellLimiting, dg, cache) - get_node_variables!(node_variables, volume_integral.limiter, volume_integral, - equations) -end - # TODO: FD. Should this definition live in a different file because it is # not strictly a DG method? """ @@ -420,10 +409,6 @@ function get_element_variables!(element_variables, u, mesh, equations, dg::DG, c dg, cache) end -function get_node_variables!(node_variables, mesh, equations, dg::DG, cache) - get_node_variables!(node_variables, mesh, equations, dg.volume_integral, dg, cache) -end - const MeshesDGSEM = Union{TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, T8codeMesh} diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 4ade26c20e..4d74eff55d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -129,11 +129,4 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) summary_box(io, "SubcellLimiterIDP", setup) end end - -function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, - ::VolumeIntegralSubcellLimiting, equations) - node_variables[:alpha_limiter] = limiter.cache.subcell_limiter_coefficients.alpha - # TODO: alpha is not filled before the first timestep. - return nothing -end end # @muladd diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index 12a3d46760..b386f150da 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -70,7 +70,7 @@ function trixi2txt(filename::AbstractString...; center_level_0, length_level_0, leaf_cells, coordinates, levels = read_meshfile(meshfile) # Read data - labels, data, n_elements, n_nodes, element_variables, node_variables, time = read_datafile(filename) + labels, data, n_elements, n_nodes, element_variables, time = read_datafile(filename) # Check if dimensions match if length(leaf_cells) != n_elements @@ -263,16 +263,7 @@ function read_datafile(filename::String) index += 1 end - # Extract node variable arrays - node_variables = Dict{String, Union{Vector{Float64}, Vector{Int}}}() - index = 1 - while haskey(file, "node_variables_$index") - varname = read(attributes(file["node_variables_$index"])["name"]) - node_variables[varname] = read(file["node_variables_$index"]) - index += 1 - end - - return labels, data, n_elements, n_nodes, element_variables, node_variables, time + return labels, data, n_elements, n_nodes, element_variables, time end end From fb4d876ce9c902fa224421d08f7b6dc3fb03498f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 16 Oct 2023 13:44:30 +0200 Subject: [PATCH 297/423] Fix last commit --- src/callbacks_step/save_solution.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 9e47a50818..14ea33368f 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -224,6 +224,7 @@ end @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, + element_variables, system = system) end From 2d8b49dd785dbceefe529381288b00fc31179e1f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 16 Oct 2023 13:54:51 +0200 Subject: [PATCH 298/423] Remove @unpack --- ...ti_shock_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...hock_bubble_shockcapturing_subcell_positivity.jl | 2 +- .../subcell_limiter_idp_correction_2d.jl | 6 +++--- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 13 ++++++------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 0a9cc2921b..42c208b6d9 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -20,7 +20,7 @@ function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMultic # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations + (; gas_constants) = equations # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving delta = 0.03 diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index a67eaeb5b2..6286840dce 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -20,7 +20,7 @@ function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMultic # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations + (; gas_constants) = equations # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving delta = 0.03 diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index f6b9144457..20219e93d6 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -6,9 +6,9 @@ #! format: noindent function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes - @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients + (; antidiffusive_flux1, antidiffusive_flux2) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + (; alpha1, alpha2) = dg.volume_integral.limiter.cache.subcell_limiter_coefficients @threaded for element in eachelement(dg, cache) # Sign switch as in apply_jacobian! diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9efe8bbc99..8bc43b3b75 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -19,7 +19,7 @@ end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; kwargs...) - @unpack alpha = limiter.cache.subcell_limiter_coefficients + (; alpha) = limiter.cache.subcell_limiter_coefficients alpha .= zero(eltype(alpha)) if limiter.local_minmax @@ -31,7 +31,7 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE end # Calculate alpha1 and alpha2 - @unpack alpha1, alpha2 = limiter.cache.subcell_limiter_coefficients + (; alpha1, alpha2) = limiter.cache.subcell_limiter_coefficients @threaded for element in eachelement(dg, semi.cache) for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) @@ -86,7 +86,7 @@ end @inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi + (; boundary_conditions) = semi # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get neighboring element ids @@ -158,15 +158,14 @@ end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients + (; antidiffusive_flux1, antidiffusive_flux2) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol("$(variable)_min")] var_max = variable_bounds[Symbol("$(variable)_max")] calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes - @unpack inverse_weights = dg.basis - @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) From 64cf39c66497f4cad720c08958a40051d8569963 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 16 Oct 2023 13:57:23 +0200 Subject: [PATCH 299/423] Add comment to `News.md` --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4b96e1e283..f77dc45593 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,7 +12,8 @@ for human readability. - Non-uniform `TreeMesh` available for hyperbolic-parabolic equations. - Capability to set truly discontinuous initial conditions in 1D. - Wetting and drying feature and examples for 1D and 2D shallow water equations -- Subcell positivity limiting support for conservative variables in 2D for `TreeMesh` +- Subcell (positivity and local min/max) limiting support for conservative variables + in 2D for `TreeMesh` #### Changed From 2d7ce4590cc8de35cc86be9db7ac23282d0de171 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 16 Oct 2023 16:24:57 +0200 Subject: [PATCH 300/423] Fix source for sedov blast setup; Formatting --- examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_sedov_blast_wave_sc_subcell.jl | 5 ++--- ..._eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...ermulti_shock_bubble_shockcapturing_subcell_positivity.jl | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index dfd99f5baa..e7b701611a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -93,4 +93,4 @@ stage_callbacks = (SubcellLimiterIDPCorrection(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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 \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index ac99c35cdb..21de64aee4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -11,7 +11,7 @@ equations = CompressibleEulerEquations2D(gamma) initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) The Sedov blast wave setup based on Flash -- http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 +- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) # Set up polar coordinates @@ -20,7 +20,7 @@ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEq y_norm = x[2] - inicenter[2] r = sqrt(x_norm^2 + y_norm^2) - # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) # r0 = 0.5 # = more reasonable setup E = 1.0 @@ -54,7 +54,6 @@ mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level=3, n_cells_max=100_000) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 42c208b6d9..4184e04de3 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -136,4 +136,4 @@ stage_callbacks = (SubcellLimiterIDPCorrection(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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 \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 6286840dce..fb750f916a 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -137,4 +137,4 @@ stage_callbacks = (SubcellLimiterIDPCorrection(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); 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 \ No newline at end of file +summary_callback() # print the timer summary From cf05403ecca1f7bdf59a7210beb10f284c2a7d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 16 Oct 2023 17:02:02 +0200 Subject: [PATCH 301/423] Removed some unnecessary operations in the Powell/GLM non-conservative flux --- src/equations/ideal_glm_mhd_2d.jl | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 45aeba3ac2..7d8e9f9eeb 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -353,13 +353,12 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - if noncons_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll f = SVector(0, B1_ll, B2_ll, @@ -372,6 +371,7 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., else #noncons_term ==2 # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) if orientation == 1 + v1_ll = rho_v1_ll / rho_ll f = SVector(0, 0, 0, @@ -382,6 +382,7 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., 0, v1_ll) else #orientation == 2 + v2_ll = rho_v2_ll / rho_ll f = SVector(0, 0, 0, @@ -413,11 +414,6 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll - if noncons_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) if orientation == 1 From c2ec8c1d074c71d9902c27d879d68bd54f84cd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 17 Oct 2023 10:41:07 +0200 Subject: [PATCH 302/423] Added two elixirs to compare performance --- ...elixir_mhd_alfven_wave_fluxdifferencing.jl | 71 +++++++++++++++++ .../elixir_mhd_alfven_wave_subcell.jl | 78 +++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl create mode 100644 examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl diff --git a/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl new file mode 100644 index 0000000000..bb2df4f0fc --- /dev/null +++ b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl @@ -0,0 +1,71 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible ideal GLM-MHD equations +gamma = 5 / 3 +equations = IdealGlmMhdEquations2D(gamma) + +initial_condition = initial_condition_convergence_test + +volume_flux = (flux_central, flux_nonconservative_powell2) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) + +basis = LobattoLegendreBasis(3) +volume_integral = VolumeIntegralFluxDifferencing(volume_flux) + +solver = DGSEM(polydeg = 3, + surface_flux = surface_flux, + volume_integral = volume_integral) + +coordinates_min = (0.0, 0.0) +coordinates_max = (sqrt(2.0), sqrt(2.0)) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +cfl = 0.5 +stepsize_callback = StepsizeCallback(cfl = cfl) + +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback, + glm_speed_callback) + +############################################################################### +# run the simulation +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(); # + 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/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl new file mode 100644 index 0000000000..1c8087811b --- /dev/null +++ b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl @@ -0,0 +1,78 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible ideal GLM-MHD equations +gamma = 5 / 3 +equations = IdealGlmMhdEquations2D(gamma) + +initial_condition = initial_condition_convergence_test + +volume_flux = (flux_central, flux_nonconservative_powell2) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) + +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons=[1], + positivity_correction_factor=0.1) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(polydeg = 3, + surface_flux = surface_flux, + volume_integral = volume_integral) + +coordinates_min = (0.0, 0.0) +coordinates_max = (sqrt(2.0), sqrt(2.0)) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 100_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +cfl = 0.5 +stepsize_callback = StepsizeCallback(cfl = cfl) + +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback, + glm_speed_callback) + +############################################################################### +# run the simulation +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); # + 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 From 6f9d3d120ff2655fbab3529071735ff3ad2b2c6e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 18 Oct 2023 15:04:13 +0200 Subject: [PATCH 303/423] Reduce allocations --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 8bc43b3b75..1f31560b2e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -162,8 +162,8 @@ end (; inverse_weights) = dg.basis (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol("$(variable)_min")] - var_max = variable_bounds[Symbol("$(variable)_max")] + var_min = variable_bounds[Symbol(string(variable) * "_min")] + var_max = variable_bounds[Symbol(string(variable) * "_max")] calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) @threaded for element in eachelement(dg, semi.cache) @@ -232,7 +232,7 @@ end (; positivity_correction_factor) = limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol("$(variable)_min")] + var_min = variable_bounds[Symbol(string(variable) * "_min")] @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] From 781e839cdf8cbe69edb1a3d3f473895f68ed15a3 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 20 Oct 2023 08:09:22 +0200 Subject: [PATCH 304/423] avoid repeated memory writing/reading --- src/equations/ideal_glm_mhd_2d.jl | 12 ++-- .../dgsem_tree/dg_2d_subcell_limiters.jl | 72 +++++++++---------- 2 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 7d8e9f9eeb..1d8f354360 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -290,8 +290,8 @@ Powell and the Galilean nonconservative term associated with the GLM multiplier of the [`IdealGlmMhdEquations2D`](@ref). This implementation uses a non-conservative term that can be written as the product -of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm -et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different +of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm +et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different results on non-conforming meshes(!). ## References - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts @@ -338,11 +338,11 @@ results on non-conforming meshes(!). end """ flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, + equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeLocal, noncons_term::Integer) -Local part of the Powell and GLM non-conservative terms. Needed for the calculation of +Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. @@ -398,11 +398,11 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., end """ flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, + equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeSymmetric, noncons_term::Integer) -Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of +Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 1bb9171486..a09fe61622 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -212,7 +212,7 @@ end # # - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts # Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. -# +# @inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::TreeMesh{2}, nonconservative_terms::True, equations, @@ -282,34 +282,31 @@ end fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L)) # Compute local contribution to non-conservative flux - for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) + for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - set_node_vars!(phi, - volume_flux_noncons(u_local, 1, equations, - NonConservativeLocal(), noncons), - equations, dg, noncons, i, j) + for noncons in 1:nnoncons(equations) + set_node_vars!(phi, + volume_flux_noncons(u_local, 1, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end end for j in eachnode(dg), i in 1:(nnodes(dg) - 1) # Conservative part for v in eachvariable(equations) - fhat_temp[v, i + 1, j] = fhat_temp[v, i, j] + - weights[i] * flux_temp[v, i, j] - fhat1_L[v, i + 1, j] = fhat_temp[v, i + 1, j] - fhat1_R[v, i + 1, j] = fhat_temp[v, i + 1, j] + value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat_temp[v, i + 1, j] = value + fhat1_L[v, i + 1, j] = value + fhat1_R[v, i + 1, j] = value end # Nonconservative part for noncons in 1:nnoncons(equations), v in eachvariable(equations) - fhat_noncons_temp[v, noncons, i + 1, j] = fhat_noncons_temp[v, noncons, i, - j] + - weights[i] * - flux_noncons_temp[v, noncons, i, - j] - - fhat1_L[v, i + 1, j] += phi[v, noncons, i, j] * - fhat_noncons_temp[v, noncons, i + 1, j] - fhat1_R[v, i + 1, j] += phi[v, noncons, i + 1, j] * - fhat_noncons_temp[v, noncons, i + 1, j] + value = fhat_noncons_temp[v, noncons, i, j] + weights[i] * flux_noncons_temp[v, noncons, i, j] + fhat_noncons_temp[v, noncons, i + 1, j] = value + + fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value + fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] + phi[v, noncons, i + 1, j] * value end end @@ -351,34 +348,31 @@ end fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L)) # Compute local contribution to non-conservative flux - for j in eachnode(dg), i in eachnode(dg), noncons in 1:nnoncons(equations) + for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - set_node_vars!(phi, - volume_flux_noncons(u_local, 2, equations, - NonConservativeLocal(), noncons), - equations, dg, noncons, i, j) + for noncons in 1:nnoncons(equations) + set_node_vars!(phi, + volume_flux_noncons(u_local, 2, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end end for j in 1:(nnodes(dg) - 1), i in eachnode(dg) # Conservative part for v in eachvariable(equations) - fhat_temp[v, i, j + 1] = fhat_temp[v, i, j] + - weights[j] * flux_temp[v, i, j] - fhat2_L[v, i, j + 1] = fhat_temp[v, i, j + 1] - fhat2_R[v, i, j + 1] = fhat_temp[v, i, j + 1] + value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat_temp[v, i, j + 1] = value + fhat2_L[v, i, j + 1] = value + fhat2_R[v, i, j + 1] = value end # Nonconservative part for noncons in 1:nnoncons(equations), v in eachvariable(equations) - fhat_noncons_temp[v, noncons, i, j + 1] = fhat_noncons_temp[v, noncons, i, - j] + - weights[j] * - flux_noncons_temp[v, noncons, i, - j] - - fhat2_L[v, i, j + 1] += phi[v, noncons, i, j] * - fhat_noncons_temp[v, noncons, i, j + 1] - fhat2_R[v, i, j + 1] += phi[v, noncons, i, j + 1] * - fhat_noncons_temp[v, noncons, i, j + 1] + value = fhat_noncons_temp[v, noncons, i, j] + weights[j] * flux_noncons_temp[v, noncons, i, j] + fhat_noncons_temp[v, noncons, i, j + 1] = value + + fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value + fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] + phi[v, noncons, i, j + 1] * value end end return nothing From c3377ecaef1025cae9bcf58d8b3d36ae82f8ff11 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 20 Oct 2023 08:49:04 +0200 Subject: [PATCH 305/423] format --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index a09fe61622..a479771fc6 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -302,11 +302,13 @@ end end # Nonconservative part for noncons in 1:nnoncons(equations), v in eachvariable(equations) - value = fhat_noncons_temp[v, noncons, i, j] + weights[i] * flux_noncons_temp[v, noncons, i, j] + value = fhat_noncons_temp[v, noncons, i, j] + + weights[i] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i + 1, j] = value fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value - fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] + phi[v, noncons, i + 1, j] * value + fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] + + phi[v, noncons, i + 1, j] * value end end @@ -368,11 +370,13 @@ end end # Nonconservative part for noncons in 1:nnoncons(equations), v in eachvariable(equations) - value = fhat_noncons_temp[v, noncons, i, j] + weights[j] * flux_noncons_temp[v, noncons, i, j] + value = fhat_noncons_temp[v, noncons, i, j] + + weights[j] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i, j + 1] = value fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value - fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] + phi[v, noncons, i, j + 1] * value + fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] + + phi[v, noncons, i, j + 1] * value end end return nothing From 39b39b685f05fae9413afa3ee61ca774b20a6ead Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 20 Oct 2023 14:22:06 +0200 Subject: [PATCH 306/423] Replace construction of Symbols --- src/solvers/dgsem_tree/subcell_limiters.jl | 11 ++++++----- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 4d74eff55d..66799cf01c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -61,13 +61,14 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; bound_keys = () if local_minmax - for i in local_minmax_variables_cons - bound_keys = (bound_keys..., Symbol("$(i)_min"), Symbol("$(i)_max")) + for v in local_minmax_variables_cons + bound_keys = (bound_keys..., Symbol(string(v), "_min"), + Symbol(string(v), "_max")) end end - for i in positivity_variables_cons - if !(i in local_minmax_variables_cons) - bound_keys = (bound_keys..., Symbol("$(i)_min")) + for v in positivity_variables_cons + if !(v in local_minmax_variables_cons) + bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 1f31560b2e..2f6288a329 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -162,8 +162,8 @@ end (; inverse_weights) = dg.basis (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol(string(variable) * "_min")] - var_max = variable_bounds[Symbol(string(variable) * "_max")] + var_min = variable_bounds[Symbol(string(variable), "_min")] + var_max = variable_bounds[Symbol(string(variable), "_max")] calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) @threaded for element in eachelement(dg, semi.cache) @@ -232,7 +232,7 @@ end (; positivity_correction_factor) = limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol(string(variable) * "_min")] + var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] From a90745c9c53bb3eeb335fbc529d2c5e767200da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 20 Oct 2023 16:57:35 +0200 Subject: [PATCH 307/423] Apply suggestions from code review Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- .../elixir_mhd_shockcapturing_subcell.jl | 4 +-- src/equations/equations.jl | 3 ++ src/equations/ideal_glm_mhd_2d.jl | 2 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 29 +++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 8ee8177949..62bb0c2043 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -52,9 +52,9 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons=[1], - positivity_variables_nonlinear = [pressure], + positivity_variables_nonlinear=[pressure], positivity_correction_factor=0.1, - bar_states = false) + bar_states=false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg=volume_flux, volume_flux_fv=surface_flux) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 857de70ca7..1a478dac7a 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -245,6 +245,7 @@ where `x` specifies the coordinates, `t` is the current time, and `equation` is struct BoundaryConditionNeumann{B} boundary_normal_flux_function::B end + """ NonConservativeLocal() @@ -253,6 +254,7 @@ When the argument `nonconservative_type` is of type `NonConservativeLocal`, the function returns the local part of the non-conservative term. """ struct NonConservativeLocal end + """ NonConservativeSymmetric() @@ -261,6 +263,7 @@ When the argument `nonconservative_type` is of type `NonConservativeSymmetric`, the function returns the symmetric part of the non-conservative term. """ struct NonConservativeSymmetric end + # set sensible default values that may be overwritten by specific equations """ have_nonconservative_terms(equations) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 0237128415..ce7e5180c1 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1039,7 +1039,7 @@ end return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end -@inline function isValidState(cons, equations::IdealGlmMhdEquations2D) +@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) p = pressure(cons, equations) if cons[1] <= 0.0 || p <= 0.0 return false diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 3ae6df94d2..8f0914debd 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -136,11 +136,9 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fhat!" begin - calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, - cache) - end +calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -148,19 +146,15 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fv!" begin - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, - cache) - end + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) # antidiffusive flux - @trixi_timeit timer() "calcflux_antidiffusive!" begin - calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, nonconservative_terms, equations, limiter, dg, - element, cache) - end + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -322,6 +316,7 @@ end return nothing end + # Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element # (**with non-conservative terms**). # @@ -501,6 +496,7 @@ end fhat_noncons_temp[v, noncons, i, j + 1] end end + return nothing end @@ -541,6 +537,7 @@ end return nothing end + # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. @inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fstar1_L, fstar1_R, fstar2_L, fstar2_R, From a06333dd02ef176683edd5c05a12444ac59ad038 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 20 Oct 2023 17:42:04 +0200 Subject: [PATCH 308/423] Fix 2 bugs + formatting --- src/callbacks_stage/subcell_bounds_check.jl | 4 ++-- src/callbacks_stage/subcell_bounds_check_2d.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters.jl | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 0cd7a319f7..c57c1f5db2 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -138,8 +138,8 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter - @unpack idp_bounds_delta = limiter.cache + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; idp_bounds_delta) = limiter.cache variables = varnames(cons2cons, semi.equations) println("─"^100) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index f66f8b8b3a..54f5d98671 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -138,7 +138,7 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterMCL, - time, iter, output_directory, save_errors, interval) + time, iter, output_directory, save_errors) @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states @unpack idp_bounds_delta = limiter.cache @@ -590,7 +590,7 @@ end deviation_min[n_vars + 1]) end - if !save_errors || (iter % interval != 0) + if !save_errors return nothing end open("$output_directory/deviations.txt", "a") do f diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 7b416e4f58..6a10f92b89 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -112,7 +112,8 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; if local_minmax for v in local_minmax_variables_cons v_string = string(v) - bound_keys = (bound_keys..., Symbol(v_string, "_min"), Symbol(v_string, "_max")) + bound_keys = (bound_keys..., Symbol(v_string, "_min"), + Symbol(v_string, "_max")) end end if spec_entropy From c5145d68af472c971fa69284b288650a6cd1695a Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 20 Oct 2023 17:57:45 +0200 Subject: [PATCH 309/423] Remove `interval` from parameters --- src/callbacks_stage/subcell_bounds_check.jl | 26 +++++++++------------ 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index c57c1f5db2..34507dced5 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -28,31 +28,27 @@ function (callback::BoundsCheckCallback)(u_ode, integrator, stage) @unpack t, iter, alg = integrator u = wrap_array(u_ode, mesh, equations, solver, cache) - save_errors_ = callback.save_errors && (callback.interval > 0) && - (stage == length(alg.c)) + save_errors = callback.save_errors && (callback.interval > 0) && + (stage == length(alg.c)) && + (iter % callback.interval == 0 || integrator.finalstep) @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, - t, iter + 1, + solver.volume_integral, t, + iter + 1, callback.output_directory, - save_errors_, callback.interval) -end - -function check_bounds(u, mesh, equations, solver, cache, t, iter, output_directory, - save_errors, interval) - check_bounds(u, mesh, equations, solver, cache, solver.volume_integral, t, iter, - output_directory, save_errors, interval) + save_errors) end function check_bounds(u, mesh, equations, solver, cache, - volume_integral::AbstractVolumeIntegral, - t, iter, output_directory, save_errors, interval) + volume_integral::AbstractVolumeIntegral, t, iter, + output_directory, save_errors) return nothing end function check_bounds(u, mesh, equations, solver, cache, - volume_integral::VolumeIntegralSubcellLimiting, - t, iter, output_directory, save_errors, interval) + volume_integral::VolumeIntegralSubcellLimiting, t, iter, + output_directory, save_errors) check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter, t, iter, - output_directory, save_errors, interval) + output_directory, save_errors) end function init_callback(callback, semi) From 38485641f602d8e7ead5a682cddae950cd2ad408 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 20 Oct 2023 18:12:50 +0200 Subject: [PATCH 310/423] Fix bug --- src/callbacks_stage/subcell_bounds_check_2d.jl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 54f5d98671..8334c108cf 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -7,13 +7,12 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, - time, iter, output_directory, save_errors, interval) + time, iter, output_directory, save_errors) @unpack local_minmax, positivity, spec_entropy, math_entropy = solver.volume_integral.limiter @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients @unpack idp_bounds_delta = limiter.cache - save_errors_ = save_errors && (iter % interval == 0) - if save_errors_ + if save_errors open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) end @@ -38,7 +37,7 @@ deviation_min) idp_bounds_delta[key_max] = max(idp_bounds_delta[key_max], deviation_max) - if save_errors_ + if save_errors deviation_min_ = deviation_min deviation_max_ = deviation_max open("$output_directory/deviations.txt", "a") do f @@ -59,7 +58,7 @@ variable_bounds[key][i, j, element] - s) end idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors_ + if save_errors deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) @@ -78,7 +77,7 @@ s - variable_bounds[key][i, j, element]) end idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_max) - if save_errors_ + if save_errors deviation_max_ = deviation_max open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_max_) @@ -100,7 +99,7 @@ variable_bounds[key][i, j, element] - var) end idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors_ + if save_errors deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) @@ -119,7 +118,7 @@ variable_bounds[key][i, j, element] - var) end idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors_ + if save_errors deviation_min_ = deviation_min open("$output_directory/deviations.txt", "a") do f print(f, ", ", deviation_min_) @@ -127,7 +126,7 @@ end end end - if save_errors_ + if save_errors open("$output_directory/deviations.txt", "a") do f println(f) end From 603d0f0f58988cd0c29348a1cdcf069e0e621112 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Sun, 22 Oct 2023 18:25:37 +0200 Subject: [PATCH 311/423] Add revised BoundsCheck for IDP Limiting --- src/callbacks_stage/subcell_bounds_check.jl | 67 ++++++--- .../subcell_bounds_check_2d.jl | 137 +++++++----------- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 4 +- 3 files changed, 101 insertions(+), 107 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 34507dced5..9a033e7236 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -8,9 +8,19 @@ """ BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) -Bounds checking routine for [`SubcellLimiterIDP`](@ref) and [`SubcellLimiterMCL`](@ref). Applied -as a stage callback for SSPRK methods. If `save_errors` is `true`, the resulting deviations are -saved in `output_directory/deviations.txt` for every `interval` time steps. +Subcell limiting techniques with [`SubcellLimiterIDP`](@ref) and [`SubcellLimiterMCL`](@ref) are +constructed to adhere certain local or global bounds. To make sure that these bounds are actually +met, this callback calculates the maximum deviation from the bounds. The maximum deviation per +applied bound is printed to the screen at the end of the simulation. +For more insights, when setting `save_errors=true` the occurring errors are exported every +`interval` time steps during the simulation. Then, the maximum deviations since the last +export are saved in "`output_directory`/deviations.txt". +The `BoundsCheckCallback` has to be applied as a stage callback for the SSPRK time integration scheme. + +!!! note + For `SubcellLimiterIDP`, the solution is corrected in the a posteriori correction stage + [`SubcellLimiterIDPCorrection`](@ref). So, to check the final solution, this bounds check + callback must be called after the correction stage. """ struct BoundsCheckCallback output_directory::String @@ -25,7 +35,7 @@ end function (callback::BoundsCheckCallback)(u_ode, integrator, stage) mesh, equations, solver, cache = mesh_equations_solver_cache(integrator.p) - @unpack t, iter, alg = integrator + (; t, iter, alg) = integrator u = wrap_array(u_ode, mesh, equations, solver, cache) save_errors = callback.save_errors && (callback.interval > 0) && @@ -51,13 +61,14 @@ function check_bounds(u, mesh, equations, solver, cache, output_directory, save_errors) end -function init_callback(callback, semi) +function init_callback(callback::BoundsCheckCallback, semi) init_callback(callback, semi, semi.solver.volume_integral) end -init_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing +init_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function init_callback(callback, semi, volume_integral::VolumeIntegralSubcellLimiting) +function init_callback(callback::BoundsCheckCallback, semi, + volume_integral::VolumeIntegralSubcellLimiting) init_callback(callback, semi, volume_integral.limiter) end @@ -66,16 +77,17 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter - @unpack output_directory = callback + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; output_directory) = callback variables = varnames(cons2cons, semi.equations) mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time") if local_minmax - for index in limiter.local_minmax_variables_cons - print(f, ", $(variables[index])_min, $(variables[index])_max") + for v in limiter.local_minmax_variables_cons + variable_string = string(variables[v]) + print(f, ", " * variable_string * "_min, " * variable_string * "_max") end end if spec_entropy @@ -85,14 +97,14 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi print(f, ", mathEntr_max") end if positivity - for index in limiter.positivity_variables_cons - if index in limiter.local_minmax_variables_cons + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons continue end - print(f, ", $(variables[index])_min") + print(f, ", " * string(variables[v]) * "_min") end for variable in limiter.positivity_variables_nonlinear - print(f, ", $(variable)_min") + print(f, ", " * string(variable) * "_min") end end println(f) @@ -106,6 +118,8 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end + # TODO: Revise Bounds Check for MCL + @unpack output_directory = callback mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f @@ -121,13 +135,13 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end -function finalize_callback(callback, semi) +function finalize_callback(callback::BoundsCheckCallback, semi) finalize_callback(callback, semi, semi.solver.volume_integral) end -finalize_callback(callback, semi, volume_integral::AbstractVolumeIntegral) = nothing +finalize_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing -function finalize_callback(callback, semi, +function finalize_callback(callback::BoundsCheckCallback, semi, volume_integral::VolumeIntegralSubcellLimiting) finalize_callback(callback, semi, volume_integral.limiter) end @@ -143,24 +157,27 @@ end println("─"^100) if local_minmax for v in limiter.local_minmax_variables_cons + v_string = string(v) println("$(variables[v]):") - println("-lower bound: ", idp_bounds_delta[Symbol("$(v)_min")]) - println("-upper bound: ", idp_bounds_delta[Symbol("$(v)_max")]) + println("-lower bound: ", idp_bounds_delta[Symbol(v_string, "_min")][2]) + println("-upper bound: ", idp_bounds_delta[Symbol(v_string, "_max")][2]) end end if spec_entropy - println("spec. entropy:\n- lower bound: ", idp_bounds_delta[:spec_entropy_min]) + println("spec. entropy:\n- lower bound: ", + idp_bounds_delta[:spec_entropy_min][2]) end if math_entropy - println("math. entropy:\n- upper bound: ", idp_bounds_delta[:math_entropy_max]) + println("math. entropy:\n- upper bound: ", + idp_bounds_delta[:math_entropy_max][2]) end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons continue end - println("$(variables[v]):\n- positivity: ", - idp_bounds_delta[Symbol("$(v)_min")]) + println(string(variables[v]) * ":\n- positivity: ", + idp_bounds_delta[Symbol(string(v), "_min")][2]) end for variable in limiter.positivity_variables_nonlinear println("$(variable):\n- positivity: ", @@ -176,6 +193,8 @@ end limiter::SubcellLimiterMCL) @unpack idp_bounds_delta = limiter.cache + # TODO: Revise bounds check for MCL + println("─"^100) println("Maximum deviation from bounds:") println("─"^100) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 8334c108cf..fe5be3d02b 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -8,128 +8,101 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors) - @unpack local_minmax, positivity, spec_entropy, math_entropy = solver.volume_integral.limiter - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - @unpack idp_bounds_delta = limiter.cache + (; local_minmax, positivity, spec_entropy, math_entropy) = solver.volume_integral.limiter + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + (; idp_bounds_delta) = limiter.cache - if save_errors - open("$output_directory/deviations.txt", "a") do f - print(f, iter, ", ", time) - end - end if local_minmax for v in limiter.local_minmax_variables_cons - key_min = Symbol("$(v)_min") - key_max = Symbol("$(v)_max") - deviation_min = zero(eltype(u)) - deviation_max = zero(eltype(u)) + v_string = string(v) + key_min = Symbol(v_string, "_min") + key_max = Symbol(v_string, "_max") + deviation_min = idp_bounds_delta[key_min] + deviation_max = idp_bounds_delta[key_max] for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) - deviation_min = max(deviation_min, - variable_bounds[key_min][i, j, element] - - u[v, i, j, element]) - deviation_max = max(deviation_max, - u[v, i, j, element] - - variable_bounds[key_max][i, j, element]) - end - idp_bounds_delta[key_min] = max(idp_bounds_delta[key_min], - deviation_min) - idp_bounds_delta[key_max] = max(idp_bounds_delta[key_max], - deviation_max) - if save_errors - deviation_min_ = deviation_min - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f - print(f, ", ", deviation_min_, ", ", deviation_max_) - end + var = u[v, i, j, element] + deviation_min[1] = max(deviation_min[1], + variable_bounds[key_min][i, j, element] - var) + deviation_max[1] = max(deviation_max[1], + var - variable_bounds[key_max][i, j, element]) end + deviation_min[2] = max(deviation_min[2], deviation_min[1]) + deviation_max[2] = max(deviation_max[2], deviation_max[1]) end end if spec_entropy key = :spec_entropy_min - deviation_min = zero(eltype(u)) + deviation = idp_bounds_delta[key] for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_min = max(deviation_min, - variable_bounds[key][i, j, element] - s) - end - idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f - print(f, ", ", deviation_min_) - end + deviation[1] = max(deviation[1], variable_bounds[key][i, j, element] - s) end + deviation[2] = max(deviation[2], deviation[1]) end if math_entropy key = :math_entropy_max - deviation_max = zero(eltype(u)) + deviation = idp_bounds_delta[key] for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) - deviation_max = max(deviation_max, - s - variable_bounds[key][i, j, element]) - end - idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_max) - if save_errors - deviation_max_ = deviation_max - open("$output_directory/deviations.txt", "a") do f - print(f, ", ", deviation_max_) - end + deviation[1] = max(deviation[1], s - variable_bounds[key][i, j, element]) end + deviation[2] = max(deviation[2], deviation[1]) end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons - continue - end - key = Symbol("$(v)_min") - deviation_min = zero(eltype(u)) + key = Symbol(string(v), "_min") + deviation = idp_bounds_delta[key] for element in eachelement(solver, cache), j in eachnode(solver), i in eachnode(solver) var = u[v, i, j, element] - deviation_min = max(deviation_min, - variable_bounds[key][i, j, element] - var) + deviation[1] = max(deviation[1], + variable_bounds[key][i, j, element] - var) end - idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f - print(f, ", ", deviation_min_) + deviation[2] = max(deviation[2], deviation[1]) + end + end + if save_errors + # Print to output file + open("$output_directory/deviations.txt", "a") do f + print(f, iter, ", ", time) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + key_min = Symbol(v_string, "_min") + key_max = Symbol(v_string, "_max") + print(f, ", ", idp_bounds_delta[key_min][1], + idp_bounds_delta[key_max][1]) end end - end - for variable in limiter.positivity_variables_nonlinear - key = Symbol("$(variable)_min") - deviation_min = zero(eltype(u)) - for element in eachelement(solver, cache), j in eachnode(solver), - i in eachnode(solver) - - var = variable(get_node_vars(u, equations, solver, i, j, element), - equations) - deviation_min = max(deviation_min, - variable_bounds[key][i, j, element] - var) + if math_entropy + key = :math_entropy_max + print(f, ", ", idp_bounds_delta[key][1]) + end + if math_entropy + key = :math_entropy_max + print(f, ", ", idp_bounds_delta[key][1]) end - idp_bounds_delta[key] = max(idp_bounds_delta[key], deviation_min) - if save_errors - deviation_min_ = deviation_min - open("$output_directory/deviations.txt", "a") do f - print(f, ", ", deviation_min_) + if positivity + for v in limiter.positivity_variables_cons + key = Symbol(string(v), "_min") + print(f, ", ", idp_bounds_delta[key][1]) end end - end - end - if save_errors - open("$output_directory/deviations.txt", "a") do f println(f) end + # Reset first entries of idp_bounds_delta + for (key, _) in idp_bounds_delta + idp_bounds_delta[key][1] = zero(eltype(idp_bounds_delta[key][1])) + end end return nothing @@ -143,6 +116,8 @@ end @unpack idp_bounds_delta = limiter.cache @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + # TODO: Revise Bounds Check for MCL + n_vars = nvariables(equations) deviation_min = zeros(eltype(u), n_vars + limiter.PressurePositivityLimiterKuzmin) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 83459c108b..19a744f38d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -24,9 +24,9 @@ function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquat # Memory for bounds checking routine with `BoundsCheckCallback`. # The first entry of each vector contains the maximum deviation since the last export. # The second one contains the total maximum deviation. - idp_bounds_delta = Dict{Symbol, real(basis)}() + idp_bounds_delta = Dict{Symbol, Vector{real(basis)}}() for key in bound_keys - idp_bounds_delta[key] = zero(real(basis)) + idp_bounds_delta[key] = zeros(real(basis), 2) end return (; cache..., subcell_limiter_coefficients, idp_bounds_delta) From 999b856a623ca798b91073fca0a9cfa2a48cc971 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Sun, 22 Oct 2023 18:48:49 +0200 Subject: [PATCH 312/423] Fix bug --- src/callbacks_stage/subcell_bounds_check.jl | 5 ++- .../subcell_bounds_check_2d.jl | 42 ++++++++++++------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 9a033e7236..0722e77d73 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -180,8 +180,9 @@ end idp_bounds_delta[Symbol(string(v), "_min")][2]) end for variable in limiter.positivity_variables_nonlinear - println("$(variable):\n- positivity: ", - idp_bounds_delta[Symbol("$(variable)_min")]) + variable_string = string(variable) + println(variable_string * ":\n- positivity: ", + idp_bounds_delta[Symbol(variable_string, "_min")][2]) end end println("─"^100 * "\n") diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index fe5be3d02b..6fa1a6d026 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -69,6 +69,19 @@ end deviation[2] = max(deviation[2], deviation[1]) end + for variable in limiter.positivity_variables_nonlinear + key = Symbol(string(variable), "_min") + deviation = idp_bounds_delta[key] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + var = variable(get_node_vars(u, equations, solver, i, j, element), + equations) + deviation[1] = max(deviation[1], + variable_bounds[key][i, j, element] - var) + end + deviation[2] = max(deviation[2], deviation[1]) + end end if save_errors # Print to output file @@ -77,24 +90,23 @@ if local_minmax for v in limiter.local_minmax_variables_cons v_string = string(v) - key_min = Symbol(v_string, "_min") - key_max = Symbol(v_string, "_max") - print(f, ", ", idp_bounds_delta[key_min][1], - idp_bounds_delta[key_max][1]) + print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], + idp_bounds_delta[Symbol(v_string, "_max")][1]) end end - if math_entropy - key = :math_entropy_max - print(f, ", ", idp_bounds_delta[key][1]) + if spec_entropy + print(f, ", ", idp_bounds_delta[:spec_entropy_min][1]) end if math_entropy - key = :math_entropy_max - print(f, ", ", idp_bounds_delta[key][1]) + print(f, ", ", idp_bounds_delta[:math_entropy_max][1]) end if positivity for v in limiter.positivity_variables_cons - key = Symbol(string(v), "_min") - print(f, ", ", idp_bounds_delta[key][1]) + print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) + end + for variable in limiter.positivity_variables_nonlinear + print(f, ", ", + idp_bounds_delta[Symbol(string(variable), "_min")][1]) end end println(f) @@ -111,10 +123,10 @@ end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterMCL, time, iter, output_directory, save_errors) - @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients - @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states - @unpack idp_bounds_delta = limiter.cache - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients + (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states + (; idp_bounds_delta) = limiter.cache + (; antidiffusive_flux1, antidiffusive_flux2) = cache.antidiffusive_fluxes # TODO: Revise Bounds Check for MCL From 535f52004f8799c0ae936d33dcdc630a969ced68 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Sun, 22 Oct 2023 19:22:26 +0200 Subject: [PATCH 313/423] Add bounds check for local limiting --- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 2 +- src/callbacks_stage/subcell_bounds_check.jl | 24 +++++++++++- .../subcell_bounds_check_2d.jl | 38 +++++++++++++++++-- src/solvers/dgsem_tree/subcell_limiters.jl | 5 ++- 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index e7b701611a..792a813dc3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -88,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 21de64aee4..eae24945c6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -84,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 4184e04de3..4e5ec4eb8d 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -131,7 +131,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index c86f266147..d7e30ab162 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -77,15 +77,24 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - (; positivity) = limiter + (; local_minmax, positivity) = limiter (; output_directory) = callback variables = varnames(cons2cons, semi.equations) mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time") + if local_minmax + for v in limiter.local_minmax_variables_cons + variable_string = string(variables[v]) + print(f, ", " * variable_string * "_min, " * variable_string * "_max") + end + end if positivity for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end print(f, ", " * string(variables[v]) * "_min") end end @@ -108,15 +117,26 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - (; positivity) = limiter + (; local_minmax, positivity) = limiter (; idp_bounds_delta) = limiter.cache variables = varnames(cons2cons, semi.equations) println("─"^100) println("Maximum deviation from bounds:") println("─"^100) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + println("$(variables[v]):") + println("-lower bound: ", idp_bounds_delta[Symbol(v_string, "_min")][2]) + println("-upper bound: ", idp_bounds_delta[Symbol(v_string, "_max")][2]) + end + end if positivity for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end println(string(variables[v]) * ":\n- positivity: ", idp_bounds_delta[Symbol(string(v), "_min")][2]) end diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 8159becb50..654b4b5449 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -8,12 +8,35 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors) - (; positivity) = solver.volume_integral.limiter + (; local_minmax, positivity) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta) = limiter.cache + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + key_min = Symbol(v_string, "_min") + key_max = Symbol(v_string, "_max") + deviation_min = idp_bounds_delta[key_min] + deviation_max = idp_bounds_delta[key_max] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + var = u[v, i, j, element] + deviation_min[1] = max(deviation_min[1], + variable_bounds[key_min][i, j, element] - var) + deviation_max[1] = max(deviation_max[1], + var - variable_bounds[key_max][i, j, element]) + end + deviation_min[2] = max(deviation_min[2], deviation_min[1]) + deviation_max[2] = max(deviation_max[2], deviation_max[1]) + end + end if positivity for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end key = Symbol(string(v), "_min") deviation = idp_bounds_delta[key] for element in eachelement(solver, cache), j in eachnode(solver), @@ -30,10 +53,19 @@ # Print to output file open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], + idp_bounds_delta[Symbol(v_string, "_max")][1]) + end + end if positivity for v in limiter.positivity_variables_cons - key = Symbol(string(v), "_min") - print(f, ", ", idp_bounds_delta[key][1]) + if v in limiter.local_minmax_variables_cons + continue + end + print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) end end println(f) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 2cec0ebf1e..1c711c9c01 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -62,8 +62,9 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; bound_keys = () if local_minmax for v in local_minmax_variables_cons - bound_keys = (bound_keys..., Symbol(string(v), "_min"), - Symbol(string(v), "_max")) + v_string = string(v) + bound_keys = (bound_keys..., Symbol(v_string, "_min"), + Symbol(v_string, "_max")) end end for v in positivity_variables_cons From 38231a873294eae02fa0c361da8188ba1241248e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 10:28:44 +0200 Subject: [PATCH 314/423] format --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 8f0914debd..13d60285bf 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -136,9 +136,9 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] -calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, - cache) + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -496,7 +496,7 @@ end fhat_noncons_temp[v, noncons, i, j + 1] end end - + return nothing end From 842399d173c747d8253755b0d9b26bc676fa5322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 10:38:12 +0200 Subject: [PATCH 315/423] Replaced scalar-vector product with scalar-scalar product --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index a479771fc6..1d99cc2a3b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -259,13 +259,12 @@ end equations, dg, ii, j) for noncons in 1:nnoncons(equations) # We multiply by 0.5 because that is done in other parts of Trixi - flux1_noncons = 0.5 * - volume_flux_noncons(u_node, u_node_ii, 1, equations, + flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[i, ii], + multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[i, ii], flux1_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[ii, i], + multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[ii, i], flux1_noncons, equations, dg, noncons, ii, j) end @@ -327,13 +326,12 @@ end equations, dg, i, jj) for noncons in 1:nnoncons(equations) # We multiply by 0.5 because that is done in other parts of Trixi - flux2_noncons = 0.5 * - volume_flux_noncons(u_node, u_node_jj, 2, equations, + flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[j, jj], + multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[j, jj], flux2_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_noncons_temp, derivative_split[jj, j], + multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[jj, j], flux2_noncons, equations, dg, noncons, i, jj) end From 4fa45bc9addeaa1c670da0424a42061cc30d9fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 10:40:54 +0200 Subject: [PATCH 316/423] Removed timers that are not compatible with multi-threading --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 1d99cc2a3b..080f24c6ce 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -82,11 +82,10 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fhat!" begin - calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, - cache) - end + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) + # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -94,19 +93,15 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fv!" begin - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, - cache) - end + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) # antidiffusive flux - @trixi_timeit timer() "calcflux_antidiffusive!" begin - calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, nonconservative_terms, equations, limiter, dg, - element, cache) - end + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) From e40f0ea96e6924ffd1ce533c72a4af3e099fc10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 10:43:34 +0200 Subject: [PATCH 317/423] Added bounds check for GLM-MHD subcell positivity example --- examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index d7ef23332f..24db8698c3 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -100,7 +100,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback From 9053e172e6fc0deed474132c04bbd9e85922aabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 10:45:01 +0200 Subject: [PATCH 318/423] Removed unneeded elixirs --- ...elixir_mhd_alfven_wave_fluxdifferencing.jl | 71 ----------------- .../elixir_mhd_alfven_wave_subcell.jl | 78 ------------------- 2 files changed, 149 deletions(-) delete mode 100644 examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl delete mode 100644 examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl diff --git a/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl deleted file mode 100644 index bb2df4f0fc..0000000000 --- a/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_fluxdifferencing.jl +++ /dev/null @@ -1,71 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5 / 3 -equations = IdealGlmMhdEquations2D(gamma) - -initial_condition = initial_condition_convergence_test - -volume_flux = (flux_central, flux_nonconservative_powell2) -surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) - -basis = LobattoLegendreBasis(3) -volume_integral = VolumeIntegralFluxDifferencing(volume_flux) - -solver = DGSEM(polydeg = 3, - surface_flux = surface_flux, - volume_integral = volume_integral) - -coordinates_min = (0.0, 0.0) -coordinates_max = (sqrt(2.0), sqrt(2.0)) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 4, - n_cells_max = 10_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 2.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (entropy, energy_total, - energy_kinetic, - energy_internal, - energy_magnetic, - cross_helicity)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 10, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim) - -cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl = cfl) - -glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback, - glm_speed_callback) - -############################################################################### -# run the simulation -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(); # - 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/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl b/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl deleted file mode 100644 index 1c8087811b..0000000000 --- a/examples/tree_2d_dgsem/convergence_subcell/elixir_mhd_alfven_wave_subcell.jl +++ /dev/null @@ -1,78 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5 / 3 -equations = IdealGlmMhdEquations2D(gamma) - -initial_condition = initial_condition_convergence_test - -volume_flux = (flux_central, flux_nonconservative_powell2) -surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) - -basis = LobattoLegendreBasis(3) -limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_correction_factor=0.1) -volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) - -solver = DGSEM(polydeg = 3, - surface_flux = surface_flux, - volume_integral = volume_integral) - -coordinates_min = (0.0, 0.0) -coordinates_max = (sqrt(2.0), sqrt(2.0)) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 4, - n_cells_max = 100_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 2.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (entropy, energy_total, - energy_kinetic, - energy_internal, - energy_magnetic, - cross_helicity)) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -save_solution = SaveSolutionCallback(interval = 10, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim) - -cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl = cfl) - -glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback, - glm_speed_callback) - -############################################################################### -# run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) - -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); # - 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 From 6605c417a37930f99eb97f1cb5a350561f605c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 11:11:03 +0200 Subject: [PATCH 319/423] format --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 080f24c6ce..583bee6653 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -256,10 +256,12 @@ end # We multiply by 0.5 because that is done in other parts of Trixi flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[i, ii], + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[i, ii], flux1_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[ii, i], + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[ii, i], flux1_noncons, equations, dg, noncons, ii, j) end @@ -323,10 +325,12 @@ end # We multiply by 0.5 because that is done in other parts of Trixi flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) - multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[j, jj], + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[j, jj], flux2_noncons, equations, dg, noncons, i, j) - multiply_add_to_node_vars!(flux_noncons_temp, 0.5 * derivative_split[jj, j], + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[jj, j], flux2_noncons, equations, dg, noncons, i, jj) end From 2b21e6a1de215569431bc781fb2a73b1f872fa98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Fri, 20 Oct 2023 16:57:35 +0200 Subject: [PATCH 320/423] Cherry-picked changes done in PR (https://github.com/bennibolm/Trixi.jl/pull/116) [a90745c] Apply suggestions from code review Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- src/equations/equations.jl | 3 +++ src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 46a549f513..2faec6892d 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -207,6 +207,7 @@ where `x` specifies the coordinates, `t` is the current time, and `equation` is struct BoundaryConditionNeumann{B} boundary_normal_flux_function::B end + """ NonConservativeLocal() @@ -215,6 +216,7 @@ When the argument `nonconservative_type` is of type `NonConservativeLocal`, the function returns the local part of the non-conservative term. """ struct NonConservativeLocal end + """ NonConservativeSymmetric() @@ -223,6 +225,7 @@ When the argument `nonconservative_type` is of type `NonConservativeSymmetric`, the function returns the symmetric part of the non-conservative term. """ struct NonConservativeSymmetric end + # set sensible default values that may be overwritten by specific equations """ have_nonconservative_terms(equations) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 583bee6653..1d7e4f1f32 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -197,6 +197,7 @@ end return nothing end + # Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element # (**with non-conservative terms**). # @@ -376,6 +377,7 @@ end phi[v, noncons, i, j + 1] * value end end + return nothing end @@ -416,6 +418,7 @@ end return nothing end + # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. @inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fstar1_L, fstar1_R, fstar2_L, fstar2_R, From baeaf02960869d14b8ce7cb71661ba332591cf83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 12:30:57 +0200 Subject: [PATCH 321/423] Renamed function dpdu --- src/equations/ideal_glm_mhd_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index ce7e5180c1..bddb25b06a 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1000,7 +1000,7 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function dpdu(u, equations::IdealGlmMhdEquations2D) +@inline function pressure(u, equations::IdealGlmMhdEquations2D, derivative::True) rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u v1 = rho_v1 / rho From 342bf60804398a0c01295b9281a28e8d195b8905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 15:23:01 +0200 Subject: [PATCH 322/423] Unified pressure derivative functions for the 2D Euler equations --- src/equations/compressible_euler_2d.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 8fd99bbfc6..09d5dee0c3 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1574,7 +1574,7 @@ end @inline entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) # Transformation from conservative variables u to d(p)/d(u) -@inline function dpdu(u, equations::CompressibleEulerEquations2D) +@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1583,9 +1583,6 @@ end return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) end -@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) - return dpdu(u, equations) -end @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD From 41dc2a1b4cc5132ed683fbc6cf525dc75d52fc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 16:22:08 +0200 Subject: [PATCH 323/423] Apply suggestions from code review Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- src/equations/ideal_glm_mhd_2d.jl | 16 +++++++++------- test/test_tree_2d_mhd.jl | 8 ++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 1d8f354360..5c486880d5 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -283,7 +283,7 @@ end """ flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D) + equations::IdealGlmMhdEquations2D) Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier @@ -336,11 +336,12 @@ results on non-conforming meshes(!). return f end + """ flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeLocal, - noncons_term::Integer) + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., @@ -396,11 +397,12 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., end return f end + """ flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index bbec0ae165..d664403616 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -151,6 +151,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") l2 = [2.9974425783503109e-02, 7.2849646345685956e-02, 7.2488477174662239e-02, 0.0000000000000000e+00, 1.2507971380965512e+00, 1.8929505145499678e-02, 1.2218606317164420e-02, 0.0000000000000000e+00, 3.0154796910479838e-03], linf = [3.2147382412340830e-01, 1.3709471664007811e+00, 1.3465154685288383e+00, 0.0000000000000000e+00, 1.6051257523415284e+01, 3.0564266749926644e-01, 2.3908016329805595e-01, 0.0000000000000000e+00, 1.3711262178549158e-01], tspan = (0.0, 0.003)) + # 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 From f00ac017be8116c89111102da970caf7ff5d68df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 23 Oct 2023 17:37:28 +0200 Subject: [PATCH 324/423] Removed timers from MCL routines (not compatible with multi-threading) --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 13d60285bf..76d75e5c1b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -184,11 +184,9 @@ end fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] fhat2_R = fhat2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fhat!" begin - calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, - cache) - end + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -196,19 +194,15 @@ end fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] - @trixi_timeit timer() "calcflux_fv!" begin - calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, - cache) - end + calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) # antidiffusive flux - @trixi_timeit timer() "calcflux_antidiffusive!" begin - calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, - fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, nonconservative_terms, equations, limiter, dg, - element, cache) - end + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) # limit antidiffusive flux calcflux_antidiffusive_limited!(u, mesh, nonconservative_terms, equations, From 50be874b40674507e2d7251ea72fcd3eb147679f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 12:37:47 +0200 Subject: [PATCH 325/423] Renamed flux_nonconservative_powell2 to flux_nonconservative_powell_local_symmetric --- .../elixir_mhd_shockcapturing_subcell.jl | 4 +- src/Trixi.jl | 2 +- src/equations/ideal_glm_mhd_2d.jl | 43 ++++++++++--------- test/test_tree_2d_mhd.jl | 2 +- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 24db8698c3..f40da6676c 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -46,8 +46,8 @@ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) end initial_condition = initial_condition_blast_wave -surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell2) -volume_flux = (flux_derigs_etal, flux_nonconservative_powell2) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell_local_symmetric) +volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; diff --git a/src/Trixi.jl b/src/Trixi.jl index f209e63a4d..c7f2371970 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -162,7 +162,7 @@ export GradientVariablesPrimitive, GradientVariablesEntropy export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_godunov, flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner, - flux_nonconservative_powell, flux_nonconservative_powell2, + flux_nonconservative_powell, flux_nonconservative_powell_local_symmetric, flux_kennedy_gruber, flux_shima_etal, flux_ec, flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_es_fjordholm_etal, flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal, diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 5c486880d5..1d5ea43a1e 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -282,8 +282,9 @@ end end """ - flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D) + flux_nonconservative_powell_local_symmetric(u_ll, u_rr, + orientation::Integer, + equations::IdealGlmMhdEquations2D) Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier @@ -297,8 +298,9 @@ results on non-conforming meshes(!). - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ -@inline function flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D) +@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr, + orientation::Integer, + equations::IdealGlmMhdEquations2D) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr @@ -338,20 +340,20 @@ results on non-conforming meshes(!). end """ - flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeLocal, - noncons_term::Integer) + flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ -@inline function flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeLocal, - noncons_term::Integer) +@inline function flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll if noncons_term == 1 @@ -399,20 +401,21 @@ the non-conservative staggered "fluxes" for subcell limiting. See, e.g., end """ - flux_nonconservative_powell2(u_ll, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) + flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. """ -@inline function flux_nonconservative_powell2(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D, - nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) +@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr, + orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index d664403616..f364fa86e7 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -158,7 +158,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 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 From 7f03d0091d090abea39330ebd6bc4a4be399cf96 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 24 Oct 2023 13:07:59 +0200 Subject: [PATCH 326/423] Add allocation tests to subcell simulation tests (only `TreeMesh`) --- test/test_tree_2d_euler.jl | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index eb95ff64c1..964dca642e 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -26,6 +26,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), l2 = [2.0633069593983843e-6, 1.9337331005472223e-6, 1.9337331005227536e-6, 5.885362117543159e-6], linf = [1.636984098429828e-5, 1.5579038690871627e-5, 1.557903868998345e-5, 5.260532107742577e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end end @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @@ -46,6 +54,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_IDP.jl"), l2 = [0.1289984161854359, 0.012899841618543363, 0.025799683237087086, 0.003224960404636081], linf = [0.9436588685021441, 0.0943658868502173, 0.1887317737004306, 0.02359147170911058]) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_density_wave.jl" begin @@ -244,6 +260,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_blast_wave_MCL.jl" begin @@ -253,6 +277,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.5), initial_refinement_level = 4, coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @@ -278,6 +310,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 1.0), initial_refinement_level=4, coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin @@ -287,6 +327,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 1.0), initial_refinement_level=4, coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @@ -398,6 +446,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=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)) < 15000 + end end @trixi_testset "elixir_euler_kelvin_helmholtz_instability_MCL.jl" begin @@ -407,6 +463,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") tspan = (0.0, 0.2), initial_refinement_level=5, coverage_override = (maxiters=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)) < 15000 + end end @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @@ -474,6 +538,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") initial_refinement_level=5, tspan = (0.0, 1.0e-4), coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_astro_jet_MCL.jl" begin @@ -483,6 +555,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") initial_refinement_level=5, tspan = (0.0, 1.0e-4), coverage_override = (maxiters=6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_vortex.jl" begin From ffbda680369842a7dea7bbb286c53c4d716a4fbe Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 24 Oct 2023 13:08:18 +0200 Subject: [PATCH 327/423] Fix allocations in `SemiDiscEntropyLimiter` --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index e165308967..2ed7d7bf4b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -1371,7 +1371,7 @@ end delta_v = v_local - v_local_m1 delta_psi = psi_local - psi_local_m1 - entProd_FV = dot(delta_v, fstar1[:, i, j]) - delta_psi + entProd_FV = dot(delta_v, view(fstar1, :, i, j)) - delta_psi delta_entProd = dot(delta_v, antidiffusive_flux_local) alpha = 1 # Initialize alpha for plotting @@ -1416,7 +1416,7 @@ end delta_v = v_local - v_local_m1 delta_psi = psi_local - psi_local_m1 - entProd_FV = dot(delta_v, fstar2[:, i, j]) - delta_psi + entProd_FV = dot(delta_v, view(fstar2, :, i, j)) - delta_psi delta_entProd = dot(delta_v, antidiffusive_flux_local) alpha = 1 # Initialize alpha for plotting From c7c3ca0fb17bddce532589eaae422fa061fe86f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 13:48:20 +0200 Subject: [PATCH 328/423] Increased maximum allowed allocation bound for subcell limiting simulation Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- test/test_tree_2d_mhd.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index f364fa86e7..b55b512498 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -157,7 +157,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 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 + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end end From 120f9ba79c67b9e603e8af02672fcc8bbcea045a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 15:24:41 +0200 Subject: [PATCH 329/423] Added explanatory comments about different non-conservative fluxes and multiple dispatch --- src/equations/ideal_glm_mhd_2d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 1d5ea43a1e..fa30c8870b 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -294,6 +294,12 @@ This implementation uses a non-conservative term that can be written as the prod of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different results on non-conforming meshes(!). + +The two functions below, which share the same name, return yield either the local +or symmetric portion of the non-conservative flux based on the type of the +nonconservative_type argument, employing multiple dispatch. They are used to +compute the subcell fluxes in dg_2d_subcell_limiters.jl. + ## References - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. @@ -349,6 +355,7 @@ Local part of the Powell and GLM non-conservative terms. Needed for the calculat the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. +This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl. """ @inline function flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, @@ -410,6 +417,7 @@ Symmetric part of the Powell and GLM non-conservative terms. Needed for the calc the non-conservative staggered "fluxes" for subcell limiting. See, e.g., - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf. +This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl. """ @inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr, orientation::Integer, From 81d40e2824a2de80a1b676addb222f18309c466e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 15:29:07 +0200 Subject: [PATCH 330/423] Changed variable name noncons_term to nonconservative_term --- src/equations/ideal_glm_mhd_2d.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index fa30c8870b..7072fa37df 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -349,7 +349,7 @@ end flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeLocal, - noncons_term::Integer) + nonconservative_term::Integer) Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., @@ -360,10 +360,10 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl @inline function flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeLocal, - noncons_term::Integer) + nonconservative_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll - if noncons_term == 1 + if nonconservative_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) v1_ll = rho_v1_ll / rho_ll v2_ll = rho_v2_ll / rho_ll @@ -378,7 +378,7 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl v2_ll, v3_ll, 0) - else #noncons_term ==2 + else #nonconservative_term ==2 # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) if orientation == 1 v1_ll = rho_v1_ll / rho_ll @@ -411,7 +411,7 @@ end flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) + nonconservative_term::Integer) Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g., @@ -423,11 +423,11 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl orientation::Integer, equations::IdealGlmMhdEquations2D, nonconservative_type::NonConservativeSymmetric, - noncons_term::Integer) + nonconservative_term::Integer) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr - if noncons_term == 1 + if nonconservative_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) if orientation == 1 B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 @@ -452,7 +452,7 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl B2_avg, 0) end - else #noncons_term == 2 + else #nonconservative_term == 2 # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 f = SVector(0, From c7dd7f5ee90168c08ee59bd22419627988e6a11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 15:36:25 +0200 Subject: [PATCH 331/423] Update docstrin of flux_nonconservative_powell_local_symmetric Co-authored-by: Michael Schlottke-Lakemper --- src/equations/ideal_glm_mhd_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 7072fa37df..54a6c17b9d 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -295,7 +295,7 @@ of local and symmetric parts. It is equivalent to the non-conservative flux of B et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different results on non-conforming meshes(!). -The two functions below, which share the same name, return yield either the local +The two other flux functions with the same name return either the local or symmetric portion of the non-conservative flux based on the type of the nonconservative_type argument, employing multiple dispatch. They are used to compute the subcell fluxes in dg_2d_subcell_limiters.jl. From 5b2b8887480714eff660b1123d3ccc6dd988b181 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 24 Oct 2023 15:36:34 +0200 Subject: [PATCH 332/423] Implement suggestions --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 13 +++++++++---- src/solvers/dgsem_tree/subcell_limiters.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 7 ++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index b947d06934..923f0ca193 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -191,10 +191,15 @@ end return nothing end -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::BoundaryConditionDirichlet, - orientation_or_normal, direction, equations, - dg, indices...) +""" + get_boundary_outer_state(boundary_condition::BoundaryConditionDirichlet, + cache, t, equations, dg, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains require the boundary +outer state. This function returns the boundary value at time `t` and for node with spatial +indices `indices`. +""" +@inline function get_boundary_outer_state(boundary_condition::BoundaryConditionDirichlet, + cache, t, equations, dg, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 1c711c9c01..8269f0dd8d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -20,8 +20,8 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) -- positivity limiting for conservative variables (`positivity_variables_cons`) +- Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) +- Positivity limiting for conservative variables (`positivity_variables_cons`) The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index b4e9b63826..193b5e6c49 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -141,11 +141,8 @@ end index = reverse(index) boundary_index += 2 end - u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[boundary_index], - orientation, boundary_index, - equations, dg, index..., element) + u_outer = get_boundary_outer_state(boundary_conditions[boundary_index], cache, + t, equations, dg, index..., element) var_outer = u_outer[variable] var_min[index..., element] = min(var_min[index..., element], var_outer) From b7bed59fd6457c1f5b515b2ccb28c2abb09a8eca Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 24 Oct 2023 15:41:32 +0200 Subject: [PATCH 333/423] Fix format --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 193b5e6c49..5ed89c8c5b 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -141,8 +141,9 @@ end index = reverse(index) boundary_index += 2 end - u_outer = get_boundary_outer_state(boundary_conditions[boundary_index], cache, - t, equations, dg, index..., element) + u_outer = get_boundary_outer_state(boundary_conditions[boundary_index], + cache, t, equations, dg, + index..., element) var_outer = u_outer[variable] var_min[index..., element] = min(var_min[index..., element], var_outer) From 79109937dc2b63697c0701814ab0b7f5f2e57759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 16:00:51 +0200 Subject: [PATCH 334/423] Renamed function nnoncons as n_nonconservative_terms --- src/equations/equations.jl | 7 +++---- src/equations/ideal_glm_mhd_2d.jl | 2 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 18 +++++++++--------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 2faec6892d..63041e103a 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -239,11 +239,10 @@ The return value will be `True()` or `False()` to allow dispatching on the retur """ have_nonconservative_terms(::AbstractEquations) = False() """ - nnoncons(equations) -Number of nonconservative terms for a particular equation. The default is 0 and -it must be defined for each nonconservative equation independently. + n_nonconservative_terms(equations) +Number of nonconservative terms in the form local * symmetric for a particular equation. """ -nnoncons(::AbstractEquations) = 0 +function n_nonconservative_terms(::AbstractEquations) end have_constant_speed(::AbstractEquations) = False() default_analysis_errors(::AbstractEquations) = (:l2_error, :linf_error) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 54a6c17b9d..9e0f935742 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -29,7 +29,7 @@ function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN) end have_nonconservative_terms(::IdealGlmMhdEquations2D) = True() -nnoncons(::IdealGlmMhdEquations2D) = 2 +n_nonconservative_terms(::IdealGlmMhdEquations2D) = 2 function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations2D) ("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3", "psi") diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 1d7e4f1f32..18b2f2097d 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -27,19 +27,19 @@ function create_cache(mesh::TreeMesh{2}, equations, flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), - nnoncons(equations), + n_nonconservative_terms(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] fhat_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), - nnoncons(equations), + n_nonconservative_terms(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] phi_threaded = A4d[A4d(undef, nvariables(equations), - nnoncons(equations), + n_nonconservative_terms(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] @@ -253,7 +253,7 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, equations, dg, ii, j) - for noncons in 1:nnoncons(equations) + for noncons in 1:n_nonconservative_terms(equations) # We multiply by 0.5 because that is done in other parts of Trixi flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, NonConservativeSymmetric(), noncons) @@ -281,7 +281,7 @@ end # Compute local contribution to non-conservative flux for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - for noncons in 1:nnoncons(equations) + for noncons in 1:n_nonconservative_terms(equations) set_node_vars!(phi, volume_flux_noncons(u_local, 1, equations, NonConservativeLocal(), noncons), @@ -298,7 +298,7 @@ end fhat1_R[v, i + 1, j] = value end # Nonconservative part - for noncons in 1:nnoncons(equations), v in eachvariable(equations) + for noncons in 1:n_nonconservative_terms(equations), v in eachvariable(equations) value = fhat_noncons_temp[v, noncons, i, j] + weights[i] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i + 1, j] = value @@ -322,7 +322,7 @@ end equations, dg, i, j) multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, equations, dg, i, jj) - for noncons in 1:nnoncons(equations) + for noncons in 1:n_nonconservative_terms(equations) # We multiply by 0.5 because that is done in other parts of Trixi flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, NonConservativeSymmetric(), noncons) @@ -350,7 +350,7 @@ end # Compute local contribution to non-conservative flux for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - for noncons in 1:nnoncons(equations) + for noncons in 1:n_nonconservative_terms(equations) set_node_vars!(phi, volume_flux_noncons(u_local, 2, equations, NonConservativeLocal(), noncons), @@ -367,7 +367,7 @@ end fhat2_R[v, i, j + 1] = value end # Nonconservative part - for noncons in 1:nnoncons(equations), v in eachvariable(equations) + for noncons in 1:n_nonconservative_terms(equations), v in eachvariable(equations) value = fhat_noncons_temp[v, noncons, i, j] + weights[j] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i, j + 1] = value From 3f9f0fec87e465ba0a3e98ec6ac16600bd18bc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 16:07:10 +0200 Subject: [PATCH 335/423] format --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 18b2f2097d..3e03924f62 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -298,7 +298,9 @@ end fhat1_R[v, i + 1, j] = value end # Nonconservative part - for noncons in 1:n_nonconservative_terms(equations), v in eachvariable(equations) + for noncons in 1:n_nonconservative_terms(equations), + v in eachvariable(equations) + value = fhat_noncons_temp[v, noncons, i, j] + weights[i] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i + 1, j] = value @@ -367,7 +369,9 @@ end fhat2_R[v, i, j + 1] = value end # Nonconservative part - for noncons in 1:n_nonconservative_terms(equations), v in eachvariable(equations) + for noncons in 1:n_nonconservative_terms(equations), + v in eachvariable(equations) + value = fhat_noncons_temp[v, noncons, i, j] + weights[j] * flux_noncons_temp[v, noncons, i, j] fhat_noncons_temp[v, noncons, i, j + 1] = value From b6646ad1d3088c16cf7c29021bb34e9d13f1b2fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 17:54:21 +0200 Subject: [PATCH 336/423] Apply suggestions from code review Co-authored-by: Michael Schlottke-Lakemper --- src/equations/ideal_glm_mhd_2d.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 9e0f935742..e8de0cedde 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -317,9 +317,9 @@ compute the subcell fluxes in dg_2d_subcell_limiters.jl. # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - psi_avg = (psi_ll + psi_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + psi_avg = (psi_ll + psi_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code if orientation == 1 - B1_avg = (B1_ll + B1_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + B1_avg = (B1_ll + B1_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code f = SVector(0, B1_ll * B1_avg, B2_ll * B1_avg, @@ -330,7 +330,7 @@ compute the subcell fluxes in dg_2d_subcell_limiters.jl. v3_ll * B1_avg, v1_ll * psi_avg) else # orientation == 2 - B2_avg = (B2_ll + B2_rr) #* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + B2_avg = (B2_ll + B2_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code f = SVector(0, B1_ll * B2_avg, B2_ll * B2_avg, @@ -430,7 +430,7 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl if nonconservative_term == 1 # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) if orientation == 1 - B1_avg = (B1_ll + B1_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + B1_avg = (B1_ll + B1_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code f = SVector(0, B1_avg, B1_avg, @@ -441,7 +441,7 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl B1_avg, 0) else # orientation == 2 - B2_avg = (B2_ll + B2_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + B2_avg = (B2_ll + B2_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code f = SVector(0, B2_avg, B2_avg, @@ -454,7 +454,7 @@ This function is used to compute the subcell fluxes in dg_2d_subcell_limiters.jl end else #nonconservative_term == 2 # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) - psi_avg = (psi_ll + psi_rr)#* 0.5 # We remove the 0.5 because the flux is always multiplied by 0.5 + psi_avg = (psi_ll + psi_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code f = SVector(0, 0, 0, From 0eee7218204abc57c11b1fec07b2013615db4123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 24 Oct 2023 18:05:25 +0200 Subject: [PATCH 337/423] Non-conservative subcell limiting cache only allocated for non-conservative equations Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 3e03924f62..f8346ff8be 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -26,30 +26,33 @@ function create_cache(mesh::TreeMesh{2}, equations, nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), - n_nonconservative_terms(equations), - nnodes(dg), nnodes(dg)) - for _ in 1:Threads.nthreads()] fhat_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), - n_nonconservative_terms(equations), - nnodes(dg), nnodes(dg)) - for _ in 1:Threads.nthreads()] - - phi_threaded = A4d[A4d(undef, nvariables(equations), - n_nonconservative_terms(equations), - nnodes(dg), nnodes(dg)) - for _ in 1:Threads.nthreads()] - antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) + + if typeof(have_nonconservative_terms(equations)) == True + flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + phi_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + cache = (; cache..., flux_nonconservative_temp_threaded, + fhat_nonconservative_temp_threaded, phi_threaded) + end + return (; cache..., antidiffusive_fluxes, fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, - flux_temp_threaded, flux_nonconservative_temp_threaded, fhat_temp_threaded, - fhat_nonconservative_temp_threaded, phi_threaded) + flux_temp_threaded, fhat_temp_threaded) end function calc_volume_integral!(du, u, From f3399b628452aac9eca41e929a016438d8f813d1 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 25 Oct 2023 12:01:07 +0200 Subject: [PATCH 338/423] Add allocation tests for `StructuredMesh` --- .../elixir_euler_double_mach.jl | 71 -- .../elixir_euler_double_mach_MCL.jl | 71 -- src/equations/compressible_euler_2d.jl | 28 +- test/test_structured_2d.jl | 638 ++++++++++-------- 4 files changed, 375 insertions(+), 433 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index ede3f6b382..3d34e28a4f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -7,81 +7,10 @@ using Trixi gamma = 1.4 equations = CompressibleEulerEquations2D(gamma) -""" - initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - -Compressible Euler setup for a double Mach reflection problem. -Involves strong shock interactions as well as steady / unsteady flow structures. -Also exercises special boundary conditions along the bottom of the domain that is a mixture of -Dirichlet and slip wall. -See Section IV c on the paper below for details. - -- Paul Woodward and Phillip Colella (1984) - The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. - [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) -""" -# @inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - -# if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) -# phi = pi / 6 -# sin_phi, cos_phi = sincos(phi) - -# rho = 8 -# v1 = 8.25 * cos_phi -# v2 = -8.25 * sin_phi -# p = 116.5 -# else -# rho = 1.4 -# v1 = 0 -# v2 = 0 -# p = 1 -# end - -# prim = SVector(rho, v1, v2, p) -# return prim2cons(prim, equations) -# end initial_condition = Trixi.initial_condition_double_mach_reflection - -# boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) - -# Supersonic outflow boundary condition. Solution is taken entirely from the internal state. -# See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. -# @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, direction, x, t, -# surface_flux_function, equations::CompressibleEulerEquations2D) -# # NOTE: Only for the supersonic outflow is this strategy valid -# # Calculate the boundary flux entirely from the internal solution state -# return flux(u_inner, normal_direction, equations) -# end - -# Special mixed boundary condition type for the :Bottom of the domain. -# It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 -# @inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, -# x, t, surface_flux_function, -# equations::CompressibleEulerEquations2D) -# if x[1] < 1 / 6 -# # # From the BoundaryConditionDirichlet -# # # get the external value of the solution -# # u_boundary = initial_condition_double_mach_reflection(x, t, equations) -# # # Calculate boundary flux -# # flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) - -# # From the BoundaryConditionCharacteristic -# # get the external state of the solution -# u_boundary = Trixi.characteristic_boundary_value_function(initial_condition, -# u_inner, normal_direction, direction, x, t, equations) -# # Calculate boundary flux -# flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) -# else # x[1] >= 1 / 6 -# # Use the free slip wall BC otherwise -# flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, surface_flux_function, equations) -# end - -# return flux -# end - boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, y_pos=boundary_condition_inflow_outflow, x_pos=boundary_condition_inflow_outflow, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 9c3d7c8943..2516d7e205 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -7,81 +7,10 @@ using Trixi gamma = 1.4 equations = CompressibleEulerEquations2D(gamma) -""" - initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - -Compressible Euler setup for a double Mach reflection problem. -Involves strong shock interactions as well as steady / unsteady flow structures. -Also exercises special boundary conditions along the bottom of the domain that is a mixture of -Dirichlet and slip wall. -See Section IV c on the paper below for details. - -- Paul Woodward and Phillip Colella (1984) - The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. - [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) -""" -# @inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - -# if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) -# phi = pi / 6 -# sin_phi, cos_phi = sincos(phi) - -# rho = 8 -# v1 = 8.25 * cos_phi -# v2 = -8.25 * sin_phi -# p = 116.5 -# else -# rho = 1.4 -# v1 = 0 -# v2 = 0 -# p = 1 -# end - -# prim = SVector(rho, v1, v2, p) -# return prim2cons(prim, equations) -# end initial_condition = Trixi.initial_condition_double_mach_reflection - -# boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) - -# Supersonic outflow boundary condition. Solution is taken entirely from the internal state. -# See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. -# @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, direction, x, t, -# surface_flux_function, equations::CompressibleEulerEquations2D) -# # NOTE: Only for the supersonic outflow is this strategy valid -# # Calculate the boundary flux entirely from the internal solution state -# return flux(u_inner, normal_direction, equations) -# end - -# Special mixed boundary condition type for the :Bottom of the domain. -# It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 -# @inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, -# x, t, surface_flux_function, -# equations::CompressibleEulerEquations2D) -# if x[1] < 1 / 6 -# # # From the BoundaryConditionDirichlet -# # # get the external value of the solution -# # u_boundary = initial_condition_double_mach_reflection(x, t, equations) -# # # Calculate boundary flux -# # flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) - -# # From the BoundaryConditionCharacteristic -# # get the external state of the solution -# u_boundary = Trixi.characteristic_boundary_value_function(initial_condition, -# u_inner, normal_direction, direction, x, t, equations) -# # Calculate boundary flux -# flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) -# else # x[1] >= 1 / 6 -# # Use the free slip wall BC otherwise -# flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, surface_flux_function, equations) -# end - -# return flux -# end - boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, y_pos=boundary_condition_inflow_outflow, x_pos=boundary_condition_inflow_outflow, diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 8fd99bbfc6..7acc950d29 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -497,33 +497,53 @@ end return cons end +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" @inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) phi = pi / 6 sin_phi, cos_phi = sincos(phi) - rho = 8 + rho = 8.0 v1 = 8.25 * cos_phi v2 = -8.25 * sin_phi p = 116.5 else rho = 1.4 - v1 = 0 - v2 = 0 - p = 1 + v1 = 0.0 + v2 = 0.0 + p = 1.0 end prim = SVector(rho, v1, v2, p) return prim2cons(prim, equations) end +# Special mixed boundary condition type for the :Bottom of the domain. +# It is charachteristic when x < 1/6 and a slip wall when x >= 1/6 @inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, direction, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) + # Note: Only for StructuredMesh if x[1] < 1 / 6 + # # From the BoundaryConditionDirichlet + # # get the external value of the solution + # u_boundary = initial_condition_double_mach_reflection(x, t, equations) + # From the BoundaryConditionCharacteristic # get the external state of the solution u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 2d09a1908e..269355e749 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -19,13 +19,13 @@ isdir(outdir) && rm(outdir, recursive=true) # Expected errors are exactly the same as with TreeMesh! l2 = [8.311947673061856e-6], linf = [6.627000273229378e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -40,13 +40,13 @@ isdir(outdir) && rm(outdir, recursive=true) errors = analysis_callback(sol) @test errors.l2 ≈ [7.816742843181738e-6, 7.816742843196112e-6] rtol=1.0e-4 @test errors.linf ≈ [6.314906965543265e-5, 6.314906965410039e-5] rtol=1.0e-4 - # 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 + # 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 @@ -55,13 +55,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), l2 = [4.220397559713772e-6], linf = [3.477948874874848e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -73,13 +73,13 @@ isdir(outdir) && rm(outdir, recursive=true) cells_per_dimension = (16, 23), polydeg = 4, cfl = 1.4) - # 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 + # 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 @@ -90,13 +90,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [8.311947673061856e-6], linf = [6.627000273229378e-5], alpha = 0.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 + # 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 @@ -106,13 +106,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [8.3122750550501e-6], linf = [6.626802581322089e-5], alpha = 0.1) - # 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 + # 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 @@ -122,13 +122,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [8.311947673061856e-6], linf = [6.627000273229378e-5], alpha = 0.5 * pi) - # 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 + # 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 @@ -138,13 +138,13 @@ isdir(outdir) && rm(outdir, recursive=true) # Expected errors are exactly the same as in elixir_advection_basic! l2 = [8.311947673061856e-6], linf = [6.627000273229378e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -152,13 +152,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_waving_flag.jl"), l2 = [0.00018553859900545866], linf = [0.0016167719118129753]) - # 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 + # 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 @@ -166,13 +166,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_free_stream.jl"), l2 = [6.8925194184204476e-15], linf = [9.903189379656396e-14]) - # 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 + # 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 @@ -180,13 +180,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonperiodic.jl"), l2 = [0.00025552740731641223], linf = [0.007252625722805939]) - # 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 + # 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 @@ -194,13 +194,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), l2 = [4.219208035582454e-6], linf = [3.438434404412494e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -211,13 +211,13 @@ isdir(outdir) && rm(outdir, recursive=true) rtol = 5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS) elixir_file="elixir_advection_waving_flag.jl", restart_file="restart_000021.h5") - # 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 + # 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 @@ -227,13 +227,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [1.0857981180834031e-13], elixir_file="elixir_advection_free_stream.jl", restart_file="restart_000036.h5") - # 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 + # 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 @@ -242,6 +242,14 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [0.3398358793878119, 0.03398358793878129, 0.06796717587756244, 0.008495896984696072], linf = [0.8360446582060936, 0.08360446582060972, 0.16720893164122444, 0.02090111645397741], tspan = (0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end end @trixi_testset "elixir_euler_convergence_wavingflag_MCL.jl" begin @@ -249,6 +257,14 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [0.33983417649330827, 0.033983417649330924, 0.06796683529866161, 0.008495854412336827], linf = [0.8360446582068146, 0.083604465820679, 0.16720893164136671, 0.02090111645399162], tspan = (0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end end @trixi_testset "elixir_euler_source_terms.jl" begin @@ -256,13 +272,13 @@ isdir(outdir) && rm(outdir, recursive=true) # Expected errors are exactly the same as with TreeMesh! l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -273,13 +289,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5], alpha = 0.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 + # 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 @@ -289,13 +305,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [9.321188057029291e-7, 1.3195106906473365e-6, 1.510307360354032e-6, 4.82455408101712e-6], linf = [9.57723626271445e-6, 1.0480225511866337e-5, 1.2817828088262928e-5, 4.886962393513272e-5], alpha = 0.1) - # 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 + # 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 @@ -305,13 +321,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [9.32127973957391e-7, 8.477824799744325e-7, 1.8175286311402784e-6, 4.824562453521076e-6], linf = [9.576898420737834e-6, 5.057704352218195e-6, 1.635260719945464e-5, 4.886978754825577e-5], alpha = 0.2 * pi) - # 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 + # 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 @@ -321,13 +337,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5], alpha = 0.5 * pi) - # 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 + # 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 @@ -335,13 +351,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_parallelogram.jl"), l2 = [1.1167802955144833e-5, 1.0805775514153104e-5, 1.953188337010932e-5, 5.5033856574857146e-5], linf = [8.297006495561199e-5, 8.663281475951301e-5, 0.00012264160606778596, 0.00041818802502024965]) - # 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 + # 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 @@ -350,19 +366,27 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [0.00816013114351954, 0.008658251709937477, 0.009351905651482216, 0.027757012781694318], linf = [0.027225615981281148, 0.040734036539016305, 0.0381940733564341, 0.08080650914262844], tspan = (0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end end @trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_waving_flag.jl"), l2 = [2.991891317562739e-5, 3.6063177168283174e-5, 2.7082941743640572e-5, 0.00011414695350996946], linf = [0.0002437454930492855, 0.0003438936171968887, 0.00024217622945688078, 0.001266380414757684]) - # 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 + # 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 @@ -371,13 +395,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, 1.4104095258528071e-14], linf = [1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, 2.7000623958883807e-13], atol = 7.0e-13) - # 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 + # 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 @@ -387,6 +411,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [1.1546319456101628e-14, 1.084687895058778e-13, 1.7050250100680842e-13, 2.0250467969162855e-13], atol = 1.0e-13, cells_per_dimension = (8, 8)) + # 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)) < 10000 + end end @trixi_testset "elixir_euler_free_stream_MCL.jl" begin @@ -395,6 +427,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [7.993605777301127e-15, 1.1611545058798356e-13, 1.7619239400801234e-13, 2.007283228522283e-13], atol = 1.0e-13, cells_per_dimension = (8, 8)) + # 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)) < 10000 + end end @trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin @@ -403,13 +443,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, 1.4104095258528071e-14], linf = [1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, 2.7000623958883807e-13], atol = 7.0e-13) - # 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 + # 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 @@ -427,6 +467,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [14.244598580563007, 138.4745277257612, 38.69633620234036, 1574.6686216469134], initial_refinement_level = 3, 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)) < 10000 + end end @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin @@ -435,6 +483,14 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [5.385492532917423, 6.575446146030286, 10.0652310822613, 51.00901293102744], cells_per_dimension = (8, 12), tspan = (0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end end @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @@ -443,19 +499,27 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [5.68876088477983, 8.165554425950146, 10.859100194836538, 50.25822408989214], cells_per_dimension = (8, 12), tspan = (0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end end @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), l2 = [2.259440511901724e-6, 2.3188881559075347e-6, 2.3188881559568146e-6, 6.332786324137878e-6], linf = [1.4987382622067003e-5, 1.918201192063762e-5, 1.918201192019353e-5, 6.052671713430158e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # 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 @@ -464,13 +528,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [0.03774907669925568, 0.02845190575242045, 0.028262802829412605, 0.13785915638851698], linf = [0.3368296929764073, 0.27644083771519773, 0.27990039685141377, 1.1971436487402016], tspan = (0.0, 0.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 + # 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 @@ -479,13 +543,13 @@ isdir(outdir) && rm(outdir, recursive=true) l2 = [3.69856202e-01, 2.35242180e-01, 2.41444928e-01, 1.28807120e+00], linf = [1.82786223e+00, 1.30452904e+00, 1.40347257e+00, 6.21791658e+00], tspan = (0.0, 0.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 + # 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 @@ -495,13 +559,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.4799214336153155, 0.024595483032220266, 0.02059808120543466, 0.03190756362943725], cells_per_dimension = (8,8), tspan = (0.0, 0.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 + # 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 @@ -509,13 +573,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), l2 = [0.0016688820596537988, 0.0025921681885685425, 0.003280950351435014], linf = [0.010994679664394269, 0.01331197845637, 0.020080117011346488]) - # 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 + # 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 @@ -523,13 +587,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_ec.jl"), l2 = [0.03647890611450939, 0.025284915444045052, 0.025340697771609126], linf = [0.32516731565355583, 0.37509762516540046, 0.29812843284727336]) - # 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 + # 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 @@ -537,13 +601,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_isothermal_wave.jl"), l2 = [0.004998778491726366, 0.004998916000294425, 9.259136963058664e-17], linf = [0.010001103673834888, 0.010051165098399503, 7.623942913643681e-16]) - # 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 + # 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 @@ -551,13 +615,13 @@ isdir(outdir) && rm(outdir, recursive=true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_wave.jl"), l2 = [0.23642682112204072, 0.20904264390331334, 8.174982691297391e-17], linf = [0.4848250368349989, 0.253350873815695, 4.984552457753618e-16]) - # 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 + # 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 @@ -567,13 +631,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [1.0771947577311836, 1.9143913544309838, 2.149549109115789], tspan = (0.0, 0.1), coverage_override = (polydeg=3,)) # Prevent long compile time in CI - # 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)) < 15000 + # 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)) < 15000 end end @@ -583,13 +647,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.35026352556630114, 0.8344372248051408, 0.8344372248051408], tspan = (0.0, 0.1), coverage_override = (polydeg=3,)) # Prevent long compile time in CI - # 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 + # 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 @@ -602,13 +666,13 @@ isdir(outdir) && rm(outdir, recursive=true) 0.9757376320946505, 0.12123736788315098, 0.12837436699267113, 0.17793825293524734, 0.03460761690059514], tspan = (0.0, 0.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 + # 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 @@ -621,13 +685,13 @@ isdir(outdir) && rm(outdir, recursive=true) 0.03817506476831778, 0.042847170999492534, 0.03761563456810613, 0.048184237474911844, 0.04114666955364693], tspan = (0.0, 1.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 + # 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 @@ -636,13 +700,13 @@ isdir(outdir) && rm(outdir, recursive=true) 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 + # 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 @@ -651,13 +715,13 @@ isdir(outdir) && rm(outdir, recursive=true) 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 + # 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 @@ -666,13 +730,13 @@ isdir(outdir) && rm(outdir, recursive=true) 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 + # 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 @@ -681,13 +745,13 @@ isdir(outdir) && rm(outdir, recursive=true) 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 + # 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 @@ -696,13 +760,13 @@ isdir(outdir) && rm(outdir, recursive=true) 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 + # 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 @@ -714,13 +778,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.25144373906033013, 0.32881947152723745, 0.3053266801502693, 0.20989755319972866, 0.9927517314507455, 0.1105172121361323, 0.1257708104676617, 0.1628334844841588, 0.02624301627479052]) - # 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 + # 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 From 113ce70b8a9624af3bdbca2542543995af2083a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 31 Oct 2023 11:19:59 +0100 Subject: [PATCH 339/423] format --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 2 +- test/test_structured_2d.jl | 293 ++++++++++----- test/test_tree_2d_euler.jl | 344 ++++++++++++------ test/test_tree_2d_eulermulti.jl | 23 +- test/test_tree_2d_mhd.jl | 46 ++- test/test_unit.jl | 15 +- 6 files changed, 480 insertions(+), 243 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index a1607d8617..ed9c193725 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -385,7 +385,7 @@ end end end end - + # FV-form flux `fhat` in x direction fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index e4d79a19ac..a3fd43a45e 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -235,40 +235,62 @@ 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 - @trixi_testset "elixir_euler_convergence_wavingflag_IDP.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_IDP.jl"), - l2 = [0.3398358793878119, 0.03398358793878129, 0.06796717587756244, 0.008495896984696072], - linf = [0.8360446582060936, 0.08360446582060972, 0.16720893164122444, 0.02090111645397741], - tspan = (0.0, 0.5)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_convergence_wavingflag_IDP.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_convergence_wavingflag_IDP.jl"), + l2=[ + 0.3398358793878119, + 0.03398358793878129, + 0.06796717587756244, + 0.008495896984696072, + ], + linf=[ + 0.8360446582060936, + 0.08360446582060972, + 0.16720893164122444, + 0.02090111645397741, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_convergence_wavingflag_MCL.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_wavingflag_MCL.jl"), - l2 = [0.33983417649330827, 0.033983417649330924, 0.06796683529866161, 0.008495854412336827], - linf = [0.8360446582068146, 0.083604465820679, 0.16720893164136671, 0.02090111645399162], - tspan = (0.0, 0.5)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_convergence_wavingflag_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_convergence_wavingflag_MCL.jl"), + l2=[ + 0.33983417649330827, + 0.033983417649330924, + 0.06796683529866161, + 0.008495854412336827, + ], + linf=[ + 0.8360446582068146, + 0.083604465820679, + 0.16720893164136671, + 0.02090111645399162, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_source_terms.jl" begin +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), # Expected errors are exactly the same as with TreeMesh! l2=[ @@ -425,25 +447,36 @@ 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 - @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [0.00816013114351954, 0.008658251709937477, 0.009351905651482216, 0.027757012781694318], - linf = [0.027225615981281148, 0.040734036539016305, 0.0381940733564341, 0.08080650914262844], - tspan = (0.0, 0.5)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_sc_subcell.jl"), + l2=[ + 0.00816013114351954, + 0.008658251709937477, + 0.009351905651482216, + 0.027757012781694318, + ], + linf=[ + 0.027225615981281148, + 0.040734036539016305, + 0.0381940733564341, + 0.08080650914262844, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin +@trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_waving_flag.jl"), l2=[ @@ -490,42 +523,63 @@ 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 - @trixi_testset "elixir_euler_free_stream_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_sc_subcell.jl"), - l2 = [2.6224749465938795e-14, 1.6175366858083413e-14, 2.358782725951525e-14, 5.910156539173304e-14], - linf = [1.1546319456101628e-14, 1.084687895058778e-13, 1.7050250100680842e-13, 2.0250467969162855e-13], - atol = 1.0e-13, - cells_per_dimension = (8, 8)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_free_stream_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_free_stream_sc_subcell.jl"), + l2=[ + 2.6224749465938795e-14, + 1.6175366858083413e-14, + 2.358782725951525e-14, + 5.910156539173304e-14, + ], + linf=[ + 1.1546319456101628e-14, + 1.084687895058778e-13, + 1.7050250100680842e-13, + 2.0250467969162855e-13, + ], + atol=1.0e-13, + cells_per_dimension=(8, 8)) + # 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)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_free_stream_MCL.jl" begin +@trixi_testset "elixir_euler_free_stream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_MCL.jl"), - l2 = [3.532639560334565e-14, 1.4787576718355913e-14, 2.109573923923632e-14, 2.54649935281524e-14], - linf = [7.993605777301127e-15, 1.1611545058798356e-13, 1.7619239400801234e-13, 2.007283228522283e-13], - atol = 1.0e-13, - cells_per_dimension = (8, 8)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 3.532639560334565e-14, + 1.4787576718355913e-14, + 2.109573923923632e-14, + 2.54649935281524e-14, + ], + linf=[ + 7.993605777301127e-15, + 1.1611545058798356e-13, + 1.7619239400801234e-13, + 2.007283228522283e-13, + ], + atol=1.0e-13, + cells_per_dimension=(8, 8)) + # 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)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin +@trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), surface_flux=FluxRotated(flux_lax_friedrichs), l2=[ @@ -548,64 +602,105 @@ 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 - @trixi_testset "elixir_euler_double_mach.jl" begin +@trixi_testset "elixir_euler_double_mach.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), - l2 = [0.8955457632754655, 6.8117495933240235, 3.2697118944675716, 77.5174041919109], - linf = [10.16165871096883, 133.2522870057006, 38.23157147773949, 1470.3950960145828], - initial_refinement_level = 3, - tspan = (0.0, 0.05)) - end + l2=[ + 0.8955457632754655, + 6.8117495933240235, + 3.2697118944675716, + 77.5174041919109, + ], + linf=[ + 10.16165871096883, + 133.2522870057006, + 38.23157147773949, + 1470.3950960145828, + ], + initial_refinement_level=3, + tspan=(0.0, 0.05)) +end - @trixi_testset "elixir_euler_double_mach_MCL.jl" begin +@trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), - l2 = [0.9266313242695542, 7.071517579972717, 3.2627078543492787, 80.24631724351916], - linf = [14.244598580563007, 138.4745277257612, 38.69633620234036, 1574.6686216469134], - initial_refinement_level = 3, - tspan = (0.0, 0.05)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.9266313242695542, + 7.071517579972717, + 3.2627078543492787, + 80.24631724351916, + ], + linf=[ + 14.244598580563007, + 138.4745277257612, + 38.69633620234036, + 1574.6686216469134, + ], + initial_refinement_level=3, + 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)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), - l2 = [1.2351468819080416, 1.1269856120551724, 1.7239124305681928, 11.715260007491556], - linf = [5.385492532917423, 6.575446146030286, 10.0652310822613, 51.00901293102744], - cells_per_dimension = (8, 12), - tspan = (0.0, 0.5)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_shock_upstream_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_shock_upstream_sc_subcell.jl"), + l2=[ + 1.2351468819080416, + 1.1269856120551724, + 1.7239124305681928, + 11.715260007491556, + ], + linf=[ + 5.385492532917423, + 6.575446146030286, + 10.0652310822613, + 51.00901293102744, + ], + cells_per_dimension=(8, 12), + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 - end - end + end +end - @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin +@trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), - l2 = [1.2607430289877726, 1.1565837325291355, 1.7791790302458714, 11.891223800389232], - linf = [5.68876088477983, 8.165554425950146, 10.859100194836538, 50.25822408989214], - cells_per_dimension = (8, 12), - tspan = (0.0, 0.5)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 1.2607430289877726, + 1.1565837325291355, + 1.7791790302458714, + 11.891223800389232, + ], + linf=[ + 5.68876088477983, + 8.165554425950146, + 10.859100194836538, + 50.25822408989214, + ], + cells_per_dimension=(8, 12), + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 - end - end + end +end @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 081076ef0f..04e7254206 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -31,22 +31,33 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 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 - @trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), - l2 = [2.0633069593983843e-6, 1.9337331005472223e-6, 1.9337331005227536e-6, 5.885362117543159e-6], - linf = [1.636984098429828e-5, 1.5579038690871627e-5, 1.557903868998345e-5, 5.260532107742577e-5]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_source_terms_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_sc_subcell.jl"), + l2=[ + 2.0633069593983843e-6, + 1.9337331005472223e-6, + 1.9337331005227536e-6, + 5.885362117543159e-6, + ], + linf=[ + 1.636984098429828e-5, + 1.5579038690871627e-5, + 1.557903868998345e-5, + 5.260532107742577e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), @@ -69,22 +80,32 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 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 - @trixi_testset "elixir_euler_convergence_IDP.jl" begin +@trixi_testset "elixir_euler_convergence_IDP.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_IDP.jl"), - l2 = [0.1289984161854359, 0.012899841618543363, 0.025799683237087086, 0.003224960404636081], - linf = [0.9436588685021441, 0.0943658868502173, 0.1887317737004306, 0.02359147170911058]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.1289984161854359, + 0.012899841618543363, + 0.025799683237087086, + 0.003224960404636081, + ], + linf=[ + 0.9436588685021441, + 0.0943658868502173, + 0.1887317737004306, + 0.02359147170911058, + ]) + # 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)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_density_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), @@ -421,42 +442,62 @@ 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 - @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin +@trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), - l2 = [0.30785094769124677, 0.17599603017990473, 0.17594201496603085, 0.6141202024471839], - linf = [1.2971828380703805, 1.1057475500114755, 1.105770653844522, 2.4364101844067916], - tspan = (0.0, 0.5), - initial_refinement_level = 4, - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.30785094769124677, + 0.17599603017990473, + 0.17594201496603085, + 0.6141202024471839, + ], + linf=[ + 1.2971828380703805, + 1.1057475500114755, + 1.105770653844522, + 2.4364101844067916, + ], + tspan=(0.0, 0.5), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end - @trixi_testset "elixir_euler_blast_wave_MCL.jl" begin +@trixi_testset "elixir_euler_blast_wave_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_MCL.jl"), - l2 = [0.32716628280821736, 0.17711362716405113, 0.17710881738119433, 0.6192141753914343], - linf = [1.3147680231795071, 1.1313232952582144, 1.1308868661560831, 2.4962119219206], - tspan = (0.0, 0.5), - initial_refinement_level = 4, - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.32716628280821736, + 0.17711362716405113, + 0.17710881738119433, + 0.6192141753914343, + ], + linf=[ + 1.3147680231795071, + 1.1313232952582144, + 1.1308868661560831, + 2.4962119219206, + ], + tspan=(0.0, 0.5), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), @@ -481,42 +522,63 @@ 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 - @trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), - l2 = [0.47651273561515994, 0.16605194156429376, 0.16605194156447747, 0.6184646142923547], - linf = [2.559717182592356, 1.3594817545576394, 1.3594817545666105, 6.451896959781657], - tspan = (0.0, 1.0), - initial_refinement_level=4, - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2=[ + 0.47651273561515994, + 0.16605194156429376, + 0.16605194156447747, + 0.6184646142923547, + ], + linf=[ + 2.559717182592356, + 1.3594817545576394, + 1.3594817545666105, + 6.451896959781657, + ], + tspan=(0.0, 1.0), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end - @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin +@trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_MCL.jl"), - l2 = [0.4740321851943766, 0.15889871334104985, 0.15889871334104988, 0.6190405536267991], - linf = [4.011954283668753, 1.8527131099524292, 1.8527131099524277, 6.465833729130187], - tspan = (0.0, 1.0), - initial_refinement_level=4, - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.4740321851943766, + 0.15889871334104985, + 0.15889871334104988, + 0.6190405536267991, + ], + linf=[ + 4.011954283668753, + 1.8527131099524292, + 1.8527131099524277, + 6.465833729130187, + ], + tspan=(0.0, 1.0), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, @@ -691,42 +753,64 @@ 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 - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), - l2 = [0.055703165296633834, 0.032987233605927, 0.05224472051711956, 0.08011565264331237], - linf = [0.24091018397460595, 0.1660190071332282, 0.12356154893467916, 0.2695167937393226], - tspan = (0.0, 0.2), - initial_refinement_level=5, - coverage_override = (maxiters=2,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), + l2=[ + 0.055703165296633834, + 0.032987233605927, + 0.05224472051711956, + 0.08011565264331237, + ], + linf=[ + 0.24091018397460595, + 0.1660190071332282, + 0.12356154893467916, + 0.2695167937393226, + ], + tspan=(0.0, 0.2), + initial_refinement_level=5, + coverage_override=(maxiters = 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)) < 15000 - end - end + end +end - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_MCL.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_MCL.jl"), - l2 = [0.055703165296633834, 0.032987233605927, 0.05224472051711956, 0.08011565264331237], - linf = [0.24091018397460595, 0.1660190071332282, 0.12356154893467916, 0.2695167937393226], - tspan = (0.0, 0.2), - initial_refinement_level=5, - coverage_override = (maxiters=2,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let +@trixi_testset "elixir_euler_kelvin_helmholtz_instability_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability_MCL.jl"), + l2=[ + 0.055703165296633834, + 0.032987233605927, + 0.05224472051711956, + 0.08011565264331237, + ], + linf=[ + 0.24091018397460595, + 0.1660190071332282, + 0.12356154893467916, + 0.2695167937393226, + ], + tspan=(0.0, 0.2), + initial_refinement_level=5, + coverage_override=(maxiters = 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)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, @@ -814,42 +898,62 @@ 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 - @trixi_testset "elixir_euler_astro_jet_subcell.jl" begin +@trixi_testset "elixir_euler_astro_jet_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_subcell.jl"), - l2 = [0.4186473232186195, 341.42386623555944, 12.913743102619245, 135260.31735534978], - linf = [6.594617349637199, 5225.251243383396, 417.4788228266706, 2.0263599311276933e6], - initial_refinement_level=5, - tspan = (0.0, 1.0e-4), - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.4186473232186195, + 341.42386623555944, + 12.913743102619245, + 135260.31735534978, + ], + linf=[ + 6.594617349637199, + 5225.251243383396, + 417.4788228266706, + 2.0263599311276933e6, + ], + initial_refinement_level=5, + tspan=(0.0, 1.0e-4), + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end - @trixi_testset "elixir_euler_astro_jet_MCL.jl" begin +@trixi_testset "elixir_euler_astro_jet_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_MCL.jl"), - l2 = [0.4142490642847159, 339.10045752248817, 12.41716316125269, 134277.32794840127], - linf = [5.649893737038036, 4628.887032664001, 373.39317079274724, 1.8133961097673306e6], - initial_refinement_level=5, - tspan = (0.0, 1.0e-4), - coverage_override = (maxiters=6,)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let + l2=[ + 0.4142490642847159, + 339.10045752248817, + 12.41716316125269, + 134277.32794840127, + ], + linf=[ + 5.649893737038036, + 4628.887032664001, + 373.39317079274724, + 1.8133961097673306e6, + ], + initial_refinement_level=5, + tspan=(0.0, 1.0e-4), + coverage_override=(maxiters = 6,)) + # 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)) < 15000 - end - end + end +end @trixi_testset "elixir_euler_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index a7bcc15f83..c4ae285090 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -76,11 +76,24 @@ end end @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin -@test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), - l2 = [76.59096367977872, 1.9879932386864356, 59851.34515039375, 0.18710988181124935, 0.010631432251136084], - linf = [212.71245739310544, 27.399221359958894, 158389.9681231281, 0.6524718882809865, 0.10630137919864985], - initial_refinement_level = 3, - tspan = (0.0, 0.001)) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), + l2=[ + 76.59096367977872, + 1.9879932386864356, + 59851.34515039375, + 0.18710988181124935, + 0.010631432251136084, + ], + linf=[ + 212.71245739310544, + 27.399221359958894, + 158389.9681231281, + 0.6524718882809865, + 0.10630137919864985, + ], + initial_refinement_level=3, + tspan=(0.0, 0.001)) end @trixi_testset "elixir_eulermulti_ec.jl" begin diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index aed29aebd7..6e2f8852b5 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -329,20 +329,40 @@ end end end - @trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin +@trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), - l2 = [3.2064026219236076e-02, 7.2461094392606618e-02, 7.2380202888062711e-02, 0.0000000000000000e+00, 8.6293936673145932e-01, 8.4091669534557805e-03, 5.2156364913231732e-03, 0.0000000000000000e+00, 2.0786952301129021e-04], - linf = [3.8778760255775635e-01, 9.4666683953698927e-01, 9.4618924645661928e-01, 0.0000000000000000e+00, 1.0980297261521951e+01, 1.0264404591009069e-01, 1.0655686942176350e-01, 0.0000000000000000e+00, 6.1013422157115546e-03], - tspan = (0.0, 0.003)) - # 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)) < 15000 - end - end + l2=[ + 3.2064026219236076e-02, + 7.2461094392606618e-02, + 7.2380202888062711e-02, + 0.0000000000000000e+00, + 8.6293936673145932e-01, + 8.4091669534557805e-03, + 5.2156364913231732e-03, + 0.0000000000000000e+00, + 2.0786952301129021e-04, + ], + linf=[ + 3.8778760255775635e-01, + 9.4666683953698927e-01, + 9.4618924645661928e-01, + 0.0000000000000000e+00, + 1.0980297261521951e+01, + 1.0264404591009069e-01, + 1.0655686942176350e-01, + 0.0000000000000000e+00, + 6.1013422157115546e-03, + ], + tspan=(0.0, 0.003)) + # 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)) < 15000 + end +end end end # module diff --git a/test/test_unit.jl b/test/test_unit.jl index a82b17b82d..29d6c4dee5 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -296,9 +296,11 @@ end end Trixi.move_connectivity!(c::MyContainer, first, last, destination) = c Trixi.delete_connectivity!(c::MyContainer, first, last) = c - Trixi.reset_data_structures!(c::MyContainer) = (c.data = Vector{Int}(undef, - c.capacity + 1); - c) + function Trixi.reset_data_structures!(c::MyContainer) + (c.data = Vector{Int}(undef, + c.capacity + 1); + c) + end function Base.:(==)(c1::MyContainer, c2::MyContainer) return (c1.capacity == c2.capacity && c1.length == c2.length && @@ -414,10 +416,13 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ("variable",), 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) + indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ("variable",), 0.1, true, + true, true, "cache", 1, (1.0, 1.0), 1.0, true, + 1.0, nothing) @test_nowarn show(stdout, indicator_idp) - indicator_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, 1.0, true, true, 1.0, nothing, true) + indicator_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, + 1.0, true, true, 1.0, nothing, true) @test_nowarn show(stdout, indicator_mcl) # TODO: TrixiShallowWater: move unit test From 400afb781ecc62a78d0c0525becc450e76d7b815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 31 Oct 2023 14:48:16 +0100 Subject: [PATCH 340/423] Updated the reference solution of some subcell limiting tests --- test/test_structured_2d.jl | 24 ++++++++++++------------ test/test_tree_2d_euler.jl | 16 ++++++++-------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index a3fd43a45e..405709242c 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -454,16 +454,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), l2=[ - 0.00816013114351954, - 0.008658251709937477, - 0.009351905651482216, - 0.027757012781694318, + 0.008160127825550706, + 0.008658254974279198, + 0.009351901915798305, + 0.0277570186711509, ], linf=[ - 0.027225615981281148, - 0.040734036539016305, - 0.0381940733564341, - 0.08080650914262844, + 0.027225588710793502, + 0.040734035190958195, + 0.03819406890281263, + 0.08080654623152705, ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -654,15 +654,15 @@ end "elixir_euler_shock_upstream_sc_subcell.jl"), l2=[ 1.2351468819080416, - 1.1269856120551724, + 1.1269856428294935, 1.7239124305681928, 11.715260007491556, ], linf=[ - 5.385492532917423, + 5.385493056976312, 6.575446146030286, - 10.0652310822613, - 51.00901293102744, + 10.06523457762742, + 51.00903155017642, ], cells_per_dimension=(8, 12), tspan=(0.0, 0.5)) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 04e7254206..8aa7d8b95d 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -448,16 +448,16 @@ end @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), l2=[ - 0.30785094769124677, - 0.17599603017990473, - 0.17594201496603085, - 0.6141202024471839, + 0.30785002807815187, + 0.1759956703391451, + 0.1759417566220675, + 0.6141201710105174, ], linf=[ - 1.2971828380703805, - 1.1057475500114755, - 1.105770653844522, - 2.4364101844067916, + 1.2971792413978331, + 1.1057407237412735, + 1.1057665512872346, + 2.436409926521213, ], tspan=(0.0, 0.5), initial_refinement_level=4, From 30b33fd7e90899fc05ed233f72c5af3bd20a03b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 31 Oct 2023 16:30:09 +0100 Subject: [PATCH 341/423] Add memory allocation test Co-authored-by: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> --- test/test_tree_2d_eulermulti.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index c4ae285090..77cf3a5d7d 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -94,6 +94,14 @@ end ], initial_refinement_level=3, tspan=(0.0, 0.001)) + # 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)) < 15000 + end end @trixi_testset "elixir_eulermulti_ec.jl" begin From 6d0164319ea0f532e7ef7570c58182e5da6ba72a Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 2 Nov 2023 11:43:01 +0100 Subject: [PATCH 342/423] Add subcell allocation tests; Add changes to minmax limiter --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 10 +++++----- test/test_tree_2d_euler.jl | 16 ++++++++++++++++ test/test_tree_2d_eulermulti.jl | 8 ++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 02378caa67..9b289a5e2c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -164,7 +164,7 @@ end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) - (; antidiffusive_flux1, antidiffusive_flux2) = cache.antidiffusive_fluxes + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes (; inverse_weights) = dg.basis (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -188,13 +188,13 @@ end # Calculate Pp and Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = inverse_weights[i] * - antidiffusive_flux1[variable, i, j, element] + antidiffusive_flux1_R[variable, i, j, element] val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1[variable, i + 1, j, element] + antidiffusive_flux1_L[variable, i + 1, j, element] val_flux2_local = inverse_weights[j] * - antidiffusive_flux2[variable, i, j, element] + antidiffusive_flux2_R[variable, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2[variable, i, j + 1, element] + antidiffusive_flux2_L[variable, i, j + 1, element] Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 44b9ea0dea..28521ccfdf 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -413,6 +413,14 @@ end tspan=(0.0, 0.5), initial_refinement_level=4, coverage_override=(maxiters = 6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @@ -459,6 +467,14 @@ end tspan=(0.0, 1.0), initial_refinement_level=4, coverage_override=(maxiters = 6,)) + # 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)) < 15000 + end end @trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index dac8329bed..30d52b37b9 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -94,6 +94,14 @@ end ], initial_refinement_level=3, tspan=(0.0, 0.001)) + # 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)) < 15000 + end end @trixi_testset "elixir_eulermulti_ec.jl" begin From 306fb19618bb9add2b32bfeaf70f7bfbe8f67a10 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 2 Nov 2023 11:45:07 +0100 Subject: [PATCH 343/423] Undo changes in elixirs --- ...xir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 4e5ec4eb8d..9823733482 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -20,7 +20,7 @@ function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMultic # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf # typical domain is rectangular, we change it to a square, as Trixi can only do squares - (; gas_constants) = equations + @unpack gas_constants = equations # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving delta = 0.03 diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 69b852e2c8..98ac60db11 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -20,7 +20,7 @@ function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMultic # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf # typical domain is rectangular, we change it to a square, as Trixi can only do squares - (; gas_constants) = equations + @unpack gas_constants = equations # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving delta = 0.03 From 5adf14c9d8bbb5cd043e36ad8067dfcd22880cb4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 2 Nov 2023 16:40:52 +0100 Subject: [PATCH 344/423] Implement suggestions --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9b289a5e2c..ca5fa5a270 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -27,7 +27,7 @@ end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; kwargs...) - (; alpha) = limiter.cache.subcell_limiter_coefficients + @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha .= zero(eltype(alpha)) if limiter.local_minmax @@ -39,7 +39,7 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE end # Calculate alpha1 and alpha2 - (; alpha1, alpha2) = limiter.cache.subcell_limiter_coefficients + @unpack alpha1, alpha2 = limiter.cache.subcell_limiter_coefficients @threaded for element in eachelement(dg, semi.cache) for j in eachnode(dg), i in 2:nnodes(dg) alpha1[i, j, element] = max(alpha[i - 1, j, element], alpha[i, j, element]) @@ -56,7 +56,7 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE return nothing end -@inline function calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) +@inline function calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) @@ -88,10 +88,10 @@ end end # Values at element boundary - calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, mesh) + calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, mesh) end -@inline function calc_bounds_2sided_interface!(var_min, var_max, variable, u, t, semi, +@inline function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; boundary_conditions) = semi @@ -170,7 +170,7 @@ end (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] var_max = variable_bounds[Symbol(string(variable), "_max")] - calc_bounds_2sided!(var_min, var_max, variable, u, t, semi) + calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] From 29ed6cea16b30274c7eddc54420bad935629596b Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 3 Nov 2023 10:08:06 +0100 Subject: [PATCH 345/423] Skip positivity limiting if local limiting is more restrictive --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index ca5fa5a270..d2b517ab3f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -92,7 +92,7 @@ end end @inline function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, - mesh::TreeMesh2D) + mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; boundary_conditions) = semi # Calc bounds at interfaces and periodic boundaries @@ -249,12 +249,14 @@ end end # Compute bound - if limiter.local_minmax - var_min[i, j, element] = max(var_min[i, j, element], - positivity_correction_factor * var) - else - var_min[i, j, element] = positivity_correction_factor * var + if limiter.local_minmax && + variable in limiter.local_minmax_variables_cons && + var_min[i, j, element] >= positivity_correction_factor * var + # Local limiting is more restrictive that positivity limiting + # => Skip positivity limiting for this node + continue end + var_min[i, j, element] = positivity_correction_factor * var # Real one-sided Zalesak-type limiter # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" From ea226d580c9d3cdbca6f6877b3f63e2a3549955f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 3 Nov 2023 14:45:23 +0100 Subject: [PATCH 346/423] Reduce allocations --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index d2b517ab3f..bc69e55f26 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -168,8 +168,9 @@ end (; inverse_weights) = dg.basis (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol(string(variable), "_min")] - var_max = variable_bounds[Symbol(string(variable), "_max")] + variable_string = string(variable) + var_min = variable_bounds[Symbol(variable_string, "_min")] + var_max = variable_bounds[Symbol(variable_string, "_max")] calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) @threaded for element in eachelement(dg, semi.cache) From 1c845f6883f53e7bdb1dfc4af8882c776d0e6f64 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 3 Nov 2023 16:13:52 +0100 Subject: [PATCH 347/423] Add unintentionally removed lines --- src/callbacks_stage/subcell_bounds_check_2d.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 7e9c241c28..963f9a938a 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -58,6 +58,9 @@ end if positivity for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end key = Symbol(string(v), "_min") deviation = idp_bounds_delta[key] for element in eachelement(solver, cache), j in eachnode(solver), @@ -102,6 +105,9 @@ end if positivity for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) end for variable in limiter.positivity_variables_nonlinear From cb899fe34c8392f3061a98498195a0b08942c0de Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Mon, 6 Nov 2023 12:25:28 +0100 Subject: [PATCH 348/423] Revise bounds check for MCL (#118) * Revise bounds check for MCL * Rename `idp_bounds_delta` for MCL to `mcl_bounds_delta` * Remove comment * Fix allocs (#1695) * Fix allocs * remove unnecessary code * rerun fmt * format * Allocation tests dgmulti 2d (#1698) * HLLE CEE 2D3D NonCartesian Meshes (#1692) * HLLE CEE 2D3D NonCartesian Meshes * format * hlle via hll * format test * format test * format * do not export hlle * Correct test vals * test values CI * Update src/equations/compressible_euler_2d.jl Co-authored-by: Hendrik Ranocha * Update src/equations/compressible_euler_1d.jl Co-authored-by: Hendrik Ranocha * Update src/equations/compressible_euler_2d.jl Co-authored-by: Hendrik Ranocha * Update src/equations/compressible_euler_3d.jl Co-authored-by: Hendrik Ranocha * Update src/equations/compressible_euler_3d.jl Co-authored-by: Hendrik Ranocha * apply suggestions * additional sentence * Fix typo * typos * correct test vals --------- Co-authored-by: Hendrik Ranocha * Bump crate-ci/typos from 1.16.15 to 1.16.21 (#1700) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.15 to 1.16.21. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/v1.16.15...v1.16.21) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add NumFOCUS + ACTRIX to acknowledgments (#1697) * Add NumFOCUS + ACTRIX to acknowledgments * Try to avoid spaces * Another try to avoid gaps between images * Hopefully fix image alignment in docs * Try new logo formats * Use smaller DUBS logo and add DUBS funding statement * Add markdown-based table for logos in docs * Try another table approach * Hopefully get a layout that finally *works*... * Arrrrrrgggggghhhhh * format examples (#1531) * format examples * check formatting of examples in CI * update style guide * fix weird formatting * fix formatting of binary operators * format again * Update differentiable_programming.jl (#1704) * Format subcell elixirs * Add warning for missing bounds check for entropy limiter (MCL) --------- Signed-off-by: dependabot[bot] Co-authored-by: Daniel Doehring Co-authored-by: Hendrik Ranocha Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Michael Schlottke-Lakemper Co-authored-by: ArseniyKholod <119304909+ArseniyKholod@users.noreply.github.com> --- .github/workflows/FormatCheck.yml | 2 +- README.md | 45 +- .../src/files/differentiable_programming.jl | 4 +- docs/src/index.md | 55 ++- docs/src/styleguide.md | 18 +- .../dgmulti_1d/elixir_advection_gauss_sbp.jl | 13 +- .../dgmulti_1d/elixir_euler_fdsbp_periodic.jl | 23 +- examples/dgmulti_1d/elixir_euler_flux_diff.jl | 12 +- .../dgmulti_2d/elixir_advection_diffusion.jl | 38 +- .../elixir_advection_diffusion_nonperiodic.jl | 54 +-- .../elixir_advection_diffusion_periodic.jl | 12 +- examples/dgmulti_2d/elixir_euler_bilinear.jl | 29 +- .../elixir_euler_brown_minion_vortex.jl | 32 +- examples/dgmulti_2d/elixir_euler_curved.jl | 22 +- .../dgmulti_2d/elixir_euler_fdsbp_periodic.jl | 23 +- examples/dgmulti_2d/elixir_euler_hohqmesh.jl | 27 +- ...ixir_euler_kelvin_helmholtz_instability.jl | 35 +- ...lixir_euler_rayleigh_taylor_instability.jl | 58 +-- .../dgmulti_2d/elixir_euler_shockcapturing.jl | 27 +- .../elixir_euler_shockcapturing_curved.jl | 31 +- .../elixir_euler_triangulate_pkg_mesh.jl | 12 +- examples/dgmulti_2d/elixir_euler_weakform.jl | 21 +- .../elixir_euler_weakform_periodic.jl | 10 +- .../dgmulti_2d/elixir_mhd_reflective_wall.jl | 93 ++-- .../dgmulti_2d/elixir_mhd_weak_blast_wave.jl | 20 +- .../elixir_mhd_weak_blast_wave_SBP.jl | 17 +- .../elixir_navierstokes_convergence.jl | 300 ++++++------ .../elixir_navierstokes_convergence_curved.jl | 307 +++++++------ .../elixir_navierstokes_lid_driven_cavity.jl | 38 +- .../elixir_shallowwater_source_terms.jl | 19 +- .../elixir_advection_tensor_wedge.jl | 22 +- examples/dgmulti_3d/elixir_euler_curved.jl | 26 +- .../dgmulti_3d/elixir_euler_fdsbp_periodic.jl | 21 +- .../elixir_euler_taylor_green_vortex.jl | 45 +- examples/dgmulti_3d/elixir_euler_weakform.jl | 16 +- .../elixir_euler_weakform_periodic.jl | 10 +- .../elixir_navierstokes_convergence.jl | 401 ++++++++-------- .../elixir_navierstokes_convergence_curved.jl | 409 +++++++++-------- ...elixir_navierstokes_taylor_green_vortex.jl | 50 +- ...ixir_advection_amr_solution_independent.jl | 149 +++--- .../elixir_advection_amr_unstructured_flag.jl | 66 ++- .../p4est_2d_dgsem/elixir_advection_basic.jl | 32 +- ..._advection_diffusion_nonperiodic_curved.jl | 54 +-- .../elixir_advection_diffusion_periodic.jl | 30 +- ...xir_advection_diffusion_periodic_curved.jl | 34 +- .../elixir_advection_extended.jl | 50 +- .../elixir_advection_nonconforming_flag.jl | 55 +-- .../elixir_advection_restart.jl | 10 +- .../elixir_advection_unstructured_flag.jl | 44 +- .../elixir_euler_blast_wave_amr.jl | 96 ++-- .../elixir_euler_double_mach_amr.jl | 140 +++--- .../elixir_euler_forward_step_amr.jl | 152 ++++--- .../elixir_euler_free_stream.jl | 70 +-- examples/p4est_2d_dgsem/elixir_euler_sedov.jl | 79 ++-- .../elixir_euler_shockcapturing_ec.jl | 44 +- ...e_terms_nonconforming_unstructured_flag.jl | 70 +-- .../elixir_euler_supersonic_cylinder.jl | 102 +++-- .../elixir_euler_wall_bc_amr.jl | 82 ++-- .../elixir_eulergravity_convergence.jl | 60 ++- .../elixir_linearizedeuler_gaussian_source.jl | 55 +-- .../p4est_2d_dgsem/elixir_mhd_alfven_wave.jl | 29 +- examples/p4est_2d_dgsem/elixir_mhd_rotor.jl | 126 +++--- .../elixir_navierstokes_convergence.jl | 307 +++++++------ ...ir_navierstokes_convergence_nonperiodic.jl | 308 +++++++------ .../elixir_navierstokes_lid_driven_cavity.jl | 54 ++- .../elixir_shallowwater_source_terms.jl | 31 +- .../p4est_3d_dgsem/elixir_advection_amr.jl | 48 +- ...lixir_advection_amr_unstructured_curved.jl | 103 ++--- .../p4est_3d_dgsem/elixir_advection_basic.jl | 35 +- .../elixir_advection_cubed_sphere.jl | 31 +- .../elixir_advection_nonconforming.jl | 54 +-- .../elixir_advection_restart.jl | 13 +- .../elixir_advection_unstructured_curved.jl | 83 ++-- .../elixir_euler_baroclinic_instability.jl | 370 +++++++-------- ...lixir_euler_circular_wind_nonconforming.jl | 126 +++--- examples/p4est_3d_dgsem/elixir_euler_ec.jl | 81 ++-- .../elixir_euler_free_stream.jl | 104 +++-- .../elixir_euler_free_stream_extruded.jl | 86 ++-- examples/p4est_3d_dgsem/elixir_euler_sedov.jl | 86 ++-- ..._euler_source_terms_nonconforming_earth.jl | 108 +++-- ...terms_nonconforming_unstructured_curved.jl | 107 ++--- .../elixir_euler_source_terms_nonperiodic.jl | 52 +-- ...euler_source_terms_nonperiodic_hohqmesh.jl | 45 +- .../elixir_mhd_alfven_wave_nonconforming.jl | 58 +-- .../elixir_mhd_shockcapturing_amr.jl | 124 ++--- .../elixir_navierstokes_convergence.jl | 420 ++++++++--------- ...elixir_navierstokes_taylor_green_vortex.jl | 70 +-- .../elixir_euler_convergence.jl | 31 +- .../elixir_eulergravity_convergence.jl | 54 +-- .../elixir_eulergravity_jeans_instability.jl | 164 +++---- .../elixir_eulergravity_sedov_blast_wave.jl | 219 ++++----- .../elixir_hypdiff_convergence.jl | 45 +- examples/special_elixirs/elixir_euler_ad.jl | 78 ++-- .../elixir_advection_basic.jl | 24 +- .../elixir_advection_nonperiodic.jl | 35 +- .../elixir_advection_shockcapturing.jl | 81 ++-- .../structured_1d_dgsem/elixir_euler_sedov.jl | 77 ++-- .../elixir_euler_source_terms.jl | 31 +- .../elixir_euler_source_terms_nonperiodic.jl | 39 +- .../elixir_advection_basic.jl | 26 +- .../elixir_advection_coupled.jl | 74 +-- .../elixir_advection_extended.jl | 34 +- .../elixir_advection_free_stream.jl | 41 +- .../elixir_advection_nonperiodic.jl | 32 +- .../elixir_advection_parallelogram.jl | 57 ++- .../elixir_advection_restart.jl | 7 +- .../elixir_advection_rotated.jl | 69 ++- .../elixir_advection_waving_flag.jl | 29 +- ...elixir_euler_convergence_wavingflag_IDP.jl | 47 +- ...elixir_euler_convergence_wavingflag_MCL.jl | 46 +- .../elixir_euler_double_mach.jl | 52 ++- .../elixir_euler_double_mach_MCL.jl | 59 +-- .../structured_2d_dgsem/elixir_euler_ec.jl | 38 +- .../elixir_euler_free_stream.jl | 39 +- .../elixir_euler_free_stream_MCL.jl | 66 +-- .../elixir_euler_free_stream_sc_subcell.jl | 63 ++- ...lixir_euler_rayleigh_taylor_instability.jl | 72 ++- .../structured_2d_dgsem/elixir_euler_sedov.jl | 79 ++-- .../elixir_euler_shock_upstream_MCL.jl | 111 ++--- .../elixir_euler_shock_upstream_sc_subcell.jl | 102 +++-- .../elixir_euler_source_terms.jl | 26 +- .../elixir_euler_source_terms_nonperiodic.jl | 41 +- ...elixir_euler_source_terms_parallelogram.jl | 26 +- .../elixir_euler_source_terms_rotated.jl | 105 +++-- .../elixir_euler_source_terms_sc_subcell.jl | 40 +- .../elixir_euler_source_terms_waving_flag.jl | 30 +- .../elixir_eulerpolytropic_ec.jl | 38 +- .../elixir_hypdiff_harmonic_nonperiodic.jl | 72 ++- .../elixir_hypdiff_nonperiodic.jl | 57 ++- .../elixir_mhd_alfven_wave.jl | 62 +-- examples/structured_2d_dgsem/elixir_mhd_ec.jl | 88 ++-- .../elixir_mhd_ec_shockcapturing.jl | 35 +- .../elixir_shallowwater_conical_island.jl | 75 +-- .../elixir_shallowwater_parabolic_bowl.jl | 80 ++-- .../elixir_shallowwater_source_terms.jl | 31 +- .../elixir_shallowwater_well_balanced.jl | 88 ++-- ...ixir_shallowwater_well_balanced_wet_dry.jl | 163 +++---- .../elixir_advection_basic.jl | 30 +- .../elixir_advection_free_stream.jl | 58 +-- .../elixir_advection_nonperiodic_curved.jl | 72 +-- .../elixir_advection_restart.jl | 13 +- .../structured_3d_dgsem/elixir_euler_ec.jl | 63 +-- .../elixir_euler_free_stream.jl | 69 +-- .../structured_3d_dgsem/elixir_euler_sedov.jl | 88 ++-- .../elixir_euler_source_terms.jl | 28 +- ...r_euler_source_terms_nonperiodic_curved.jl | 85 ++-- .../elixir_mhd_alfven_wave.jl | 37 +- examples/structured_3d_dgsem/elixir_mhd_ec.jl | 67 +-- .../elixir_mhd_ec_shockcapturing.jl | 71 +-- .../elixir_eulergravity_convergence.jl | 39 +- .../t8code_2d_dgsem/elixir_mhd_alfven_wave.jl | 28 +- .../elixir_shallowwater_source_terms.jl | 25 +- .../tree_1d_dgsem/elixir_advection_amr.jl | 47 +- .../elixir_advection_amr_nonperiodic.jl | 53 +-- .../tree_1d_dgsem/elixir_advection_basic.jl | 30 +- .../elixir_advection_diffusion.jl | 68 +-- .../elixir_advection_extended.jl | 40 +- .../elixir_advection_finite_volume.jl | 21 +- .../tree_1d_dgsem/elixir_burgers_basic.jl | 35 +- .../elixir_burgers_linear_stability.jl | 36 +- .../elixir_burgers_rarefaction.jl | 61 ++- .../tree_1d_dgsem/elixir_burgers_shock.jl | 57 ++- .../tree_1d_dgsem/elixir_euler_blast_wave.jl | 77 ++-- ...blast_wave_neuralnetwork_perssonperaire.jl | 89 ++-- ...r_blast_wave_neuralnetwork_rayhesthaven.jl | 89 ++-- .../elixir_euler_convergence_pure_fv.jl | 37 +- .../elixir_euler_density_wave.jl | 30 +- examples/tree_1d_dgsem/elixir_euler_ec.jl | 33 +- .../tree_1d_dgsem/elixir_euler_positivity.jl | 101 ++--- .../elixir_euler_sedov_blast_wave.jl | 100 ++-- .../elixir_euler_sedov_blast_wave_pure_fv.jl | 86 ++-- .../elixir_euler_shockcapturing.jl | 43 +- .../elixir_euler_source_terms.jl | 35 +- .../elixir_euler_source_terms_nonperiodic.jl | 43 +- .../elixir_eulergravity_convergence.jl | 54 ++- .../elixir_eulermulti_convergence_ec.jl | 37 +- .../elixir_eulermulti_convergence_es.jl | 37 +- .../tree_1d_dgsem/elixir_eulermulti_ec.jl | 38 +- .../tree_1d_dgsem/elixir_eulermulti_es.jl | 42 +- ..._eulermulti_two_interacting_blast_waves.jl | 98 ++-- .../elixir_hypdiff_harmonic_nonperiodic.jl | 63 ++- .../elixir_hypdiff_nonperiodic.jl | 38 +- .../tree_1d_dgsem/elixir_mhd_alfven_wave.jl | 45 +- .../elixir_mhd_briowu_shock_tube.jl | 91 ++-- examples/tree_1d_dgsem/elixir_mhd_ec.jl | 35 +- .../elixir_mhd_ryujones_shock_tube.jl | 71 ++- .../elixir_mhd_shu_osher_shock_tube.jl | 128 +++--- .../elixir_mhd_torrilhon_shock_tube.jl | 73 ++- .../elixir_mhdmulti_briowu_shock_tube.jl | 122 ++--- .../elixir_mhdmulti_convergence.jl | 36 +- examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl | 33 +- examples/tree_1d_dgsem/elixir_mhdmulti_es.jl | 37 +- ...lixir_navierstokes_convergence_periodic.jl | 166 +++---- .../elixir_navierstokes_convergence_walls.jl | 212 ++++----- ...ixir_navierstokes_convergence_walls_amr.jl | 226 ++++----- .../elixir_shallowwater_beach.jl | 100 ++-- .../tree_1d_dgsem/elixir_shallowwater_ec.jl | 63 +-- .../elixir_shallowwater_parabolic_bowl.jl | 82 ++-- .../elixir_shallowwater_shock_capturing.jl | 83 ++-- .../elixir_shallowwater_source_terms.jl | 30 +- ...xir_shallowwater_source_terms_dirichlet.jl | 28 +- ...lixir_shallowwater_twolayer_convergence.jl | 32 +- .../elixir_shallowwater_twolayer_dam_break.jl | 71 +-- ...xir_shallowwater_twolayer_well_balanced.jl | 42 +- .../elixir_shallowwater_well_balanced.jl | 57 +-- ..._shallowwater_well_balanced_nonperiodic.jl | 48 +- ...ixir_shallowwater_well_balanced_wet_dry.jl | 141 +++--- .../tree_1d_fdsbp/elixir_advection_upwind.jl | 12 +- .../elixir_advection_upwind_periodic.jl | 12 +- .../tree_1d_fdsbp/elixir_burgers_basic.jl | 40 +- .../elixir_burgers_linear_stability.jl | 39 +- .../tree_1d_fdsbp/elixir_euler_convergence.jl | 40 +- .../elixir_euler_density_wave.jl | 36 +- .../elixir_acoustics_convergence.jl | 31 +- .../tree_2d_dgsem/elixir_acoustics_gauss.jl | 27 +- .../elixir_acoustics_gauss_wall.jl | 40 +- .../elixir_acoustics_gaussian_source.jl | 53 ++- .../elixir_acoustics_monopole.jl | 134 +++--- .../tree_2d_dgsem/elixir_advection_amr.jl | 47 +- .../elixir_advection_amr_coarsen_twice.jl | 69 ++- .../elixir_advection_amr_nonperiodic.jl | 50 +- .../elixir_advection_amr_refine_twice.jl | 69 ++- ...ixir_advection_amr_solution_independent.jl | 141 +++--- .../elixir_advection_amr_visualization.jl | 60 ++- .../tree_2d_dgsem/elixir_advection_basic.jl | 30 +- .../elixir_advection_callbacks.jl | 132 +++--- .../elixir_advection_diffusion.jl | 49 +- .../elixir_advection_diffusion_nonperiodic.jl | 48 +- .../elixir_advection_extended.jl | 40 +- .../tree_2d_dgsem/elixir_advection_mortar.jl | 40 +- .../tree_2d_dgsem/elixir_advection_restart.jl | 10 +- .../elixir_advection_timeintegration.jl | 45 +- .../elixir_euler_astro_jet_MCL.jl | 89 ++-- .../elixir_euler_astro_jet_amr.jl | 119 +++-- .../elixir_euler_astro_jet_subcell.jl | 83 ++-- .../tree_2d_dgsem/elixir_euler_blast_wave.jl | 75 ++- .../elixir_euler_blast_wave_MCL.jl | 89 ++-- .../elixir_euler_blast_wave_amr.jl | 93 ++-- ...ixir_euler_blast_wave_neuralnetwork_cnn.jl | 86 ++-- ...blast_wave_neuralnetwork_perssonperaire.jl | 86 ++-- ...r_blast_wave_neuralnetwork_rayhesthaven.jl | 88 ++-- .../elixir_euler_blast_wave_pure_fv.jl | 63 ++- .../elixir_euler_blast_wave_sc_subcell.jl | 77 ++-- .../tree_2d_dgsem/elixir_euler_blob_amr.jl | 131 +++--- .../tree_2d_dgsem/elixir_euler_blob_mortar.jl | 119 +++-- .../elixir_euler_colliding_flow.jl | 116 ++--- .../elixir_euler_colliding_flow_amr.jl | 119 +++-- .../elixir_euler_convergence_IDP.jl | 47 +- .../elixir_euler_convergence_MCL.jl | 48 +- .../elixir_euler_convergence_pure_fv.jl | 28 +- .../elixir_euler_density_wave.jl | 31 +- examples/tree_2d_dgsem/elixir_euler_ec.jl | 37 +- ...ixir_euler_kelvin_helmholtz_instability.jl | 66 +-- ..._euler_kelvin_helmholtz_instability_MCL.jl | 81 ++-- ..._euler_kelvin_helmholtz_instability_amr.jl | 88 ++-- ...bility_amr_neuralnetwork_perssonperaire.jl | 124 ++--- ...in_helmholtz_instability_fjordholm_etal.jl | 128 +++--- ...er_kelvin_helmholtz_instability_restart.jl | 20 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 72 +-- .../tree_2d_dgsem/elixir_euler_positivity.jl | 104 ++--- .../elixir_euler_sedov_blast_wave.jl | 102 ++--- .../elixir_euler_sedov_blast_wave_MCL.jl | 101 +++-- ...blast_wave_neuralnetwork_perssonperaire.jl | 121 +++-- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 89 ++-- .../elixir_euler_shockcapturing.jl | 43 +- .../elixir_euler_shockcapturing_subcell.jl | 74 ++- .../elixir_euler_source_terms.jl | 30 +- ...r_euler_source_terms_amr_refine_coarsen.jl | 86 ++-- .../elixir_euler_source_terms_nonperiodic.jl | 47 +- .../elixir_euler_source_terms_sc_subcell.jl | 43 +- examples/tree_2d_dgsem/elixir_euler_vortex.jl | 98 ++-- .../tree_2d_dgsem/elixir_euler_vortex_amr.jl | 191 ++++---- .../elixir_euler_vortex_mortar.jl | 104 ++--- ...ixir_euler_vortex_mortar_shockcapturing.jl | 114 ++--- .../elixir_euler_vortex_mortar_split.jl | 106 ++--- .../elixir_euler_vortex_shockcapturing.jl | 110 ++--- ..._euleracoustics_co-rotating_vortex_pair.jl | 377 +++++++-------- .../elixir_eulermulti_convergence_ec.jl | 37 +- .../elixir_eulermulti_convergence_es.jl | 37 +- .../tree_2d_dgsem/elixir_eulermulti_ec.jl | 38 +- .../tree_2d_dgsem/elixir_eulermulti_es.jl | 39 +- .../elixir_eulermulti_shock_bubble.jl | 214 ++++----- ...ck_bubble_shockcapturing_subcell_minmax.jl | 202 +++++---- ...ubble_shockcapturing_subcell_positivity.jl | 207 ++++----- .../tree_2d_dgsem/elixir_hypdiff_godunov.jl | 88 ++-- .../elixir_hypdiff_harmonic_nonperiodic.jl | 76 ++-- .../elixir_hypdiff_lax_friedrichs.jl | 86 ++-- .../elixir_hypdiff_nonperiodic.jl | 45 +- examples/tree_2d_dgsem/elixir_kpp.jl | 73 +-- examples/tree_2d_dgsem/elixir_lbm_constant.jl | 37 +- examples/tree_2d_dgsem/elixir_lbm_couette.jl | 113 +++-- .../elixir_lbm_lid_driven_cavity.jl | 89 ++-- .../elixir_linearizedeuler_convergence.jl | 31 +- .../elixir_linearizedeuler_gauss_wall.jl | 38 +- .../tree_2d_dgsem/elixir_mhd_alfven_wave.jl | 45 +- .../elixir_mhd_alfven_wave_mortar.jl | 49 +- .../tree_2d_dgsem/elixir_mhd_blast_wave.jl | 102 ++--- examples/tree_2d_dgsem/elixir_mhd_ec.jl | 36 +- .../tree_2d_dgsem/elixir_mhd_orszag_tang.jl | 86 ++-- examples/tree_2d_dgsem/elixir_mhd_rotor.jl | 113 +++-- .../elixir_mhd_shockcapturing_subcell.jl | 96 ++-- .../elixir_mhdmulti_convergence.jl | 39 +- examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl | 40 +- examples/tree_2d_dgsem/elixir_mhdmulti_es.jl | 40 +- .../tree_2d_dgsem/elixir_mhdmulti_rotor.jl | 121 +++-- .../elixir_navierstokes_convergence.jl | 315 ++++++------- .../elixir_navierstokes_lid_driven_cavity.jl | 45 +- .../elixir_navierstokes_shearlayer_amr.jl | 71 ++- ...elixir_navierstokes_taylor_green_vortex.jl | 53 +-- .../elixir_shallowwater_conical_island.jl | 75 +-- .../tree_2d_dgsem/elixir_shallowwater_ec.jl | 100 ++-- .../elixir_shallowwater_parabolic_bowl.jl | 83 ++-- .../elixir_shallowwater_source_terms.jl | 30 +- ...xir_shallowwater_source_terms_dirichlet.jl | 29 +- ...lixir_shallowwater_twolayer_convergence.jl | 31 +- ...xir_shallowwater_twolayer_well_balanced.jl | 55 +-- .../elixir_shallowwater_well_balanced.jl | 89 ++-- .../elixir_shallowwater_well_balanced_wall.jl | 89 ++-- ...ixir_shallowwater_well_balanced_wet_dry.jl | 156 ++++--- .../elixir_advection_extended.jl | 28 +- .../tree_2d_fdsbp/elixir_euler_convergence.jl | 41 +- ...ixir_euler_kelvin_helmholtz_instability.jl | 69 ++- examples/tree_2d_fdsbp/elixir_euler_vortex.jl | 102 ++--- .../tree_3d_dgsem/elixir_advection_amr.jl | 46 +- .../tree_3d_dgsem/elixir_advection_basic.jl | 30 +- .../elixir_advection_diffusion_amr.jl | 76 ++-- .../elixir_advection_diffusion_nonperiodic.jl | 52 +-- .../elixir_advection_extended.jl | 40 +- .../tree_3d_dgsem/elixir_advection_mortar.jl | 43 +- .../tree_3d_dgsem/elixir_advection_restart.jl | 8 +- examples/tree_3d_dgsem/elixir_euler_amr.jl | 71 ++- .../tree_3d_dgsem/elixir_euler_blob_amr.jl | 137 +++--- .../tree_3d_dgsem/elixir_euler_convergence.jl | 33 +- .../elixir_euler_convergence_pure_fv.jl | 33 +- .../elixir_euler_density_pulse.jl | 57 ++- examples/tree_3d_dgsem/elixir_euler_ec.jl | 33 +- examples/tree_3d_dgsem/elixir_euler_mortar.jl | 37 +- .../elixir_euler_sedov_blast_wave.jl | 159 ++++--- .../elixir_euler_shockcapturing.jl | 43 +- .../elixir_euler_shockcapturing_amr.jl | 58 ++- .../elixir_euler_source_terms.jl | 33 +- .../elixir_euler_taylor_green_vortex.jl | 61 +-- .../elixir_eulergravity_convergence.jl | 56 ++- .../elixir_hypdiff_lax_friedrichs.jl | 93 ++-- .../elixir_hypdiff_nonperiodic.jl | 49 +- examples/tree_3d_dgsem/elixir_lbm_constant.jl | 37 +- .../elixir_lbm_taylor_green_vortex.jl | 60 ++- .../tree_3d_dgsem/elixir_mhd_alfven_wave.jl | 38 +- .../elixir_mhd_alfven_wave_mortar.jl | 43 +- examples/tree_3d_dgsem/elixir_mhd_ec.jl | 36 +- .../elixir_mhd_ec_shockcapturing.jl | 38 +- .../elixir_navierstokes_convergence.jl | 428 +++++++++--------- ...elixir_navierstokes_taylor_green_vortex.jl | 58 +-- .../elixir_advection_extended.jl | 28 +- .../tree_3d_fdsbp/elixir_euler_convergence.jl | 40 +- .../elixir_euler_taylor_green_vortex.jl | 72 +-- .../elixir_acoustics_gauss_wall.jl | 45 +- .../elixir_advection_basic.jl | 29 +- .../elixir_euler_basic.jl | 43 +- .../unstructured_2d_dgsem/elixir_euler_ec.jl | 31 +- .../elixir_euler_free_stream.jl | 41 +- .../elixir_euler_periodic.jl | 19 +- .../elixir_euler_restart.jl | 13 +- .../elixir_euler_sedov.jl | 78 ++-- .../elixir_euler_wall_bc.jl | 64 +-- .../elixir_mhd_alfven_wave.jl | 49 +- .../unstructured_2d_dgsem/elixir_mhd_ec.jl | 79 ++-- .../elixir_shallowwater_dirichlet.jl | 51 ++- .../elixir_shallowwater_ec.jl | 101 +++-- .../elixir_shallowwater_ec_shockcapturing.jl | 104 +++-- .../elixir_shallowwater_source_terms.jl | 33 +- ...ixir_shallowwater_three_mound_dam_break.jl | 99 ++-- ...lixir_shallowwater_twolayer_convergence.jl | 34 +- .../elixir_shallowwater_twolayer_dam_break.jl | 139 +++--- ...xir_shallowwater_twolayer_well_balanced.jl | 58 +-- ...xir_shallowwater_wall_bc_shockcapturing.jl | 82 ++-- .../elixir_shallowwater_well_balanced.jl | 92 ++-- src/callbacks_stage/subcell_bounds_check.jl | 20 +- .../subcell_bounds_check_2d.jl | 290 ++++++------ src/solvers/dgsem_tree/subcell_limiters_2d.jl | 6 +- test/test_tree_2d_euler.jl | 31 ++ 381 files changed, 13696 insertions(+), 13627 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 81d18f4105..a733cb7cc2 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -30,7 +30,7 @@ jobs: # format(".") run: | julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter"))' - julia -e 'using JuliaFormatter; format(["benchmark", "ext", "src", "test", "utils"])' + julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])' - name: Format check run: | julia -e ' diff --git a/README.md b/README.md index 673708d8b8..1d52089ae3 100644 --- a/README.md +++ b/README.md @@ -256,31 +256,48 @@ or [create an issue](https://github.com/trixi-framework/Trixi.jl/issues/new). ## Acknowledgments -

- +

-This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -under Germany's Excellence Strategy EXC 2044-390685587, Mathematics Münster: -Dynamics-Geometry-Structure. - -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -through the research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and -Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +This project has benefited from funding by the [Deutsche +Forschungsgemeinschaft](https://www.dfg.de/) (DFG, German Research Foundation) +through the following grants: +* Excellence Strategy EXC 2044-390685587, Mathematics Münster: Dynamics-Geometry-Structure. +* Research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and + Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +* Individual grant no. 528753982. -This project has benefited from funding from the European Research Council through the +This project has benefited from funding from the [European Research Council](https://erc.europa.eu) +through the ERC Starting Grant "An Exascale aware and Un-crashable Space-Time-Adaptive Discontinuous Spectral Element Solver for Non-Linear Conservation Laws" (Extreme), ERC grant agreement no. 714487. -This project has benefited from funding from Vetenskapsrådet (VR, Swedish Research Council), Sweden +This project has benefited from funding from [Vetenskapsrådet](https://www.vr.se) +(VR, Swedish Research Council), Sweden through the VR Starting Grant "Shallow water flows including sediment transport and morphodynamics", VR grant agreement 2020-03642 VR. -This project has benefited from funding from the United States National Science Foundation under awards +This project has benefited from funding from the United States +[National Science Foundation](https://www.nsf.gov/) (NSF) under awards DMS-1719818 and DMS-1943186. -This project has benefited from funding from the German Federal Ministry of -Education and Research through the project grant "Adaptive earth system modeling +This project has benefited from funding from the German +[Federal Ministry of Education and Research](https://www.bmbf.de) (BMBF) +through the project grant "Adaptive earth system modeling with significantly reduced computation time for exascale supercomputers (ADAPTEX)" (funding id: 16ME0668K). + +This project has benefited from funding by the +[Daimler und Benz Stiftung](https://www.daimler-benz-stiftung.de) (Daimler and Benz Foundation) +through grant no. 32-10/22. + +Trixi.jl is supported by [NumFOCUS](https://numfocus.org/) as an Affiliated Project. diff --git a/docs/literate/src/files/differentiable_programming.jl b/docs/literate/src/files/differentiable_programming.jl index 33427803af..0960ba25d9 100644 --- a/docs/literate/src/files/differentiable_programming.jl +++ b/docs/literate/src/files/differentiable_programming.jl @@ -43,7 +43,7 @@ scatter(real.(λ), imag.(λ), label="central flux") # As you can see here, the maximal real part is close to zero. relative_maximum = maximum(real, λ) / maximum(abs, λ) -@test 3.0e-10 < relative_maximum < 8.0e-10 #src +@test 3.0e-10 < relative_maximum < 9.0e-10 #src # Interestingly, if we add dissipation by switching to the `flux_lax_friedrichs` # at the interfaces, the maximal real part of the eigenvalues increases. @@ -87,7 +87,7 @@ scatter(real.(λ), imag.(λ), label="central flux") # Here, the maximal real part is basically zero to machine accuracy. relative_maximum = maximum(real, λ) / maximum(abs, λ) -@test 1.0e-17 < relative_maximum < 1.0e-15 #src +@test 1.0e-17 < relative_maximum < 2.0e-15 #src # Moreover, the eigenvectors are not as ill-conditioned as in 2D. diff --git a/docs/src/index.md b/docs/src/index.md index 9ffaee26c4..fd92334892 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -344,29 +344,58 @@ or [create an issue](https://github.com/trixi-framework/Trixi.jl/issues/new). ## Acknowledgments -![funding-logo](https://user-images.githubusercontent.com/3637659/233821022-84910be7-8649-4999-a0ff-22d5e20f0b90.jpg) - -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -under Germany's Excellence Strategy EXC 2044-390685587, Mathematics Münster: -Dynamics-Geometry-Structure. +```@raw html +
+
+
+
+
+
+
+
+``` -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -through the research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and -Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +This project has benefited from funding by the [Deutsche +Forschungsgemeinschaft](https://www.dfg.de/) (DFG, German Research Foundation) +through the following grants: +* Excellence Strategy EXC 2044-390685587, Mathematics Münster: Dynamics-Geometry-Structure. +* Research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and + Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +* Individual grant no. 528753982. -This project has benefited from funding from the European Research Council through the +This project has benefited from funding from the [European Research Council](https://erc.europa.eu) +through the ERC Starting Grant "An Exascale aware and Un-crashable Space-Time-Adaptive Discontinuous Spectral Element Solver for Non-Linear Conservation Laws" (Extreme), ERC grant agreement no. 714487. -This project has benefited from funding from Vetenskapsrådet (VR, Swedish Research Council), Sweden +This project has benefited from funding from [Vetenskapsrådet](https://www.vr.se) +(VR, Swedish Research Council), Sweden through the VR Starting Grant "Shallow water flows including sediment transport and morphodynamics", VR grant agreement 2020-03642 VR. -This project has benefited from funding from the United States National Science Foundation under awards +This project has benefited from funding from the United States +[National Science Foundation](https://www.nsf.gov/) (NSF) under awards DMS-1719818 and DMS-1943186. -This project has benefited from funding from the German Federal Ministry of -Education and Research through the project grant "Adaptive earth system modeling +This project has benefited from funding from the German +[Federal Ministry of Education and Research](https://www.bmbf.de) (BMBF) +through the project grant "Adaptive earth system modeling with significantly reduced computation time for exascale supercomputers (ADAPTEX)" (funding id: 16ME0668K). + +This project has benefited from funding by the +[Daimler und Benz Stiftung](https://www.daimler-benz-stiftung.de) (Daimler and Benz Foundation) +through grant no. 32-10/22. + +Trixi.jl is supported by [NumFOCUS](https://numfocus.org/) as an Affiliated Project. diff --git a/docs/src/styleguide.md b/docs/src/styleguide.md index 60e227204c..2f28dbfcb1 100644 --- a/docs/src/styleguide.md +++ b/docs/src/styleguide.md @@ -17,11 +17,11 @@ conventions, we apply and enforce automated source code formatting * Maximum line length (strictly): **92**. * Functions that mutate their *input* are named with a trailing `!`. * Functions order their parameters [similar to Julia Base](https://docs.julialang.org/en/v1/manual/style-guide/#Write-functions-with-argument-ordering-similar-to-Julia-Base-1). - * The main modified argument comes first. For example, if the right-hand side `du` is modified, - it should come first. If only the `cache` is modified, e.g., in `prolong2interfaces!` + * The main modified argument comes first. For example, if the right-hand side `du` is modified, + it should come first. If only the `cache` is modified, e.g., in `prolong2interfaces!` and its siblings, put the `cache` first. * Otherwise, use the order `mesh, equations, solver, cache`. - * If something needs to be specified in more detail for dispatch, put the additional argument before the general one + * If something needs to be specified in more detail for dispatch, put the additional argument before the general one that is specified in more detail. For example, we use `have_nonconservative_terms(equations), equations` and `dg.mortar, dg`. * Prefer `for i in ...` to `for i = ...` for better semantic clarity and greater flexibility. @@ -55,7 +55,7 @@ julia -e 'using Pkg; Pkg.add("JuliaFormatter")' ``` You can then recursively format the core Julia files in the Trixi.jl repo by executing ```shell -julia -e 'using JuliaFormatter; format(["benchmark", "ext", "src", "utils"])' +julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])' ``` from inside the Trixi.jl repository. For convenience, there is also a script you can directly run from your terminal shell, which will automatically install JuliaFormatter in a @@ -67,12 +67,12 @@ You can get more information about using the convenience script by running it wi `--help`/`-h` flag. ### Checking formatting before committing -It can be convenient to check the formatting of source code automatically before each commit. +It can be convenient to check the formatting of source code automatically before each commit. We use git-hooks for it and provide a `pre-commit` script in the `utils` folder. The script uses -[JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) just like formatting script that -runs over the whole Trixi.jl directory. -You can copy the `pre-commit`-script into `.git/hooks/pre-commit` and it will check your formatting +[JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl) just like formatting script that +runs over the whole Trixi.jl directory. +You can copy the `pre-commit`-script into `.git/hooks/pre-commit` and it will check your formatting before each commit. If errors are found the commit is aborted and you can add the corrections via -```shell +```shell git add -p ``` diff --git a/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl index d06ed05a62..09d66fe8ae 100644 --- a/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl +++ b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl @@ -23,8 +23,8 @@ dg = DGMulti(polydeg = 3, cells_per_dimension = (8,) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-1.0,), coordinates_max=(1.0,), - periodicity=true) + coordinates_min = (-1.0,), coordinates_max = (1.0,), + periodicity = true) ############################################################################### # setup the test problem (no source term needed for linear advection) @@ -49,10 +49,10 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = 100, uEltype = real(dg)) # handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.75) +stepsize_callback = StepsizeCallback(cfl = 0.75) # collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) @@ -60,9 +60,8 @@ callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() - diff --git a/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl index 3566185d11..6abd7118fe 100644 --- a/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl @@ -2,8 +2,10 @@ using Trixi, OrdinaryDiffEq dg = DGMulti(element_type = Line(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=50), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 50), surface_flux = flux_hll, volume_integral = VolumeIntegralWeakForm()) @@ -11,8 +13,8 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -mesh = DGMultiMesh(dg, coordinates_min=(-1.0,), - coordinates_max=( 1.0,)) +mesh = DGMultiMesh(dg, coordinates_min = (-1.0,), + coordinates_max = (1.0,)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -21,15 +23,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_1d/elixir_euler_flux_diff.jl b/examples/dgmulti_1d/elixir_euler_flux_diff.jl index 489b23e37b..56a24d25d0 100644 --- a/examples/dgmulti_1d/elixir_euler_flux_diff.jl +++ b/examples/dgmulti_1d/elixir_euler_flux_diff.jl @@ -13,17 +13,17 @@ source_terms = source_terms_convergence_test cells_per_dimension = (8,) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-1.0,), coordinates_max=(1.0,), periodicity=true) + coordinates_min = (-1.0,), coordinates_max = (1.0,), periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg; - source_terms=source_terms) + source_terms = source_terms) tspan = (0.0, 1.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) @@ -31,7 +31,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion.jl b/examples/dgmulti_2d/elixir_advection_diffusion.jl index 8a79e9700a..ce7b0e745a 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion.jl @@ -11,48 +11,52 @@ initial_condition_zero(x, t, equations::LinearScalarAdvectionEquation2D) = SVect initial_condition = initial_condition_zero # tag different boundary segments -left(x, tol=50*eps()) = abs(x[1] + 1) < tol -right(x, tol=50*eps()) = abs(x[1] - 1) < tol -bottom(x, tol=50*eps()) = abs(x[2] + 1) < tol -top(x, tol=50*eps()) = abs(x[2] - 1) < tol +left(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +right(x, tol = 50 * eps()) = abs(x[1] - 1) < tol +bottom(x, tol = 50 * eps()) = abs(x[2] + 1) < tol +top(x, tol = 50 * eps()) = abs(x[2] - 1) < tol is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; is_on_boundary) # BC types -boundary_condition_left = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + 0.1 * x[2])) +boundary_condition_left = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + + 0.1 * + x[2])) boundary_condition_zero = BoundaryConditionDirichlet((x, t, equations) -> SVector(0.0)) boundary_condition_neumann_zero = BoundaryConditionNeumann((x, t, equations) -> SVector(0.0)) # define inviscid boundary conditions boundary_conditions = (; :left => boundary_condition_left, - :bottom => boundary_condition_zero, - :top => boundary_condition_do_nothing, - :right => boundary_condition_do_nothing) + :bottom => boundary_condition_zero, + :top => boundary_condition_do_nothing, + :right => boundary_condition_do_nothing) # define viscous boundary conditions boundary_conditions_parabolic = (; :left => boundary_condition_left, - :bottom => boundary_condition_zero, - :top => boundary_condition_zero, - :right => boundary_condition_neumann_zero) + :bottom => boundary_condition_zero, + :top => boundary_condition_zero, + :right => boundary_condition_neumann_zero) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) tspan = (0.0, 1.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-6 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl index 7e87d9f097..d2f11f1850 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl @@ -16,61 +16,63 @@ equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_erikkson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # Note: this requires epsilon < 0.6 due to the sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # Note: this requires epsilon < 0.6 due to the sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_erikkson_johnson # tag different boundary segments -left(x, tol=50*eps()) = abs(x[1] + 1) < tol -right(x, tol=50*eps()) = abs(x[1]) < tol -bottom(x, tol=50*eps()) = abs(x[2] + 0.5) < tol -top(x, tol=50*eps()) = abs(x[2] - 0.5) < tol -entire_boundary(x, tol=50*eps()) = true +left(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +right(x, tol = 50 * eps()) = abs(x[1]) < tol +bottom(x, tol = 50 * eps()) = abs(x[2] + 0.5) < tol +top(x, tol = 50 * eps()) = abs(x[2] - 0.5) < tol +entire_boundary(x, tol = 50 * eps()) = true is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom, :entire_boundary => entire_boundary) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; - coordinates_min=(-1.0, -0.5), - coordinates_max=(0.0, 0.5), + coordinates_min = (-1.0, -0.5), + coordinates_max = (0.0, 0.5), is_on_boundary) # BC types boundary_condition = BoundaryConditionDirichlet(initial_condition) # define inviscid boundary conditions, enforce "do nothing" boundary condition at the outflow -boundary_conditions = (; :left => boundary_condition, - :top => boundary_condition, - :bottom => boundary_condition, - :right => boundary_condition_do_nothing) +boundary_conditions = (; :left => boundary_condition, + :top => boundary_condition, + :bottom => boundary_condition, + :right => boundary_condition_do_nothing) # define viscous boundary conditions boundary_conditions_parabolic = (; :entire_boundary => boundary_condition) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) tspan = (0.0, 1.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl index 76512f1e39..c498e5468d 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl @@ -8,12 +8,12 @@ equations = LinearScalarAdvectionEquation2D(0.0, 0.0) equations_parabolic = LaplaceDiffusion2D(5.0e-1, equations) function initial_condition_sharp_gaussian(x, t, equations::LinearScalarAdvectionEquation2D) - return SVector(exp(-100 * (x[1]^2 + x[2]^2))) + return SVector(exp(-100 * (x[1]^2 + x[2]^2))) end initial_condition = initial_condition_sharp_gaussian cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg) @@ -21,16 +21,16 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-6 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - dt = time_int_tol, ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = time_int_tol, ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_bilinear.jl b/examples/dgmulti_2d/elixir_euler_bilinear.jl index bdd582610e..cd498bf39b 100644 --- a/examples/dgmulti_2d/elixir_euler_bilinear.jl +++ b/examples/dgmulti_2d/elixir_euler_bilinear.jl @@ -10,27 +10,28 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -vertex_coordinates, EToV = StartUpDG.uniform_mesh(dg.basis.element_type, cells_per_dimension...) +vertex_coordinates, EToV = StartUpDG.uniform_mesh(dg.basis.element_type, + cells_per_dimension...) for i in eachindex(vertex_coordinates[1]) - vx, vy = getindex.(vertex_coordinates, i) - setindex!.(vertex_coordinates, mapping(vx, vy), i) + vx, vy = getindex.(vertex_coordinates, i) + setindex!.(vertex_coordinates, mapping(vx, vy), i) end -mesh = DGMultiMesh(dg, vertex_coordinates, EToV, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, vertex_coordinates, EToV, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -40,15 +41,15 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl b/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl index 4bb05c0b06..e7830c4736 100644 --- a/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl +++ b/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl @@ -1,6 +1,6 @@ using Trixi, OrdinaryDiffEq -dg = DGMulti(polydeg=4, element_type = Quad(), approximation_type = Polynomial(), +dg = DGMulti(polydeg = 4, element_type = Quad(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(FluxLaxFriedrichs()), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) @@ -16,38 +16,38 @@ incompressible version. [DOI: 10.1006/jcph.1995.1205](https://doi.org/10.1006/jcph.1995.1205) """ function initial_condition_BM_vortex(x, t, equations::CompressibleEulerEquations2D) - pbar = 9.0 / equations.gamma - delta = 0.05 - epsilon = 30 - H = (x[2] < 0) ? tanh(epsilon * (x[2] + 0.25)) : tanh(epsilon * (0.25 - x[2])) - rho = 1.0 - v1 = H - v2 = delta * cos(2.0 * pi * x[1]) - p = pbar - return prim2cons(SVector(rho, v1, v2, p), equations) + pbar = 9.0 / equations.gamma + delta = 0.05 + epsilon = 30 + H = (x[2] < 0) ? tanh(epsilon * (x[2] + 0.25)) : tanh(epsilon * (0.25 - x[2])) + rho = 1.0 + v1 = H + v2 = delta * cos(2.0 * pi * x[1]) + p = pbar + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_BM_vortex cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-0.5, -0.5), coordinates_max=(0.5, 0.5), - periodicity=true) + coordinates_min = (-0.5, -0.5), coordinates_max = (0.5, 0.5), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation tol = 1.0e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=tol, reltol=tol, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = tol, reltol = tol, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_curved.jl b/examples/dgmulti_2d/elixir_euler_curved.jl index 39e3a0a036..48662f4b12 100644 --- a/examples/dgmulti_2d/elixir_euler_curved.jl +++ b/examples/dgmulti_2d/elixir_euler_curved.jl @@ -10,21 +10,21 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -34,16 +34,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation alg = RDPK3SpFSAL49() -sol = solve(ode, alg; abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, alg; abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl index d41ca2c5b3..3a73089b56 100644 --- a/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl @@ -2,8 +2,10 @@ using Trixi, OrdinaryDiffEq dg = DGMulti(element_type = Quad(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=50), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 50), surface_flux = flux_hll, volume_integral = VolumeIntegralWeakForm()) @@ -11,8 +13,8 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -mesh = DGMultiMesh(dg, coordinates_min=(-1.0, -1.0), - coordinates_max=( 1.0, 1.0)) +mesh = DGMultiMesh(dg, coordinates_min = (-1.0, -1.0), + coordinates_max = (1.0, 1.0)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -21,15 +23,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl index b9a24dc245..f534b5bc8a 100644 --- a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl +++ b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl @@ -15,11 +15,11 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (; :Slant => boundary_condition_convergence_test, - :Bezier => boundary_condition_convergence_test, - :Right => boundary_condition_convergence_test, - :Bottom => boundary_condition_convergence_test, - :Top => boundary_condition_convergence_test ) +boundary_conditions = (; :Slant => boundary_condition_convergence_test, + :Bezier => boundary_condition_convergence_test, + :Right => boundary_condition_convergence_test, + :Bottom => boundary_condition_convergence_test, + :Top => boundary_condition_convergence_test) ############################################################################### # Get the DG approximation space @@ -32,8 +32,9 @@ dg = DGMulti(polydeg = 8, element_type = Quad(), approximation_type = SBP(), # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = DGMultiMesh(dg, mesh_file) @@ -42,8 +43,8 @@ mesh = DGMultiMesh(dg, mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -54,9 +55,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -66,7 +67,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - dt = time_int_tol, ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = time_int_tol, ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl b/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl index 39e98d1a2c..14de0bf0e8 100644 --- a/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl @@ -15,23 +15,24 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability cells_per_dimension = (32, 32) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) @@ -39,9 +40,9 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) @@ -49,7 +50,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl b/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl index f5adc7bf83..49c8b28eaf 100644 --- a/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl +++ b/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl @@ -29,34 +29,34 @@ defined below. """ @inline function initial_condition_rayleigh_taylor_instability(x, t, equations::CompressibleEulerEquations2D, - slope=1000) - tol = 1e2*eps() - - if x[2] < 0.5 - p = 2*x[2] + 1 - else - p = x[2] + 3/2 - end - - # smooth the discontinuity to avoid ambiguity at element interfaces - smoothed_heaviside(x, left, right) = left + 0.5*(1 + tanh(slope * x)) * (right-left) - rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) - - c = sqrt(equations.gamma * p / rho) - # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the - # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. - v = -0.025 * c * cos(8*pi*x[1]) * sin(pi*x[2])^6 - u = 0.0 - - return prim2cons(SVector(rho, u, v, p), equations) + slope = 1000) + tol = 1e2 * eps() + + if x[2] < 0.5 + p = 2 * x[2] + 1 + else + p = x[2] + 3 / 2 + end + + # smooth the discontinuity to avoid ambiguity at element interfaces + smoothed_heaviside(x, left, right) = left + 0.5 * (1 + tanh(slope * x)) * (right - left) + rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) + + c = sqrt(equations.gamma * p / rho) + # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the + # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. + v = -0.025 * c * cos(8 * pi * x[1]) * sin(pi * x[2])^6 + u = 0.0 + + return prim2cons(SVector(rho, u, v, p), equations) end @inline function source_terms_rayleigh_taylor_instability(u, x, t, equations::CompressibleEulerEquations2D) - g = 1.0 - rho, rho_v1, rho_v2, rho_e = u + g = 1.0 + rho, rho_v1, rho_v2, rho_e = u - return SVector(0.0, 0.0, g*rho, g*rho_v2) + return SVector(0.0, 0.0, g * rho, g * rho_v2) end # numerical parameters @@ -67,8 +67,8 @@ dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = Polynomial num_elements = 16 cells_per_dimension = (num_elements, 4 * num_elements) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(0.0, 0.0), coordinates_max=(0.25, 1.0), - periodicity=(true, false)) + coordinates_min = (0.0, 0.0), coordinates_max = (0.25, 1.0), + periodicity = (true, false)) initial_condition = initial_condition_rayleigh_taylor_instability boundary_conditions = (; :entire_boundary => boundary_condition_slip_wall) @@ -86,9 +86,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -97,7 +97,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_shockcapturing.jl b/examples/dgmulti_2d/elixir_euler_shockcapturing.jl index 4b2a408c75..36494b268d 100644 --- a/examples/dgmulti_2d/elixir_euler_shockcapturing.jl +++ b/examples/dgmulti_2d/elixir_euler_shockcapturing.jl @@ -10,25 +10,25 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 -basis = DGMultiBasis(Quad(), polydeg, approximation_type=GaussSBP()) +basis = DGMultiBasis(Quad(), polydeg, approximation_type = GaussSBP()) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) dg = DGMulti(basis, surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = volume_integral) cells_per_dimension = (8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) @@ -36,16 +36,15 @@ tspan = (0.0, 0.15) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary - diff --git a/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl b/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl index dad898b99b..5e8d9e6c8e 100644 --- a/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl +++ b/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl @@ -10,27 +10,27 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 -basis = DGMultiBasis(Quad(), polydeg, approximation_type=GaussSBP()) +basis = DGMultiBasis(Quad(), polydeg, approximation_type = GaussSBP()) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) dg = DGMulti(basis, surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = volume_integral) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, mapping) @@ -41,16 +41,15 @@ tspan = (0.0, 0.15) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary - diff --git a/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl b/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl index c10b5e46a1..53661af259 100644 --- a/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl +++ b/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl @@ -13,11 +13,11 @@ meshIO = StartUpDG.triangulate_domain(StartUpDG.RectangularDomainWithHole()) # the pre-defined Triangulate geometry in StartUpDG has integer boundary tags. this routine # assigns boundary faces based on these integer boundary tags. -mesh = DGMultiMesh(dg, meshIO, Dict(:outer_boundary=>1, :inner_boundary=>2)) +mesh = DGMultiMesh(dg, meshIO, Dict(:outer_boundary => 1, :inner_boundary => 2)) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :outer_boundary => boundary_condition_convergence_test, - :inner_boundary => boundary_condition_convergence_test) + :inner_boundary => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -27,14 +27,14 @@ tspan = (0.0, 0.2) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_weakform.jl b/examples/dgmulti_2d/elixir_euler_weakform.jl index 486a30b37f..ecf5e94a86 100644 --- a/examples/dgmulti_2d/elixir_euler_weakform.jl +++ b/examples/dgmulti_2d/elixir_euler_weakform.jl @@ -10,16 +10,16 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) cells_per_dimension = (8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -29,15 +29,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.5) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.5) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl b/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl index c4c83fff64..307bf5cbf4 100644 --- a/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl +++ b/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl @@ -10,7 +10,7 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test cells_per_dimension = (4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -18,14 +18,14 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl b/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl index a1351cf824..1167028852 100644 --- a/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl +++ b/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl @@ -8,70 +8,72 @@ using LinearAlgebra: norm, dot # for use in the MHD boundary condition equations = IdealGlmMhdEquations2D(1.4) function initial_condition_perturbation(x, t, equations::IdealGlmMhdEquations2D) - # pressure perturbation in a vertically magnetized field on the domain [-1, 1]^2 + # pressure perturbation in a vertically magnetized field on the domain [-1, 1]^2 - r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^2 + r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^2 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = 1 + 0.5 * exp(-100 * r2) + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = 1 + 0.5 * exp(-100 * r2) - # the pressure and magnetic field are chosen to be strongly - # magnetized, such that p / ||B||^2 ≈ 0.01. - B1 = 0.0 - B2 = 40.0 / sqrt(4.0 * pi) - B3 = 0.0 + # the pressure and magnetic field are chosen to be strongly + # magnetized, such that p / ||B||^2 ≈ 0.01. + B1 = 0.0 + B2 = 40.0 / sqrt(4.0 * pi) + B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_perturbation surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGMulti(polydeg=3, element_type = Quad(), approximation_type = GaussSBP(), +solver = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -x_neg(x, tol=50*eps()) = abs(x[1] + 1) < tol -x_pos(x, tol=50*eps()) = abs(x[1] - 1) < tol -y_neg(x, tol=50*eps()) = abs(x[2] + 1) < tol -y_pos(x, tol=50*eps()) = abs(x[2] - 1) < tol +x_neg(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +x_pos(x, tol = 50 * eps()) = abs(x[1] - 1) < tol +y_neg(x, tol = 50 * eps()) = abs(x[2] + 1) < tol +y_pos(x, tol = 50 * eps()) = abs(x[2] - 1) < tol is_on_boundary = Dict(:x_neg => x_neg, :x_pos => x_pos, :y_neg => y_neg, :y_pos => y_pos) cells_per_dimension = (16, 16) -mesh = DGMultiMesh(solver, cells_per_dimension; periodicity=(false, false), is_on_boundary) +mesh = DGMultiMesh(solver, cells_per_dimension; periodicity = (false, false), + is_on_boundary) # Create a "reflective-like" boundary condition by mirroring the velocity but leaving the magnetic field alone. # Note that this boundary condition is probably not entropy stable. -function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::IdealGlmMhdEquations2D) +function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::IdealGlmMhdEquations2D) - # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later - norm_ = norm(normal_direction) - normal = normal_direction / norm_ + # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later + norm_ = norm(normal_direction) + normal = normal_direction / norm_ - # compute the primitive variables - rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations) + # compute the primitive variables + rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations) - v_normal = dot(normal, SVector(v1, v2)) - u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1], - v2 - 2 * v_normal * normal[2], - v3, p, B1, B2, B3, psi), equations) + v_normal = dot(normal, SVector(v1, v2)) + u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1], + v2 - 2 * v_normal * normal[2], + v3, p, B1, B2, B3, psi), equations) - return surface_flux_function(u_inner, u_mirror, normal, equations) * norm_ + return surface_flux_function(u_inner, u_mirror, normal, equations) * norm_ end -boundary_conditions = (; x_neg=boundary_condition_velocity_slip_wall, - x_pos=boundary_condition_velocity_slip_wall, - y_neg=boundary_condition_do_nothing, - y_pos=BoundaryConditionDirichlet(initial_condition)) +boundary_conditions = (; x_neg = boundary_condition_velocity_slip_wall, + x_pos = boundary_condition_velocity_slip_wall, + y_neg = boundary_condition_do_nothing, + y_pos = BoundaryConditionDirichlet(initial_condition)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -82,12 +84,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) -alive_callback = AliveCallback(alive_interval=10) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) +alive_callback = AliveCallback(alive_interval = 10) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -98,8 +101,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1e-5, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1e-5, # 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/dgmulti_2d/elixir_mhd_weak_blast_wave.jl b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl index bf5045ce8b..663301e189 100644 --- a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl +++ b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl @@ -11,14 +11,14 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = Polynomial(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-2.0, -2.0), coordinates_max=(2.0, 2.0), - periodicity=true) + coordinates_min = (-2.0, -2.0), coordinates_max = (2.0, 2.0), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) ############################################################################### @@ -30,13 +30,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -47,8 +47,8 @@ callbacks = CallbackSet(summary_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); +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/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl index 9c8dfcb380..3dc070a729 100644 --- a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl +++ b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl @@ -15,13 +15,13 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = SBP(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-2.0, -2.0), coordinates_max=(2.0, 2.0), - periodicity=true) + coordinates_min = (-2.0, -2.0), coordinates_max = (2.0, 2.0), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) ############################################################################### @@ -33,8 +33,8 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # See comment above and https://github.com/trixi-framework/Trixi.jl/issues/881 # DGMulti uses a conservative timestep estimate, so we can use a large CFL here. @@ -46,8 +46,7 @@ alive_callback = AliveCallback(analysis_interval=analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, #stepsize_callback, - alive_callback, - #=glm_speed_callback=#) + alive_callback) #=glm_speed_callback=# ############################################################################### # run the simulation @@ -56,7 +55,7 @@ callbacks = CallbackSet(summary_callback, # 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); -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks) +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/dgmulti_2d/elixir_navierstokes_convergence.jl b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl index 23c9c2e8ed..38cf3d7984 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_convergence.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl @@ -10,169 +10,180 @@ mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) # Note: If you change the Navier-Stokes parameters here, also change them in the initial condition # I really do not like this structure but it should work for now -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=(true, false), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = (true, false), is_on_boundary) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -180,10 +191,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -193,15 +205,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl b/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl index 86b5ae6434..87ffd0e099 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl @@ -10,24 +10,26 @@ mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) # Note: If you change the Navier-Stokes parameters here, also change them in the initial condition # I really do not like this structure but it should work for now -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false), + is_on_boundary) # This initial condition is taken from `examples/dgmulti_2d/elixir_navierstokes_convergence.jl` @@ -36,150 +38,160 @@ mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false), # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -187,10 +199,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -200,15 +213,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl index 97b779ebaf..7c55cbf0cc 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,27 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) - +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) -top(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top(x, tol) +top(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top(x, tol) is_on_boundary = Dict(:top => top, :rest_of_boundary => rest_of_boundary) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; is_on_boundary) function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -43,15 +42,16 @@ boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity # define inviscid boundary conditions boundary_conditions = (; :top => boundary_condition_slip_wall, - :rest_of_boundary => boundary_condition_slip_wall) + :rest_of_boundary => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top => boundary_condition_lid, - :rest_of_boundary => boundary_condition_cavity) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) + :rest_of_boundary => boundary_condition_cavity) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -61,15 +61,15 @@ tspan = (0.0, 10.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl b/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl index 3551c863ff..f7120d8091 100644 --- a/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl +++ b/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl @@ -4,24 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = SBP(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (8, 8) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(0.0, 0.0), coordinates_max=(sqrt(2), sqrt(2)), - periodicity=true) - + coordinates_min = (0.0, 0.0), coordinates_max = (sqrt(2), sqrt(2)), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg; - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,8 +31,8 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -42,7 +41,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-7, reltol=1.0e-7, - ode_default_options()..., callback=callbacks); +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/dgmulti_3d/elixir_advection_tensor_wedge.jl b/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl index 4f43f2571a..e877e60254 100644 --- a/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl +++ b/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl @@ -16,17 +16,15 @@ dg = DGMulti(element_type = Wedge(), surface_flux = flux_lax_friedrichs, polydeg = tensor_polydeg) - cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, +mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min = (-1.0, -1.0, -1.0), + coordinates_min = (-1.0, -1.0, -1.0), coordinates_max = (1.0, 1.0, 1.0), periodicity = true) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, - boundary_conditions=boundary_condition_periodic) + boundary_conditions = boundary_condition_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -37,20 +35,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + stepsize_callback) ############################################################################### # run the simulation sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), dt = 1.0, - save_everystep=false, callback=callbacks); + save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_curved.jl b/examples/dgmulti_3d/elixir_euler_curved.jl index d8c4df5dd6..67c84b5097 100644 --- a/examples/dgmulti_3d/elixir_euler_curved.jl +++ b/examples/dgmulti_3d/elixir_euler_curved.jl @@ -1,7 +1,7 @@ using Trixi, OrdinaryDiffEq -dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type=SBP(), +dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(flux_hll), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) @@ -10,22 +10,22 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top_boundary(x, tol) +top_boundary(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top_boundary(x, tol) is_on_boundary = Dict(:top => top_boundary, :rest => rest_of_boundary) function mapping(xi, eta, zeta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y, z) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -35,14 +35,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl index 35f7aee879..0eb3867468 100644 --- a/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl @@ -10,19 +10,20 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -volume_flux = flux_ranocha +volume_flux = flux_ranocha solver = DGMulti(element_type = Hex(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=20), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 20), surface_flux = flux_lax_friedrichs, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -mesh = DGMultiMesh(solver, coordinates_min=(-1.0, -1.0, -1.0), - coordinates_max=( 1.0, 1.0, 1.0)) +mesh = DGMultiMesh(solver, coordinates_min = (-1.0, -1.0, -1.0), + coordinates_max = (1.0, 1.0, 1.0)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - source_terms=source_terms) - + source_terms = source_terms) ############################################################################### # ODE solvers, callbacks etc. @@ -33,14 +34,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation diff --git a/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl b/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl index 253d248646..fea43ad4d2 100644 --- a/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl +++ b/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl @@ -12,35 +12,38 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex -volume_flux = flux_ranocha +volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs solver = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), - surface_integral= SurfaceIntegralWeakForm(surface_flux), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + surface_integral = SurfaceIntegralWeakForm(surface_flux), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (8, 8, 8) mesh = DGMultiMesh(solver, cells_per_dimension, - coordinates_min=(-pi, -pi, -pi), coordinates_max=(pi, pi, pi), - periodicity=true) + coordinates_min = (-pi, -pi, -pi), coordinates_max = (pi, pi, pi), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,14 +53,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation diff --git a/examples/dgmulti_3d/elixir_euler_weakform.jl b/examples/dgmulti_3d/elixir_euler_weakform.jl index b167377af5..6e06b35c4f 100644 --- a/examples/dgmulti_3d/elixir_euler_weakform.jl +++ b/examples/dgmulti_3d/elixir_euler_weakform.jl @@ -10,16 +10,16 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top_boundary(x, tol) +top_boundary(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top_boundary(x, tol) is_on_boundary = Dict(:top => top_boundary, :rest => rest_of_boundary) cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -29,14 +29,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl b/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl index 6b17d4bba6..bc963a3a2f 100644 --- a/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl +++ b/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl @@ -10,7 +10,7 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -19,14 +19,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_convergence.jl b/examples/dgmulti_3d/elixir_navierstokes_convergence.jl index 9a237b2d2f..5fa0ad7ce6 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_convergence.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_convergence.jl @@ -8,219 +8,225 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=(true, false, true), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = (true, false, true), + is_on_boundary) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:4]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:4]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -228,10 +234,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -241,15 +248,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl b/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl index c14d662080..c58d78d258 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl @@ -8,25 +8,27 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) function mapping(xi, eta, zeta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y, z) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false, true), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false, true), + is_on_boundary) # This initial condition is taken from `examples/dgmulti_3d/elixir_navierstokes_convergence.jl` @@ -35,200 +37,204 @@ mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false, t # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:4]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:4]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -236,10 +242,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -249,15 +256,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl b/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl index 7953838afe..dedd8267a3 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl @@ -10,26 +10,30 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex @@ -39,11 +43,11 @@ dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = GaussSBP(), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi cells_per_dimension = (8, 8, 8) mesh = DGMultiMesh(dg, cells_per_dimension; coordinates_min, coordinates_max, - periodicity=(true, true, true)) + periodicity = (true, true, true)) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg) @@ -55,18 +59,18 @@ tspan = (0.0, 10.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg), - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg), + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl index 841a080947..5a2537be4e 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -7,74 +7,73 @@ module TrixiExtension using Trixi -struct IndicatorSolutionIndependent{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorSolutionIndependent{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorSolutionIndependent(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) - return IndicatorSolutionIndependent{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) + return IndicatorSolutionIndependent{typeof(cache)}(cache) end -function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - - mesh = indicator.cache.mesh - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - #Predict the theoretical center. - advection_velocity = (0.2, -0.7) - center = t.*advection_velocity - - inner_distance = 1 - outer_distance = 1.85 - - #Iterate over all elements - for element in 1:length(alpha) - # Calculate periodic distance between cell and center. - # This requires an uncurved mesh! - coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + - cache.elements.node_coordinates[1, end, 1, element]), - 0.5 * (cache.elements.node_coordinates[2, 1, 1, element] + - cache.elements.node_coordinates[2, 1, end, element])) - - #The geometric shape of the amr should be preserved when the base_level is increased. - #This is done by looking at the original coordinates of each cell. - cell_coordinates = original_coordinates(coordinates, 5/8) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) - if cell_distance < (inner_distance+outer_distance)/2 - cell_coordinates = original_coordinates(coordinates, 5/16) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + mesh = indicator.cache.mesh + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + #Predict the theoretical center. + advection_velocity = (0.2, -0.7) + center = t .* advection_velocity + + inner_distance = 1 + outer_distance = 1.85 + + #Iterate over all elements + for element in 1:length(alpha) + # Calculate periodic distance between cell and center. + # This requires an uncurved mesh! + coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + + cache.elements.node_coordinates[1, end, 1, element]), + 0.5 * (cache.elements.node_coordinates[2, 1, 1, element] + + cache.elements.node_coordinates[2, 1, end, element])) + + #The geometric shape of the amr should be preserved when the base_level is increased. + #This is done by looking at the original coordinates of each cell. + cell_coordinates = original_coordinates(coordinates, 5 / 8) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + if cell_distance < (inner_distance + outer_distance) / 2 + cell_coordinates = original_coordinates(coordinates, 5 / 16) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + end + + #Set alpha according to cells position inside the circles. + target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) + alpha[element] = target_level / 2 end - - #Set alpha according to cells position inside the circles. - target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) - alpha[element] = target_level/2 - end - return alpha + return alpha end # For periodic domains, distance between two points must take into account # periodic extensions of the domain function periodic_distance_2d(coordinates, center, domain_length) - dx = coordinates .- center - dx_shifted = abs.(dx .% domain_length) - dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) - return sqrt(sum(dx_periodic.^2)) + dx = coordinates .- center + dx_shifted = abs.(dx .% domain_length) + dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) + return sqrt(sum(dx_periodic .^ 2)) end #This takes a cells coordinates and transforms them into the coordinates of a parent-cell it originally refined from. #It does it so that the parent-cell has given cell_length. function original_coordinates(coordinates, cell_length) - offset = coordinates .% cell_length - offset_sign = sign.(offset) - border = coordinates - offset - center = border + (offset_sign .* cell_length/2) - return center + offset = coordinates .% cell_length + offset_sign = sign.(offset) + border = coordinates - offset + center = border + (offset_sign .* cell_length / 2) + return center end end # module TrixiExtension @@ -88,21 +87,19 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) trees_per_dimension = (1, 1) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=4) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 4) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -112,38 +109,38 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorSolutionIndependent(semi), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtension.IndicatorSolutionIndependent(semi), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl index 7e6d99c83b..0a50b3644f 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl @@ -12,18 +12,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-5.0, 5 * s - 5.0) -f2(s) = SVector( 5.0, 5 * s + 5.0) +f2(s) = SVector(5.0, 5 * s + 5.0) f3(s) = SVector(5 * s, -5.0 + 5 * sin(0.5 * pi * s)) -f4(s) = SVector(5 * s, 5.0 + 5 * sin(0.5 * pi * s)) +f4(s) = SVector(5 * s, 5.0 + 5 * sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) # This creates a mapping that transforms [-1, 1]^2 to the domain with the faces defined above. @@ -34,17 +32,16 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) - -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=1) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -55,41 +52,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=1, - med_level=2, med_threshold=0.1, - max_level=3, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 0.1, + max_level = 3, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1, # 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/p4est_2d_dgsem/elixir_advection_basic.jl b/examples/p4est_2d_dgsem/elixir_advection_basic.jl index 0b2de85da4..ed235bf839 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_basic.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_basic.jl @@ -11,21 +11,21 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) trees_per_dimension = (8, 8) # Create P4estMesh with 8 x 8 trees and 16 x 16 elements -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -38,26 +38,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl index 55682f73fc..5497f13aa6 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl @@ -16,15 +16,15 @@ equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_eriksson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_eriksson_johnson @@ -33,34 +33,35 @@ boundary_conditions = Dict(:x_neg => BoundaryConditionDirichlet(initial_conditio :y_pos => BoundaryConditionDirichlet(initial_condition), :x_pos => boundary_condition_do_nothing) -boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), - :x_pos => BoundaryConditionDirichlet(initial_condition), - :y_neg => BoundaryConditionDirichlet(initial_condition), +boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :x_pos => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), :y_pos => BoundaryConditionDirichlet(initial_condition)) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) -coordinates_min = (-1.0, -0.5) -coordinates_max = ( 0.0, 0.5) +coordinates_min = (-1.0, -0.5) +coordinates_max = (0.0, 0.5) # This maps the domain [-1, 1]^2 to [-1, 0] x [-0.5, 0.5] while also # introducing a curved warping to interior nodes. function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) return SVector(0.5 * (1 + x) - 1, 0.5 * y) -end +end trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - mapping=mapping, periodicity=(false, false)) + polydeg = 3, initial_refinement_level = 2, + mapping = mapping, periodicity = (false, false)) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, - boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver, + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -75,22 +76,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl index 1cd075e84e..0b5129e3c0 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl @@ -9,19 +9,21 @@ advection_velocity = (1.0, 0.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) x_normalized = x .- center x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length return center + x_shifted + x_offset end # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) # Store translated coordinate for easy use of exact solution # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) x_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) - + nu = diffusivity() c = 0.0 A = 1.0 @@ -32,23 +34,22 @@ end initial_condition = initial_condition_diffusive_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-pi, -pi) # minimum coordinates (min(x), min(y)) -coordinates_max = ( pi, pi) # maximum coordinates (max(x), max(y)) +coordinates_max = (pi, pi) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -62,22 +63,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl index b438fb8a29..130def3799 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl @@ -9,19 +9,21 @@ advection_velocity = (1.0, 0.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) x_normalized = x .- center x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length return center + x_shifted + x_offset end # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) # Store translated coordinate for easy use of exact solution # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) x_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) - + nu = diffusivity() c = 0.0 A = 1.0 @@ -32,28 +34,27 @@ end initial_condition = initial_condition_diffusive_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # This maps the domain [-1, 1]^2 to [-pi, pi]^2 while also # introducing a curved warping to interior nodes. function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return pi * SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return pi * SVector(x, y) end trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - mapping=mapping, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + mapping = mapping, + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,22 +68,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_extended.jl b/examples/p4est_2d_dgsem/elixir_advection_extended.jl index 6d8e7030ac..66a5b7e0f5 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_extended.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_extended.jl @@ -12,31 +12,28 @@ initial_condition = initial_condition_convergence_test # BCs must be passed as Dict boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :x_neg => boundary_condition, - :x_pos => boundary_condition, - :y_neg => boundary_condition, - :y_pos => boundary_condition -) +boundary_conditions = Dict(:x_neg => boundary_condition, + :x_pos => boundary_condition, + :y_neg => boundary_condition, + :y_pos => boundary_condition) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # The initial condition is 2-periodic coordinates_min = (-1.5, 1.3) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.5, 5.3) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.5, 5.3) # maximum coordinates (max(x), max(y)) trees_per_dimension = (19, 37) # Create curved mesh with 19 x 37 elements -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=false) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = false) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -51,24 +48,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -76,14 +73,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl index 0e6e314ebd..b47b0d6119 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -10,42 +9,44 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 4 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) # Create P4estMesh with 3 x 2 trees and 6 x 4 elements, # approximate the geometry with a smaller polydeg for testing. trees_per_dimension = (3, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - faces=(f1, f2, f3, f4), - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + faces = (f1, f2, f3, f4), + initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 4 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 4 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 4 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 4 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -58,26 +59,26 @@ ode = semidiscretize(semi, (0.0, 0.2)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_restart.jl b/examples/p4est_2d_dgsem/elixir_advection_restart.jl index 52917616a6..4f43e122ab 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_restart.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_restart.jl @@ -10,7 +10,6 @@ restart_file = "restart_000021.h5" trixi_include(@__MODULE__, joinpath(@__DIR__, elixir_file)) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -21,7 +20,7 @@ restart_filename = joinpath("out", restart_file) mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -30,14 +29,13 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) - ############################################################################### # run the simulation diff --git a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl index 9f5b813639..37fcc547f6 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl @@ -3,7 +3,6 @@ using Downloads: download using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -13,19 +12,17 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) Trixi.validate_faces(faces) @@ -33,16 +30,17 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=2) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -56,26 +54,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl index e3f33fb0d2..0ca4fdc2eb 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl @@ -17,49 +17,48 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Unstructured mesh with 48 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=Dict( - :all => BoundaryConditionDirichlet(initial_condition) - )) + boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition))) ############################################################################### # ODE solvers, callbacks etc. @@ -70,40 +69,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - max_level =3, max_threshold=0.01) + base_level = 1, + max_level = 3, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl index 70a0e10c29..92928146d7 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl @@ -21,64 +21,66 @@ See Section IV c on the paper below for details. The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) """ -@inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - - if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) - phi = pi / 6 - sin_phi, cos_phi = sincos(phi) - - rho = 8.0 - v1 = 8.25 * cos_phi - v2 = -8.25 * sin_phi - p = 116.5 - else - rho = 1.4 - v1 = 0.0 - v2 = 0.0 - p = 1.0 - end - - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_double_mach_reflection - boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) # Supersonic outflow boundary condition. Solution is taken entirely from the internal state. # See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - # NOTE: Only for the supersonic outflow is this strategy valid - # Calculate the boundary flux entirely from the internal solution state - return flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::CompressibleEulerEquations2D) + # NOTE: Only for the supersonic outflow is this strategy valid + # Calculate the boundary flux entirely from the internal solution state + return flux(u_inner, normal_direction, equations) end # Special mixed boundary condition type for the :Bottom of the domain. # It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 -@inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, +@inline function boundary_condition_mixed_dirichlet_wall(u_inner, + normal_direction::AbstractVector, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - if x[1] < 1 / 6 - # From the BoundaryConditionDirichlet - # get the external value of the solution - u_boundary = initial_condition_double_mach_reflection(x, t, equations) - # Calculate boundary flux - flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) - else # x[1] >= 1 / 6 - # Use the free slip wall BC otherwise - flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function, equations) - end - - return flux + if x[1] < 1 / 6 + # From the BoundaryConditionDirichlet + # get the external value of the solution + u_boundary = initial_condition_double_mach_reflection(x, t, equations) + # Calculate boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, + surface_flux_function, equations) + end + + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_mixed_dirichlet_wall, - :Top => boundary_condition_inflow, - :Right => boundary_condition_outflow, - :Left => boundary_condition_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_mixed_dirichlet_wall, + :Top => boundary_condition_inflow, + :Right => boundary_condition_outflow, + :Left => boundary_condition_inflow) volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs @@ -86,25 +88,27 @@ surface_flux = flux_lax_friedrichs polydeg = 4 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + 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__, "abaqus_double_mach.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -115,27 +119,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=3, med_threshold=0.05, - max_level=6, max_threshold=0.1) + base_level = 0, + med_level = 3, med_threshold = 0.05, + max_level = 6, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -143,11 +147,11 @@ callbacks = CallbackSet(summary_callback, amr_callback) # positivity limiter necessary for this example with strong shocks -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl index 667834ea10..0ec9fc222f 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl @@ -20,19 +20,18 @@ See Section IV b on the paper below for details. [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) """ @inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.4 - v1 = 3.0 - v2 = 0.0 - p_freestream = 1.0 - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = initial_condition_mach3_flow - boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_mach3_flow) # Outflow boundary condition. @@ -46,46 +45,47 @@ boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_mach3_f # Inflow/Outflow Boundary Conditions with Application to FUN3D. # [NASA TM 20110022658](https://ntrs.nasa.gov/citations/20110022658) @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - # # This would be for the general case where we need to check the magnitude of the local Mach number - # norm_ = norm(normal_direction) - # # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later - # normal = normal_direction / norm_ - - # # Rotate the internal solution state - # u_local = Trixi.rotate_to_x(u_inner, normal, equations) - - # # Compute the primitive variables - # rho_local, v_normal, v_tangent, p_local = cons2prim(u_local, equations) - - # # Compute local Mach number - # a_local = sqrt( equations.gamma * p_local / rho_local ) - # Mach_local = abs( v_normal / a_local ) - # if Mach_local <= 1.0 - # p_local = # Set to the external reference pressure value (somehow? maybe stored in `equations`) - # end - - # # Create the `u_surface` solution state where the local pressure is possibly set from an external value - # prim = SVector(rho_local, v_normal, v_tangent, p_local) - # u_boundary = prim2cons(prim, equations) - # u_surface = Trixi.rotate_from_x(u_boundary, normal, equations) - - # Compute the flux using the appropriate mixture of internal / external solution states - # flux = Trixi.flux(u_surface, normal_direction, equations) - - # NOTE: Only for the supersonic outflow is this strategy valid - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) - - return flux + surface_flux_function, + equations::CompressibleEulerEquations2D) + # # This would be for the general case where we need to check the magnitude of the local Mach number + # norm_ = norm(normal_direction) + # # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later + # normal = normal_direction / norm_ + + # # Rotate the internal solution state + # u_local = Trixi.rotate_to_x(u_inner, normal, equations) + + # # Compute the primitive variables + # rho_local, v_normal, v_tangent, p_local = cons2prim(u_local, equations) + + # # Compute local Mach number + # a_local = sqrt( equations.gamma * p_local / rho_local ) + # Mach_local = abs( v_normal / a_local ) + # if Mach_local <= 1.0 + # p_local = # Set to the external reference pressure value (somehow? maybe stored in `equations`) + # end + + # # Create the `u_surface` solution state where the local pressure is possibly set from an external value + # prim = SVector(rho_local, v_normal, v_tangent, p_local) + # u_boundary = prim2cons(prim, equations) + # u_surface = Trixi.rotate_from_x(u_boundary, normal, equations) + + # Compute the flux using the appropriate mixture of internal / external solution states + # flux = Trixi.flux(u_surface, normal_direction, equations) + + # NOTE: Only for the supersonic outflow is this strategy valid + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) + + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_slip_wall, - :Step_Front => boundary_condition_slip_wall, - :Step_Top => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Step_Front => boundary_condition_slip_wall, + :Step_Top => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_inflow) volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs @@ -93,25 +93,27 @@ surface_flux = flux_lax_friedrichs polydeg = 4 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + 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__, "abaqus_forward_step.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -122,27 +124,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=2000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 2000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=2, med_threshold=0.05, - max_level=5, max_threshold=0.1) + base_level = 0, + med_level = 2, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -150,12 +152,12 @@ callbacks = CallbackSet(summary_callback, amr_callback) # positivity limiter necessary for this example with strong shocks -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - maxiters=999999, ode_default_options()..., - callback=callbacks); + maxiters = 999999, ode_default_options()..., + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl index e88baa2223..38307a7d78 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl @@ -10,21 +10,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end ############################################################################### @@ -32,34 +32,34 @@ end # Unstructured mesh with 48 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + mesh_file) # Map the unstructured mesh with the mapping above -mesh = P4estMesh{2}(mesh_file, polydeg=3, mapping=mapping, initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping, initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 3 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 3 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=Dict( - :all => BoundaryConditionDirichlet(initial_condition) - )) - + boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition))) ############################################################################### # ODE solvers, callbacks etc. @@ -70,16 +70,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_euler_sedov.jl b/examples/p4est_2d_dgsem/elixir_euler_sedov.jl index d5d8e0c78b..539ddb4539 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,26 +43,27 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -75,15 +76,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -94,7 +95,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl b/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl index 6ef551c486..0cb18526f8 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl @@ -14,30 +14,30 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -47,16 +47,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -66,7 +66,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl index d9a322b065..09d018309a 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl @@ -14,18 +14,16 @@ source_terms = source_terms_convergence_test # BCs must be passed as Dict boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) Trixi.validate_faces(faces) @@ -34,34 +32,36 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) - + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -72,19 +72,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -93,7 +93,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl index 366be700f9..36c5624ba9 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl @@ -23,14 +23,14 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) @inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.4 - v1 = 3.0 - v2 = 0.0 - p_freestream = 1.0 - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = initial_condition_mach3_flow @@ -38,30 +38,32 @@ initial_condition = initial_condition_mach3_flow # Supersonic inflow boundary condition. # Calculate the boundary flux entirely from the external solution state, i.e., set # external solution state values for everything entering the domain. -@inline function boundary_condition_supersonic_inflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - u_boundary = initial_condition_mach3_flow(x, t, equations) - flux = Trixi.flux(u_boundary, normal_direction, equations) - - return flux +@inline function boundary_condition_supersonic_inflow(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach3_flow(x, t, equations) + flux = Trixi.flux(u_boundary, normal_direction, equations) + + return flux end - # Supersonic outflow boundary condition. # Calculate the boundary flux entirely from the internal solution state. Analogous to supersonic inflow # except all the solution state values are set from the internal solution as everything leaves the domain @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::CompressibleEulerEquations2D) + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_slip_wall, - :Circle => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_supersonic_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Circle => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_supersonic_inflow) volume_flux = flux_ranocha_turbo surface_flux = flux_lax_friedrichs @@ -69,25 +71,27 @@ surface_flux = flux_lax_friedrichs polydeg = 3 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + 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__, "abaqus_cylinder_in_channel.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers @@ -100,26 +104,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=3, med_threshold=0.05, - max_level=5, max_threshold=0.1) + base_level = 0, + med_level = 3, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -128,11 +132,11 @@ callbacks = CallbackSet(summary_callback, # positivity limiter necessary for this example with strong shocks. Very sensitive # to the order of the limiter variables, pressure must come first. -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-7, 1.0e-6), - variables=(pressure, Trixi.density)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-7, 1.0e-6), + variables = (pressure, Trixi.density)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl index 7c7896ce37..8b8d05bade 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl @@ -9,45 +9,46 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) @inline function uniform_flow_state(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.0 - u_freestream = 0.3 - p_freestream = inv(equations.gamma) - - theta = pi / 90.0 # analogous with a two degree angle of attack - si, co = sincos(theta) - v1 = u_freestream * co - v2 = u_freestream * si - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.0 + u_freestream = 0.3 + p_freestream = inv(equations.gamma) + + theta = pi / 90.0 # analogous with a two degree angle of attack + si, co = sincos(theta) + v1 = u_freestream * co + v2 = u_freestream * si + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = uniform_flow_state boundary_condition_uniform_flow = BoundaryConditionDirichlet(uniform_flow_state) -boundary_conditions = Dict( :Body => boundary_condition_uniform_flow, - :Button1 => boundary_condition_slip_wall, - :Button2 => boundary_condition_slip_wall, - :Eye1 => boundary_condition_slip_wall, - :Eye2 => boundary_condition_slip_wall, - :Smile => boundary_condition_slip_wall, - :Bowtie => boundary_condition_slip_wall ) +boundary_conditions = Dict(:Body => boundary_condition_uniform_flow, + :Button1 => boundary_condition_slip_wall, + :Button2 => boundary_condition_slip_wall, + :Eye1 => boundary_condition_slip_wall, + :Eye2 => boundary_condition_slip_wall, + :Smile => boundary_condition_slip_wall, + :Bowtie => boundary_condition_slip_wall) volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "abaqus_gingerbread_man.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -58,36 +59,35 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=density) +amr_indicator = IndicatorLöhner(semi, variable = density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=1, med_threshold=0.05, - max_level=3, max_threshold=0.1) + base_level = 0, + med_level = 1, med_threshold = 0.05, + max_level = 3, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-7, reltol=1.0e-7, - ode_default_options()..., callback=callbacks); +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/p4est_2d_dgsem/elixir_eulergravity_convergence.jl b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl index b34c73d2a4..d55a59ca5c 100644 --- a/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl @@ -2,10 +2,8 @@ using OrdinaryDiffEq using Trixi - initial_condition = initial_condition_eoc_test_coupled_euler_gravity - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 2.0 @@ -18,13 +16,13 @@ coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) trees_per_dimension = (1, 1) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=2) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 2) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -32,24 +30,23 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 # rho0 is (ab)used to add a "+8π" term to the source terms # for the manufactured solution - gravitational_constant=1.0, # aka G - cfl=1.1, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) + gravitational_constant = 1.0, # aka G + cfl = 1.1, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -57,31 +54,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) callbacks = CallbackSet(summary_callback, stepsize_callback, save_restart, save_solution, analysis_callback, alive_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl b/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl index ba2ec82777..364e029644 100644 --- a/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl +++ b/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl @@ -8,20 +8,22 @@ using Trixi # Oscillating Gaussian-shaped source terms function source_terms_gauss(u, x, t, equations::LinearizedEulerEquations2D) - r = 0.1 - A = 1.0 - f = 2.0 + r = 0.1 + A = 1.0 + f = 2.0 - # Velocity sources - s2 = 0.0 - s3 = 0.0 - # Density and pressure source - s1 = s4 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) + # Velocity sources + s2 = 0.0 + s3 = 0.0 + # Density and pressure source + s1 = s4 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) - return SVector(s1, s2, s3, s4) + return SVector(s1, s2, s3, s4) end -initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) = SVector(0.0, 0.0, 0.0, 0.0) +function initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) + SVector(0.0, 0.0, 0.0, 0.0) +end ############################################################################### # semidiscretization of the linearized Euler equations @@ -30,28 +32,27 @@ initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) = SVector(0. c = cospi(2 * 30.0 / 360.0) s = sinpi(2 * 30.0 / 360.0) rot_mat = Trixi.SMatrix{2, 2}([c -s; s c]) -mapping(xi, eta) = rot_mat * SVector(3.0*xi, 3.0*eta) +mapping(xi, eta) = rot_mat * SVector(3.0 * xi, 3.0 * eta) # Mean density and speed of sound are slightly off from 1.0 to allow proper verification of # curved LEE implementation using this elixir (some things in the LEE cancel if both are 1.0) -equations = LinearizedEulerEquations2D(v_mean_global=Tuple(rot_mat * SVector(-0.5, 0.25)), - c_mean_global=1.02, rho_mean_global=1.01) +equations = LinearizedEulerEquations2D(v_mean_global = Tuple(rot_mat * SVector(-0.5, 0.25)), + c_mean_global = 1.02, rho_mean_global = 1.01) initial_condition = initial_condition_zero # Create DG solver with polynomial degree = 3 and upwind flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) # Create a uniformly refined mesh with periodic boundaries trees_per_dimension = (4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - mapping=mapping, - periodicity=true, initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + mapping = mapping, + periodicity = true, initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_gauss) - + source_terms = source_terms_gauss) ############################################################################### # ODE solvers, callbacks etc. @@ -65,25 +66,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100) +save_solution = SaveSolutionCallback(interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl index 66bce781f6..93db7bfdba 100644 --- a/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -2,28 +2,27 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -coordinates_min = (0.0 , 0.0 ) +coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) trees_per_dimension = (8, 8) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=0, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 0, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -36,14 +35,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 0.9 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,7 +53,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_mhd_rotor.jl b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl index 58915a8f6a..380db48735 100644 --- a/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl @@ -16,74 +16,74 @@ The classical MHD rotor test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_rotor(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho = 10.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - else - rho = 1.0 + 9.0*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho = 10.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + else + rho = 1.0 + 9.0 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Affine type mapping to take the [-1,1]^2 domain from the mesh file # and put it onto the rotor domain [0,1]^2 and then warp it with a mapping # as described in https://arxiv.org/abs/2012.12040 function mapping_twist(xi, eta) - y = 0.5 * (eta + 1.0) + 0.05 * cos(1.5 * pi * (2.0 * xi - 1.0)) * cos(0.5 * pi * (2.0 * eta - 1.0)) - x = 0.5 * (xi + 1.0) + 0.05 * cos(0.5 * pi * (2.0 * xi - 1.0)) * cos(2.0 * pi * y) - return SVector(x, y) + y = 0.5 * (eta + 1.0) + + 0.05 * cos(1.5 * pi * (2.0 * xi - 1.0)) * cos(0.5 * pi * (2.0 * eta - 1.0)) + x = 0.5 * (xi + 1.0) + 0.05 * cos(0.5 * pi * (2.0 * xi - 1.0)) * cos(2.0 * pi * y) + return SVector(x, y) end - mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) mesh = P4estMesh{2}(mesh_file, - polydeg=4, - mapping=mapping_twist, - initial_refinement_level=1) + polydeg = 4, + mapping = mapping_twist, + initial_refinement_level = 1) boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :all => boundary_condition ) +boundary_conditions = Dict(:all => boundary_condition) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -94,31 +94,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - med_level =3, med_threshold=0.05, - max_level =5, max_threshold=0.1) + base_level = 1, + med_level = 3, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -131,7 +131,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_2d_dgsem/elixir_navierstokes_convergence.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl index b0c6086ad6..7aa14e2575 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl @@ -8,174 +8,182 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, false)) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, false)) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types velocity_bc_top_bottom = NoSlip() do x, t, equations - u = initial_condition_navier_stokes_convergence_test(x, t, equations) - return SVector(u[2], u[3]) + u = initial_condition_navier_stokes_convergence_test(x, t, equations) + return SVector(u[2], u[3]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, @@ -185,9 +193,11 @@ boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, boundary_conditions_parabolic = Dict(:y_neg => boundary_condition_top_bottom, :y_pos => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) # ############################################################################### # # ODE solvers, callbacks etc. @@ -197,16 +207,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl index 935f132ba4..b4177fe853 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl @@ -8,171 +8,182 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(false, false)) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (false, false)) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) boundary_condition_left_right = BoundaryConditionDirichlet(initial_condition_navier_stokes_convergence_test) @@ -188,9 +199,11 @@ boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_left_right, :y_neg => boundary_condition_top_bottom, :y_pos => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) # ############################################################################### # # ODE solvers, callbacks etc. @@ -200,16 +213,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl index 051f4defe5..e6566edb18 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,28 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(false, false)) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (false, false)) function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -42,21 +42,21 @@ boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) # define periodic boundary conditions everywhere -boundary_conditions = Dict( :x_neg => boundary_condition_slip_wall, - :y_neg => boundary_condition_slip_wall, - :y_pos => boundary_condition_slip_wall, - :x_pos => boundary_condition_slip_wall) +boundary_conditions = Dict(:x_neg => boundary_condition_slip_wall, + :y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall, + :x_pos => boundary_condition_slip_wall) -boundary_conditions_parabolic = Dict( :x_neg => boundary_condition_cavity, - :y_neg => boundary_condition_cavity, - :y_pos => boundary_condition_lid, - :x_pos => boundary_condition_cavity) +boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_cavity, + :y_neg => boundary_condition_cavity, + :y_pos => boundary_condition_lid, + :x_pos => boundary_condition_cavity) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -66,17 +66,15 @@ tspan = (0.0, 25.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=100) +alive_callback = AliveCallback(alive_interval = 100) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - - diff --git a/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl index b185a8ce39..c7922fd3b7 100644 --- a/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the P4estMesh and setup a periodic mesh @@ -25,14 +25,13 @@ coordinates_max = (sqrt(2.0), sqrt(2.0)) # maximum coordinates (max(x), max(y)) # Create P4estMesh with 8 x 8 trees and 16 x 16 elements trees_per_dimension = (8, 8) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -44,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -58,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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/p4est_3d_dgsem/elixir_advection_amr.jl b/examples/p4est_3d_dgsem/elixir_advection_amr.jl index 0473fd2b23..d56ecc233f 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_amr.jl @@ -11,23 +11,21 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) trees_per_dimension = (1, 1, 1) # Note that it is not necessary to use mesh polydeg lower than the solver polydeg # on a Cartesian mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=4) - +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 4) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -68,7 +66,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl index fb87c361c1..cd280cf5bf 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl @@ -12,54 +12,55 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_gauss boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/4 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/4 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/4 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the size of [-5,5]^3 to match IC - return SVector(5 * x, 5 * y, 5 * z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 4 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 4 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 4 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the size of [-5,5]^3 to match IC + return SVector(5 * x, 5 * y, 5 * z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=1) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 1) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -70,29 +71,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=1, - med_level=2, med_threshold=0.1, - max_level=3, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 0.1, + max_level = 3, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -105,7 +106,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_3d_dgsem/elixir_advection_basic.jl b/examples/p4est_3d_dgsem/elixir_advection_basic.jl index a165d1ff13..02ffa5c7af 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_basic.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_basic.jl @@ -11,19 +11,20 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create P4estMesh with 8 x 8 x 8 elements (note `refinement_level=1`) trees_per_dimension = (4, 4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -37,30 +38,30 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl b/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl index 07a8b36bb4..cd641ca4af 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl @@ -9,21 +9,20 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :inside => boundary_condition, - :outside => boundary_condition, -) +boundary_conditions = Dict(:inside => boundary_condition, + :outside => boundary_condition) mesh = Trixi.P4estMeshCubedSphere(5, 3, 0.5, 0.5, - polydeg=3, initial_refinement_level=0) + polydeg = 3, initial_refinement_level = 0) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +36,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl index 93ff17c784..34b0e95834 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -10,39 +9,42 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) trees_per_dimension = (1, 1, 1) # Note that it is not necessary to use mesh polydeg lower than the solver polydeg # on a Cartesian mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 2) # Refine bottom left quadrant of each tree to level 3 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 3 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 3 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 3 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -56,26 +58,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_restart.jl b/examples/p4est_3d_dgsem/elixir_advection_restart.jl index 26d10cf882..cd97d69d69 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_restart.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_restart.jl @@ -6,8 +6,7 @@ using Trixi # create a restart file trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), - trees_per_dimension=(2, 2, 2)) - + trees_per_dimension = (2, 2, 2)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,7 +17,8 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), restart_filename = joinpath("out", "restart_000010.h5") mesh = load_mesh(restart_filename) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -27,14 +27,13 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) - ############################################################################### # run the simulation diff --git a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl index 85fd0b9a2c..6df9ac0b16 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl @@ -10,51 +10,54 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=3, - mapping=mapping, - initial_refinement_level=2) +mesh = P4estMesh{3}(mesh_file, polydeg = 3, + mapping = mapping, + initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -68,32 +71,32 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, + save_solution, stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl b/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl index 27c8ceb130..0274a89aec 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl @@ -22,190 +22,194 @@ equations = CompressibleEulerEquations3D(gamma) # Initial condition for an idealized baroclinic instability test # https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A -function initial_condition_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) +function initial_condition_baroclinic_instability(x, t, + equations::CompressibleEulerEquations3D) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Stream function type perturbation - u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) + # Stream function type perturbation + u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) - u += u_perturbation - v = v_perturbation + u += u_perturbation + v = v_perturbation - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - sin(lat) * cos(lon) * v - v2 = cos(lon) * u - sin(lat) * sin(lon) * v - v3 = cos(lat) * v + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u - sin(lat) * cos(lon) * v + v2 = cos(lon) * u - sin(lat) * sin(lon) * v + v3 = cos(lat) * v - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end # Steady state for RHS correction below function steady_state_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - v2 = cos(lon) * u - v3 = 0.0 + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u + v2 = cos(lon) * u + v3 = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end function cartesian_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end # Unperturbed balanced steady-state. # Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). # The other velocity components are zero. function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - radius_earth = 6.371229e6 # a - half_width_parameter = 2 # b - gravitational_acceleration = 9.80616 # g - k = 3 # k - surface_pressure = 1e5 # p₀ - gas_constant = 287 # R - surface_equatorial_temperature = 310.0 # T₀ᴱ - surface_polar_temperature = 240.0 # T₀ᴾ - lapse_rate = 0.005 # Γ - angular_velocity = 7.29212e-5 # Ω - - # Distance to the center of the Earth - r = z + radius_earth - - # In the paper: T₀ - temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) - # In the paper: A, B, C, H - const_a = 1 / lapse_rate - const_b = (temperature0 - surface_polar_temperature) / - (temperature0 * surface_polar_temperature) - const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / - (surface_equatorial_temperature * surface_polar_temperature) - const_h = gas_constant * temperature0 / gravitational_acceleration - - # In the paper: (r - a) / bH - scaled_z = z / (half_width_parameter * const_h) - - # Temporary variables - temp1 = exp(lapse_rate/temperature0 * z) - temp2 = exp(-scaled_z^2) - - # In the paper: ̃τ₁, ̃τ₂ - tau1 = const_a * lapse_rate / temperature0 * temp1 + const_b * (1 - 2 * scaled_z^2) * temp2 - tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 - - # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' - inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 - inttau2 = const_c * z * temp2 - - # Temporary variables - temp3 = r/radius_earth * cos(lat) - temp4 = temp3^k - k/(k + 2) * temp3^(k+2) - - # In the paper: T - temperature = 1 / ((r/radius_earth)^2 * (tau1 - tau2 * temp4)) - - # In the paper: U, u (zonal wind, first component of spherical velocity) - big_u = gravitational_acceleration/radius_earth * k * temperature * inttau2 * (temp3^(k-1) - temp3^(k+1)) - temp5 = radius_earth * cos(lat) - u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) - - # Hydrostatic pressure - p = surface_pressure * exp(-gravitational_acceleration/gas_constant * (inttau1 - inttau2 * temp4)) - - # Density (via ideal gas law) - rho = p / (gas_constant * temperature) - - return rho, u, p + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + radius_earth = 6.371229e6 # a + half_width_parameter = 2 # b + gravitational_acceleration = 9.80616 # g + k = 3 # k + surface_pressure = 1e5 # p₀ + gas_constant = 287 # R + surface_equatorial_temperature = 310.0 # T₀ᴱ + surface_polar_temperature = 240.0 # T₀ᴾ + lapse_rate = 0.005 # Γ + angular_velocity = 7.29212e-5 # Ω + + # Distance to the center of the Earth + r = z + radius_earth + + # In the paper: T₀ + temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) + # In the paper: A, B, C, H + const_a = 1 / lapse_rate + const_b = (temperature0 - surface_polar_temperature) / + (temperature0 * surface_polar_temperature) + const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / + (surface_equatorial_temperature * surface_polar_temperature) + const_h = gas_constant * temperature0 / gravitational_acceleration + + # In the paper: (r - a) / bH + scaled_z = z / (half_width_parameter * const_h) + + # Temporary variables + temp1 = exp(lapse_rate / temperature0 * z) + temp2 = exp(-scaled_z^2) + + # In the paper: ̃τ₁, ̃τ₂ + tau1 = const_a * lapse_rate / temperature0 * temp1 + + const_b * (1 - 2 * scaled_z^2) * temp2 + tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 + + # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' + inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 + inttau2 = const_c * z * temp2 + + # Temporary variables + temp3 = r / radius_earth * cos(lat) + temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) + + # In the paper: T + temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) + + # In the paper: U, u (zonal wind, first component of spherical velocity) + big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * + (temp3^(k - 1) - temp3^(k + 1)) + temp5 = radius_earth * cos(lat) + u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) + + # Hydrostatic pressure + p = surface_pressure * + exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) + + # Density (via ideal gas law) + rho = p / (gas_constant * temperature) + + return rho, u, p end # Perturbation as in Equations 25 and 26 of the paper (analytical derivative) function perturbation_stream_function(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - perturbation_radius = 1/6 # d₀ / a - perturbed_wind_amplitude = 1.0 # Vₚ - perturbation_lon = pi/9 # Longitude of perturbation location - perturbation_lat = 2 * pi/9 # Latitude of perturbation location - pertz = 15000 # Perturbation height cap - - # Great circle distance (d in the paper) divided by a (radius of the Earth) - # because we never actually need d without dividing by a - great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + - cos(perturbation_lat) * cos(lat) * - cos(lon - perturbation_lon)) - - # In the first case, the vertical taper function is per definition zero. - # In the second case, the stream function is per definition zero. - if z > pertz || great_circle_distance_by_a > perturbation_radius - return 0.0, 0.0 - end - - # Vertical tapering of stream function - perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 - - # sin/cos(pi * d / (2 * d_0)) in the paper - sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) - - # Common factor for both u and v - factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ - - u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + - cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon) - ) / sin(great_circle_distance_by_a) - - v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / - sin(great_circle_distance_by_a) - - return u_perturbation, v_perturbation -end + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + perturbation_radius = 1 / 6 # d₀ / a + perturbed_wind_amplitude = 1.0 # Vₚ + perturbation_lon = pi / 9 # Longitude of perturbation location + perturbation_lat = 2 * pi / 9 # Latitude of perturbation location + pertz = 15000 # Perturbation height cap + + # Great circle distance (d in the paper) divided by a (radius of the Earth) + # because we never actually need d without dividing by a + great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + + cos(perturbation_lat) * cos(lat) * + cos(lon - perturbation_lon)) + + # In the first case, the vertical taper function is per definition zero. + # In the second case, the stream function is per definition zero. + if z > pertz || great_circle_distance_by_a > perturbation_radius + return 0.0, 0.0 + end + + # Vertical tapering of stream function + perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 + + # sin/cos(pi * d / (2 * d_0)) in the paper + sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) + # Common factor for both u and v + factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ -@inline function source_terms_baroclinic_instability(u, x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 # a - gravitational_acceleration = 9.80616 # g - angular_velocity = 7.29212e-5 # Ω + u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + + cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / + sin(great_circle_distance_by_a) - r = norm(x) - # Make sure that r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) - r = z + radius_earth + v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / + sin(great_circle_distance_by_a) - du1 = zero(eltype(u)) + return u_perturbation, v_perturbation +end + +@inline function source_terms_baroclinic_instability(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 # a + gravitational_acceleration = 9.80616 # g + angular_velocity = 7.29212e-5 # Ω + + r = norm(x) + # Make sure that r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + r = z + radius_earth - # Gravity term - temp = -gravitational_acceleration * radius_earth^2 / r^3 - du2 = temp * u[1] * x[1] - du3 = temp * u[1] * x[2] - du4 = temp * u[1] * x[3] - du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) + du1 = zero(eltype(u)) - # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] - du2 -= -2 * angular_velocity * u[3] - du3 -= 2 * angular_velocity * u[2] + # Gravity term + temp = -gravitational_acceleration * radius_earth^2 / r^3 + du2 = temp * u[1] * x[1] + du3 = temp * u[1] * x[2] + du4 = temp * u[1] * x[3] + du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) - return SVector(du1, du2, du3, du4, du5) + # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] + du2 -= -2 * angular_velocity * u[3] + du3 -= 2 * angular_velocity * u[2] + + return SVector(du1, du2, du3, du4, du5) end ############################################################################### @@ -213,26 +217,24 @@ end initial_condition = initial_condition_baroclinic_instability -boundary_conditions = Dict( - :inside => boundary_condition_slip_wall, - :outside => boundary_condition_slip_wall, -) +boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) # This is a good estimate for the speed of sound in this example. # Other values between 300 and 400 should work as well. surface_flux = FluxLMARS(340) -volume_flux = flux_kennedy_gruber -solver = DGSEM(polydeg=5, surface_flux=surface_flux, volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = flux_kennedy_gruber +solver = DGSEM(polydeg = 5, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # For optimal results, use (16, 8) here trees_per_cube_face = (8, 4) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=5, initial_refinement_level=0) + polydeg = 5, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_baroclinic_instability, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_baroclinic_instability, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -250,20 +252,20 @@ tspan = (0.0, 10 * 24 * 60 * 60.0) # time in seconds for 10 days u_steady_state = compute_coefficients(steady_state_baroclinic_instability, tspan[1], semi) # Use a `let` block for performance (otherwise du_steady_state will be a global variable) let du_steady_state = similar(u_steady_state) - # Save RHS of the steady state - Trixi.rhs!(du_steady_state, u_steady_state, semi, tspan[1]) - - global function corrected_rhs!(du, u, semi, t) - # Normal RHS evaluation - Trixi.rhs!(du, u, semi, t) - # Correct by subtracting the steady-state RHS - Trixi.@trixi_timeit Trixi.timer() "rhs correction" begin - # Use Trixi.@threaded for threaded performance - Trixi.@threaded for i in eachindex(du) - du[i] -= du_steady_state[i] - end + # Save RHS of the steady state + Trixi.rhs!(du_steady_state, u_steady_state, semi, tspan[1]) + + global function corrected_rhs!(du, u, semi, t) + # Normal RHS evaluation + Trixi.rhs!(du, u, semi, t) + # Correct by subtracting the steady-state RHS + Trixi.@trixi_timeit Trixi.timer() "rhs correction" begin + # Use Trixi.@threaded for threaded performance + Trixi.@threaded for i in eachindex(du) + du[i] -= du_steady_state[i] + end + end end - end end u0 = compute_coefficients(tspan[1], semi) ode = ODEProblem(corrected_rhs!, u0, tspan, semi) @@ -271,27 +273,27 @@ ode = ODEProblem(corrected_rhs!, u0, tspan, semi) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) 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 # Enable threading of the RK method for better performance on multiple threads -sol = solve(ode, RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()); abstol = 1.0e-6, + reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl index 63e937620f..34a43a5b53 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl @@ -14,78 +14,77 @@ using LinearAlgebra gamma = 1.4 equations = CompressibleEulerEquations3D(gamma) - function initial_condition_circular_wind(x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 - p = 1e5 - rho = 1.0 - v1 = -10 * x[2] / radius_earth - v2 = 10 * x[1] / radius_earth - v3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + radius_earth = 6.371229e6 + p = 1e5 + rho = 1.0 + v1 = -10 * x[2] / radius_earth + v2 = 10 * x[1] / radius_earth + v3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end -@inline function source_terms_circular_wind(u, x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 - rho = 1.0 +@inline function source_terms_circular_wind(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 + rho = 1.0 - du1 = 0.0 - du2 = -rho * (10 / radius_earth) * (10 * x[1] / radius_earth) - du3 = -rho * (10 / radius_earth) * (10 * x[2] / radius_earth) - du4 = 0.0 - du5 = 0.0 + du1 = 0.0 + du2 = -rho * (10 / radius_earth) * (10 * x[1] / radius_earth) + du3 = -rho * (10 / radius_earth) * (10 * x[2] / radius_earth) + du4 = 0.0 + du5 = 0.0 - return SVector(du1, du2, du3, du4, du5) + return SVector(du1, du2, du3, du4, du5) end - -function indicator_test(u::AbstractArray{<:Any,5}, +function indicator_test(u::AbstractArray{<:Any, 5}, mesh, equations, dg::DGSEM, cache; kwargs...) - alpha = zeros(Int, nelements(dg, cache)) - - for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, k, element) - lambda, phi, r = cart_to_sphere(x) - if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 - alpha[element] = 1 - end + alpha = zeros(Int, nelements(dg, cache)) + + for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, + k, element) + lambda, phi, r = cart_to_sphere(x) + if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 + alpha[element] = 1 + end + end end - end - return alpha + return alpha end function cart_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end -function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), ::AMRCallback) - return nothing +function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), + ::AMRCallback) + return nothing end initial_condition = initial_condition_circular_wind -boundary_conditions = Dict( - :inside => boundary_condition_slip_wall, - :outside => boundary_condition_slip_wall -) +boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) # The speed of sound in this example is 374 m/s. surface_flux = FluxLMARS(374) # Note that a free stream is not preserved if N < 2 * N_geo, where N is the # polydeg of the solver and N_geo is the polydeg of the mesh. # However, the FSP error is negligible in this example. -solver = DGSEM(polydeg=4, surface_flux=surface_flux) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux) # Other mesh configurations to run this simulation on. # The cylinder allows to use a structured mesh, the face of the cubed sphere @@ -113,12 +112,11 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux) trees_per_cube_face = (6, 2) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=4, initial_refinement_level=0) + polydeg = 4, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_circular_wind, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_circular_wind, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -129,22 +127,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, indicator_test, - base_level=0, - max_level=1, max_threshold=0.6) + base_level = 0, + max_level = 1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=0, # Only initial refinement - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 0, # Only initial refinement + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -152,13 +150,13 @@ callbacks = CallbackSet(summary_callback, save_solution, amr_callback) - ############################################################################### # run the simulation # Use a Runge-Kutta method with automatic (error based) time step size control # Enable threading of the RK method for better performance on multiple threads -sol = solve(ode, RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()); abstol = 1.0e-6, + reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_ec.jl b/examples/p4est_3d_dgsem/elixir_euler_ec.jl index 463a26fca5..d9d774a7ff 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_ec.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_ec.jl @@ -6,56 +6,59 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations3D(5/3) +equations = CompressibleEulerEquations3D(5 / 3) initial_condition = initial_condition_weak_blast_wave -boundary_conditions = Dict( - :all => boundary_condition_slip_wall -) +boundary_conditions = Dict(:all => boundary_condition_slip_wall) # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a file # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=5, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 5, + mapping = mapping, + initial_refinement_level = 0) # create the semidiscretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -66,15 +69,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -85,7 +88,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_3d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl index 3450adfe86..24a781ca59 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl @@ -10,70 +10,75 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -boundary_conditions = Dict( - :all => BoundaryConditionDirichlet(initial_condition) -) +boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition)) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. This can yield problematic geometries if the unrefined mesh # is not fine enough. function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 0) # Refine bottom left quadrant of each second tree to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if iseven(convert(Int, which_tree)) && quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if iseven(convert(Int, which_tree)) && quadrant_obj.x == 0 && quadrant_obj.y == 0 && + quadrant_obj.z == 0 && quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of every second tree has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -84,27 +89,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) 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); +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/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl index 630a269b4a..f56fe3a429 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl @@ -10,12 +10,10 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -boundary_conditions = Dict( - :all => BoundaryConditionDirichlet(initial_condition) -) +boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition)) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. # This particular mesh is unstructured in the yz-plane, but extruded in x-direction. @@ -23,47 +21,52 @@ solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, # in x-direction to ensure free stream preservation on a non-conforming mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. function mapping(xi, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 - z = zeta + 1/6 * (cos(1.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) + z = zeta + + 1 / 6 * (cos(1.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) - y = eta + 1/6 * (cos(0.5 * pi * (2 * eta - 3)/3) * - cos(2 * pi * (2 * z - 3)/3)) + y = eta + 1 / 6 * (cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(2 * pi * (2 * z - 3) / 3)) - return SVector(xi, y, z) + return SVector(xi, y, z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=3, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 3, + mapping = mapping, + initial_refinement_level = 0) # Refine quadrants in y-direction of each tree at one edge to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if convert(Int, which_tree) < 4 && quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if convert(Int, which_tree) < 4 && quadrant_obj.x == 0 && quadrant_obj.y == 0 && + quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each desired quadrant has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -74,30 +77,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), #maxiters=1, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), #maxiters=1, + 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/p4est_3d_dgsem/elixir_euler_sedov.jl b/examples/p4est_3d_dgsem/elixir_euler_sedov.jl index 6fa285b556..8df95a3cc2 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_sedov.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_sedov.jl @@ -14,28 +14,29 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 with smaller strength of the initial discontinuity. """ -function initial_condition_medium_sedov_blast_wave(x, t, equations::CompressibleEulerEquations3D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) - p0_outer = 1.0e-3 - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_medium_sedov_blast_wave(x, t, + equations::CompressibleEulerEquations3D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) + p0_outer = 1.0e-3 + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_medium_sedov_blast_wave @@ -45,24 +46,25 @@ volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) trees_per_dimension = (4, 4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=0, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 0, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -76,15 +78,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -95,7 +97,7 @@ callbacks = CallbackSet(summary_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); +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/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl index c5e349934a..28a300cd68 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl @@ -11,68 +11,68 @@ using LinearAlgebra gamma = 1.4 equations = CompressibleEulerEquations3D(gamma) +function initial_condition_convergence_test_sphere(x, t, + equations::CompressibleEulerEquations3D) + x_scaled = x / 6.371229e6 + t_scaled = t / 6.371229e6 -function initial_condition_convergence_test_sphere(x, t, equations::CompressibleEulerEquations3D) - x_scaled = x / 6.371229e6 - t_scaled = t / 6.371229e6 - - return initial_condition_convergence_test(x_scaled, t_scaled, equations) + return initial_condition_convergence_test(x_scaled, t_scaled, equations) end -@inline function source_terms_convergence_test_sphere(u, x, t, equations::CompressibleEulerEquations3D) - x_scaled = x / 6.371229e6 - t_scaled = t / 6.371229e6 +@inline function source_terms_convergence_test_sphere(u, x, t, + equations::CompressibleEulerEquations3D) + x_scaled = x / 6.371229e6 + t_scaled = t / 6.371229e6 - return source_terms_convergence_test(u, x_scaled, t_scaled, equations) / 6.371229e6 + return source_terms_convergence_test(u, x_scaled, t_scaled, equations) / 6.371229e6 end - -function indicator_test(u::AbstractArray{<:Any,5}, +function indicator_test(u::AbstractArray{<:Any, 5}, mesh, equations, dg::DGSEM, cache; kwargs...) - alpha = zeros(Int, nelements(dg, cache)) - - for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, k, element) - lambda, phi, r = cart_to_sphere(x) - if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 - alpha[element] = 1 - end + alpha = zeros(Int, nelements(dg, cache)) + + for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, + k, element) + lambda, phi, r = cart_to_sphere(x) + if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 + alpha[element] = 1 + end + end end - end - return alpha + return alpha end function cart_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end -function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), ::AMRCallback) - return nothing +function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), + ::AMRCallback) + return nothing end initial_condition = initial_condition_convergence_test_sphere boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :inside => boundary_condition, - :outside => boundary_condition -) +boundary_conditions = Dict(:inside => boundary_condition, + :outside => boundary_condition) surface_flux = flux_hll # Note that a free stream is not preserved if N < 2 * N_geo, where N is the # polydeg of the solver and N_geo is the polydeg of the mesh. # However, the FSP error is negligible in this example. -solver = DGSEM(polydeg=4, surface_flux=surface_flux) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux) # For performance reasons, only one face of the cubed sphere can be used: @@ -87,12 +87,11 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux) trees_per_cube_face = (6, 2) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=4, initial_refinement_level=0) + polydeg = 4, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test_sphere, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test_sphere, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -103,22 +102,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, indicator_test, - base_level=0, - max_level=1, max_threshold=0.6) + base_level = 0, + max_level = 1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=0, # Only initial refinement - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 0, # Only initial refinement + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -126,12 +125,11 @@ callbacks = CallbackSet(summary_callback, save_solution, amr_callback) - ############################################################################### # run the simulation # Use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl index dd39409175..0de22eaea4 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl @@ -11,73 +11,77 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the cube [0,2]^3 - return SVector(x + 1, y + 1, z + 1) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the cube [0,2]^3 + return SVector(x + 1, y + 1, z + 1) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 0) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -88,27 +92,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl index cd796c33e4..fc5e4da3ce 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -10,31 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :x_neg => boundary_condition, - :x_pos => boundary_condition, - :y_neg => boundary_condition, - :y_pos => boundary_condition, - :z_neg => boundary_condition, - :z_pos => boundary_condition -) - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +boundary_conditions = Dict(:x_neg => boundary_condition, + :x_pos => boundary_condition, + :y_neg => boundary_condition, + :y_pos => boundary_condition, + :z_neg => boundary_condition, + :z_pos => boundary_condition) + +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=false, initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = false, initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -45,27 +42,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl index ff101bea8a..0fa3a28fe8 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl @@ -11,25 +11,25 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Bottom => boundary_condition, - :Top => boundary_condition, - :Circle => boundary_condition, - :Cut => boundary_condition ) +boundary_conditions = Dict(:Bottom => boundary_condition, + :Top => boundary_condition, + :Circle => boundary_condition, + :Cut => boundary_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Unstructured 3D half circle mesh from HOHQMesh default_mesh_file = joinpath(@__DIR__, "abaqus_half_circle_3d.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", + default_mesh_file) mesh_file = default_mesh_file -mesh = P4estMesh{3}(mesh_file, initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,17 +40,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=50, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -58,12 +58,11 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1, # 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/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl index 8fe96ae3de..6a62368ef9 100644 --- a/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl @@ -5,40 +5,43 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) # Create P4estMesh with 2 x 2 x 2 trees trees_per_dimension = (2, 2, 2) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # OBS! Workaround to add a refinement patch after mesh is constructed # Refine bottom left quadrant of each tree to level 4 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 4 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 4 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 4 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -52,18 +55,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -71,11 +74,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl b/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl index fc95d427ab..3941a40b2e 100644 --- a/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl @@ -17,71 +17,74 @@ Weak magnetic blast wave setup taken from Section 6.1 of the paper: [doi: 10.1016/j.jcp.2021.110580](https://doi.org/10.1016/j.jcp.2021.110580) """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations3D) - # Center of the blast wave is selected for the domain [0, 3]^3 - inicenter = (1.5, 1.5, 1.5) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - delta_0 = 0.1 - r_0 = 0.3 - lambda = exp(5.0 / delta_0 * (r - r_0)) - - prim_inner = SVector(1.2, 0.1, 0.0, 0.1, 0.9, 1.0, 1.0, 1.0, 0.0) - prim_outer = SVector(1.2, 0.2, -0.4, 0.2, 0.3, 1.0, 1.0, 1.0, 0.0) - prim_vars = (prim_inner + lambda * prim_outer) / (1.0 + lambda) - - return prim2cons(prim_vars, equations) + # Center of the blast wave is selected for the domain [0, 3]^3 + inicenter = (1.5, 1.5, 1.5) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + delta_0 = 0.1 + r_0 = 0.3 + lambda = exp(5.0 / delta_0 * (r - r_0)) + + prim_inner = SVector(1.2, 0.1, 0.0, 0.1, 0.9, 1.0, 1.0, 1.0, 0.0) + prim_outer = SVector(1.2, 0.2, -0.4, 0.2, 0.3, 1.0, 1.0, 1.0, 0.0) + prim_vars = (prim_inner + lambda * prim_outer) / (1.0 + lambda) + + return prim2cons(prim_vars, equations) end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but with slightly less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/11 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/11 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/11 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 11 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 11 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 11 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end trees_per_dimension = (2, 2, 2) mesh = P4estMesh(trees_per_dimension, - polydeg=3, - mapping=mapping, - initial_refinement_level=2, - periodicity=true) + polydeg = 3, + mapping = mapping, + initial_refinement_level = 2, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -95,24 +98,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =4, max_threshold=0.15) + base_level = 2, + max_level = 4, max_threshold = 0.15) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -121,11 +124,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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/p4est_3d_dgsem/elixir_navierstokes_convergence.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl index 0109e58dfb..c640b255b0 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl @@ -8,240 +8,241 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, false, true), initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, false, true), initial_refinement_level = 2) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types velocity_bc_top_bottom = NoSlip() do x, t, equations - u = initial_condition_navier_stokes_convergence_test(x, t, equations) - return SVector(u[2], u[3], u[4]) + u = initial_condition_navier_stokes_convergence_test(x, t, equations) + return SVector(u[2], u[3], u[4]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions -boundary_conditions = Dict( - :y_neg => boundary_condition_slip_wall, - :y_pos => boundary_condition_slip_wall - ) +boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall) # define viscous boundary conditions -boundary_conditions_parabolic = Dict( - :y_neg => boundary_condition_top_bottom, - :y_pos => boundary_condition_top_bottom - ) +boundary_conditions_parabolic = Dict(:y_neg => boundary_condition_top_bottom, + :y_pos => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -251,16 +252,15 @@ tspan = (0.0, 0.2) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index c5b9ccf2e3..d785013f5a 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,42 +10,45 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=2) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 2) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -59,24 +62,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback,save_solution) + alive_callback, save_solution) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl index 316f36adc9..aabfce0f66 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl @@ -8,18 +8,16 @@ equations = CompressibleEulerEquations2D(2.0) initial_condition = initial_condition_eoc_test_coupled_euler_gravity -solver = DGSEM(polydeg=3, surface_flux=flux_hll) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_eoc_test_euler) - + source_terms = source_terms_eoc_test_euler) ############################################################################### # ODE solvers, callbacks etc. @@ -29,26 +27,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_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); +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/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl index f2693c8958..ce1d2cd05b 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl @@ -2,10 +2,8 @@ using OrdinaryDiffEq using Trixi - initial_condition = initial_condition_eoc_test_coupled_euler_gravity - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 2.0 @@ -17,12 +15,12 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -30,24 +28,23 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 # rho0 is (ab)used to add a "+8π" term to the source terms # for the manufactured solution - gravitational_constant=1.0, # aka G - cfl=1.1, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) + gravitational_constant = 1.0, # aka G + cfl = 1.1, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -55,28 +52,27 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl index fb445616cd..f081f6bb91 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - """ initial_condition_jeans_instability(x, t, equations::Union{CompressibleEulerEquations2D, @@ -19,52 +18,51 @@ The classical Jeans instability taken from in CGS (centimeter, gram, second) units. """ function initial_condition_jeans_instability(x, t, - equations::CompressibleEulerEquations2D) - # Jeans gravitational instability test case - # see Derigs et al. https://arxiv.org/abs/1605.03572; Sec. 4.6 - # OBS! this uses cgs (centimeter, gram, second) units - # periodic boundaries - # domain size [0,L]^2 depends on the wave number chosen for the perturbation - # OBS! Be very careful here L must be chosen such that problem is periodic - # typical final time is T = 5 - # gamma = 5/3 - dens0 = 1.5e7 # g/cm^3 - pres0 = 1.5e7 # dyn/cm^2 - delta0 = 1e-3 - # set wave vector values for perturbation (units 1/cm) - # see FLASH manual: https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 - kx = 2.0*pi/0.5 # 2π/λ_x, λ_x = 0.5 - ky = 0.0 # 2π/λ_y, λ_y = 1e10 - k_dot_x = kx*x[1] + ky*x[2] - # perturb density and pressure away from reference states ρ_0 and p_0 - dens = dens0*(1.0 + delta0*cos(k_dot_x)) # g/cm^3 - pres = pres0*(1.0 + equations.gamma*delta0*cos(k_dot_x)) # dyn/cm^2 - # flow starts as stationary - velx = 0.0 # cm/s - vely = 0.0 # cm/s - return prim2cons((dens, velx, vely, pres), equations) + equations::CompressibleEulerEquations2D) + # Jeans gravitational instability test case + # see Derigs et al. https://arxiv.org/abs/1605.03572; Sec. 4.6 + # OBS! this uses cgs (centimeter, gram, second) units + # periodic boundaries + # domain size [0,L]^2 depends on the wave number chosen for the perturbation + # OBS! Be very careful here L must be chosen such that problem is periodic + # typical final time is T = 5 + # gamma = 5/3 + dens0 = 1.5e7 # g/cm^3 + pres0 = 1.5e7 # dyn/cm^2 + delta0 = 1e-3 + # set wave vector values for perturbation (units 1/cm) + # see FLASH manual: https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 + kx = 2.0 * pi / 0.5 # 2π/λ_x, λ_x = 0.5 + ky = 0.0 # 2π/λ_y, λ_y = 1e10 + k_dot_x = kx * x[1] + ky * x[2] + # perturb density and pressure away from reference states ρ_0 and p_0 + dens = dens0 * (1.0 + delta0 * cos(k_dot_x)) # g/cm^3 + pres = pres0 * (1.0 + equations.gamma * delta0 * cos(k_dot_x)) # dyn/cm^2 + # flow starts as stationary + velx = 0.0 # cm/s + vely = 0.0 # cm/s + return prim2cons((dens, velx, vely, pres), equations) end function initial_condition_jeans_instability(x, t, equations::HyperbolicDiffusionEquations2D) - # gravity equation: -Δϕ = -4πGρ - # Constants taken from the FLASH manual - # https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 - rho0 = 1.5e7 - delta0 = 1e-3 - - phi = rho0*delta0 # constant background perturbation magnitude - q1 = 0.0 - q2 = 0.0 - return (phi, q1, q2) + # gravity equation: -Δϕ = -4πGρ + # Constants taken from the FLASH manual + # https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 + rho0 = 1.5e7 + delta0 = 1e-3 + + phi = rho0 * delta0 # constant background perturbation magnitude + q1 = 0.0 + q2 = 0.0 + return (phi, q1, q2) end initial_condition = initial_condition_jeans_instability - ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 @@ -73,11 +71,11 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -85,22 +83,21 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=1.5e7, # aka rho0 - gravitational_constant=6.674e-8, # aka G - cfl=1.6, - resid_tol=1.0e-4, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_carpenter_kennedy_erk54_2N!) +parameters = ParametersEulerGravity(background_density = 1.5e7, # aka rho0 + gravitational_constant = 6.674e-8, # aka G + cfl = 1.6, + resid_tol = 1.0e-4, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_carpenter_kennedy_erk54_2N!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 5.0) @@ -108,51 +105,58 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) Trixi.pretty_form_utf(::Val{:energy_potential}) = "∑e_potential" Trixi.pretty_form_ascii(::Val{:energy_potential}) = "e_potential" -function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t, semi::SemidiscretizationEulerGravity) - - u_gravity = Trixi.wrap_array(semi.cache.u_ode, semi.semi_gravity) - - mesh, equations_euler, dg, cache = Trixi.mesh_equations_solver_cache(semi.semi_euler) - _, equations_gravity, _, _ = Trixi.mesh_equations_solver_cache(semi.semi_gravity) - - e_potential = Trixi.integrate_via_indices(u_euler, mesh, equations_euler, dg, cache, equations_gravity, u_gravity) do u, i, j, element, equations_euler, dg, equations_gravity, u_gravity - u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element) - u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j, element) - # OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7 - return (u_euler_local[1] - 1.5e7) * u_gravity_local[1] - end - return e_potential +function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t, + semi::SemidiscretizationEulerGravity) + u_gravity = Trixi.wrap_array(semi.cache.u_ode, semi.semi_gravity) + + mesh, equations_euler, dg, cache = Trixi.mesh_equations_solver_cache(semi.semi_euler) + _, equations_gravity, _, _ = Trixi.mesh_equations_solver_cache(semi.semi_gravity) + + e_potential = Trixi.integrate_via_indices(u_euler, mesh, equations_euler, dg, cache, + equations_gravity, + u_gravity) do u, i, j, element, + equations_euler, dg, + equations_gravity, u_gravity + u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element) + u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j, + element) + # OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7 + return (u_euler_local[1] - 1.5e7) * u_gravity_local[1] + end + return e_potential end -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal, Val(:energy_potential))) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal, + Val(:energy_potential))) callbacks = CallbackSet(summary_callback, stepsize_callback, save_restart, save_solution, analysis_callback, alive_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl index 8933224a2c..b7be232022 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl @@ -19,33 +19,33 @@ based on Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ function initial_condition_sedov_self_gravity(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - r = sqrt(x[1]^2 + x[2]^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 - r0 = 0.125 # = 4.0 * smallest dx (for domain length=8 and max-ref=8) - E = 1.0 - p_inner = (equations.gamma - 1) * E / (pi * r0^2) - p_ambient = 1e-5 # = true Sedov setup - - # Calculate primitive variables - # use a logistic function to transfer density value smoothly - L = 1.0 # maximum of function - x0 = 1.0 # center point of function - k = -150.0 # sharpness of transfer - logistic_function_rho = L/(1.0 + exp(-k*(r - x0))) - rho_ambient = 1e-5 - rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny - - # velocities are zero - v1 = 0.0 - v2 = 0.0 - - # use a logistic function to transfer pressure value smoothly - logistic_function_p = p_inner/(1.0 + exp(-k*(r - r0))) - p = max(logistic_function_p, p_ambient) - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + r = sqrt(x[1]^2 + x[2]^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 + r0 = 0.125 # = 4.0 * smallest dx (for domain length=8 and max-ref=8) + E = 1.0 + p_inner = (equations.gamma - 1) * E / (pi * r0^2) + p_ambient = 1e-5 # = true Sedov setup + + # Calculate primitive variables + # use a logistic function to transfer density value smoothly + L = 1.0 # maximum of function + x0 = 1.0 # center point of function + k = -150.0 # sharpness of transfer + logistic_function_rho = L / (1.0 + exp(-k * (r - x0))) + rho_ambient = 1e-5 + rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny + + # velocities are zero + v1 = 0.0 + v2 = 0.0 + + # use a logistic function to transfer pressure value smoothly + logistic_function_p = p_inner / (1.0 + exp(-k * (r - r0))) + p = max(logistic_function_p, p_ambient) + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_self_gravity @@ -65,50 +65,50 @@ Should be used together with [`initial_condition_sedov_self_gravity`](@ref). function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - # velocities are zero, density/pressure are ambient values according to - # initial_condition_sedov_self_gravity - rho = 1e-5 - v1 = 0.0 - v2 = 0.0 - p = 1e-5 - - u_boundary = prim2cons(SVector(rho, v1, v2, p), equations) - - # 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 + # velocities are zero, density/pressure are ambient values according to + # initial_condition_sedov_self_gravity + rho = 1e-5 + v1 = 0.0 + v2 = 0.0 + p = 1e-5 + + u_boundary = prim2cons(SVector(rho, v1, v2, p), equations) + + # 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 boundary_conditions = boundary_condition_sedov_self_gravity surface_flux = flux_hll -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations_euler, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver_euler = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-4, -4) -coordinates_max = ( 4, 4) +coordinates_max = (4, 4) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=100_000, - periodicity=false) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - boundary_conditions=boundary_conditions) + initial_refinement_level = 2, + n_cells_max = 100_000, + periodicity = false) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + boundary_conditions = boundary_conditions) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -125,12 +125,13 @@ based on - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ -function initial_condition_sedov_self_gravity(x, t, equations::HyperbolicDiffusionEquations2D) - # for now just use constant initial condition for sedov blast wave (can likely be improved) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - return SVector(phi, q1, q2) +function initial_condition_sedov_self_gravity(x, t, + equations::HyperbolicDiffusionEquations2D) + # for now just use constant initial condition for sedov blast wave (can likely be improved) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + return SVector(phi, q1, q2) end """ @@ -147,39 +148,38 @@ based on Should be used together with [`initial_condition_sedov_self_gravity`](@ref). """ function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, - surface_flux_function, - equations::HyperbolicDiffusionEquations2D) - u_boundary = initial_condition_sedov_self_gravity(x, t, equations) - - # 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 + surface_flux_function, + equations::HyperbolicDiffusionEquations2D) + u_boundary = initial_condition_sedov_self_gravity(x, t, equations) + + # 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 solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=0.0, # aka rho0 - gravitational_constant=6.674e-8, # aka G - cfl=2.4, - resid_tol=1.0e-4, - n_iterations_max=100, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 0.0, # aka rho0 + gravitational_constant = 6.674e-8, # aka G + cfl = 2.4, + resid_tol = 1.0e-4, + n_iterations_max = 100, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 1.0) @@ -188,41 +188,42 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.0, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =8, max_threshold=0.0003) + base_level = 2, + max_level = 8, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) callbacks = CallbackSet(summary_callback, amr_callback, stepsize_callback, save_solution, analysis_callback, alive_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl index 029c19380c..df6e4e6349 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl @@ -9,10 +9,10 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic # 1 => -x, 2 => +x, 3 => -y, 4 => +y as usual for orientations -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) polydeg = 3 surface_flux = flux_lax_friedrichs @@ -21,15 +21,13 @@ solver = DGSEM(polydeg, surface_flux) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=(false, true)) - + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,29 +38,28 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 1.0e-10 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 500 -alive_callback = AliveCallback(analysis_interval=analysis_interval) -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) callbacks = CallbackSet(summary_callback, steady_state_callback, stepsize_callback, save_solution, analysis_callback, alive_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); +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/special_elixirs/elixir_euler_ad.jl b/examples/special_elixirs/elixir_euler_ad.jl index 48fd37cc9d..3aa44f9a77 100644 --- a/examples/special_elixirs/elixir_euler_ad.jl +++ b/examples/special_elixirs/elixir_euler_ad.jl @@ -6,10 +6,10 @@ using Trixi, LinearAlgebra, ForwardDiff equations = CompressibleEulerEquations2D(1.4) mesh = TreeMesh((-1.0, -1.0), (1.0, 1.0), - initial_refinement_level=2, n_cells_max=10^5) + initial_refinement_level = 2, n_cells_max = 10^5) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) """ initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) @@ -21,43 +21,45 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_isentropic_vortex, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_isentropic_vortex, + solver) u0_ode = compute_coefficients(0.0, semi) J = ForwardDiff.jacobian((du_ode, γ) -> begin - equations_inner = CompressibleEulerEquations2D(first(γ)) - semi_inner = Trixi.remake(semi, equations=equations_inner, uEltype=eltype(γ)) - Trixi.rhs!(du_ode, u0_ode, semi_inner, 0.0) - end, similar(u0_ode), [1.4]); # γ needs to be an `AbstractArray` + equations_inner = CompressibleEulerEquations2D(first(γ)) + semi_inner = Trixi.remake(semi, equations = equations_inner, + uEltype = eltype(γ)) + Trixi.rhs!(du_ode, u0_ode, semi_inner, 0.0) + end, similar(u0_ode), [1.4]); # γ needs to be an `AbstractArray` diff --git a/examples/structured_1d_dgsem/elixir_advection_basic.jl b/examples/structured_1d_dgsem/elixir_advection_basic.jl index 82464f2396..cdabeb4c61 100644 --- a/examples/structured_1d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_1d_dgsem/elixir_advection_basic.jl @@ -11,7 +11,7 @@ advection_velocity = 1.0 equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0,) # minimum coordinate coordinates_max = (1.0,) # maximum coordinate @@ -21,8 +21,8 @@ cells_per_dimension = (16,) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,26 +35,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl b/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl index e87e0b36b0..1e0c579ffc 100644 --- a/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl +++ b/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl @@ -11,18 +11,16 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (5.0,) -mesh = StructuredMesh((16,), coordinates_min, coordinates_max, periodicity=false) - +mesh = StructuredMesh((16,), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -33,31 +31,30 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_1d_dgsem/elixir_advection_shockcapturing.jl b/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl index 313812fe08..96566bc237 100644 --- a/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl +++ b/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl @@ -17,30 +17,30 @@ Slight simplification from [DOI: 10.1006/jcph.1996.0130](https://doi.org/10.1006/jcph.1996.0130) """ function initial_condition_composite(x, t, equations::LinearScalarAdvectionEquation1D) - xmin, xmax = -1.0, 1.0 # Only works if the domain is [-1.0,1.0] - x_trans = x[1] - t - L = xmax - xmin - if x_trans > xmax - x_ = x_trans - L * floor((x_trans + xmin) / L) - elseif x_trans < xmin - x_ = x_trans + L * floor((xmax - x_trans) / L) - else - x_ = x_trans - end - - if x_ > -0.8 && x_ < -0.6 - value = exp(-log(2.0) * (x_ + 0.7)^2 / 0.0009) - elseif x_ > -0.4 && x_ < -0.2 - value = 1.0 - elseif x_ > 0.0 && x_ < 0.2 - value = 1.0 - abs(10.0 * (x_ - 0.1)) - elseif x_ > 0.4 && x_ < 0.6 - value = sqrt(1.0 - 100.0 * (x_ - 0.5)^2) - else - value = 0.0 - end - - return SVector(value) + xmin, xmax = -1.0, 1.0 # Only works if the domain is [-1.0,1.0] + x_trans = x[1] - t + L = xmax - xmin + if x_trans > xmax + x_ = x_trans - L * floor((x_trans + xmin) / L) + elseif x_trans < xmin + x_ = x_trans + L * floor((xmax - x_trans) / L) + else + x_ = x_trans + end + + if x_ > -0.8 && x_ < -0.6 + value = exp(-log(2.0) * (x_ + 0.7)^2 / 0.0009) + elseif x_ > -0.4 && x_ < -0.2 + value = 1.0 + elseif x_ > 0.0 && x_ < 0.2 + value = 1.0 - abs(10.0 * (x_ - 0.1)) + elseif x_ > 0.4 && x_ < 0.6 + value = sqrt(1.0 - 100.0 * (x_ - 0.5)^2) + else + value = 0.0 + end + + return SVector(value) end initial_condition = initial_condition_composite @@ -52,13 +52,13 @@ volume_flux = flux_central polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=Trixi.first) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.first) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Create curved mesh @@ -66,12 +66,11 @@ cells_per_dimension = (120,) coordinates_min = (-1.0,) # minimum coordinate coordinates_max = (1.0,) # maximum coordinate mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, - periodicity=true) + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -84,23 +83,23 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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 \ No newline at end of file +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_1d_dgsem/elixir_euler_sedov.jl b/examples/structured_1d_dgsem/elixir_euler_sedov.jl index 9d7be21a5c..4ffa100cc7 100644 --- a/examples/structured_1d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_1d_dgsem/elixir_euler_sedov.jl @@ -14,50 +14,50 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) shock_indicator_variable = density_pressure indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=shock_indicator_variable) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = shock_indicator_variable) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) cells_per_dimension = (64,) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=true) +coordinates_max = (2.0,) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,16 +67,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -84,11 +84,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_1d_dgsem/elixir_euler_source_terms.jl b/examples/structured_1d_dgsem/elixir_euler_source_terms.jl index cbda708705..97767f3e12 100644 --- a/examples/structured_1d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_1d_dgsem/elixir_euler_source_terms.jl @@ -13,7 +13,7 @@ initial_condition = initial_condition_convergence_test # Note that the expected EOC of 5 is not reached with this flux. # Using flux_hll instead yields the expected EOC. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (2.0,) @@ -21,10 +21,8 @@ cells_per_dimension = (16,) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -35,29 +33,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 9aa5b7f497..d506383813 100644 --- a/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -15,20 +15,18 @@ source_terms = source_terms_convergence_test # 1*ndims == 2 directions or you can pass a tuple containing BCs for # each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) f1() = SVector(0.0) f2() = SVector(2.0) -mesh = StructuredMesh((16,), (f1, f2), periodicity=false) - +mesh = StructuredMesh((16,), (f1, f2), periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) - + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -39,30 +37,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_advection_basic.jl b/examples/structured_2d_dgsem/elixir_advection_basic.jl index 7d2e1f4927..1d7235fc21 100644 --- a/examples/structured_2d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_2d_dgsem/elixir_advection_basic.jl @@ -11,10 +11,10 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) cells_per_dimension = (16, 16) @@ -22,8 +22,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -36,26 +36,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_coupled.jl b/examples/structured_2d_dgsem/elixir_advection_coupled.jl index 1e54e411db..2a56d23f4c 100644 --- a/examples/structured_2d_dgsem/elixir_advection_coupled.jl +++ b/examples/structured_2d_dgsem/elixir_advection_coupled.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # Coupled semidiscretization of two linear advection systems, which are connected periodically # @@ -35,11 +34,11 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # First mesh is the left half of a [-1,1]^2 square coordinates_min1 = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max1 = ( 0.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max1 = (0.0, 1.0) # maximum coordinates (max(x), max(y)) # Define identical resolution as a variable such that it is easier to change from `trixi_include` cells_per_dimension = (8, 16) @@ -49,32 +48,45 @@ cells_per_dimension1 = cells_per_dimension mesh1 = StructuredMesh(cells_per_dimension1, coordinates_min1, coordinates_max1) # A semidiscretization collects data structures and functions for the spatial discretization -semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, solver, - boundary_conditions=( - # Connect left boundary with right boundary of right mesh - x_neg=BoundaryConditionCoupled(2, (:end, :i_forward), Float64), - # Connect right boundary with left boundary of right mesh - x_pos=BoundaryConditionCoupled(2, (:begin, :i_forward), Float64), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic)) - +semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, + solver, + boundary_conditions = ( + # Connect left boundary with right boundary of right mesh + x_neg = BoundaryConditionCoupled(2, + (:end, + :i_forward), + Float64), + # Connect right boundary with left boundary of right mesh + x_pos = BoundaryConditionCoupled(2, + (:begin, + :i_forward), + Float64), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic)) # Second mesh is the right half of a [-1,1]^2 square coordinates_min2 = (0.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max2 = (1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max2 = (1.0, 1.0) # maximum coordinates (max(x), max(y)) cells_per_dimension2 = cells_per_dimension mesh2 = StructuredMesh(cells_per_dimension2, coordinates_min2, coordinates_max2) -semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, solver, - boundary_conditions=( - # Connect left boundary with right boundary of left mesh - x_neg=BoundaryConditionCoupled(1, (:end, :i_forward), Float64), - # Connect right boundary with left boundary of left mesh - x_pos=BoundaryConditionCoupled(1, (:begin, :i_forward), Float64), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic)) +semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, + solver, + boundary_conditions = ( + # Connect left boundary with right boundary of left mesh + x_neg = BoundaryConditionCoupled(1, + (:end, + :i_forward), + Float64), + # Connect right boundary with left boundary of left mesh + x_pos = BoundaryConditionCoupled(1, + (:begin, + :i_forward), + Float64), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic)) # Create a semidiscretization that bundles semi1 and semi2 semi = SemidiscretizationCoupled(semi1, semi2) @@ -90,28 +102,28 @@ ode = semidiscretize(semi, (0.0, 2.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback1 = AnalysisCallback(semi1, interval=100) -analysis_callback2 = AnalysisCallback(semi2, interval=100) +analysis_callback1 = AnalysisCallback(semi1, interval = 100) +analysis_callback2 = AnalysisCallback(semi2, interval = 100) analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_extended.jl b/examples/structured_2d_dgsem/elixir_advection_extended.jl index fbaa7783d9..df7e1f375a 100644 --- a/examples/structured_2d_dgsem/elixir_advection_extended.jl +++ b/examples/structured_2d_dgsem/elixir_advection_extended.jl @@ -18,11 +18,11 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # The initial condition is 2-periodic coordinates_min = (-1.5, 1.3) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.5, 5.3) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.5, 5.3) # maximum coordinates (max(x), max(y)) cells_per_dimension = (19, 37) @@ -31,8 +31,7 @@ mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_free_stream.jl b/examples/structured_2d_dgsem/elixir_advection_free_stream.jl index 155a2d19fc..7785b4f9e1 100644 --- a/examples/structured_2d_dgsem/elixir_advection_free_stream.jl +++ b/examples/structured_2d_dgsem/elixir_advection_free_stream.jl @@ -11,21 +11,21 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_constant # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -36,7 +36,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -48,30 +47,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl index 2aad3a0156..e2e113b168 100644 --- a/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl @@ -13,16 +13,14 @@ initial_condition = initial_condition_gauss # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) -mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity=false) - +coordinates_max = (5.0, 5.0) +mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -33,17 +31,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -52,7 +50,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_advection_parallelogram.jl b/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl index b9a6d3f91a..b70deb1231 100644 --- a/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl +++ b/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl @@ -7,24 +7,23 @@ using OrdinaryDiffEq using Trixi - # initial_condition_convergence_test transformed to the parallelogram function initial_condition_parallelogram(x, t, equation::LinearScalarAdvectionEquation2D) - # Transform back to unit square - x_transformed = SVector(x[1] - x[2], x[2]) - a = equation.advection_velocity - a_transformed = SVector(a[1] - a[2], a[2]) - - # Store translated coordinate for easy use of exact solution - x_translated = x_transformed - a_transformed * t - - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_translated)) - return SVector(scalar) + # Transform back to unit square + x_transformed = SVector(x[1] - x[2], x[2]) + a = equation.advection_velocity + a_transformed = SVector(a[1] - a[2], a[2]) + + # Store translated coordinate for easy use of exact solution + x_translated = x_transformed - a_transformed * t + + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_translated)) + return SVector(scalar) end ############################################################################### @@ -35,7 +34,7 @@ advection_velocity = (-0.5, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Define faces for a parallelogram that looks like this # @@ -49,11 +48,11 @@ mapping(xi, eta) = SVector(xi + eta, eta) cells_per_dimension = (16, 16) # Create curved mesh with 16 x 16 elements, periodic in both dimensions -mesh = StructuredMesh(cells_per_dimension, mapping; periodicity=(true, true)) +mesh = StructuredMesh(cells_per_dimension, mapping; periodicity = (true, true)) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_parallelogram, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_parallelogram, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -66,26 +65,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_restart.jl b/examples/structured_2d_dgsem/elixir_advection_restart.jl index 82eaa21333..19863faae8 100644 --- a/examples/structured_2d_dgsem/elixir_advection_restart.jl +++ b/examples/structured_2d_dgsem/elixir_advection_restart.jl @@ -10,7 +10,6 @@ restart_file = "restart_000021.h5" trixi_include(@__MODULE__, joinpath(@__DIR__, elixir_file)) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -29,9 +28,9 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) diff --git a/examples/structured_2d_dgsem/elixir_advection_rotated.jl b/examples/structured_2d_dgsem/elixir_advection_rotated.jl index 7dfee23a06..826c7ebaac 100644 --- a/examples/structured_2d_dgsem/elixir_advection_rotated.jl +++ b/examples/structured_2d_dgsem/elixir_advection_rotated.jl @@ -7,7 +7,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -17,40 +16,41 @@ using Trixi # initial_condition_convergence_test transformed to the rotated rectangle struct InitialConditionConvergenceTestRotated - sin_alpha::Float64 - cos_alpha::Float64 + sin_alpha::Float64 + cos_alpha::Float64 end function InitialConditionConvergenceTestRotated(alpha) - sin_alpha, cos_alpha = sincos(alpha) + sin_alpha, cos_alpha = sincos(alpha) - InitialConditionConvergenceTestRotated(sin_alpha, cos_alpha) + InitialConditionConvergenceTestRotated(sin_alpha, cos_alpha) end -function (initial_condition::InitialConditionConvergenceTestRotated)(x, t, equation::LinearScalarAdvectionEquation2D) - sin_ = initial_condition.sin_alpha - cos_ = initial_condition.cos_alpha +function (initial_condition::InitialConditionConvergenceTestRotated)(x, t, + equation::LinearScalarAdvectionEquation2D) + sin_ = initial_condition.sin_alpha + cos_ = initial_condition.cos_alpha - # Rotate back to unit square + # Rotate back to unit square - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x_rot = SVector(cos_ * x[1] + sin_ * x[2], -sin_ * x[1] + cos_ * x[2]) - a = equation.advection_velocity - a_rot = SVector(cos_ * a[1] + sin_ * a[2], -sin_ * a[1] + cos_ * a[2]) + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x_rot = SVector(cos_ * x[1] + sin_ * x[2], -sin_ * x[1] + cos_ * x[2]) + a = equation.advection_velocity + a_rot = SVector(cos_ * a[1] + sin_ * a[2], -sin_ * a[1] + cos_ * a[2]) - # Store translated coordinate for easy use of exact solution - x_trans = x_rot - a_rot * t + # Store translated coordinate for easy use of exact solution + x_trans = x_rot - a_rot * t - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_trans)) + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) - return SVector(scalar) + return SVector(scalar) end end # module TrixiExtensionAdvectionRotated @@ -70,7 +70,7 @@ advection_velocity = Tuple(T * [0.2, -0.7]) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) mapping(xi, eta) = T * SVector(xi, eta) @@ -82,7 +82,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -94,26 +93,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl b/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl index d0db19ea63..50393d50a1 100644 --- a/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl +++ b/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl @@ -11,14 +11,14 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (16, 16) @@ -28,7 +28,6 @@ mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -40,30 +39,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 5761e638e4..57c2d2a780 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -14,26 +14,26 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14), - bar_states=true, - smoothness_indicator=false) + positivity_variables_cons = [1], + positivity_variables_nonlinear = (pressure,), + positivity_correction_factor = 0.1, + spec_entropy = false, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + bar_states = true, + smoothness_indicator = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (4, 4) @@ -41,7 +41,6 @@ mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -51,16 +50,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -69,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index fa59e5e0d3..20a20a9c20 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -14,25 +14,26 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - Plotting=true) + DensityLimiter = false, + DensityAlphaForAll = false, + SequentialLimiter = false, + ConservativeLimiter = false, + DensityPositivityLimiter = true, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = true, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (4, 4) @@ -40,7 +41,6 @@ mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,16 +50,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -68,9 +68,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 3d34e28a4f..d306b70cb7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -11,33 +11,35 @@ initial_condition = Trixi.initial_condition_double_mach_reflection boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, - y_pos=boundary_condition_inflow_outflow, - x_pos=boundary_condition_inflow_outflow, - x_neg=boundary_condition_inflow_outflow) +boundary_conditions = (y_neg = Trixi.boundary_condition_mixed_dirichlet_wall, + y_pos = boundary_condition_inflow_outflow, + x_pos = boundary_condition_inflow_outflow, + x_neg = boundary_condition_inflow_outflow) surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - positivity_correction_factor=0.1, max_iterations_newton=100, - bar_states=true) + local_minmax_variables_cons = [1], + spec_entropy = true, + positivity_correction_factor = 0.1, + max_iterations_newton = 100, + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) coordinates_min = (0.0, 0.0) coordinates_max = (4.0, 1.0) -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -48,17 +50,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -68,9 +70,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 2516d7e205..c7df12f27a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -11,37 +11,38 @@ initial_condition = Trixi.initial_condition_double_mach_reflection boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (y_neg=Trixi.boundary_condition_mixed_dirichlet_wall, - y_pos=boundary_condition_inflow_outflow, - x_pos=boundary_condition_inflow_outflow, - x_neg=boundary_condition_inflow_outflow) +boundary_conditions = (y_neg = Trixi.boundary_condition_mixed_dirichlet_wall, + y_pos = boundary_condition_inflow_outflow, + x_pos = boundary_condition_inflow_outflow, + x_neg = boundary_condition_inflow_outflow) surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - DensityPositivityLimiter=false, - PressurePositivityLimiterKuzmin=false, - SemiDiscEntropyLimiter=false, - Plotting=true) + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + DensityPositivityLimiter = false, + PressurePositivityLimiterKuzmin = false, + SemiDiscEntropyLimiter = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) initial_refinement_level = 6 cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) coordinates_min = (0.0, 0.0) coordinates_max = (4.0, 1.0) -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -52,17 +53,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -72,9 +73,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_ec.jl b/examples/structured_2d_dgsem/elixir_euler_ec.jl index 2c91349ff9..29686bd3cb 100644 --- a/examples/structured_2d_dgsem/elixir_euler_ec.jl +++ b/examples/structured_2d_dgsem/elixir_euler_ec.jl @@ -13,25 +13,25 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=4, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -53,15 +53,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -72,7 +72,7 @@ callbacks = CallbackSet(summary_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); +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_euler_free_stream.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream.jl index c4ddb887e5..3aab4be979 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream.jl @@ -9,21 +9,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -32,7 +32,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -42,16 +41,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -61,7 +60,7 @@ callbacks = CallbackSet(summary_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); +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_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 8999d435ec..163cc6519a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -10,23 +10,24 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=true, - SemiDiscEntropyLimiter=false, - smoothness_indicator=false, - Plotting=true) + DensityLimiter = false, + DensityAlphaForAll = false, + SequentialLimiter = false, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = true, + SemiDiscEntropyLimiter = false, + smoothness_indicator = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. @@ -37,21 +38,21 @@ solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (32, 32) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -64,29 +65,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 6b70438044..639fb92875 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -10,22 +10,22 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - smoothness_indicator=false, - bar_states=true, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14)) + positivity_variables_cons = [1], + positivity_variables_nonlinear = (pressure,), + positivity_correction_factor = 0.1, + spec_entropy = false, + smoothness_indicator = false, + bar_states = true, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14)) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. @@ -36,21 +36,21 @@ solver = DGSEM(basis, surface_flux, volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (32, 32) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -63,29 +63,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_rayleigh_taylor_instability.jl b/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl index bb5870ab9d..6c254e8bd8 100644 --- a/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl +++ b/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl @@ -29,40 +29,40 @@ defined below. """ @inline function initial_condition_rayleigh_taylor_instability(x, t, equations::CompressibleEulerEquations2D, - slope=1000) - tol = 1e2*eps() - - if x[2] < 0.5 - p = 2*x[2] + 1 - else - p = x[2] + 3/2 - end - - # smooth the discontinuity to avoid ambiguity at element interfaces - smoothed_heaviside(x, left, right) = left + 0.5*(1 + tanh(slope * x)) * (right-left) - rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) - - c = sqrt(equations.gamma * p / rho) - # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the - # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. - v = -0.025 * c * cos(8*pi*x[1]) * sin(pi*x[2])^6 - u = 0.0 - - return prim2cons(SVector(rho, u, v, p), equations) + slope = 1000) + tol = 1e2 * eps() + + if x[2] < 0.5 + p = 2 * x[2] + 1 + else + p = x[2] + 3 / 2 + end + + # smooth the discontinuity to avoid ambiguity at element interfaces + smoothed_heaviside(x, left, right) = left + 0.5 * (1 + tanh(slope * x)) * (right - left) + rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) + + c = sqrt(equations.gamma * p / rho) + # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the + # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. + v = -0.025 * c * cos(8 * pi * x[1]) * sin(pi * x[2])^6 + u = 0.0 + + return prim2cons(SVector(rho, u, v, p), equations) end @inline function source_terms_rayleigh_taylor_instability(u, x, t, equations::CompressibleEulerEquations2D) - g = 1.0 - rho, rho_v1, rho_v2, rho_e = u + g = 1.0 + rho, rho_v1, rho_v2, rho_e = u - return SVector(0.0, 0.0, g*rho, g*rho_v2) + return SVector(0.0, 0.0, g * rho, g * rho_v2) end # numerical parameters volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # The domain is [0, 0.25] x [0, 1] mapping(xi, eta) = SVector(0.25 * 0.5 * (1.0 + xi), 0.5 * (1.0 + eta)) @@ -72,12 +72,10 @@ cells_per_dimension = (num_elements_per_dimension, num_elements_per_dimension * mesh = StructuredMesh(cells_per_dimension, mapping) initial_condition = initial_condition_rayleigh_taylor_instability -boundary_conditions = ( - x_neg=boundary_condition_slip_wall, - x_pos=boundary_condition_slip_wall, - y_neg=boundary_condition_slip_wall, - y_pos=boundary_condition_slip_wall, - ) +boundary_conditions = (x_neg = boundary_condition_slip_wall, + x_pos = boundary_condition_slip_wall, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall) # # Alternative setup: left/right periodic BCs and Dirichlet BCs on the top/bottom. # boundary_conditions = ( @@ -88,8 +86,8 @@ boundary_conditions = ( # ) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - source_terms=source_terms_rayleigh_taylor_instability, - boundary_conditions=boundary_conditions) + source_terms = source_terms_rayleigh_taylor_instability, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -100,9 +98,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -111,7 +109,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_sedov.jl b/examples/structured_2d_dgsem/elixir_euler_sedov.jl index efc3b6627c..42094d7191 100644 --- a/examples/structured_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,29 +43,30 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) # create the semidiscretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -79,15 +80,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -98,7 +99,7 @@ callbacks = CallbackSet(summary_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); +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_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 2d4f8f608a..06eaceb4f7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -17,37 +17,38 @@ A version of the classical Kelvin-Helmholtz instability based on [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ function initial_condition_inviscid_bow(x, t, equations::CompressibleEulerEquations2D) - rho = 1.4 - p = 1.0 - v1 = 4.0 - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) + rho = 1.4 + p = 1.0 + v1 = 4.0 + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_inviscid_bow boundary_condition = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition_slip_wall, - y_neg=boundary_condition, - y_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition_slip_wall, + y_neg = boundary_condition, + y_pos = boundary_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=false, PressurePositivityLimiterKuzminExact=false, - DensityPositivityLimiter=false, - SemiDiscEntropyLimiter=false, - Plotting=true) + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = false, + PressurePositivityLimiterKuzminExact = false, + DensityPositivityLimiter = false, + SemiDiscEntropyLimiter = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain @@ -68,19 +69,21 @@ alpha = acos(3.85 / 5.9) l = (pi / 4) / (pi / 2 + 1) f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)) # left function f2(s) # right - t = 0.5 * s + 0.5 # in [0,1] - if 0 <= t <= l - beta = t / l # in [0,1] - return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) - elseif l < t <= 1 - l # 0 <= t - l <= 1-2l - beta = (t - l) / (1 - 2 * l) # in [0,1] - return SVector(-0.5, -0.5 + beta) - else # 1 - l < t <= 1 - beta = (t + l - 1) / l # in [0,1] - return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) - end + t = 0.5 * s + 0.5 # in [0,1] + if 0 <= t <= l + beta = t / l # in [0,1] + return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), + 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) + elseif l < t <= 1 - l # 0 <= t - l <= 1-2l + beta = (t - l) / (1 - 2 * l) # in [0,1] + return SVector(-0.5, -0.5 + beta) + else # 1 - l < t <= 1 + beta = (t + l - 1) / l # in [0,1] + return SVector(0.5 * cos(pi - beta * 0.5 * pi), + 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) + end end -f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom +f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a) # top faces = (f1, f2, f3, f4) @@ -89,21 +92,22 @@ Trixi.validate_faces(faces) mapping_bow = Trixi.transfinite_mapping(faces) mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi / 4) / (pi / 2 + 1); " * - "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * - "function f2(s); t = 0.5 * s + 0.5; " * - "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * - "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * - "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * - "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * - "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * - "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" + "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * + "function f2(s); t = 0.5 * s + 0.5; " * + "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * + "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * + "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * + "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * + "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * + "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" cells_per_dimension = (24, 36) -mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string=mapping_as_string, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping_bow, + mapping_as_string = mapping_as_string, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -114,29 +118,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=2000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 2000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 5d26662976..def69ecc28 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -17,33 +17,33 @@ A version of the classical Kelvin-Helmholtz instability based on [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ function initial_condition_inviscid_bow(x, t, equations::CompressibleEulerEquations2D) - rho = 1.4 - p = 1.0 - v1 = 4.0 - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) + rho = 1.4 + p = 1.0 + v1 = 4.0 + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_inviscid_bow boundary_condition = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition_slip_wall, - y_neg=boundary_condition, - y_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition_slip_wall, + y_neg = boundary_condition, + y_pos = boundary_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - max_iterations_newton=100, - bar_states=true) + local_minmax_variables_cons = [1], + spec_entropy = true, + max_iterations_newton = 100, + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # domain @@ -64,19 +64,21 @@ alpha = acos(3.85 / 5.9) l = (pi / 4) / (pi / 2 + 1) f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)) # left function f2(s) # right - t = 0.5 * s + 0.5 # in [0,1] - if 0 <= t <= l - beta = t / l # in [0,1] - return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) - elseif l < t <= 1 - l # 0 <= t - l <= 1-2l - beta = (t - l) / (1 - 2 * l) # in [0,1] - return SVector(-0.5, -0.5 + beta) - else # 1 - l < t <= 1 - beta = (t + l - 1) / l # in [0,1] - return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) - end + t = 0.5 * s + 0.5 # in [0,1] + if 0 <= t <= l + beta = t / l # in [0,1] + return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), + 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5) + elseif l < t <= 1 - l # 0 <= t - l <= 1-2l + beta = (t - l) / (1 - 2 * l) # in [0,1] + return SVector(-0.5, -0.5 + beta) + else # 1 - l < t <= 1 + beta = (t + l - 1) / l # in [0,1] + return SVector(0.5 * cos(pi - beta * 0.5 * pi), + 0.5 * sin(pi - beta * 0.5 * pi) + 0.5) + end end -f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom +f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a) # bottom f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a) # top faces = (f1, f2, f3, f4) @@ -85,21 +87,22 @@ Trixi.validate_faces(faces) mapping_bow = Trixi.transfinite_mapping(faces) mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi / 4) / (pi / 2 + 1); " * - "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * - "function f2(s); t = 0.5 * s + 0.5; " * - "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * - "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * - "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * - "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * - "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * - "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" + "f1(s) = SVector(5.9 * cos(pi - s * alpha) + 3.85, 5.9 * sin(pi - s * alpha)); " * + "function f2(s); t = 0.5 * s + 0.5; " * + "if 0 <= t <= l; beta = t / l; return SVector(0.5 * cos(1.5 * pi - beta * 0.5 * pi), 0.5 * sin(1.5 * pi - beta * 0.5 * pi) - 0.5); " * + "elseif l < t <= 1 - l; beta = (t - l) / (1 - 2 * l); return SVector(-0.5, -0.5 + beta); " * + "else beta = (t + l - 1) / l; return SVector(0.5 * cos(pi - beta * 0.5 * pi), 0.5 * sin(pi - beta * 0.5 * pi) + 0.5); end; end; " * + "f3(s) = SVector(0.0, (a - 1.0) * 0.5 * (s + 1.0) - a); " * + "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * + "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" cells_per_dimension = (24, 36) -mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string=mapping_as_string, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping_bow, + mapping_as_string = mapping_as_string, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -110,29 +113,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=2000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 2000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms.jl index 70d3e060dd..6827848e18 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms.jl @@ -11,7 +11,7 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) @@ -20,10 +20,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +32,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +51,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 94537ecef0..f42d223611 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -12,21 +12,20 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition,) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) -mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity=false) +mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,19 +36,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -58,7 +57,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_parallelogram.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl index a9c08049f4..5d6b090838 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl @@ -9,7 +9,7 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Define faces for a parallelogram that looks like this # @@ -24,10 +24,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -38,16 +36,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -57,7 +55,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_rotated.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl index fdd189ffb5..f2e3c44889 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -12,68 +11,69 @@ using Trixi # initial_condition_convergence_test transformed to the rotated rectangle struct InitialConditionSourceTermsRotated - sin_alpha::Float64 - cos_alpha::Float64 + sin_alpha::Float64 + cos_alpha::Float64 end function InitialConditionSourceTermsRotated(alpha) - sin_alpha, cos_alpha = sincos(alpha) + sin_alpha, cos_alpha = sincos(alpha) - InitialConditionSourceTermsRotated(sin_alpha, cos_alpha) + InitialConditionSourceTermsRotated(sin_alpha, cos_alpha) end -function (initial_condition::InitialConditionSourceTermsRotated)(x, t, equations::CompressibleEulerEquations2D) - sin_ = initial_condition.sin_alpha - cos_ = initial_condition.cos_alpha +function (initial_condition::InitialConditionSourceTermsRotated)(x, t, + equations::CompressibleEulerEquations2D) + sin_ = initial_condition.sin_alpha + cos_ = initial_condition.cos_alpha - # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 + # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x1 = cos_ * x[1] + sin_ * x[2] + 1 - x2 = -sin_ * x[1] + cos_ * x[2] + 1 + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x1 = cos_ * x[1] + sin_ * x[2] + 1 + x2 = -sin_ * x[1] + cos_ * x[2] + 1 - rho, rho_v1, rho_v2, rho_e = initial_condition_convergence_test(SVector(x1, x2), t, equations) + rho, rho_v1, rho_v2, rho_e = initial_condition_convergence_test(SVector(x1, x2), t, + equations) - # Rotate velocity vector counterclockwise - # Multiply with [ cos(α) -sin(α); - # sin(α) cos(α)] - rho_v1_rot = cos_ * rho_v1 - sin_ * rho_v2 - rho_v2_rot = sin_ * rho_v1 + cos_ * rho_v2 + # Rotate velocity vector counterclockwise + # Multiply with [ cos(α) -sin(α); + # sin(α) cos(α)] + rho_v1_rot = cos_ * rho_v1 - sin_ * rho_v2 + rho_v2_rot = sin_ * rho_v1 + cos_ * rho_v2 - return SVector(rho, rho_v1_rot, rho_v2_rot, rho_e) + return SVector(rho, rho_v1_rot, rho_v2_rot, rho_e) end +@inline function (source_terms::InitialConditionSourceTermsRotated)(u, x, t, + equations::CompressibleEulerEquations2D) + sin_ = source_terms.sin_alpha + cos_ = source_terms.cos_alpha -@inline function (source_terms::InitialConditionSourceTermsRotated)(u, x, t, equations::CompressibleEulerEquations2D) - sin_ = source_terms.sin_alpha - cos_ = source_terms.cos_alpha - - # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 + # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x1 = cos_ * x[1] + sin_ * x[2] + 1 - x2 = -sin_ * x[1] + cos_ * x[2] + 1 + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x1 = cos_ * x[1] + sin_ * x[2] + 1 + x2 = -sin_ * x[1] + cos_ * x[2] + 1 - du1, du2, du3, du4 = source_terms_convergence_test(u, SVector(x1, x2), t, equations) + du1, du2, du3, du4 = source_terms_convergence_test(u, SVector(x1, x2), t, equations) - # Rotate velocity vector counterclockwise - # Multiply with [ cos(α) -sin(α); - # sin(α) cos(α)] - du2_rotated = cos_ * du2 - sin_ * du3 - du3_rotated = sin_ * du2 + cos_ * du3 + # Rotate velocity vector counterclockwise + # Multiply with [ cos(α) -sin(α); + # sin(α) cos(α)] + du2_rotated = cos_ * du2 - sin_ * du3 + du3_rotated = sin_ * du2 + cos_ * du3 - return SVector(du1, du2_rotated, du3_rotated, du4) + return SVector(du1, du2_rotated, du3_rotated, du4) end end # module TrixiExtensionEulerRotated import .TrixiExtensionEulerRotated - ############################################################################### # semidiscretization of the compressible Euler equations @@ -85,8 +85,7 @@ sin_ = initial_condition_source_terms.sin_alpha cos_ = initial_condition_source_terms.cos_alpha T = [cos_ -sin_; sin_ cos_] - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) mapping(xi, eta) = T * SVector(xi, eta) @@ -94,10 +93,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_source_terms, solver, - source_terms=initial_condition_source_terms) - + source_terms = initial_condition_source_terms) ############################################################################### # ODE solvers, callbacks etc. @@ -108,16 +105,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -127,7 +124,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 13ed29db2b..53c07261c3 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -16,26 +16,26 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - bar_states=false) + local_minmax_variables_cons = [1], + spec_entropy = true, + bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Waving flag f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) mapping = Trixi.transfinite_mapping((f1, f2, f3, f4)) cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms) + source_terms = source_terms) ############################################################################### # ODE solvers, callbacks etc. @@ -46,16 +46,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -65,9 +65,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_source_terms_waving_flag.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl index 505e28ecd8..4a78b65ae0 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl @@ -9,23 +9,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -36,16 +34,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -55,7 +53,7 @@ callbacks = CallbackSet(summary_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); +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_eulerpolytropic_ec.jl b/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl index de15f6b2bc..b96f1d3cd6 100644 --- a/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl +++ b/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl @@ -15,25 +15,25 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_winters_etal -solver = DGSEM(polydeg=4, surface_flux=flux_winters_etal, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_winters_etal, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -55,15 +55,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -74,7 +74,7 @@ callbacks = CallbackSet(summary_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); +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_hypdiff_harmonic_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index 6730b1c4be..ccb74fa4b6 100644 --- a/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -7,43 +7,42 @@ using Trixi equations = HyperbolicDiffusionEquations2D() -@inline function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω - if t == 0.0 - phi = 1.0 - q1 = 1.0 - q2 = 1.0 - else - C = inv(sinh(pi)) - sinpi_x1, cospi_x1 = sincos(pi*x[1]) - sinpi_x2, cospi_x2 = sincos(pi*x[2]) - sinh_pix1 = sinh(pi*x[1]) - cosh_pix1 = cosh(pi*x[1]) - sinh_pix2 = sinh(pi*x[2]) - cosh_pix2 = cosh(pi*x[2]) - phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) - q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) - q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) - end - return SVector(phi, q1, q2) +@inline function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω + if t == 0.0 + phi = 1.0 + q1 = 1.0 + q2 = 1.0 + else + C = inv(sinh(pi)) + sinpi_x1, cospi_x1 = sincos(pi * x[1]) + sinpi_x2, cospi_x2 = sincos(pi * x[2]) + sinh_pix1 = sinh(pi * x[1]) + cosh_pix1 = cosh(pi * x[1]) + sinh_pix2 = sinh(pi * x[2]) + cosh_pix2 = cosh(pi * x[2]) + phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) + q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) + q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) cells_per_dimension = (8, 8) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, - periodicity=false) - + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -54,30 +53,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_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); +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_hypdiff_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl index ba77dca9a9..681b3bd781 100644 --- a/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -9,40 +9,38 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic -solver = DGSEM(polydeg=6, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 6, surface_flux = flux_lax_friedrichs) -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) ############################################################################### # Get the curved quad mesh from a mapping function # # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end # Create curved mesh with 8 x 8 elements cells_per_dimension = (8, 8) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=(false, true)) - +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -53,31 +51,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 4000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=4000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 4000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.9) +stepsize_callback = StepsizeCallback(cfl = 1.9) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_mhd_alfven_wave.jl b/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl index 259875050c..e8f2b2ecc3 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,31 +5,34 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/1809.01178 function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0, sqrt(2)] - # Note, we use the domain [0, sqrt(2)]^2 for the Alfvén wave convergence test case - xi = 0.5 * sqrt(2) * xi_ + 0.5 * sqrt(2) - eta = 0.5 * sqrt(2) * eta_ + 0.5 * sqrt(2) + # Transform input variables between -1 and 1 onto [0, sqrt(2)] + # Note, we use the domain [0, sqrt(2)]^2 for the Alfvén wave convergence test case + xi = 0.5 * sqrt(2) * xi_ + 0.5 * sqrt(2) + eta = 0.5 * sqrt(2) * eta_ + 0.5 * sqrt(2) - y = eta + sqrt(2)/12 * (cos(1.5 * pi * (2 * xi - sqrt(2))/sqrt(2)) * - cos(0.5 * pi * (2 * eta - sqrt(2))/sqrt(2))) + y = eta + + sqrt(2) / 12 * (cos(1.5 * pi * (2 * xi - sqrt(2)) / sqrt(2)) * + cos(0.5 * pi * (2 * eta - sqrt(2)) / sqrt(2))) - x = xi + sqrt(2)/12 * (cos(0.5 * pi * (2 * xi - sqrt(2))/sqrt(2)) * - cos(2 * pi * (2 * y - sqrt(2))/sqrt(2))) + x = xi + + sqrt(2) / 12 * (cos(0.5 * pi * (2 * xi - sqrt(2)) / sqrt(2)) * + cos(2 * pi * (2 * y - sqrt(2)) / sqrt(2))) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (4, 4) @@ -47,21 +50,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 2.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,7 +79,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_ec.jl b/examples/structured_2d_dgsem/elixir_mhd_ec.jl index 634738e5c8..a6c31744ca 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_ec.jl @@ -8,45 +8,46 @@ using Trixi equations = IdealGlmMhdEquations2D(1.4) function initial_condition_shifted_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) - # Same discontinuity in the velocities but with magnetic fields - # Set up polar coordinates - inicenter = (1.5, 1.5) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) - v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) - p = r > 0.5 ? 1.0 : 1.245 - - return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) + # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) + # Same discontinuity in the velocities but with magnetic fields + # Set up polar coordinates + inicenter = (1.5, 1.5) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) + p = r > 0.5 ? 1.0 : 1.245 + + return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) end initial_condition = initial_condition_shifted_weak_blast_wave # Get the DG approximation space volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=5, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end # Create curved mesh with 8 x 8 elements @@ -65,21 +66,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -91,7 +95,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_ec_shockcapturing.jl b/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl index 084aeca90b..6668014a0b 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations equations = IdealGlmMhdEquations2D(1.4) @@ -10,17 +9,17 @@ equations = IdealGlmMhdEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Get the curved quad mesh from a mapping function @@ -31,16 +30,14 @@ function mapping(xi, eta) x = 2.0 * xi + 1.0 / 6.0 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) return SVector(x, y) - end +end cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) - +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,14 +47,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -68,7 +65,7 @@ callbacks = CallbackSet(summary_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); +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_conical_island.jl b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl index 44bc7a12b3..e65ed19221 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -2,12 +2,12 @@ using OrdinaryDiffEq using Trixi - ############################################################################### - # Semidiscretization of the shallow water equations +############################################################################### +# Semidiscretization of the shallow water equations # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.4) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) """ initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) @@ -20,29 +20,29 @@ discontinuous water height is smoothed by a logistic function. This simulation u boundary conditions. """ function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values + # Set the background values - v1 = 0.0 - v2 = 0.0 + v1 = 0.0 + v2 = 0.0 - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) + 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 + # 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)))) + H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_conical_island @@ -51,19 +51,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -71,7 +72,7 @@ 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) +coordinates_max = (1.0, 1.0) cells_per_dimension = (16, 16) @@ -92,22 +93,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +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 index 15cfe6698f..bc198f1883 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) @@ -28,53 +28,52 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) + a = 1.0 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v1 = -sigma * ω * sin(ω * t) + v2 = sigma * ω * cos(ω * t) + + b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_parabolic_bowl - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) - ############################################################################### coordinates_min = (-2.0, -2.0) @@ -96,24 +95,25 @@ 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)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl index 18f4808085..48fe37b999 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,13 +5,14 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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)) +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)) @@ -20,10 +21,8 @@ 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) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +33,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +52,7 @@ callbacks = CallbackSet(summary_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); +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 index 17836fa6b8..61dd252fd8 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -7,21 +7,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.0) +equations = ShallowWaterEquations2D(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::ShallowWaterEquations2D) - # 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) + # 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 @@ -30,16 +30,17 @@ 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), +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)) +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) +coordinates_max = (2.0, 2.0) cells_per_dimension = (4, 4) @@ -64,30 +65,33 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -96,16 +100,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_wet_dry.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index b18b02e0b4..8e492b1ba0 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,8 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant=9.812) +equations = ShallowWaterEquations2D(gravity_constant = 9.812) """ initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) @@ -24,29 +23,30 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations2D) + v1 = 0 + v2 = 0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -56,23 +56,23 @@ initial_condition = initial_condition_complex_bottom_well_balanced volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +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) + 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) + 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 @@ -83,7 +83,6 @@ 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) @@ -107,18 +106,20 @@ ode = semidiscretize(semi, tspan) 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]) + 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 - 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 ############################################################################### @@ -127,25 +128,27 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + stepsize_callback) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +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); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -160,39 +163,43 @@ summary_callback() # print the timer summary function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) h, _, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max( 2.5 , b + equations.threshold_limiter ) - else - H0_wet_dry = max( 1.5 , b + equations.threshold_limiter ) - end - - return abs(H0_wet_dry - (h + b)) + # 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) +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])) + " 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) diff --git a/examples/structured_3d_dgsem/elixir_advection_basic.jl b/examples/structured_3d_dgsem/elixir_advection_basic.jl index 47ae635248..5b0bb371fe 100644 --- a/examples/structured_3d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_3d_dgsem/elixir_advection_basic.jl @@ -11,18 +11,18 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) cells_per_dimension = (8, 8, 8) # Create curved mesh with 8 x 8 x 8 elements mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,30 +35,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, save_restart, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, save_restart, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_3d_dgsem/elixir_advection_free_stream.jl b/examples/structured_3d_dgsem/elixir_advection_free_stream.jl index 749233b8c6..12d52f1516 100644 --- a/examples/structured_3d_dgsem/elixir_advection_free_stream.jl +++ b/examples/structured_3d_dgsem/elixir_advection_free_stream.jl @@ -13,24 +13,27 @@ solver = DGSEM(3, flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) @@ -41,7 +44,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_constant, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -53,26 +55,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl b/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl index fa8ae75656..1a20a9c853 100644 --- a/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl +++ b/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl @@ -11,36 +11,38 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -51,20 +53,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -76,7 +78,7 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_advection_restart.jl b/examples/structured_3d_dgsem/elixir_advection_restart.jl index 921c531034..e81ad5d643 100644 --- a/examples/structured_3d_dgsem/elixir_advection_restart.jl +++ b/examples/structured_3d_dgsem/elixir_advection_restart.jl @@ -6,8 +6,7 @@ using Trixi # create a restart file trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), - cells_per_dimension=(4, 4, 4)) - + cells_per_dimension = (4, 4, 4)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,7 +17,8 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), restart_filename = joinpath("out", "restart_000010.h5") mesh = load_mesh(restart_filename) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -27,14 +27,13 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) - ############################################################################### # run the simulation diff --git a/examples/structured_3d_dgsem/elixir_euler_ec.jl b/examples/structured_3d_dgsem/elixir_euler_ec.jl index 0009eb3118..1330006760 100644 --- a/examples/structured_3d_dgsem/elixir_euler_ec.jl +++ b/examples/structured_3d_dgsem/elixir_euler_ec.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations3D(5/3) +equations = CompressibleEulerEquations3D(5 / 3) initial_condition = initial_condition_weak_blast_wave @@ -13,32 +13,35 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a file # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -59,15 +62,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -78,7 +81,7 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_euler_free_stream.jl b/examples/structured_3d_dgsem/elixir_euler_free_stream.jl index b0e7143576..1b01287100 100644 --- a/examples/structured_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/structured_3d_dgsem/elixir_euler_free_stream.jl @@ -9,29 +9,32 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -40,7 +43,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,30 +52,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_3d_dgsem/elixir_euler_sedov.jl b/examples/structured_3d_dgsem/elixir_euler_sedov.jl index e0595437c9..1f2d9d2eeb 100644 --- a/examples/structured_3d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_3d_dgsem/elixir_euler_sedov.jl @@ -14,28 +14,29 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 with smaller strength of the initial discontinuity. """ -function initial_condition_medium_sedov_blast_wave(x, t, equations::CompressibleEulerEquations3D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) - p0_outer = 1.0e-3 - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_medium_sedov_blast_wave(x, t, + equations::CompressibleEulerEquations3D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) + p0_outer = 1.0e-3 + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_medium_sedov_blast_wave @@ -45,30 +46,31 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta, zeta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) - z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) + z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) - return SVector(x, y, z) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -82,15 +84,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -101,7 +103,7 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_euler_source_terms.jl b/examples/structured_3d_dgsem/elixir_euler_source_terms.jl index d8c6ea4bb8..ebf1336c12 100644 --- a/examples/structured_3d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_3d_dgsem/elixir_euler_source_terms.jl @@ -11,8 +11,8 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # coordinates_min = (0.0, 0.0, 0.0) # coordinates_max = (2.0, 2.0, 2.0) @@ -28,8 +28,7 @@ cells_per_dimension = (4, 4, 4) mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4, f5, f6)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,27 +39,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl b/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl index 8ddfd42655..eb358fa5da 100644 --- a/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl +++ b/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl @@ -12,46 +12,48 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition, - z_neg=boundary_condition, - z_pos=boundary_condition,) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition, + z_neg = boundary_condition, + z_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the cube [0,2]^3 - return SVector(x + 1, y + 1, z + 1) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the cube [0,2]^3 + return SVector(x + 1, y + 1, z + 1) end cells_per_dimension = (4, 4, 4) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -62,27 +64,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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_3d_dgsem/elixir_mhd_alfven_wave.jl b/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl index f4da8ee947..6eb35078ef 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,13 +5,13 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=5, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Create the mesh # Note, we use the domain [-1, 1]^3 for the Alfvén wave convergence test case so the @@ -19,13 +19,13 @@ solver = DGSEM(polydeg=5, surface_flux=(flux_hll, flux_nonconservative_powell), # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta, zeta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) - z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) + z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) - return SVector(x, y, z) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -43,18 +43,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.2 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -62,11 +62,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_mhd_ec.jl b/examples/structured_3d_dgsem/elixir_mhd_ec.jl index a8c2288e81..5b3cd6f371 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_ec.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_ec.jl @@ -10,31 +10,35 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Create a heavily warped curved mesh # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -52,19 +56,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -72,11 +76,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_mhd_ec_shockcapturing.jl b/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl index d669c2350a..084e2ee962 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -10,42 +10,46 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Create a heavily warped curved mesh # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) @@ -63,25 +67,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, glm_speed_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); +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/t8code_2d_dgsem/elixir_eulergravity_convergence.jl b/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl index 32649eacff..6d6bb27e0c 100644 --- a/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/t8code_2d_dgsem/elixir_eulergravity_convergence.jl @@ -22,9 +22,9 @@ mesh = T8codeMesh(trees_per_dimension, polydeg = 1, mapping = mapping, initial_refinement_level = 2) -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) - +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -32,24 +32,23 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 # rho0 is (ab)used to add a "+8π" term to the source terms # for the manufactured solution - gravitational_constant=1.0, # aka G - cfl=1.1, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) + gravitational_constant = 1.0, # aka G + cfl = 1.1, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -57,21 +56,21 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) callbacks = CallbackSet(summary_callback, stepsize_callback, analysis_callback, alive_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl index 463f916fa2..8040f79caf 100644 --- a/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -4,26 +4,26 @@ using Trixi ############################################################################### # Semidiscretization of the compressible ideal GLM-MHD equations. -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -coordinates_min = (0.0 , 0.0 ) +coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mapping = Trixi.coordinates2mapping(coordinates_min, coordinates_max) trees_per_dimension = (8, 8) -mesh = T8codeMesh(trees_per_dimension, polydeg=3, - mapping=mapping, - initial_refinement_level=0, periodicity=true) +mesh = T8codeMesh(trees_per_dimension, polydeg = 3, + mapping = mapping, + initial_refinement_level = 0, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -36,14 +36,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 0.9 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,7 +54,7 @@ callbacks = CallbackSet(summary_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); +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/t8code_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/t8code_2d_dgsem/elixir_shallowwater_source_terms.jl index c19f440ebc..b2d5097036 100644 --- a/examples/t8code_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/t8code_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -4,17 +4,17 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations. -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the P4estMesh and setup a periodic mesh @@ -26,14 +26,13 @@ mapping = Trixi.coordinates2mapping(coordinates_min, coordinates_max) trees_per_dimension = (8, 8) -mesh = T8codeMesh(trees_per_dimension, polydeg=3, - mapping=mapping, - initial_refinement_level=1) +mesh = T8codeMesh(trees_per_dimension, polydeg = 3, + mapping = mapping, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -45,9 +44,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) @@ -55,6 +54,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) # 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); +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_advection_amr.jl b/examples/tree_1d_dgsem/elixir_advection_amr.jl index dc371233bc..1071c98ab7 100644 --- a/examples/tree_1d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_1d_dgsem/elixir_advection_amr.jl @@ -10,18 +10,16 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0,) -coordinates_max = ( 5.0,) +coordinates_max = (5.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -31,37 +29,36 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_advection_amr_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl index 098deedb9d..ff62e90542 100644 --- a/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl @@ -11,21 +11,19 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (5.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -36,40 +34,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_advection_basic.jl b/examples/tree_1d_dgsem/elixir_advection_basic.jl index d61062c772..cba522f636 100644 --- a/examples/tree_1d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_1d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = 1.0 equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_diffusion.jl b/examples/tree_1d_dgsem/elixir_advection_diffusion.jl index 0472bd25a7..72b8b3f193 100644 --- a/examples/tree_1d_dgsem/elixir_advection_diffusion.jl +++ b/examples/tree_1d_dgsem/elixir_advection_diffusion.jl @@ -11,49 +11,52 @@ diffusivity() = 0.1 equations_parabolic = LaplaceDiffusion1D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -pi # minimum coordinate -coordinates_max = pi # maximum coordinate +coordinates_max = pi # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) - -function x_trans_periodic(x, domain_length = SVector(2*pi), center = SVector(0.0)) - x_normalized = x .- center - x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5*domain_length) - (x_shifted .> 0.5*domain_length)) .* domain_length - return center + x_shifted + x_offset + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) + +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) + x_normalized = x .- center + x_shifted = x_normalized .% domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length + return center + x_shifted + x_offset end # Define initial condition -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation1D) - # Store translated coordinate for easy use of exact solution - x_trans = x_trans_periodic(x - equation.advection_velocity * t) - - nu = diffusivity() - c = 0.0 - A = 1.0 - L = 2 - f = 1/L - omega = 1.0 - scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) - return SVector(scalar) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation1D) + # Store translated coordinate for easy use of exact solution + x_trans = x_trans_periodic(x - equation.advection_velocity * t) + + nu = diffusivity() + c = 0.0 + A = 1.0 + L = 2 + f = 1 / L + omega = 1.0 + scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) + return SVector(scalar) end initial_condition = initial_condition_diffusive_convergence_test - + # define periodic boundary conditions everywhere boundary_conditions = boundary_condition_periodic boundary_conditions_parabolic = boundary_condition_periodic # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition_diffusive_convergence_test, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition_diffusive_convergence_test, + solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -67,23 +70,22 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=100) +alive_callback = AliveCallback(analysis_interval = 100) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-10 time_abs_tol = 1.0e-10 -sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, - save_everystep=false, callback=callbacks) +sol = solve(ode, KenCarp4(autodiff = false), abstol = time_abs_tol, reltol = time_int_tol, + save_everystep = false, callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_extended.jl b/examples/tree_1d_dgsem/elixir_advection_extended.jl index 5c87ac7ef5..df18583470 100644 --- a/examples/tree_1d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_1d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl b/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl index 28518e7276..62701f3ecf 100644 --- a/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl +++ b/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl @@ -10,19 +10,19 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 0, i.e., a first order finite volume solver, # with (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=0, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 0, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 5, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,22 +35,21 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks sol = solve(ode, Euler(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_burgers_basic.jl b/examples/tree_1d_dgsem/elixir_burgers_basic.jl index cebd9b1120..f57b8e730f 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_basic.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_basic.jl @@ -9,18 +9,16 @@ equations = InviscidBurgersEquation1D() initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -31,29 +29,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_burgers_linear_stability.jl b/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl index 6a25f94ca0..ae2039edde 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl @@ -8,23 +8,22 @@ using Trixi equations = InviscidBurgersEquation1D() function initial_condition_linear_stability(x, t, equation::InviscidBurgersEquation1D) - k = 1 - 2 + sinpi(k * (x[1] - 0.7)) |> SVector + k = 1 + 2 + sinpi(k * (x[1] - 0.7)) |> SVector end volume_flux = flux_ec -solver = DGSEM(polydeg=3, surface_flux=flux_ec, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ec, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, solver) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,23 +34,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_burgers_rarefaction.jl b/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl index 28ab7b7c76..d32b9d6f1f 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl @@ -10,18 +10,18 @@ equations = InviscidBurgersEquation1D() basis = LobattoLegendreBasis(3) # Use shock capturing techniques to suppress oscillations at discontinuities indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) -volume_flux = flux_ec +volume_flux = flux_ec surface_flux = flux_lax_friedrichs volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) - + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + solver = DGSEM(basis, surface_flux, volume_integral) coordinate_min = 0.0 @@ -29,42 +29,41 @@ coordinate_max = 1.0 # Make sure to turn periodicity explicitly off as special boundary conditions are specified mesh = TreeMesh(coordinate_min, coordinate_max, - initial_refinement_level=6, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 10_000, + periodicity = false) # Discontinuous initial condition (Riemann Problem) leading to a rarefaction fan. function initial_condition_rarefaction(x, t, equation::InviscidBurgersEquation1D) - scalar = x[1] < 0.5 ? 0.5 : 1.5 + scalar = x[1] < 0.5 ? 0.5 : 1.5 - return SVector(scalar) -end + return SVector(scalar) +end ############################################################################### # Specify non-periodic boundary conditions function inflow(x, t, equations::InviscidBurgersEquation1D) - return initial_condition_rarefaction(coordinate_min, t, equations) + return initial_condition_rarefaction(coordinate_min, t, equations) end boundary_condition_inflow = BoundaryConditionDirichlet(inflow) function boundary_condition_outflow(u_inner, orientation, normal_direction, x, t, - surface_flux_function, equations::InviscidBurgersEquation1D) - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::InviscidBurgersEquation1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end +boundary_conditions = (x_neg = boundary_condition_inflow, + x_pos = boundary_condition_outflow) -boundary_conditions = (x_neg=boundary_condition_inflow, - x_pos=boundary_condition_outflow) - initial_condition = initial_condition_rarefaction semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,12 +74,11 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -stepsize_callback = StepsizeCallback(cfl=0.9) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,9 +87,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=42, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_burgers_shock.jl b/examples/tree_1d_dgsem/elixir_burgers_shock.jl index 00b5314e19..1f0b0e7e04 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_shock.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_shock.jl @@ -10,17 +10,17 @@ equations = InviscidBurgersEquation1D() basis = LobattoLegendreBasis(3) # Use shock capturing techniques to suppress oscillations at discontinuities indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) -volume_flux = flux_ec +volume_flux = flux_ec surface_flux = flux_lax_friedrichs volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=surface_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = surface_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -29,42 +29,41 @@ coordinate_max = 1.0 # Make sure to turn periodicity explicitly off as special boundary conditions are specified mesh = TreeMesh(coordinate_min, coordinate_max, - initial_refinement_level=6, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 10_000, + periodicity = false) # Discontinuous initial condition (Riemann Problem) leading to a shock to test e.g. correct shock speed. function initial_condition_shock(x, t, equation::InviscidBurgersEquation1D) - scalar = x[1] < 0.5 ? 1.5 : 0.5 + scalar = x[1] < 0.5 ? 1.5 : 0.5 - return SVector(scalar) + return SVector(scalar) end ############################################################################### # Specify non-periodic boundary conditions function inflow(x, t, equations::InviscidBurgersEquation1D) - return initial_condition_shock(coordinate_min, t, equations) + return initial_condition_shock(coordinate_min, t, equations) end boundary_condition_inflow = BoundaryConditionDirichlet(inflow) function boundary_condition_outflow(u_inner, orientation, normal_direction, x, t, - surface_flux_function, equations::InviscidBurgersEquation1D) - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::InviscidBurgersEquation1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end - -boundary_conditions = (x_neg=boundary_condition_inflow, - x_pos=boundary_condition_outflow) +boundary_conditions = (x_neg = boundary_condition_inflow, + x_pos = boundary_condition_outflow) initial_condition = initial_condition_shock semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,12 +74,11 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -stepsize_callback = StepsizeCallback(cfl=0.85) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +stepsize_callback = StepsizeCallback(cfl = 0.85) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,9 +87,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=42, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl index 2318063c2b..9cba4936d2 100644 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl @@ -16,49 +16,47 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + # The following code is equivalent to + # phi = atan(0.0, x_norm) + # cos_phi = cos(phi) + # in 1D but faster + cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -69,27 +67,26 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_euler_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl index d35dec6bc7..05f392624f 100644 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl +++ b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelnnpp-0.97-0.0001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.97-0.0001.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.97-0.0001.bson", + network) model1d = load(network, @__MODULE__)[:model1d] using OrdinaryDiffEq @@ -14,7 +15,6 @@ using Trixi # University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper # This motivates the particular choice of fluxes, mesh resolution etc. - ############################################################################### # semidiscretization of the compressible Euler equations @@ -29,53 +29,51 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + # The following code is equivalent to + # phi = atan(0.0, x_norm) + # cos_phi = cos(phi) + # in 1D but faster + cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=false, - alpha_amr=false, - variable=density_pressure, - network=model1d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = false, + alpha_amr = false, + variable = density_pressure, + network = model1d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,27 +84,26 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_euler_blast_wave_neuralnetwork_rayhesthaven.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl index fb36f8540f..de2f5134a4 100644 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl +++ b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelnnrh-0.95-0.009.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrh-0.95-0.009.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrh-0.95-0.009.bson", + network) model1d = load(network, @__MODULE__)[:model1d] using OrdinaryDiffEq @@ -14,7 +15,6 @@ using Trixi # University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper # This motivates the particular choice of fluxes, mesh resolution etc. - ############################################################################### # semidiscretization of the compressible Euler equations @@ -29,53 +29,51 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + # The following code is equivalent to + # phi = atan(0.0, x_norm) + # cos_phi = cos(phi) + # in 1D but faster + cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkRayHesthaven(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=false, - alpha_amr=false, - variable=density_pressure, - network=model1d) + indicator_type = NeuralNetworkRayHesthaven(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = false, + alpha_amr = false, + variable = density_pressure, + network = model1d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,27 +84,26 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_euler_convergence_pure_fv.jl b/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl index fe221ea5bd..1fa07d4edd 100644 --- a/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralPureLGLFiniteVolume(flux_hllc)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc)) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_euler_density_wave.jl b/examples/tree_1d_dgsem/elixir_euler_density_wave.jl index 746989dfe5..01ccbb2b51 100644 --- a/examples/tree_1d_dgsem/elixir_euler_density_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_density_wave.jl @@ -8,18 +8,16 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_density_wave -solver = DGSEM(polydeg=5, surface_flux=flux_central) +solver = DGSEM(polydeg = 5, surface_flux = flux_central) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -29,16 +27,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 2000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -48,7 +46,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_euler_ec.jl b/examples/tree_1d_dgsem/elixir_euler_ec.jl index f20bd4fd69..0be9c8fbf4 100644 --- a/examples/tree_1d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_1d_dgsem/elixir_euler_ec.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -31,27 +29,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_euler_positivity.jl b/examples/tree_1d_dgsem/elixir_euler_positivity.jl index 966661e889..3fb96fb807 100644 --- a/examples/tree_1d_dgsem/elixir_euler_positivity.jl +++ b/examples/tree_1d_dgsem/elixir_euler_positivity.jl @@ -14,97 +14,92 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 4.0) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 4, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=2, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 2, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) - +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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_euler_sedov_blast_wave.jl b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl index 106ccacf4f..b67b2bc602 100644 --- a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -14,96 +14,92 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) shock_indicator_variable = density_pressure indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=shock_indicator_variable) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = shock_indicator_variable) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 12.5) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_euler_sedov_blast_wave_pure_fv.jl b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl index ebe8fa7ceb..8a0241680b 100644 --- a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl +++ b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -42,59 +42,55 @@ volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000) - + initial_refinement_level = 7, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 12.5) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=7, max_threshold=0.01) + base_level = 4, + max_level = 7, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.25) +stepsize_callback = StepsizeCallback(cfl = 0.25) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_euler_shockcapturing.jl b/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl index 90547f8ddc..0836750537 100644 --- a/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl @@ -10,28 +10,26 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_shima_etal +volume_flux = flux_shima_etal basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -2.0 -coordinates_max = 2.0 +coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,27 +39,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_euler_source_terms.jl b/examples/tree_1d_dgsem/elixir_euler_source_terms.jl index 213206eb9e..555910f69f 100644 --- a/examples/tree_1d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_1d_dgsem/elixir_euler_source_terms.jl @@ -11,18 +11,16 @@ initial_condition = initial_condition_convergence_test # Note that the expected EOC of 5 is not reached with this flux. # Using flux_hll instead yields the expected EOC. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,29 +31,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_euler_source_terms_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 3794e0c8d5..922ac3dd97 100644 --- a/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -13,23 +13,21 @@ initial_condition = initial_condition_convergence_test # 1*ndims == 2 directions or you can pass a tuple containing BCs for # each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,30 +38,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_eulergravity_convergence.jl b/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl index 42de0e18e5..acde04780e 100644 --- a/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl @@ -15,11 +15,11 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -27,22 +27,21 @@ equations_gravity = HyperbolicDiffusionEquations1D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 - gravitational_constant=1.0, # aka G - cfl=1.5, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 + gravitational_constant = 1.0, # aka G + cfl = 1.5, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -51,20 +50,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,11 +72,10 @@ callbacks = CallbackSet(summary_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl index 2444fe8611..6d6316898b 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0,) -coordinates_max = ( 1.0,) +coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_eulermulti_convergence_es.jl b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl index 86f4a4bad0..1b37a8a227 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0,) -coordinates_max = ( 1.0,) +coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_eulermulti_ec.jl b/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl index 04d937a9a8..73f8de15d8 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4)) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_eulermulti_es.jl b/examples/tree_1d_dgsem/elixir_eulermulti_es.jl index 7abb3b0d02..7fbec0c005 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_es.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_es.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,31 +31,30 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_eulermulti_two_interacting_blast_waves.jl b/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl index 8196619418..c093420cc7 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl @@ -5,8 +5,8 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), - gas_constants = (0.4, 0.4, 0.4)) +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), + gas_constants = (0.4, 0.4, 0.4)) """ initial_condition_two_interacting_blast_waves(x, t, equations::CompressibleEulerMulticomponentEquations1D) @@ -16,69 +16,67 @@ A multicomponent two interacting blast wave test taken from The consistent multi-fluid advection method [arXiv: 9807241](https://arxiv.org/pdf/astro-ph/9807241.pdf) """ -function initial_condition_two_interacting_blast_waves(x, t, equations::CompressibleEulerMulticomponentEquations1D) +function initial_condition_two_interacting_blast_waves(x, t, + equations::CompressibleEulerMulticomponentEquations1D) + rho1 = 0.5 * x[1]^2 + rho2 = 0.5 * (sin(20 * x[1]))^2 + rho3 = 1 - rho1 - rho2 - rho1 = 0.5 * x[1]^2 - rho2 = 0.5 * (sin(20 * x[1]))^2 - rho3 = 1 - rho1 - rho2 + prim_rho = SVector{3, real(equations)}(rho1, rho2, rho3) - prim_rho = SVector{3, real(equations)}(rho1, rho2, rho3) + v1 = 0.0 - v1 = 0.0 + if x[1] <= 0.1 + p = 1000 + elseif x[1] < 0.9 + p = 0.01 + else + p = 100 + end - if x[1] <= 0.1 - p = 1000 - elseif x[1] < 0.9 - p = 0.01 - else - p = 100 - end + prim_other = SVector{2, real(equations)}(v1, p) - prim_other = SVector{2, real(equations)}(v1, p) - - return prim2cons(vcat(prim_other, prim_rho), equations) + return prim2cons(vcat(prim_other, prim_rho), equations) end initial_condition = initial_condition_two_interacting_blast_waves -function boundary_condition_two_interacting_blast_waves(u_inner, orientation, direction, x, t, - surface_flux_function, +function boundary_condition_two_interacting_blast_waves(u_inner, orientation, direction, + x, t, surface_flux_function, equations::CompressibleEulerMulticomponentEquations1D) - - u_inner_reflect = SVector(-u_inner[1], u_inner[2], u_inner[3], u_inner[4], u_inner[5]) - # 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_inner_reflect, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_inner_reflect, u_inner, orientation, equations) - end - - return flux + u_inner_reflect = SVector(-u_inner[1], u_inner[2], u_inner[3], u_inner[4], u_inner[5]) + # 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_inner_reflect, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_inner_reflect, u_inner, orientation, equations) + end + + return flux end boundary_conditions = boundary_condition_two_interacting_blast_waves surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, alpha_max = 0.8, alpha_min = 0.0, alpha_smooth = true, - variable=pressure) + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0,) coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=9, - n_cells_max=10_000, - periodicity=false) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 9, + n_cells_max = 10_000, + periodicity = false) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -90,16 +88,16 @@ summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.1) +stepsize_callback = StepsizeCallback(cfl = 0.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -109,7 +107,7 @@ callbacks = CallbackSet(summary_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); +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_hypdiff_harmonic_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index 9a19807ae2..b9173ec9f4 100644 --- a/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the hyperbolic diffusion equations -equations = HyperbolicDiffusionEquations1D(nu=1.25) +equations = HyperbolicDiffusionEquations1D(nu = 1.25) """ initial_condition_poisson_nonperiodic(x, t, equations::HyperbolicDiffusionEquations1D) @@ -16,36 +16,36 @@ A non-priodic harmonic function used in combination with !!! note The only harmonic functions in 1D have the form phi(x) = A + Bx """ -function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations1D) - # elliptic equation: -νΔϕ = f - if t == 0.0 - phi = 5.0 - q1 = 0.0 - else - A = 3 - B = exp(1) - phi = A + B * x[1] - q1 = B - end - return SVector(phi, q1) +function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations1D) + # elliptic equation: -νΔϕ = f + if t == 0.0 + phi = 5.0 + q1 = 0.0 + else + A = 3 + B = exp(1) + phi = A + B * x[1] + q1 = B + end + return SVector(phi, q1) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 -coordinates_max = 2.0 +coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=false) + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -56,30 +56,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.75) +stepsize_callback = StepsizeCallback(cfl = 1.75) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_hypdiff_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl index 827d8d25ce..4da3b33a46 100644 --- a/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -11,19 +11,18 @@ initial_condition = initial_condition_poisson_nonperiodic boundary_conditions = boundary_condition_poisson_nonperiodic -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_poisson_nonperiodic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_poisson_nonperiodic) ############################################################################### # ODE solvers, callbacks etc. @@ -34,31 +33,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_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); +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_mhd_alfven_wave.jl b/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl index 82bca93c70..1a66ac60b9 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) initial_condition = initial_condition_convergence_test volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,32 +30,33 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +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); +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_mhd_briowu_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl index c5727109d9..bb294af68c 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl @@ -17,46 +17,44 @@ MHD extension of the Sod shock tube. Taken from Section V of the article [DOI: 10.1016/0021-9991(88)90120-9](https://doi.org/10.1016/0021-9991(88)90120-9) """ function initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [0, 1], γ = 2, final time = 0.12 - rho = x[1] < 0.5 ? 1.0 : 0.125 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] < 0.5 ? 1.0 : 0.1 - B1 = 0.75 - B2 = x[1] < 0.5 ? 1.0 : -1.0 - B3 = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [0, 1], γ = 2, final time = 0.12 + rho = x[1] < 0.5 ? 1.0 : 0.125 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] < 0.5 ? 1.0 : 0.1 + B1 = 0.75 + B2 = x[1] < 0.5 ? 1.0 : -1.0 + B3 = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_briowu_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_hll -volume_flux = flux_derigs_etal +volume_flux = flux_derigs_etal basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -67,45 +65,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.65) +stepsize_callback = StepsizeCallback(cfl = 0.65) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_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); +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_mhd_ec.jl b/examples/tree_1d_dgsem/elixir_mhd_ec.jl index 1f2e77006b..e5da808f69 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,17 @@ equations = IdealGlmMhdEquations1D(gamma) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_hindenlang_gassner, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hindenlang_gassner, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_mhd_ryujones_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl index 010788d48f..b6f856fbc6 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -22,48 +22,46 @@ present in the one dimensional MHD equations. It is the second test from Section This paper has a typo in the initial conditions. Their variable `E` should be `p`. """ function initial_condition_ryujones_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [0, 1], γ = 5/3, final time = 0.2 - rho = x[1] <= 0.5 ? 1.08 : 1.0 - v1 = x[1] <= 0.5 ? 1.2 : 0.0 - v2 = x[1] <= 0.5 ? 0.01 : 0.0 - v3 = x[1] <= 0.5 ? 0.5 : 0.0 - p = x[1] <= 0.5 ? 0.95 : 1.0 - inv_sqrt4pi = 1.0 / sqrt(4 * pi) - B1 = 2 * inv_sqrt4pi - B2 = x[1] <= 0.5 ? 3.6 * inv_sqrt4pi : 4.0 * inv_sqrt4pi - B3 = B1 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [0, 1], γ = 5/3, final time = 0.2 + rho = x[1] <= 0.5 ? 1.08 : 1.0 + v1 = x[1] <= 0.5 ? 1.2 : 0.0 + v2 = x[1] <= 0.5 ? 0.01 : 0.0 + v3 = x[1] <= 0.5 ? 0.5 : 0.0 + p = x[1] <= 0.5 ? 0.95 : 1.0 + inv_sqrt4pi = 1.0 / sqrt(4 * pi) + B1 = 2 * inv_sqrt4pi + B2 = x[1] <= 0.5 ? 3.6 * inv_sqrt4pi : 4.0 * inv_sqrt4pi + B3 = B1 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_ryujones_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_hll -volume_flux = flux_hindenlang_gassner +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=Trixi.density) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.density) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 7, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -74,27 +72,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) 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); +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_mhd_shu_osher_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl index 8c60b449e9..8c0317277b 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -17,19 +17,19 @@ Taken from Section 4.1 of [DOI: 10.1016/j.jcp.2016.04.048](https://doi.org/10.1016/j.jcp.2016.04.048) """ function initial_condition_shu_osher_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 - # initial shock location is taken to be at x = -4 - x_0 = -4.0 - rho = x[1] <= x_0 ? 3.5 : 1.0 + 0.2 * sin(5.0 * x[1]) - v1 = x[1] <= x_0 ? 5.8846 : 0.0 - v2 = x[1] <= x_0 ? 1.1198 : 0.0 - v3 = 0.0 - p = x[1] <= x_0 ? 42.0267 : 1.0 - B1 = 1.0 - B2 = x[1] <= x_0 ? 3.6359 : 1.0 - B3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 + # initial shock location is taken to be at x = -4 + x_0 = -4.0 + rho = x[1] <= x_0 ? 3.5 : 1.0 + 0.2 * sin(5.0 * x[1]) + v1 = x[1] <= x_0 ? 5.8846 : 0.0 + v2 = x[1] <= x_0 ? 1.1198 : 0.0 + v3 = 0.0 + p = x[1] <= x_0 ? 42.0267 : 1.0 + B1 = 1.0 + B2 = x[1] <= x_0 ? 3.6359 : 1.0 + B3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end """ @@ -41,50 +41,49 @@ but shock propagates from right to left. !!! note This is useful to exercise some of the components of the HLL flux. """ -function initial_condition_shu_osher_shock_tube_flipped(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 - # initial shock location is taken to be at x = 4 - x_0 = 4.0 - rho = x[1] <= x_0 ? 1.0 + 0.2 * sin(5.0 * x[1]) : 3.5 - v1 = x[1] <= x_0 ? 0.0 : -5.8846 - v2 = x[1] <= x_0 ? 0.0 : -1.1198 - v3 = 0.0 - p = x[1] <= x_0 ? 1.0 : 42.0267 - B1 = 1.0 - B2 = x[1] <= x_0 ? 1.0 : 3.6359 - B3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) +function initial_condition_shu_osher_shock_tube_flipped(x, t, + equations::IdealGlmMhdEquations1D) + # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 + # initial shock location is taken to be at x = 4 + x_0 = 4.0 + rho = x[1] <= x_0 ? 1.0 + 0.2 * sin(5.0 * x[1]) : 3.5 + v1 = x[1] <= x_0 ? 0.0 : -5.8846 + v2 = x[1] <= x_0 ? 0.0 : -1.1198 + v3 = 0.0 + p = x[1] <= x_0 ? 1.0 : 42.0267 + B1 = 1.0 + B2 = x[1] <= x_0 ? 1.0 : 3.6359 + B3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_shu_osher_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_hll -volume_flux = flux_hindenlang_gassner +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -5.0 -coordinates_max = 5.0 +coordinates_max = 5.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -95,42 +94,43 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=7, max_threshold=0.01) + base_level = 4, + max_level = 7, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_mhd_torrilhon_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl index 6855676429..3b366c35e0 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -16,46 +16,44 @@ Torrilhon's shock tube test case for one dimensional ideal MHD equations. [DOI: 10.1017/S0022377803002186](https://doi.org/10.1017/S0022377803002186) """ function initial_condition_torrilhon_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-1, 1.5], γ = 5/3, final time = 0.4 - rho = x[1] <= 0 ? 3.0 : 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] <= 0 ? 3.0 : 1.0 - B1 = 1.5 - B2 = x[1] <= 0 ? 1.0 : cos(1.5) - B3 = x[1] <= 0 ? 0.0 : sin(1.5) - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [-1, 1.5], γ = 5/3, final time = 0.4 + rho = x[1] <= 0 ? 3.0 : 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] <= 0 ? 3.0 : 1.0 + B1 = 1.5 + B2 = x[1] <= 0 ? 1.0 : cos(1.5) + B3 = x[1] <= 0 ? 0.0 : sin(1.5) + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_torrilhon_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_central +volume_flux = flux_central basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -1.0 -coordinates_max = 1.5 +coordinates_max = 1.5 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 7, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -66,29 +64,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +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); +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_mhdmulti_briowu_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl index 376f11d52a..831fa7afed 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl @@ -4,8 +4,8 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0), - gas_constants = (2.0, 2.0)) +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0), + gas_constants = (2.0, 2.0)) """ initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdMulticomponentEquations1D) @@ -16,55 +16,62 @@ MHD extension of the Sod shock tube. Taken from Section V of the article An Upwind Differencing Scheme for the Equations of Ideal Magnetohydrodynamics [DOI: 10.1016/0021-9991(88)90120-9](https://doi.org/10.1016/0021-9991(88)90120-9) """ -function initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdMulticomponentEquations1D) - # domain must be set to [0, 1], γ = 2, final time = 0.12 - if x[1] < 0.5 - rho = 1.0 - prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i-1) * (1-2)/(1-2^ncomponents(equations)) * rho for i in eachcomponent(equations)) - else - rho = 0.125 - prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i-1) * (1-2)/(1-2^ncomponents(equations)) * rho for i in eachcomponent(equations)) - end - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] < 0.5 ? 1.0 : 0.1 - B1 = 0.75 - B2 = x[1] < 0.5 ? 1.0 : -1.0 - B3 = 0.0 - - prim_other = SVector(v1, v2, v3, p, B1, B2, B3) - return prim2cons(vcat(prim_other, prim_rho), equations) +function initial_condition_briowu_shock_tube(x, t, + equations::IdealGlmMhdMulticomponentEquations1D) + # domain must be set to [0, 1], γ = 2, final time = 0.12 + if x[1] < 0.5 + rho = 1.0 + prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) * (1 - 2) / + (1 - + 2^ncomponents(equations)) * + rho + for i in eachcomponent(equations)) + else + rho = 0.125 + prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) * (1 - 2) / + (1 - + 2^ncomponents(equations)) * + rho + for i in eachcomponent(equations)) + end + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] < 0.5 ? 1.0 : 0.1 + B1 = 0.75 + B2 = x[1] < 0.5 ? 1.0 : -1.0 + B3 = 0.0 + + prim_other = SVector(v1, v2, v3, p, B1, B2, B3) + return prim2cons(vcat(prim_other, prim_rho), equations) end initial_condition = initial_condition_briowu_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_hindenlang_gassner +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.8, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.8, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,45 +82,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_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); +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_mhdmulti_convergence.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl index 573bf6bc3e..a1636c0847 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl @@ -5,25 +5,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (5/3, 5/3, 5/3), - gas_constants = (2.08, 2.08, 2.08)) +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (5 / 3, 5 / 3, 5 / 3), + gas_constants = (2.08, 2.08, 2.08)) initial_condition = initial_condition_convergence_test volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,17 +31,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -51,11 +50,10 @@ callbacks = CallbackSet(summary_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); +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_mhdmulti_ec.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl index 69ea0551be..71466f3138 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), gas_constants = (2.0, 2.0, 2.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_hindenlang_gassner, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hindenlang_gassner, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,26 +30,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_mhdmulti_es.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl index 93cf3e0fdb..37623e048e 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), gas_constants = (2.0, 2.0, 2.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_navierstokes_convergence_periodic.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl index 3f72d319b0..33ad0d5271 100644 --- a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl @@ -10,101 +10,101 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations1D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number()) # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) # (Simplified version of the 2D) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_t) - v1 = sin(pi_x) * cos(pi_t) - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_t) + v1 = sin(pi_x) * cos(pi_t) + p = rho^2 - return prim2cons(SVector(rho, v1, p), equations) + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_navier_stokes_convergence_test @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_t) - - v1 = sin(pi_x) * cos(pi_t) - v1_t = -pi * sin(pi_x) * sin(pi_t) - v1_x = pi * cos(pi_x) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * cos(pi_t) - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - - E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t - + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - # stress tensor from x-direction - - v1_xx * mu_) - - # total energy equation - du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - # stress tensor and temperature gradient terms from x-direction - - v1_xx * v1 * mu_ - - v1_x * v1_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_) - - return SVector(du1, du2, du3) + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_t) + + v1 = sin(pi_x) * cos(pi_t) + v1_t = -pi * sin(pi_x) * sin(pi_t) + v1_x = pi * cos(pi_x) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * cos(pi_t) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from x-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) end volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - + initial_refinement_level = 4, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, @@ -119,9 +119,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -131,6 +131,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-9 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl index 181a2cb209..40030d5334 100644 --- a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl @@ -8,135 +8,145 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations1D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) # and by the initial condition (which passes in `CompressibleEulerEquations1D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t - rho = c + A * cos(pi_x) * cos(pi_t) - v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0)) ) * cos(pi_t) - p = rho^2 + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0))) * cos(pi_t) + p = rho^2 - return prim2cons(SVector(rho, v1, p), equations) + return prim2cons(SVector(rho, v1, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - x = x[1] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * cos(pi_x) * cos(pi_t) - rho_t = -pi * A * cos(pi_x) * sin(pi_t) - rho_x = -pi * A * sin(pi_x) * cos(pi_t) - rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) - - v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) - v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) - v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) - v1_xx = (( 2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - - A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - - (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x - - # y-momentum equation - du2 = ( rho_t * v1 + rho * v1_t - + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - # stress tensor from y-direction - - v1_xx * mu_) - - # total energy equation - du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - # stress tensor and temperature gradient terms from x-direction - - v1_xx * v1 * mu_ - - v1_x * v1_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ ) - - return SVector(du1, du2, du3) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = ((2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - + A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - + (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from y-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2]) - -heat_bc_left = Isothermal((x, t, equations) -> - Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), - equations_parabolic)) +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations_parabolic)) heat_bc_right = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_left) -boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_right) +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_right) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_slip_wall, - x_pos = boundary_condition_slip_wall) + x_pos = boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_left, - x_pos = boundary_condition_right) + x_pos = boundary_condition_right) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -146,15 +156,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl index 1daeab04a7..e833155a68 100644 --- a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl @@ -8,135 +8,145 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations1D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesEntropy()) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesEntropy()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) # and by the initial condition (which passes in `CompressibleEulerEquations1D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t - rho = c + A * cos(pi_x) * cos(pi_t) - v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0)) ) * cos(pi_t) - p = rho^2 + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0))) * cos(pi_t) + p = rho^2 - return prim2cons(SVector(rho, v1, p), equations) + return prim2cons(SVector(rho, v1, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - x = x[1] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * cos(pi_x) * cos(pi_t) - rho_t = -pi * A * cos(pi_x) * sin(pi_t) - rho_x = -pi * A * sin(pi_x) * cos(pi_t) - rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) - - v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) - v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) - v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) - v1_xx = (( 2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - - A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - - (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x - - # y-momentum equation - du2 = ( rho_t * v1 + rho * v1_t - + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - # stress tensor from y-direction - - v1_xx * mu_) - - # total energy equation - du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - # stress tensor and temperature gradient terms from x-direction - - v1_xx * v1 * mu_ - - v1_x * v1_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ ) - - return SVector(du1, du2, du3) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = ((2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - + A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - + (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from y-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2]) - -heat_bc_left = Isothermal((x, t, equations) -> - Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), - equations_parabolic)) +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations_parabolic)) heat_bc_right = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_left) -boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_right) +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_right) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_slip_wall, - x_pos = boundary_condition_slip_wall) + x_pos = boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_left, - x_pos = boundary_condition_right) + x_pos = boundary_condition_right) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -146,19 +156,19 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -amr_controller = ControllerThreeLevel(semi, - IndicatorLöhner(semi, variable=Trixi.density), - base_level=3, - med_level=4, med_threshold=0.005, - max_level=5, max_threshold=0.01) +amr_controller = ControllerThreeLevel(semi, + IndicatorLöhner(semi, variable = Trixi.density), + base_level = 3, + med_level = 4, med_threshold = 0.005, + max_level = 5, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true) + interval = 5, + adapt_initial_condition = true) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) @@ -167,6 +177,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl index 1288bc5e66..378079ca33 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.812) +equations = ShallowWaterEquations1D(gravity_constant = 9.812) """ initial_condition_beach(x, t, equations:: ShallowWaterEquations1D) @@ -22,33 +22,33 @@ found in section 5.2 of the paper: Finite volume evolution Galerkin methods for the shallow water equations with dry beds\n [DOI: 10.4208/cicp.220210.020710a](https://dx.doi.org/10.4208/cicp.220210.020710a) """ -function initial_condition_beach(x, t, equations:: ShallowWaterEquations1D) - D = 1 - delta = 0.02 - gamma = sqrt((3 * delta) / (4 * D)) - x_a = sqrt((4 * D) / (3 * delta)) * acosh(sqrt(20)) - - f = D + 40 * delta * sech(gamma * (8 * x[1] - x_a))^2 - - # steep curved beach - b = 0.01 + 99 / 409600 * 4^x[1] - - if x[1] >= 6 - H = b - v = 0.0 - else - H = f - v = sqrt(equations.gravity / D) * H - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_beach(x, t, equations::ShallowWaterEquations1D) + D = 1 + delta = 0.02 + gamma = sqrt((3 * delta) / (4 * D)) + x_a = sqrt((4 * D) / (3 * delta)) * acosh(sqrt(20)) + + f = D + 40 * delta * sech(gamma * (8 * x[1] - x_a))^2 + + # steep curved beach + b = 0.01 + 99 / 409600 * 4^x[1] + + if x[1] >= 6 + H = b + v = 0.0 + else + H = f + v = sqrt(equations.gravity / D) * H + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_beach @@ -58,19 +58,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -81,13 +82,13 @@ 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) + 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) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks etc. @@ -98,24 +99,25 @@ 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)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(dt=0.5, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl index 1469afec1c..a3df37fb96 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl @@ -6,7 +6,7 @@ using Trixi # Semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) # Initial condition with a truly discontinuous water height, velocity, and bottom # topography function as an academic testcase for entropy conservation. @@ -16,23 +16,23 @@ equations = ShallowWaterEquations1D(gravity_constant=9.81) # 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::ShallowWaterEquations1D) - # 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) + # 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 @@ -41,8 +41,9 @@ 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)) +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 @@ -50,8 +51,8 @@ solver = DGSEM(polydeg=4, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = -1.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) + initial_refinement_level = 4, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -68,15 +69,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -84,7 +85,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_parabolic_bowl.jl b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl index 916bba76ec..a586562af7 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations1D) @@ -28,26 +28,26 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations1D) - a = 1 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v = -sigma * ω * sin(ω * t) - - b = h_0 * x[1]^2 / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations1D) + a = 1 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v = -sigma * ω * sin(ω * t) + + b = h_0 * x[1]^2 / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_parabolic_bowl @@ -56,19 +56,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -79,8 +80,8 @@ coordinates_min = -2.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) + initial_refinement_level = 6, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -94,24 +95,25 @@ 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)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +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 index 62346d7b5a..511f33d110 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl @@ -5,36 +5,37 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.812, H0=1.75) +equations = ShallowWaterEquations1D(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::ShallowWaterEquations1D) +function initial_condition_stone_throw_discontinuous_bottom(x, t, + equations::ShallowWaterEquations1D) - # Calculate primitive variables + # Calculate primitive variables - # flat lake - H = equations.H0 + # 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 + # 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 ) ) ) + 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 + # 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) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_stone_throw_discontinuous_bottom @@ -45,18 +46,19 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -66,9 +68,9 @@ solver = DGSEM(basis, surface_flux, volume_integral) 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) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, @@ -86,28 +88,29 @@ 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, - lake_at_rest_error)) +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) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution)#, - # visualization) +# 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); +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_source_terms.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl index 2f9f93f433..af596a377f 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(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)) +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 @@ -23,13 +23,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ 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) + 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) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +40,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +54,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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 index c8ef1c1b70..cbc98a30f9 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -16,8 +16,8 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) 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)) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -25,14 +25,14 @@ solver = DGSEM(polydeg=3, surface_flux=surface_flux, 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) + 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) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -57,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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_twolayer_convergence.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl index e9f444aed2..fc76b4f034 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -5,18 +5,18 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - +solver = DGSEM(polydeg = 3, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -24,13 +24,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ 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) + 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) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -41,13 +41,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -55,6 +55,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control - sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, - save_everystep=false, callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl index 60770d158f..b2e6a81401 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl @@ -6,28 +6,29 @@ using Trixi # Semidiscretization of the two-layer shallow water equations for a dam break # test with a discontinuous bottom topography function to test entropy conservation -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=9.81, H0=2.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 9.81, H0 = 2.0, + rho_upper = 0.9, rho_lower = 1.0) # Initial condition of a dam break with a discontinuous water heights and bottom topography. # Works as intended for TreeMesh1D with `initial_refinement_level=5`. If the mesh # refinement level is changed the initial condition below may need changed as well to # ensure that the discontinuities lie on an element interface. function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations1D) - v1_upper = 0.0 - v1_lower = 0.0 - - # Set the discontinuity - if x[1] <= 10.0 - H_lower = 2.0 - H_upper = 4.0 - b = 0.0 - else - H_lower = 1.5 - H_upper = 3.0 - b = 0.5 - end - - return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) + v1_upper = 0.0 + v1_lower = 0.0 + + # Set the discontinuity + if x[1] <= 10.0 + H_lower = 2.0 + H_upper = 4.0 + b = 0.0 + else + H_lower = 1.5 + H_upper = 3.0 + b = 0.5 + end + + return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) end initial_condition = initial_condition_dam_break @@ -36,8 +37,9 @@ initial_condition = initial_condition_dam_break # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a non-periodic mesh @@ -45,20 +47,20 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = 0.0 coordinates_max = 20.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10000, - periodicity=false) + initial_refinement_level = 5, + n_cells_max = 10000, + periodicity = false) boundary_condition = boundary_condition_slip_wall # create the semidiscretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers -tspan = (0.0,0.4) +tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) ############################################################################### @@ -67,16 +69,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -84,6 +89,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index bec0b8ab69..7236f1697d 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -5,7 +5,8 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations to test well-balancedness -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=1.0, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 1.0, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) """ initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations1D) @@ -15,7 +16,8 @@ Initial condition to test well balanced with a bottom topography from Fjordholm Energy conservative and stable schemes for the two-layer shallow water equations. [DOI: 10.1142/9789814417099_0039](https://doi.org/10.1142/9789814417099_0039) """ -function initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations1D) +function initial_condition_fjordholm_well_balanced(x, t, + equations::ShallowWaterTwoLayerEquations1D) inicenter = 0.5 x_norm = x[1] - inicenter r = abs(x_norm) @@ -24,9 +26,9 @@ function initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWater H_upper = 0.6 v1_upper = 0.0 v1_lower = 0.0 - b = r <= 0.1 ? 0.2 * (cos(10 * pi * (x[1] - 0.5)) + 1) : 0.0 + b = r <= 0.1 ? 0.2 * (cos(10 * pi * (x[1] - 0.5)) + 1) : 0.0 return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) - end +end initial_condition = initial_condition_fjordholm_well_balanced @@ -34,8 +36,9 @@ initial_condition = initial_condition_fjordholm_well_balanced # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -43,9 +46,9 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_es_fjordholm_etal, flux_nonconserva coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -59,16 +62,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -76,7 +80,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl index e07bc04d76..649e5023f6 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations1D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations1D(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 @@ -15,18 +15,19 @@ equations = ShallowWaterEquations1D(gravity_constant=9.81, H0=3.25) # 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::ShallowWaterEquations1D) - # 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) +function initial_condition_discontinuous_well_balancedness(x, t, + equations::ShallowWaterEquations1D) + # 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 @@ -36,17 +37,17 @@ initial_condition = initial_condition_discontinuous_well_balancedness 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)) +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 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -63,16 +64,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -80,7 +81,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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 index ef707b803e..e55fffc101 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl @@ -5,19 +5,19 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=1.0, H0=3.0) +equations = ShallowWaterEquations1D(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::ShallowWaterEquations1D) - # Set the background values - H = equations.H0 - v = 0.0 + # 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))) + 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) + return prim2cons(SVector(H, v, b), equations) end - + initial_condition = initial_condition_well_balancedness boundary_condition = BoundaryConditionDirichlet(initial_condition) @@ -26,8 +26,8 @@ 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)) +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 @@ -35,9 +35,9 @@ solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_fjordholm 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) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, @@ -52,25 +52,25 @@ 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,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, +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); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index 8de46c6179..26a8960ab4 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,7 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.812) +equations = ShallowWaterEquations1D(gravity_constant = 9.812) """ initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations1D) @@ -23,28 +23,29 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations1D) - v = 0.0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations1D) + v = 0.0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -53,19 +54,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -76,8 +78,8 @@ coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) + initial_refinement_level = 6, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -91,26 +93,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.5) +stepsize_callback = StepsizeCallback(cfl = 1.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +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); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -123,35 +126,39 @@ summary_callback() # print the timer summary # Declare a special version of the function to compute the lake-at-rest error # OBS! The reference water height values are hardcoded for convenience. function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations1D) - h, _, b = u - - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max( 2.5 , b + equations.threshold_limiter ) - else - H0_wet_dry = max( 1.5 , b + equations.threshold_limiter ) - end - - return abs(H0_wet_dry - (h + b)) - end + 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) +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 @@ -162,4 +169,4 @@ println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summa @printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) @printf(" % 10.8e", l1_well_balance_error) println() -println("─"^100) \ No newline at end of file +println("─"^100) diff --git a/examples/tree_1d_fdsbp/elixir_advection_upwind.jl b/examples/tree_1d_fdsbp/elixir_advection_upwind.jl index 1f2498e086..389a8566c9 100644 --- a/examples/tree_1d_fdsbp/elixir_advection_upwind.jl +++ b/examples/tree_1d_fdsbp/elixir_advection_upwind.jl @@ -24,7 +24,7 @@ solver = FDSBP(D_upw, volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level = 4, n_cells_max = 10_000, @@ -32,7 +32,6 @@ mesh = TreeMesh(coordinates_min, coordinates_max, semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_sin, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -42,17 +41,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl b/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl index 035d3568a8..2d7c13d7e5 100644 --- a/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl +++ b/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl @@ -23,7 +23,7 @@ solver = FDSBP(D_upw, volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level = 0, n_cells_max = 10_000, @@ -31,7 +31,6 @@ mesh = TreeMesh(coordinates_min, coordinates_max, semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_sin, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,17 +40,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_burgers_basic.jl b/examples/tree_1d_fdsbp/elixir_burgers_basic.jl index c7b0176dfd..c58fc497e1 100644 --- a/examples/tree_1d_fdsbp/elixir_burgers_basic.jl +++ b/examples/tree_1d_fdsbp/elixir_burgers_basic.jl @@ -12,24 +12,23 @@ equations = InviscidBurgersEquation1D() initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=32) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 32) flux_splitting = splitting_lax_friedrichs solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,25 +39,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl b/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl index 20508feba2..eeaae7a784 100644 --- a/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl +++ b/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl @@ -10,28 +10,28 @@ using Trixi equations = InviscidBurgersEquation1D() function initial_condition_linear_stability(x, t, equation::InviscidBurgersEquation1D) - k = 1 - 2 + sinpi(k * (x[1] - 0.7)) |> SVector + k = 1 + 2 + sinpi(k * (x[1] - 0.7)) |> SVector end D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_lax_friedrichs solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, solver) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -42,19 +42,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_euler_convergence.jl b/examples/tree_1d_fdsbp/elixir_euler_convergence.jl index f9f9297f7c..7b6bfee946 100644 --- a/examples/tree_1d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_1d_fdsbp/elixir_euler_convergence.jl @@ -12,24 +12,23 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=32) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 32) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=10_000) + initial_refinement_level = 1, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,25 +39,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl b/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl index 5c5192a3fb..a28cd01120 100644 --- a/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl +++ b/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl @@ -11,24 +11,23 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_density_wave D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_coirier_vanleer solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,23 +37,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 10000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl b/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl index d34399a557..615da95187 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl @@ -4,26 +4,25 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.5, 0.3), c_mean_global=2.0, - rho_mean_global=0.9) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.5, 0.3), c_mean_global = 2.0, + rho_mean_global = 0.9) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (2.0, 2.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +36,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl b/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl index fa608e7869..b3fe55dcce 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl @@ -10,20 +10,19 @@ rho_mean_global = 1.0 equations = AcousticPerturbationEquations2D(v_mean_global, c_mean_global, rho_mean_global) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_gauss, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -36,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl b/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl index 78102eaf87..918c0831fc 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl @@ -4,20 +4,20 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.5, 0.0), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.5, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 5 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=5, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs) coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 4, + n_cells_max = 100_000, + periodicity = false) """ initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) @@ -26,20 +26,19 @@ A Gaussian pulse, used in the `gauss_wall` example elixir in combination with [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. """ function initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) + prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_gauss_wall # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_wall) - + boundary_conditions = boundary_condition_wall) ############################################################################### # ODE solvers, callbacks etc. @@ -53,24 +52,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2state) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2state) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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) +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) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl b/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl index 0a0e252058..71d4f1a9f6 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl @@ -3,45 +3,45 @@ using Trixi # Oscillating Gaussian-shaped source terms function source_terms_gauss(u, x, t, equations::AcousticPerturbationEquations2D) - r = 0.1 - A = 1.0 - f = 2.0 + r = 0.1 + A = 1.0 + f = 2.0 - # Velocity sources - s1 = 0.0 - s2 = 0.0 - # Pressure source - s3 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) + # Velocity sources + s1 = 0.0 + s2 = 0.0 + # Pressure source + s3 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) - # Mean sources - s4 = s5 = s6 = s7 = 0.0 + # Mean sources + s4 = s5 = s6 = s7 = 0.0 - return SVector(s1, s2, s3, s4, s5, s6, s7) + return SVector(s1, s2, s3, s4, s5, s6, s7) end ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(-0.5, 0.25), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (-0.5, 0.25), + c_mean_global = 1.0, + rho_mean_global = 1.0) initial_condition = initial_condition_constant # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-3.0, -3.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 3.0, 3.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (3.0, 3.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_gauss) - + source_terms = source_terms_gauss) ############################################################################### # ODE solvers, callbacks etc. @@ -55,30 +55,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The TimeSeriesCallback records the solution at the given points over time time_series = TimeSeriesCallback(semi, [(0.0, 0.0), (-1.0, 0.5)]) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, time_series, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl b/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl index 0fdcbd22c4..d726577511 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl @@ -4,11 +4,11 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.0, 0.0), c_mean_global=0.0, - rho_mean_global=0.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.0, 0.0), c_mean_global = 0.0, + rho_mean_global = 0.0) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-20.6, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (30.6, 51.2) # maximum coordinates (max(x), max(y)) @@ -20,20 +20,20 @@ Initial condition for the monopole in a boundary layer setup, used in combinatio [`boundary_condition_monopole`](@ref). """ function initial_condition_monopole(x, t, equations::AcousticPerturbationEquations2D) - m = 0.3 # Mach number + m = 0.3 # Mach number - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = 0.0 + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = 0.0 - v1_mean = x[2] > 1 ? m : m * (2*x[2] - 2*x[2]^2 + x[2]^4) - v2_mean = 0.0 - c_mean = 1.0 - rho_mean = 1.0 + v1_mean = x[2] > 1 ? m : m * (2 * x[2] - 2 * x[2]^2 + x[2]^4) + v2_mean = 0.0 + c_mean = 1.0 + rho_mean = 1.0 - prim = SVector(v1_prime, v2_prime, p_prime, v1_mean, v2_mean, c_mean, rho_mean) + prim = SVector(v1_prime, v2_prime, p_prime, v1_mean, v2_mean, c_mean, rho_mean) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_monopole # does not use the global mean values given above @@ -45,32 +45,35 @@ Boundary condition for a monopole in a boundary layer at the -y boundary, i.e. ` This will return an error for any other direction. This boundary condition is used in combination with [`initial_condition_monopole`](@ref). """ -function boundary_condition_monopole(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_monopole(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - if direction != 3 - error("expected direction = 3, got $direction instead") - end - - # Wall at the boundary in -y direction with a monopole at -0.05 <= x <= 0.05. In the monopole area - # we use a sinusoidal boundary state for the perturbed variables. For the rest of the -y boundary - # we set the boundary state to the inner state and multiply the perturbed velocity in the - # y-direction by -1. - if -0.05 <= x[1] <= 0.05 # Monopole - v1_prime = 0.0 - v2_prime = p_prime = sin(2 * pi * t) - - prim_boundary = SVector(v1_prime, v2_prime, p_prime, u_inner[4], u_inner[5], u_inner[6], u_inner[7]) - - u_boundary = prim2cons(prim_boundary, equations) - else # Wall - u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4], u_inner[5], u_inner[6], - u_inner[7]) - end - - # Calculate boundary flux - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + if direction != 3 + error("expected direction = 3, got $direction instead") + end + + # Wall at the boundary in -y direction with a monopole at -0.05 <= x <= 0.05. In the monopole area + # we use a sinusoidal boundary state for the perturbed variables. For the rest of the -y boundary + # we set the boundary state to the inner state and multiply the perturbed velocity in the + # y-direction by -1. + if -0.05 <= x[1] <= 0.05 # Monopole + v1_prime = 0.0 + v2_prime = p_prime = sin(2 * pi * t) + + prim_boundary = SVector(v1_prime, v2_prime, p_prime, u_inner[4], u_inner[5], + u_inner[6], u_inner[7]) + + u_boundary = prim2cons(prim_boundary, equations) + else # Wall + u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4], u_inner[5], + u_inner[6], + u_inner[7]) + end + + # Calculate boundary flux + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - return flux + return flux end """ @@ -80,42 +83,42 @@ end Boundary condition that uses a boundary state where the state variables are zero and the mean variables are the same as in `u_inner`. """ -function boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_zero(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - value = zero(eltype(u_inner)) - u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) + value = zero(eltype(u_inner)) + u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) - # 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 + # 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 + return flux end -boundary_conditions = (x_neg=boundary_condition_zero, - x_pos=boundary_condition_zero, - y_neg=boundary_condition_monopole, - y_pos=boundary_condition_zero) +boundary_conditions = (x_neg = boundary_condition_zero, + x_pos = boundary_condition_zero, + y_neg = boundary_condition_monopole, + y_pos = boundary_condition_zero) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 100_000, + periodicity = false) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. # Create ODE problem with time span from 0.0 to 24.0 -tspan = (0.0, 24.0) +tspan = (0.0, 24.0) ode = semidiscretize(semi, tspan) # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup @@ -123,24 +126,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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) +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) # Print the timer summary -summary_callback() \ No newline at end of file +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_amr.jl b/examples/tree_2d_dgsem/elixir_advection_amr.jl index 8484187744..c3f971d2ff 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,37 +28,36 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_advection_amr_coarsen_twice.jl b/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl index 897d3569e1..aa042e7500 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl @@ -3,7 +3,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -11,27 +10,27 @@ module TrixiExtensionCoarsen using Trixi -struct IndicatorAlwaysCoarsen{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorAlwaysCoarsen{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorAlwaysCoarsen(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorAlwaysCoarsen{typeof(cache)}(cache) + return IndicatorAlwaysCoarsen{typeof(cache)}(cache) end -function (indicator::IndicatorAlwaysCoarsen)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorAlwaysCoarsen)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) - alpha .= -1.0 + alpha .= -1.0 - return alpha + return alpha end end # module TrixiExtensionCoarsen @@ -46,18 +45,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,37 +64,37 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionCoarsen.IndicatorAlwaysCoarsen(semi), - base_level=2, max_level=2, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionCoarsen.IndicatorAlwaysCoarsen(semi), + base_level = 2, max_level = 2, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_advection_amr_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl index 42aee98588..abb8a5035b 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl @@ -14,19 +14,17 @@ initial_condition = initial_condition_gauss # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -65,7 +63,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # 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_advection_amr_refine_twice.jl b/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl index e69cab29bb..7b44177520 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl @@ -3,7 +3,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -11,27 +10,27 @@ module TrixiExtensionRefine using Trixi -struct IndicatorAlwaysRefine{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorAlwaysRefine{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorAlwaysRefine(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorAlwaysRefine{typeof(cache)}(cache) + return IndicatorAlwaysRefine{typeof(cache)}(cache) end -function (indicator::IndicatorAlwaysRefine)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorAlwaysRefine)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) - alpha .= 1.0 + alpha .= 1.0 - return alpha + return alpha end end # module TrixiExtensionRefine @@ -46,18 +45,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,37 +64,37 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionRefine.IndicatorAlwaysRefine(semi), - base_level=4, max_level=4, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionRefine.IndicatorAlwaysRefine(semi), + base_level = 4, max_level = 4, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_advection_amr_solution_independent.jl b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl index efd282dab1..03a213689e 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -7,69 +7,68 @@ module TrixiExtension using Trixi -struct IndicatorSolutionIndependent{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorSolutionIndependent{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorSolutionIndependent(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) - return IndicatorSolutionIndependent{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) + return IndicatorSolutionIndependent{typeof(cache)}(cache) end -function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - - mesh = indicator.cache.mesh - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - #Predict the theoretical center. - advection_velocity = (0.2, -0.7) - center = t.*advection_velocity - - inner_distance = 1 - outer_distance = 1.85 - - #Iterate over all elements - for element in 1:length(alpha) - #Calculate periodic distance between cell and center. - cell_id = cache.elements.cell_ids[element] - coordinates = mesh.tree.coordinates[1:2, cell_id] - - #The geometric shape of the amr should be preserved when the base_level is increased. - #This is done by looking at the original coordinates of each cell. - cell_coordinates = original_coordinates(coordinates, 5/8) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) - if cell_distance < (inner_distance+outer_distance)/2 - cell_coordinates = original_coordinates(coordinates, 5/16) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + mesh = indicator.cache.mesh + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + #Predict the theoretical center. + advection_velocity = (0.2, -0.7) + center = t .* advection_velocity + + inner_distance = 1 + outer_distance = 1.85 + + #Iterate over all elements + for element in 1:length(alpha) + #Calculate periodic distance between cell and center. + cell_id = cache.elements.cell_ids[element] + coordinates = mesh.tree.coordinates[1:2, cell_id] + + #The geometric shape of the amr should be preserved when the base_level is increased. + #This is done by looking at the original coordinates of each cell. + cell_coordinates = original_coordinates(coordinates, 5 / 8) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + if cell_distance < (inner_distance + outer_distance) / 2 + cell_coordinates = original_coordinates(coordinates, 5 / 16) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + end + + #Set alpha according to cells position inside the circles. + target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) + alpha[element] = target_level / 2 end - - #Set alpha according to cells position inside the circles. - target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) - alpha[element] = target_level/2 - end - return alpha + return alpha end # For periodic domains, distance between two points must take into account # periodic extensions of the domain function periodic_distance_2d(coordinates, center, domain_length) - dx = coordinates .- center - dx_shifted = abs.(dx .% domain_length) - dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) - return sqrt(sum(dx_periodic.^2)) + dx = coordinates .- center + dx_shifted = abs.(dx .% domain_length) + dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) + return sqrt(sum(dx_periodic .^ 2)) end #This takes a cells coordinates and transforms them into the coordinates of a parent-cell it originally refined from. #It does it so that the parent-cell has given cell_length. function original_coordinates(coordinates, cell_length) - offset = coordinates .% cell_length - offset_sign = sign.(offset) - border = coordinates - offset - center = border + (offset_sign .* cell_length/2) - return center + offset = coordinates .% cell_length + offset_sign = sign.(offset) + border = coordinates - offset + center = border + (offset_sign .* cell_length / 2) + return center end end # module TrixiExtension @@ -83,18 +82,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -104,38 +101,38 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorSolutionIndependent(semi), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtension.IndicatorSolutionIndependent(semi), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_advection_amr_visualization.jl b/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl index f517b4eb1c..7b67b81117 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl @@ -9,27 +9,26 @@ using Plots advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) -function initial_condition_gauss_largedomain(x, t, equation::LinearScalarAdvectionEquation2D) - # Store translated coordinate for easy use of exact solution - domain_length = SVector(10, 10) - x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t, domain_length) +function initial_condition_gauss_largedomain(x, t, + equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + domain_length = SVector(10, 10) + x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t, domain_length) - return SVector(exp(-(x_trans[1]^2 + x_trans[2]^2))) + return SVector(exp(-(x_trans[1]^2 + x_trans[2]^2))) end initial_condition = initial_condition_gauss_largedomain -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -39,41 +38,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # Enable in-situ visualization with a new plot generated every 20 time steps # and additional plotting options passed as keyword arguments -visualization = VisualizationCallback(interval=20, clims=(0,1)) +visualization = VisualizationCallback(interval = 20, clims = (0, 1)) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=3, - med_level=4, med_threshold=0.1, - max_level=5, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 3, + med_level = 4, med_threshold = 0.1, + max_level = 5, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, visualization, amr_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); +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_advection_basic.jl b/examples/tree_2d_dgsem/elixir_advection_basic.jl index 269ab8cdd0..0ec0bc3629 100644 --- a/examples/tree_2d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_callbacks.jl b/examples/tree_2d_dgsem/elixir_advection_callbacks.jl index 2ddd3e92ed..708cd0aa3a 100644 --- a/examples/tree_2d_dgsem/elixir_advection_callbacks.jl +++ b/examples/tree_2d_dgsem/elixir_advection_callbacks.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - # define new structs inside a module to allow re-evaluating the file module TrixiExtensionExample @@ -14,83 +13,81 @@ using OrdinaryDiffEq: DiscreteCallback, u_modified! # each time it is called. Its sole purpose here is to showcase how to implement # a stage callback for Trixi.jl. struct ExampleStageCallback - times::Vector{Float64} - min_values::Vector{Float64} - max_values::Vector{Float64} - - # You can optionally define an inner constructor like the one below to set up - # some required stuff. You can also create outer constructors (not demonstrated - # here) for further customization options. - function ExampleStageCallback() - new(Float64[], Float64[], Float64[]) - end + times::Vector{Float64} + min_values::Vector{Float64} + max_values::Vector{Float64} + + # You can optionally define an inner constructor like the one below to set up + # some required stuff. You can also create outer constructors (not demonstrated + # here) for further customization options. + function ExampleStageCallback() + new(Float64[], Float64[], Float64[]) + end end # This method is called when the `ExampleStageCallback` is used as `stage_limiter!` # which gets called after every RK stage. There is no specific initialization # method for such `stage_limiter!`s in OrdinaryDiffEq.jl. function (example_stage_callback::ExampleStageCallback)(u_ode, _, semi, t) + min_val, max_val = extrema(u_ode) + push!(example_stage_callback.times, t) + push!(example_stage_callback.min_values, min_val) + push!(example_stage_callback.max_values, max_val) - min_val, max_val = extrema(u_ode) - push!(example_stage_callback.times, t) - push!(example_stage_callback.min_values, min_val) - push!(example_stage_callback.max_values, max_val) - - return nothing + return nothing end - # This is an example implementation for a simple step callback (i.e., a callable # that is potentially executed after each Runge-Kutta *step*), which records # some values each time it is called. Its sole purpose here is to showcase # how to implement a step callback for Trixi.jl. struct ExampleStepCallback - message::String - times::Vector{Float64} - min_values::Vector{Float64} - max_values::Vector{Float64} - - # You can optionally define an inner constructor like the one below to set up - # some required stuff. You can also create outer constructors (not demonstrated - # here) for further customization options. - function ExampleStepCallback(message::String) - new(message, Float64[], Float64[], Float64[]) - end + message::String + times::Vector{Float64} + min_values::Vector{Float64} + max_values::Vector{Float64} + + # You can optionally define an inner constructor like the one below to set up + # some required stuff. You can also create outer constructors (not demonstrated + # here) for further customization options. + function ExampleStepCallback(message::String) + new(message, Float64[], Float64[], Float64[]) + end end # This method is called when the `ExampleStepCallback` is used as callback # which gets called after RK steps. function (example_callback::ExampleStepCallback)(integrator) - u_ode = integrator.u - t = integrator.t - # You can also access semi = integrator.p - - min_val, max_val = extrema(u_ode) - push!(example_callback.times, t) - push!(example_callback.min_values, min_val) - push!(example_callback.max_values, max_val) - - # avoid re-evaluating possible FSAL stages - u_modified!(integrator, false) - return nothing + u_ode = integrator.u + t = integrator.t + # You can also access semi = integrator.p + + min_val, max_val = extrema(u_ode) + push!(example_callback.times, t) + push!(example_callback.min_values, min_val) + push!(example_callback.max_values, max_val) + + # avoid re-evaluating possible FSAL stages + u_modified!(integrator, false) + return nothing end # This method is used to wrap an `ExampleStepCallback` inside a `DiscreteCallback` # which gets called after every RK step. You can pass an additional initialization # method and a separate condition specifying whether the callback shall be called. function ExampleStepCallback(; message::String) - # Call the `ExampleStepCallback` after every RK step. - condition = (u_ode, t, integrator) -> true + # Call the `ExampleStepCallback` after every RK step. + condition = (u_ode, t, integrator) -> true - # You can optionally pass an initialization method. There, you can access the - # `ExampleStepCallback` as `cb.affect!`. - initialize = (cb, u_ode, t, integrator) -> println(cb.affect!.message) + # You can optionally pass an initialization method. There, you can access the + # `ExampleStepCallback` as `cb.affect!`. + initialize = (cb, u_ode, t, integrator) -> println(cb.affect!.message) - example_callback = ExampleStepCallback(message) + example_callback = ExampleStepCallback(message) - DiscreteCallback(condition, example_callback, - save_positions=(false,false), - initialize=initialize) + DiscreteCallback(condition, example_callback, + save_positions = (false, false), + initialize = initialize) end end # module TrixiExtensionExample @@ -104,18 +101,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -125,19 +120,19 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_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=cons2cons) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) -example_callback = TrixiExtensionExample.ExampleStepCallback(message="안녕하세요?") +example_callback = TrixiExtensionExample.ExampleStepCallback(message = "안녕하세요?") -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -158,9 +153,10 @@ example_stage_callback! = TrixiExtensionExample.ExampleStageCallback() ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(example_stage_callback!, 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); +sol = solve(ode, + CarpenterKennedy2N54(example_stage_callback!, 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 # Check whether we recorded the same values. diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl index a716bd278b..1f765ff356 100644 --- a/examples/tree_2d_dgsem/elixir_advection_diffusion.jl +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl @@ -10,30 +10,31 @@ diffusivity() = 5.0e-2 equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=true, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = true, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Define initial condition -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) - # Store translated coordinate for easy use of exact solution - x_trans = x - equation.advection_velocity * t - - nu = diffusivity() - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) - return SVector(scalar) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) end initial_condition = initial_condition_diffusive_convergence_test @@ -45,9 +46,8 @@ boundary_conditions_parabolic = boundary_condition_periodic semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -62,23 +62,22 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks alg = RDPK3SpFSAL49() time_int_tol = 1.0e-11 -sol = solve(ode, alg; abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, alg; abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl index c3cd2ebeb2..8da542b0b5 100644 --- a/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -10,16 +10,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -0.5) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.0, 0.5) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.0, 0.5) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Example setup taken from # - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). @@ -28,22 +28,22 @@ mesh = TreeMesh(coordinates_min, coordinates_max, # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_eriksson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_eriksson_johnson boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), - y_neg = BoundaryConditionDirichlet(initial_condition), - y_pos = BoundaryConditionDirichlet(initial_condition), - x_pos = boundary_condition_do_nothing) + y_neg = BoundaryConditionDirichlet(initial_condition), + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing) boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) @@ -51,9 +51,8 @@ boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -68,22 +67,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_extended.jl b/examples/tree_2d_dgsem/elixir_advection_extended.jl index 278dc85386..4d3da47b04 100644 --- a/examples/tree_2d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_2d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=40, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 40, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,15 +71,14 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -alg = CarpenterKennedy2N54(williamson_condition=false) +alg = CarpenterKennedy2N54(williamson_condition = false) sol = solve(ode, alg, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks; ode_default_options()...); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks; ode_default_options()...); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_mortar.jl b/examples/tree_2d_dgsem/elixir_advection_mortar.jl index 2a283fb900..645c55ba43 100644 --- a/examples/tree_2d_dgsem/elixir_advection_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_advection_mortar.jl @@ -9,22 +9,19 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -1.0), coordinates_max=(1.0, 1.0)), -) +coordinates_max = (1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -1.0), + coordinates_max = (1.0, 1.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000,) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) 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); +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_advection_restart.jl b/examples/tree_2d_dgsem/elixir_advection_restart.jl index b63a8d1f7b..770629bb15 100644 --- a/examples/tree_2d_dgsem/elixir_advection_restart.jl +++ b/examples/tree_2d_dgsem/elixir_advection_restart.jl @@ -4,10 +4,10 @@ using Trixi ############################################################################### # Define time integration algorithm -alg = CarpenterKennedy2N54(williamson_condition=false) +alg = CarpenterKennedy2N54(williamson_condition = false) # Create a restart file -trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl"), alg = alg, tspan = (0.0, 10.0)) - +trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl"), alg = alg, + tspan = (0.0, 10.0)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -28,8 +28,8 @@ ode = semidiscretize(semi, tspan, restart_filename); save_solution.condition.save_initial_solution = false integrator = init(ode, alg, - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks; ode_default_options()...) + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks; ode_default_options()...) # Load saved context for adaptive time integrator if integrator.opts.adaptive diff --git a/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl b/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl index be87f24f81..06982bb9a2 100644 --- a/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl +++ b/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,39 +28,38 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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=cons2cons) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation # sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), ode_algorithm = Trixi.CarpenterKennedy2N54() sol = Trixi.solve(ode, ode_algorithm, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index f51b73dd49..69148f5bdb 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) # Initial condition adopted from @@ -13,57 +13,56 @@ equations = CompressibleEulerEquations2D(gamma) # https://tinyurl.com/c76fjtx4 # Mach = 2000 jet function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) - @unpack gamma = equations - rho = 0.5 - v1 = 0 - v2 = 0 - p = 0.4127 - # add inflow for t>0 at x=-0.5 - # domain size is [-0.5,+0.5]^2 - if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) - rho = 5 - v1 = 800 # about Mach number Ma = 2000 + @unpack gamma = equations + rho = 0.5 + v1 = 0 v2 = 0 p = 0.4127 - end - return prim2cons(SVector(rho, v1, v2, p), equations) + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_astro_jet -boundary_conditions = ( - x_neg=BoundaryConditionCharacteristic(initial_condition_astro_jet), - x_pos=BoundaryConditionCharacteristic(initial_condition_astro_jet), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) +boundary_conditions = (x_neg = BoundaryConditionCharacteristic(initial_condition_astro_jet), + x_pos = BoundaryConditionCharacteristic(initial_condition_astro_jet), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_chandrashekar # works with Ranocha flux as well +volume_flux = flux_chandrashekar # works with Ranocha flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=true, - SequentialLimiter=true, - PressurePositivityLimiterKuzmin=true, - DensityPositivityLimiter=false, - SemiDiscEntropyLimiter=false, - Plotting=true) + DensityLimiter = true, + DensityAlphaForAll = true, + SequentialLimiter = true, + PressurePositivityLimiterKuzmin = true, + DensityPositivityLimiter = false, + SemiDiscEntropyLimiter = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=8, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 8, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -74,16 +73,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -93,9 +92,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + maxiters = 1e6, dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl index c5790e455b..1393f4a6cc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) # Initial condition adopted from @@ -13,55 +13,54 @@ equations = CompressibleEulerEquations2D(gamma) # https://tinyurl.com/c76fjtx4 # Mach = 2000 jet function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) - @unpack gamma = equations - rho = 0.5 - v1 = 0 - v2 = 0 - p = 0.4127 - # add inflow for t>0 at x=-0.5 - # domain size is [-0.5,+0.5]^2 - if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) - rho = 5 - v1 = 800 # about Mach number Ma = 2000 + @unpack gamma = equations + rho = 0.5 + v1 = 0 v2 = 0 p = 0.4127 - end - return prim2cons(SVector(rho, v1, v2, p), equations) + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_astro_jet -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), - x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_astro_jet), + x_pos = BoundaryConditionDirichlet(initial_condition_astro_jet), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.3, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.3, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 6, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -72,43 +71,43 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) - -amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=2, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =8, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) - -amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +amr_indicator = IndicatorHennemannGassner(semi, + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) + +amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, + base_level = 2, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 8, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, amr_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 1e-7 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 5b95fef374..3bf4f230d4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) # Initial condition adopted from @@ -13,54 +13,53 @@ equations = CompressibleEulerEquations2D(gamma) # https://tinyurl.com/c76fjtx4 # Mach = 2000 jet function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) - @unpack gamma = equations - rho = 0.5 - v1 = 0 - v2 = 0 - p = 0.4127 - # add inflow for t>0 at x=-0.5 - # domain size is [-0.5,+0.5]^2 - if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) - rho = 5 - v1 = 800 # about Mach number Ma = 2000 + @unpack gamma = equations + rho = 0.5 + v1 = 0 v2 = 0 p = 0.4127 - end - return prim2cons(SVector(rho, v1, v2, p), equations) + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_astro_jet -boundary_conditions = ( - x_neg=BoundaryConditionCharacteristic(initial_condition_astro_jet), - x_pos=BoundaryConditionCharacteristic(initial_condition_astro_jet), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) +boundary_conditions = (x_neg = BoundaryConditionCharacteristic(initial_condition_astro_jet), + x_pos = BoundaryConditionCharacteristic(initial_condition_astro_jet), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_chandrashekar # works with Ranocha flux as well +volume_flux = flux_chandrashekar # works with Ranocha flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - bar_states=true, - max_iterations_newton=25) + local_minmax_variables_cons = [1], + spec_entropy = true, + bar_states = true, + max_iterations_newton = 25) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=8, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 8, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -71,16 +70,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,9 +88,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - maxiters=1e6, dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + maxiters = 1e6, dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl index 0da18b7120..ccd7b54086 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl @@ -16,48 +16,46 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,27 +65,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) 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); +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_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 0e5a85e00a..3e90ef7da2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -16,54 +16,52 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=true, - SequentialLimiter=false, - ConservativeLimiter=true, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, - PressurePositivityLimiterKuzminExact=false, - SemiDiscEntropyLimiter=true, - smoothness_indicator=true, - Plotting=false) + DensityLimiter = true, + DensityAlphaForAll = true, + SequentialLimiter = false, + ConservativeLimiter = true, + DensityPositivityLimiter = true, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = false, + SemiDiscEntropyLimiter = true, + smoothness_indicator = true, + Plotting = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -73,29 +71,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_blast_wave_amr.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl index 6ce9268486..d32c2e51b0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl @@ -16,48 +16,46 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,40 +65,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_euler_blast_wave_neuralnetwork_cnn.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl index 659788f2f5..79d7474dc6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelcnn-0.964-0.001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelcnn-0.964-0.001.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelcnn-0.964-0.001.bson", + network) model2dcnn = load(network, @__MODULE__)[:model2dcnn] using OrdinaryDiffEq @@ -28,52 +29,50 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkCNN(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2dcnn) + indicator_type = NeuralNetworkCNN(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = false, + variable = density_pressure, + network = model2dcnn) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -83,27 +82,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) 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); +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_euler_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl index 3f4862674d..27398593ef 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", + network) model2d = load(network, @__MODULE__)[:model2d] using OrdinaryDiffEq @@ -28,52 +29,50 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = false, + variable = density_pressure, + network = model2d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -83,27 +82,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) 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); +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_euler_blast_wave_neuralnetwork_rayhesthaven.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl index db2fffacb3..6c67f94863 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl @@ -3,7 +3,8 @@ using Flux using Random using BSON: load network = joinpath(@__DIR__, "modelnnrhs-0.973-0.001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrhs-0.973-0.001.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrhs-0.973-0.001.bson", + network) model2d = load(network, @__MODULE__)[:model2d] using OrdinaryDiffEq @@ -29,54 +30,52 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkRayHesthaven(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkRayHesthaven(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = false, + variable = density_pressure, + network = model2d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) refinement_patches = () # To allow for specifying them via `trixi_include` mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - refinement_patches=refinement_patches, - n_cells_max=10_000) - + initial_refinement_level = 6, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,27 +85,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) 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); +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_euler_blast_wave_pure_fv.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl index a0fc934969..a2392d05e5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl @@ -16,40 +16,38 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave -surface_flux = flux_hllc +surface_flux = flux_hllc basis = LobattoLegendreBasis(3) volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -59,27 +57,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) 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); +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_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 0e44f62c7b..fab3a86e53 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -16,48 +16,46 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - math_entropy=true, - bar_states=false, - smoothness_indicator=true) + local_minmax_variables_cons = [1], + math_entropy = true, + bar_states = false, + smoothness_indicator = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,29 +65,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_blob_amr.jl b/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl index f404073266..2b3659017a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) """ @@ -16,67 +16,67 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^2, 256^2 - # domain size is [-20.0,20.0]^2 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - dens0 = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh/1.6 # crushing time - # determine background velocity - velx0 = 2*R*sqrt(Chi)/tau_cr - vely0 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = velx0/Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p0 = c*c*dens0/equations.gamma - # initial center of the blob - inicenter = [-15,0] - x_rel = x-inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - # velocity blob is zero - velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - return prim2cons(SVector(dens, velx, vely0, p0), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^2, 256^2 + # domain size is [-20.0,20.0]^2 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + dens0 = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + velx0 = 2 * R * sqrt(Chi) / tau_cr + vely0 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = velx0 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p0 = c * c * dens0 / equations.gamma + # initial center of the blob + inicenter = [-15, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + dens = dens0 + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + velx = velx0 - velx0 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(dens, velx, vely0, p0), equations) end initial_condition = initial_condition_blob surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.4, - alpha_min=0.0001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.4, + alpha_min = 0.0001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-20.0, -20.0) -coordinates_max = ( 20.0, 20.0) +coordinates_max = (20.0, 20.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000,) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,42 +86,41 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=4, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =7, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) + base_level = 4, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 7, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.25) +stepsize_callback = StepsizeCallback(cfl = 0.25) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_euler_blob_mortar.jl b/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl index 5b7365f860..8bd5db00c9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) """ @@ -16,71 +16,71 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^2, 256^2 - # domain size is [-20.0,20.0]^2 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - dens0 = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh/1.6 # crushing time - # determine background velocity - velx0 = 2*R*sqrt(Chi)/tau_cr - vely0 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = velx0/Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p0 = c*c*dens0/equations.gamma - # initial center of the blob - inicenter = [-15,0] - x_rel = x-inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - # velocity blob is zero - velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - return prim2cons(SVector(dens, velx, vely0, p0), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^2, 256^2 + # domain size is [-20.0,20.0]^2 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + dens0 = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + velx0 = 2 * R * sqrt(Chi) / tau_cr + vely0 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = velx0 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p0 = c * c * dens0 / equations.gamma + # initial center of the blob + inicenter = [-15, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + dens = dens0 + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + velx = velx0 - velx0 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(dens, velx, vely0, p0), equations) end initial_condition = initial_condition_blob surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.05, - alpha_min=0.0001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.05, + alpha_min = 0.0001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-32.0, -32.0) -coordinates_max = ( 32.0, 32.0) -refinement_patches = ( - (type="box", coordinates_min=(-40.0, -5.0), coordinates_max=(40.0, 5.0)), - (type="box", coordinates_min=(-40.0, -5.0), coordinates_max=(40.0, 5.0)), -) +coordinates_max = (32.0, 32.0) +refinement_patches = ((type = "box", coordinates_min = (-40.0, -5.0), + coordinates_max = (40.0, 5.0)), + (type = "box", coordinates_min = (-40.0, -5.0), + coordinates_max = (40.0, 5.0))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=100_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -90,27 +90,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +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); +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_euler_colliding_flow.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl index cb2a5b1681..984ac3ff1f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl @@ -10,71 +10,71 @@ equations = CompressibleEulerEquations2D(gamma) # This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both # sides, with relative low temperature, such that pressure keeps relatively small # Computed with gamma close to 1, to simulate isothermal gas -function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) - # domain size is [-64,+64]^2 - @unpack gamma = equations - # the quantities are chosen such, that they are as close as possible to the astro examples - # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) - rho = 0.0247 - c = 0.2 - p = c^2 / gamma * rho - vel = 13.907432274789372 - slope = 1.0 - v1 = -vel*tanh(slope * x[1]) - # add small initial disturbance to the field, but only close to the interface - if abs(x[1]) < 10 - v1 = v1 * (1 + 0.01 * sin(pi * x[2])) - end - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_colliding_flow_astro(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) + # domain size is [-64,+64]^2 + @unpack gamma = equations + # the quantities are chosen such, that they are as close as possible to the astro examples + # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) + rho = 0.0247 + c = 0.2 + p = c^2 / gamma * rho + vel = 13.907432274789372 + slope = 1.0 + v1 = -vel * tanh(slope * x[1]) + # add small initial disturbance to the field, but only close to the interface + if abs(x[1]) < 10 + v1 = v1 * (1 + 0.01 * sin(pi * x[2])) + end + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_colliding_flow_astro - -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) - - +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + x_pos = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example, however alpha_max = 0.5 is fine indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-64.0, -64.0) -coordinates_max = ( 64.0, 64.0) +coordinates_max = (64.0, 64.0) # only refinement in a patch. Needs x=-17/+17 to trigger refinement due to coarse base mesh -refinement_patches = ( - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores -) +refinement_patches = ((type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)) + #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores + ) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - refinement_patches=refinement_patches, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 3, + refinement_patches = refinement_patches, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -85,26 +85,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 5e-3 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl index 21de07147c..a9eb671929 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl @@ -10,62 +10,59 @@ equations = CompressibleEulerEquations2D(gamma) # This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both # sides, with relative low temperature, such that pressure keeps relatively small # Computed with gamma close to 1, to simulate isothermal gas -function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) - # domain size is [-64,+64]^2 - @unpack gamma = equations - # the quantities are chosen such, that they are as close as possible to the astro examples - # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) - rho = 0.0247 - c = 0.2 - p = c^2 / gamma * rho - vel = 13.907432274789372 - slope = 1.0 - v1 = -vel*tanh(slope * x[1]) - # add small initial disturbance to the field, but only close to the interface - if abs(x[1]) < 10 - v1 = v1 * (1 + 0.01 * sin(pi*x[2])) - end - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_colliding_flow_astro(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) + # domain size is [-64,+64]^2 + @unpack gamma = equations + # the quantities are chosen such, that they are as close as possible to the astro examples + # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) + rho = 0.0247 + c = 0.2 + p = c^2 / gamma * rho + vel = 13.907432274789372 + slope = 1.0 + v1 = -vel * tanh(slope * x[1]) + # add small initial disturbance to the field, but only close to the interface + if abs(x[1]) < 10 + v1 = v1 * (1 + 0.01 * sin(pi * x[2])) + end + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_colliding_flow_astro - -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) - - +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + x_pos = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example, however alpha_max = 0.5 is fine indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-64.0, -64.0) -coordinates_max = ( 64.0, 64.0) +coordinates_max = (64.0, 64.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 4, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -76,44 +73,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # Simulation also feasible without AMR: AMR reduces CPU time by a factor of about 2 amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=2, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =8, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) + base_level = 2, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 8, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, amr_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 5e-3 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index bf6064dc21..eccf13c6d2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -14,29 +14,28 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - positivity_correction_factor=0.1, - spec_entropy=false, - max_iterations_newton=10, - newton_tolerances=(1.0e-12, 1.0e-14), - bar_states=true, - smoothness_indicator=false) + positivity_variables_cons = [1], + positivity_variables_nonlinear = (pressure,), + positivity_correction_factor = 0.1, + spec_entropy = false, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + bar_states = true, + smoothness_indicator = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) 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) + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -46,16 +45,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -64,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index d7e4250bb6..d82aed8ba3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -14,28 +14,28 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - DensityPositivityLimiter=true, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - Plotting=true) + DensityLimiter = false, + DensityAlphaForAll = false, + SequentialLimiter = false, + ConservativeLimiter = false, + DensityPositivityLimiter = true, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = true, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 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) + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -45,16 +45,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -63,9 +63,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_convergence_pure_fv.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl index 89d7422cfe..96184b5ba4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -18,13 +18,11 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -35,16 +33,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -54,7 +52,7 @@ callbacks = CallbackSet(summary_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); +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_euler_density_wave.jl b/examples/tree_2d_dgsem/elixir_euler_density_wave.jl index a5e9d30e38..0f9e232fa1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_density_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_density_wave.jl @@ -9,18 +9,16 @@ equations = CompressibleEulerEquations2D(gamma) initial_condition = initial_condition_density_wave -solver = DGSEM(polydeg=5, surface_flux=flux_central) +solver = DGSEM(polydeg = 5, surface_flux = flux_central) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,27 +28,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) 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); +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_euler_ec.jl b/examples/tree_2d_dgsem/elixir_euler_ec.jl index 88f65c3d68..e634a383cd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec.jl @@ -9,20 +9,18 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 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, - periodicity=true) - + initial_refinement_level = 5, + n_cells_max = 10_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_periodic) - + boundary_conditions = boundary_condition_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +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); +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_euler_kelvin_helmholtz_instability.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl index 4fdedf516e..5e6b1e0cc0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl @@ -16,40 +16,41 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.002, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### @@ -61,27 +62,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=20, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 20, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) 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); +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_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 3be50d0199..548485a1ab 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -16,45 +16,47 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=false, - DensityAlphaForAll=false, - SequentialLimiter=false, - ConservativeLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - DensityPositivityLimiter=true, - SemiDiscEntropyLimiter=false, - Plotting=true) + DensityLimiter = false, + DensityAlphaForAll = false, + SequentialLimiter = false, + ConservativeLimiter = false, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = true, + DensityPositivityLimiter = true, + SemiDiscEntropyLimiter = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### @@ -66,32 +68,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=50000, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 50000, + save_final_restart = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_restart, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +stage_callbacks = (BoundsCheckCallback(save_errors = false),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - maxiters=1e7, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + maxiters = 1e7, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl index b8927c3fd6..5c237835cc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl @@ -16,45 +16,44 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.002, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) - + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -64,41 +63,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level=0, med_threshold=0.0003, # med_level = current level - max_level=6, max_threshold=0.003) + base_level = 4, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 6, max_threshold = 0.003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl index 952fa37269..d2cab04223 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", + network) model2d = load(network, @__MODULE__)[:model2d] using Random: seed! @@ -28,55 +29,59 @@ equations = CompressibleEulerEquations2D(gamma) A version of the classical Kelvin-Helmholtz instability based on https://rsaa.anu.edu.au/research/established-projects/fyris/2-d-kelvin-helmholtz-test. """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-0.5,0.5]^2 - dens0 = 1.0 # outside density - dens1 = 2.0 # inside density - velx0 = -0.5 # outside velocity - velx1 = 0.5 # inside velocity - slope = 50 # used for tanh instead of discontinuous initial condition - # pressure equilibrium - p = 2.5 - # y velocity v2 is only white noise - v2 = 0.01*(rand(Float64,1)[1]-0.5) - # density - rho = dens0 + (dens1-dens0) * 0.5*(1+(tanh(slope*(x[2]+0.25)) - (tanh(slope*(x[2]-0.25)) + 1))) - # x velocity is also augmented with noise - v1 = velx0 + (velx1-velx0) * 0.5*(1+(tanh(slope*(x[2]+0.25)) - (tanh(slope*(x[2]-0.25)) + 1)))+0.01*(rand(Float64,1)[1]-0.5) - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-0.5,0.5]^2 + dens0 = 1.0 # outside density + dens1 = 2.0 # inside density + velx0 = -0.5 # outside velocity + velx1 = 0.5 # inside velocity + slope = 50 # used for tanh instead of discontinuous initial condition + # pressure equilibrium + p = 2.5 + # y velocity v2 is only white noise + v2 = 0.01 * (rand(Float64, 1)[1] - 0.5) + # density + rho = dens0 + + (dens1 - dens0) * 0.5 * + (1 + (tanh(slope * (x[2] + 0.25)) - (tanh(slope * (x[2] - 0.25)) + 1))) + # x velocity is also augmented with noise + v1 = velx0 + + (velx1 - velx0) * 0.5 * + (1 + (tanh(slope * (x[2] + 0.25)) - (tanh(slope * (x[2] - 0.25)) + 1))) + + 0.01 * (rand(Float64, 1)[1] - 0.5) + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 0.002, + alpha_min = 0.0001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = false, + variable = density_pressure, + network = model2d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) - + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,45 +91,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorNeuralNetwork(semi, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - alpha_continuous=true, - alpha_amr=true, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + alpha_continuous = true, + alpha_amr = true, + variable = density_pressure, + network = model2d) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level=6, med_threshold=0.3, # med_level = current level - max_level=7, max_threshold=0.5) + base_level = 4, + med_level = 6, med_threshold = 0.3, # med_level = current level + max_level = 7, max_threshold = 0.5) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_euler_kelvin_helmholtz_instability_fjordholm_etal.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl index 8e7484a96d..5b2b80d84f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 1.4 @@ -16,83 +15,86 @@ A version of the classical Kelvin-Helmholtz instability based on solutions for hyperbolic systems of conservation laws [arXiv: 1402.0909](https://arxiv.org/abs/1402.0909) """ -function initial_condition_kelvin_helmholtz_instability_fjordholm_etal(x, t, equations::CompressibleEulerEquations2D) - # typical resolution 128^2, 256^2 - # domain size is [0,+1]^2 - # interface is sharp, but randomly perturbed - # The random numbers used in the initial conditions have been generated as follows: - # - # using StableRNGs - # - # rng = StableRNG(100) - # - # a1 = rand(rng, m) - # a2 = rand(rng, m) - # a1 .= a1 / sum(a1) - # a2 .= a2 / sum(a2) - # b1 = (rand(rng, m) .- 0.5) .* pi - # b2 = (rand(rng, m) .- 0.5) .* pi - - m = 10 - a1 = [0.04457096674422902, 0.03891512410182607, 0.0030191053979293433, 0.0993913172320319, +function initial_condition_kelvin_helmholtz_instability_fjordholm_etal(x, t, + equations::CompressibleEulerEquations2D) + # typical resolution 128^2, 256^2 + # domain size is [0,+1]^2 + # interface is sharp, but randomly perturbed + # The random numbers used in the initial conditions have been generated as follows: + # + # using StableRNGs + # + # rng = StableRNG(100) + # + # a1 = rand(rng, m) + # a2 = rand(rng, m) + # a1 .= a1 / sum(a1) + # a2 .= a2 / sum(a2) + # b1 = (rand(rng, m) .- 0.5) .* pi + # b2 = (rand(rng, m) .- 0.5) .* pi + + m = 10 + a1 = [0.04457096674422902, 0.03891512410182607, 0.0030191053979293433, + 0.0993913172320319, 0.1622302137588842, 0.1831383653456182, 0.11758003014101702, 0.07964318348142958, 0.0863245324711805, 0.18518716132585408] - a2 = [0.061688440856337096, 0.23000237877135882, 0.04453793881833177, 0.19251530387370916, + a2 = [0.061688440856337096, 0.23000237877135882, 0.04453793881833177, + 0.19251530387370916, 0.11107917357941084, 0.05898041974649702, 0.09949312336096268, 0.07022276346006465, 0.10670366489014596, 0.02477679264318211] - b1 = [0.06582340543754152, 0.9857886297001535, 0.8450452205037154, -1.279648120993805, + b1 = [0.06582340543754152, 0.9857886297001535, 0.8450452205037154, -1.279648120993805, 0.45454198915209526, -0.13359370986823993, 0.07062615913363897, -1.0097986278512623, 1.0810669017430343, -0.14207309803877177] - b2 = [-1.1376882185131414, -1.4798197129947765, 0.6139290513283818, -0.3319087388365522, + b2 = [-1.1376882185131414, -1.4798197129947765, 0.6139290513283818, -0.3319087388365522, 0.14633328999192285, -0.06373231463100072, -0.6270101051216724, 0.13941252226261905, -1.0337526453303645, 1.0441408867083155] - Y1 = 0.0 - Y2 = 0.0 - for n = 1:m - Y1 += a1[n] * cos(b1[n] + 2 * n * pi * x[1]) - Y2 += a2[n] * cos(b2[n] + 2 * n * pi * x[1]) - end - - J1 = 0.25 - J2 = 0.75 - epsilon = 0.01 - I1 = J1 + epsilon * Y1 - I2 = J2 + epsilon * Y2 - - if (x[2] > I1) && (x[2] < I2) - rho = 2 - v1 = -0.5 - else - rho = 1 - v1 = 0.5 - end - v2 = 0 - p = 2.5 - - return prim2cons(SVector(rho, v1, v2, p), equations) + Y1 = 0.0 + Y2 = 0.0 + for n in 1:m + Y1 += a1[n] * cos(b1[n] + 2 * n * pi * x[1]) + Y2 += a2[n] * cos(b2[n] + 2 * n * pi * x[1]) + end + + J1 = 0.25 + J2 = 0.75 + epsilon = 0.01 + I1 = J1 + epsilon * Y1 + I2 = J2 + epsilon * Y2 + + if (x[2] > I1) && (x[2] < I2) + rho = 2 + v1 = -0.5 + else + rho = 1 + v1 = 0.5 + end + v2 = 0 + p = 2.5 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability_fjordholm_etal surface_flux = flux_hllc -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.001, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.001, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -105,14 +107,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 400 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=400, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 400, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -121,5 +123,5 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation sol = solve(ode, SSPRK43(); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl index e31a0476a4..dc54bb1fb3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_restart.jl @@ -11,15 +11,15 @@ new_path = path tspan = (load_time(restart_filename), 6.7) ode = semidiscretize(semi, tspan, restart_filename); -save_solution = SaveSolutionCallback(output_directory=path, - interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(output_directory = path, + interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(output_directory=path, - interval=50000, - save_final_restart=true) +save_restart = SaveRestartCallback(output_directory = path, + interval = 50000, + save_final_restart = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -27,6 +27,6 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution) sol = Trixi.solve(ode, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 42b529cb63..8f07b7ca92 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -16,41 +16,42 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - spec_entropy=false, - bar_states=true) + positivity_variables_cons = [1], + positivity_variables_nonlinear = (pressure,), + spec_entropy = false, + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### @@ -62,32 +63,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=50000, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 50000, + save_final_restart = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, save_restart, save_solution) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity.jl b/examples/tree_2d_dgsem/elixir_euler_positivity.jl index 4c7dd7eb6c..6fec4c1bf9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity.jl @@ -14,53 +14,51 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -70,42 +68,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 4, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=2, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 2, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) - +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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_euler_sedov_blast_wave.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl index 512e582237..5b8959b97d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -14,53 +14,51 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -70,29 +68,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -101,7 +99,7 @@ callbacks = CallbackSet(summary_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); +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_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index af239b7c1a..a5e7532854 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -14,57 +14,57 @@ The Sedov blast wave setup based on Flash - http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter=true, - DensityAlphaForAll=false, - SequentialLimiter=true, - ConservativeLimiter=false, - DensityPositivityLimiter=false, - PressurePositivityLimiterKuzmin=true, PressurePositivityLimiterKuzminExact=true, - SemiDiscEntropyLimiter=true, - smoothness_indicator=false, - Plotting=true) + DensityLimiter = true, + DensityAlphaForAll = false, + SequentialLimiter = true, + ConservativeLimiter = false, + DensityPositivityLimiter = false, + PressurePositivityLimiterKuzmin = true, + PressurePositivityLimiterKuzminExact = true, + SemiDiscEntropyLimiter = true, + smoothness_indicator = false, + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -74,18 +74,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) -limiting_analysis_callback = LimitingAnalysisCallback(output_directory="out", interval=1) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -94,9 +95,11 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors=false),) +output_directory = "out" +stage_callbacks = (BoundsCheckCallback(save_errors = true, interval = 100, + output_directory = output_directory),) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl index 5fd32da2e5..39ea947f87 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl @@ -2,7 +2,8 @@ using Downloads: download using Flux using BSON: load network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) +download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", + network) model2d = load(network, @__MODULE__)[:model2d] using OrdinaryDiffEq @@ -26,57 +27,55 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = false, + variable = density_pressure, + network = model2d) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,33 +85,33 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorNeuralNetwork(semi, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=true, - variable=density_pressure, - network=model2d) + indicator_type = NeuralNetworkPerssonPeraire(), + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + alpha_continuous = true, + alpha_amr = true, + variable = density_pressure, + network = model2d) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.22) + base_level = 4, + max_level = 6, max_threshold = 0.22) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -121,7 +120,7 @@ callbacks = CallbackSet(summary_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); +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_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 9886106441..b460b7a507 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -14,53 +14,51 @@ The Sedov blast wave setup based on Flash - http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on http://flash.uchicago.edu/site/flashcode/user_support/flash_ug_devel/node184.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - spec_entropy=true, - smoothness_indicator=false, - bar_states=true) + local_minmax_variables_cons = [1], + spec_entropy = true, + smoothness_indicator = false, + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -70,18 +68,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) -limiting_analysis_callback = LimitingAnalysisCallback(output_directory="out", interval=1) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -91,9 +90,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl index f0a7ed0b95..40f19cbd4e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl @@ -10,28 +10,26 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_shima_etal +volume_flux = flux_shima_etal basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,26 +39,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_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); +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_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 810c37ff5b..4e64cb3a91 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -16,46 +16,45 @@ A medium blast wave (modified to lower density and higher pressure) taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - 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) - - # Calculate primitive variables "normal" medium blast wave - rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + # Calculate primitive variables "normal" medium blast wave + rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_correction_factor=0.5, - bar_states=false) + positivity_variables_cons = [1], + positivity_correction_factor = 0.5, + bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + 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) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -65,29 +64,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_source_terms.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms.jl index 36d9314728..ec23014553 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms.jl @@ -8,18 +8,16 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -30,16 +28,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -49,7 +47,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_amr_refine_coarsen.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl index 231486b11c..28ab4cec1d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl @@ -10,60 +10,57 @@ module TrixiExtensionEulerAMR using Trixi -struct IndicatorRefineCoarsen{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorRefineCoarsen{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorRefineCoarsen(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorRefineCoarsen{typeof(cache)}(cache) + return IndicatorRefineCoarsen{typeof(cache)}(cache) end -function (indicator::IndicatorRefineCoarsen)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorRefineCoarsen)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - if t >= 0.7 && t < 1.0 - # Refine to max level - alpha .= 1.0 - elseif t >= 1.0 - # Coarsen to base level - alpha .= -1.0 - else - alpha .= 0.0 - end - - return alpha + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + if t >= 0.7 && t < 1.0 + # Refine to max level + alpha .= 1.0 + elseif t >= 1.0 + # Coarsen to base level + alpha .= -1.0 + else + alpha .= 0.0 + end + + return alpha end end # module TrixiExtensionEulerAMR import .TrixiExtensionEulerAMR - ############################################################################### # semidiscretization of the compressible Euler equations equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -74,25 +71,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionEulerAMR.IndicatorRefineCoarsen(semi), - base_level=3, max_level=6, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionEulerAMR.IndicatorRefineCoarsen(semi), + base_level = 3, max_level = 6, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -102,7 +100,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 9826a53d3d..05ed7ba78c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -12,26 +12,23 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition,) - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -42,19 +39,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -63,7 +60,7 @@ callbacks = CallbackSet(summary_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); +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_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 5c92414e66..6d5281fcbc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -14,25 +14,24 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[1], - positivity_variables_cons=[1], - positivity_variables_nonlinear=(pressure,), - bar_states=true, - smoothness_indicator=true) + local_minmax_variables_cons = [1], + positivity_variables_cons = [1], + positivity_variables_nonlinear = (pressure,), + bar_states = true, + smoothness_indicator = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,16 +42,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -61,9 +60,9 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_vortex.jl b/examples/tree_2d_dgsem/elixir_euler_vortex.jl index 14e46ce754..c87d6f49ba 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex.jl @@ -17,46 +17,45 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -69,30 +68,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) 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); +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_euler_vortex_amr.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl index 6f6eb25efa..e9831c9552 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl @@ -7,55 +7,54 @@ module TrixiExtension using Trixi -struct IndicatorVortex{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorVortex{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorVortex(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - A = Array{real(basis), 2} - indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) - for _ in 1:Threads.nthreads()] - cache = (; semi.mesh, alpha, indicator_threaded) - - return IndicatorVortex{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + A = Array{real(basis), 2} + indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) + for _ in 1:Threads.nthreads()] + cache = (; semi.mesh, alpha, indicator_threaded) + + return IndicatorVortex{typeof(cache)}(cache) end -function (indicator_vortex::IndicatorVortex)(u::AbstractArray{<:Any,4}, +function (indicator_vortex::IndicatorVortex)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - mesh = indicator_vortex.cache.mesh - alpha = indicator_vortex.cache.alpha - indicator_threaded = indicator_vortex.cache.indicator_threaded - resize!(alpha, nelements(dg, cache)) - - - # get analytical vortex center (based on assumption that center=[0.0,0.0] - # at t=0.0 and that we stop after one period) - domain_length = mesh.tree.length_level_0 - if t < 0.5 * domain_length - center = (t, t) - else - center = (t-domain_length, t-domain_length) - end - - Threads.@threads for element in eachelement(dg, cache) - cell_id = cache.elements.cell_ids[element] - coordinates = (mesh.tree.coordinates[1, cell_id], mesh.tree.coordinates[2, cell_id]) - # use the negative radius as indicator since the AMR controller increases - # the level with increasing value of the indicator and we want to use - # high levels near the vortex center - alpha[element] = -periodic_distance_2d(coordinates, center, domain_length) - end - - return alpha + mesh = indicator_vortex.cache.mesh + alpha = indicator_vortex.cache.alpha + indicator_threaded = indicator_vortex.cache.indicator_threaded + resize!(alpha, nelements(dg, cache)) + + # get analytical vortex center (based on assumption that center=[0.0,0.0] + # at t=0.0 and that we stop after one period) + domain_length = mesh.tree.length_level_0 + if t < 0.5 * domain_length + center = (t, t) + else + center = (t - domain_length, t - domain_length) + end + + Threads.@threads for element in eachelement(dg, cache) + cell_id = cache.elements.cell_ids[element] + coordinates = (mesh.tree.coordinates[1, cell_id], mesh.tree.coordinates[2, cell_id]) + # use the negative radius as indicator since the AMR controller increases + # the level with increasing value of the indicator and we want to use + # high levels near the vortex center + alpha[element] = -periodic_distance_2d(coordinates, center, domain_length) + end + + return alpha end function periodic_distance_2d(coordinates, center, domain_length) - dx = @. abs(coordinates - center) - dx_periodic = @. min(dx, domain_length - dx) - return sqrt(sum(abs2, dx_periodic)) + dx = @. abs(coordinates - center) + dx_periodic = @. min(dx, domain_length - dx) + return sqrt(sum(abs2, dx_periodic)) end end # module TrixiExtension @@ -77,48 +76,47 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - - cent = x - cent # distance to center point - - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + + cent = x - cent # distance to center point + + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -132,39 +130,40 @@ summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=50, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorVortex(semi), - base_level=3, - med_level=4, med_threshold=-3.0, - max_level=5, max_threshold=-2.0) + base_level = 3, + med_level = 4, med_threshold = -3.0, + max_level = 5, max_threshold = -2.0) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_euler_vortex_mortar.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl index 637133b9b2..858799d2d3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl @@ -17,49 +17,48 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -72,30 +71,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) 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); +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_euler_vortex_mortar_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl index dc6a326c5d..026f6d1462 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl @@ -17,36 +17,36 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex @@ -56,24 +56,23 @@ volume_flux = flux_shima_etal polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -86,30 +85,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +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); +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_euler_vortex_mortar_split.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl index 99036c3645..d719e01fd7 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl @@ -17,52 +17,51 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex volume_flux = flux_shima_etal -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -75,30 +74,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) 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); +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_euler_vortex_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl index 65a497374e..99e4b09063 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl @@ -17,36 +17,36 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex @@ -56,20 +56,20 @@ volume_flux = flux_shima_etal polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000,) + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -82,22 +82,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -107,7 +109,7 @@ callbacks = CallbackSet(summary_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); +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_euleracoustics_co-rotating_vortex_pair.jl b/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl index 38b48b5d53..ea81bd049e 100644 --- a/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl +++ b/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl @@ -19,203 +19,199 @@ module VortexPairSetup using LinearAlgebra: norm using Trixi - # Parameters that describe the co-rotating vortex pair -struct VortexPair{RealT<:Real} - r0::RealT # Distance between origin and each vortex center - rc::RealT # Vortex core radius - c0::RealT # Speed of sound - circulation::RealT # Circulation of the vortices - rho0::RealT # Density +struct VortexPair{RealT <: Real} + r0::RealT # Distance between origin and each vortex center + rc::RealT # Vortex core radius + c0::RealT # Speed of sound + circulation::RealT # Circulation of the vortices + rho0::RealT # Density end - # Analytical flow solution, used for the initial condition of the flow simulation function velocity(x, t, vortex_pair::VortexPair) - @unpack r0, rc, circulation = vortex_pair + @unpack r0, rc, circulation = vortex_pair - omega = circulation / (4 * pi * r0^2) - si, co = sincos(omega * t) - b = SVector(r0 * co, r0 * si) # vortex centers are b and -b - z_plus = x - b - z_minus = x + b + omega = circulation / (4 * pi * r0^2) + si, co = sincos(omega * t) + b = SVector(r0 * co, r0 * si) # vortex centers are b and -b + z_plus = x - b + z_minus = x + b - # Transform to polar coordinates - r_plus = norm(z_plus) - r_minus = norm(z_minus) - theta_plus = atan(z_plus[2], z_plus[1]) - theta_minus = atan(z_minus[2], z_minus[1]) + # Transform to polar coordinates + r_plus = norm(z_plus) + r_minus = norm(z_minus) + theta_plus = atan(z_plus[2], z_plus[1]) + theta_minus = atan(z_minus[2], z_minus[1]) - si_plus, co_plus = sincos(theta_plus) - si_minus, co_minus = sincos(theta_minus) + si_plus, co_plus = sincos(theta_plus) + si_minus, co_minus = sincos(theta_minus) - v1 = -circulation/(2 * pi) * ( r_plus /(rc^2 + r_plus^2) * si_plus + - r_minus/(rc^2 + r_minus^2) * si_minus) - v2 = circulation/(2 * pi) * ( r_plus /(rc^2 + r_plus^2) * co_plus + - r_minus/(rc^2 + r_minus^2) * co_minus ) + v1 = -circulation / (2 * pi) * (r_plus / (rc^2 + r_plus^2) * si_plus + + r_minus / (rc^2 + r_minus^2) * si_minus) + v2 = circulation / (2 * pi) * (r_plus / (rc^2 + r_plus^2) * co_plus + + r_minus / (rc^2 + r_minus^2) * co_minus) - return SVector(v1, v2) + return SVector(v1, v2) end - # Initial condition of the flow simulation. Uses constant density rho0 and analytical velocities. # The pressure is calculated using the given speed of sound c0 and Bernoulli's principle -struct InitialCondition{RealT<:Real} - vortex_pair::VortexPair{RealT} +struct InitialCondition{RealT <: Real} + vortex_pair::VortexPair{RealT} end -function (initial_condition::InitialCondition)(x, t, equations::CompressibleEulerEquations2D) - @unpack vortex_pair = initial_condition - @unpack rho0, c0 = vortex_pair - gamma = equations.gamma +function (initial_condition::InitialCondition)(x, t, + equations::CompressibleEulerEquations2D) + @unpack vortex_pair = initial_condition + @unpack rho0, c0 = vortex_pair + gamma = equations.gamma - v = velocity(x, t, vortex_pair) - p0 = rho0 * c0^2 / gamma - p = p0 - 0.5 * (gamma-1)/gamma * sum(v.^2) # Bernoulli's principle + v = velocity(x, t, vortex_pair) + p0 = rho0 * c0^2 / gamma + p = p0 - 0.5 * (gamma - 1) / gamma * sum(v .^ 2) # Bernoulli's principle - prim = SVector(rho0, v[1], v[2], p) - return prim2cons(prim, equations) + prim = SVector(rho0, v[1], v[2], p) + return prim2cons(prim, equations) end - # For both the flow and acoustics solvers, a sponge layer is used to dampen the density # and pressure towards the freestream values (for the flow solver) and the perturbed pressure # to zero (for the acoustics solver). -struct SpongeLayer{RealT<:Real, uEltype<:Real, N, SourceTerms} - sponge_layer_min::NTuple{4, RealT} # (-x,+x,-y,+y) min coordinates of sponge layer per direction - sponge_layer_max::NTuple{4, RealT} # (-x,+x,-y,+y) max coordinates of sponge layer per direction - reference_values::NTuple{N, uEltype} # reference values for variables affected by sponge layer - source_terms::SourceTerms # source terms to be used outside the sponge zone +struct SpongeLayer{RealT <: Real, uEltype <: Real, N, SourceTerms} + sponge_layer_min::NTuple{4, RealT} # (-x,+x,-y,+y) min coordinates of sponge layer per direction + sponge_layer_max::NTuple{4, RealT} # (-x,+x,-y,+y) max coordinates of sponge layer per direction + reference_values::NTuple{N, uEltype} # reference values for variables affected by sponge layer + source_terms::SourceTerms # source terms to be used outside the sponge zone end -function SpongeLayer(; sponge_layer_min, sponge_layer_max, reference_values, source_terms=nothing) - return SpongeLayer(sponge_layer_min, sponge_layer_max, reference_values, source_terms) +function SpongeLayer(; sponge_layer_min, sponge_layer_max, reference_values, + source_terms = nothing) + return SpongeLayer(sponge_layer_min, sponge_layer_max, reference_values, source_terms) end function (sponge_layer::SpongeLayer)(u, x, t, equations) - @unpack sponge_layer_min, sponge_layer_max, reference_values, source_terms = sponge_layer - - if lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) - return source_term_sponge_layer(u, x, t, equations, sponge_layer_min, sponge_layer_max, - reference_values) - elseif source_terms !== nothing - return source_terms(u, x, t, equations) - else - return SVector(ntuple(v -> zero(eltype(u)), Val(nvariables(equations)))) - end + @unpack sponge_layer_min, sponge_layer_max, reference_values, source_terms = sponge_layer + + if lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) + return source_term_sponge_layer(u, x, t, equations, sponge_layer_min, + sponge_layer_max, + reference_values) + elseif source_terms !== nothing + return source_terms(u, x, t, equations) + else + return SVector(ntuple(v -> zero(eltype(u)), Val(nvariables(equations)))) + end end function lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) - return (sponge_layer_min[1] <= x[1] <= sponge_layer_max[1]) || # -x direction - (sponge_layer_min[2] <= x[1] <= sponge_layer_max[2]) || # +x direction - (sponge_layer_min[3] <= x[2] <= sponge_layer_max[3]) || # -y direction - (sponge_layer_min[4] <= x[2] <= sponge_layer_max[4]) # +y direction + return (sponge_layer_min[1] <= x[1] <= sponge_layer_max[1]) || # -x direction + (sponge_layer_min[2] <= x[1] <= sponge_layer_max[2]) || # +x direction + (sponge_layer_min[3] <= x[2] <= sponge_layer_max[3]) || # -y direction + (sponge_layer_min[4] <= x[2] <= sponge_layer_max[4]) # +y direction end function source_term_sponge_layer(u, x, t, equations::AcousticPerturbationEquations2D, sponge_layer_min::NTuple{4}, sponge_layer_max::NTuple{4}, reference_values) - # Perturbed pressure source is -alpha^2 * (u - reference_value) where alpha in [0,1] is a damping - # factor depending on the position inside the sponge layer + # Perturbed pressure source is -alpha^2 * (u - reference_value) where alpha in [0,1] is a damping + # factor depending on the position inside the sponge layer - # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge - # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge - # zones for two directions overlap - alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), - Val(2*ndims(equations))) - alpha_square = maximum(alphas)^2 + # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge + # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge + # zones for two directions overlap + alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), + Val(2 * ndims(equations))) + alpha_square = maximum(alphas)^2 - return SVector(0, 0, -alpha_square*(u[3] - reference_values[1]/u[6]^2), 0, 0, 0, 0) + return SVector(0, 0, -alpha_square * (u[3] - reference_values[1] / u[6]^2), 0, 0, 0, 0) end function source_term_sponge_layer(u, x, t, equations::CompressibleEulerEquations2D, sponge_layer_min::NTuple{4}, sponge_layer_max::NTuple{4}, reference_values) - # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge - # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge - # zones for two directions overlap - alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), - Val(2*ndims(equations))) - alpha_square = maximum(alphas)^2 - - u_prim = cons2prim(u, equations) - s = SVector(-alpha_square*(u_prim[1] - reference_values[1]), 0, 0, - -alpha_square*(u_prim[4] - reference_values[2])) - - return prim2cons(s, equations) + # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge + # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge + # zones for two directions overlap + alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), + Val(2 * ndims(equations))) + alpha_square = maximum(alphas)^2 + + u_prim = cons2prim(u, equations) + s = SVector(-alpha_square * (u_prim[1] - reference_values[1]), 0, 0, + -alpha_square * (u_prim[4] - reference_values[2])) + + return prim2cons(s, equations) end function calc_damping_factor(x, direction, sponge_layer_min, sponge_layer_max) - # Damping factor alpha grows linearly from 0 to 1 depending on how deep x lies in the sponge layer - # If x does not lie in the sponge layer, this returns 0 - - # Get the coordinate that determines how deep we are in the sponge zone - if direction in (1, 2) - pos = x[1] - else - pos = x[2] - end - - # Determine where the sponge layer begins/ends to allow calculating the damping factor - if iseven(direction) - sponge_begin = sponge_layer_min[direction] - sponge_end = sponge_layer_max[direction] - else - sponge_begin = sponge_layer_max[direction] - sponge_end = sponge_layer_min[direction] - end - - alpha = (pos - sponge_begin) / (sponge_end - sponge_begin) - - # alpha lies in [0, 1] if and only if x lies in the sponge zone - if 0 <= alpha <= 1 - return alpha - else - return zero(alpha) - end + # Damping factor alpha grows linearly from 0 to 1 depending on how deep x lies in the sponge layer + # If x does not lie in the sponge layer, this returns 0 + + # Get the coordinate that determines how deep we are in the sponge zone + if direction in (1, 2) + pos = x[1] + else + pos = x[2] + end + + # Determine where the sponge layer begins/ends to allow calculating the damping factor + if iseven(direction) + sponge_begin = sponge_layer_min[direction] + sponge_end = sponge_layer_max[direction] + else + sponge_begin = sponge_layer_max[direction] + sponge_end = sponge_layer_min[direction] + end + + alpha = (pos - sponge_begin) / (sponge_end - sponge_begin) + + # alpha lies in [0, 1] if and only if x lies in the sponge zone + if 0 <= alpha <= 1 + return alpha + else + return zero(alpha) + end end - # Boundary condition for the flow problem: The sponge layer dampens density and pressure towards the # freestream values. The freestream values (converted into conservative variables) are therefore # used as a Dirichlet boundary struct BoundaryCondition{uEltype} - rho::uEltype - rho_e::uEltype + rho::uEltype + rho_e::uEltype end function (bc::BoundaryCondition)(u_inner, orientation, direction, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - u_boundary = SVector(bc.rho, zero(bc.rho), zero(bc.rho), bc.rho_e) + u_boundary = SVector(bc.rho, zero(bc.rho), zero(bc.rho), bc.rho_e) - # 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 + # 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 + return flux end end # module - import .VortexPairSetup - ############################################################################### # shared parameters, mesh and solver for both semidiscretizations # Parameters of the vortex pair -Mach = 1/9 +Mach = 1 / 9 c0 = 1.0 r0 = 1.0 circulation = 4 * pi * r0 * c0 * Mach rho = 1.0 -rc = 2/9 * r0 * 1.0 +rc = 2 / 9 * r0 * 1.0 T_r = 8 * pi^2 * r0^2 / circulation # Rotational period of the vortex pair T_a = T_r / 2 # Acoustic period of the vortex pair @@ -223,24 +219,22 @@ T_a = T_r / 2 # Acoustic period of the vortex pair vortex_pair = VortexPairSetup.VortexPair(r0, rc, c0, circulation, rho) # Shared mesh for both semidiscretizations -coordinates_min = (-135*r0, -135*r0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 135*r0, 135*r0) # maximum coordinates (max(x), max(y)) -refinement_patches = ( - (type="sphere", center=(0.0, 0.0), radius=85.0*r0), - (type="sphere", center=(0.0, 0.0), radius=20.0*r0), - (type="sphere", center=(0.0, 0.0), radius=10.0*r0), - (type="sphere", center=(0.0, 0.0), radius=5.0*r0) -) -initial_refinement_level=7 -n_cells_max=500_000 +coordinates_min = (-135 * r0, -135 * r0) # minimum coordinates (min(x), min(y)) +coordinates_max = (135 * r0, 135 * r0) # maximum coordinates (max(x), max(y)) +refinement_patches = ((type = "sphere", center = (0.0, 0.0), radius = 85.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 20.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 10.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 5.0 * r0)) +initial_refinement_level = 7 +n_cells_max = 500_000 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=initial_refinement_level, - refinement_patches=refinement_patches, - n_cells_max=n_cells_max, # set maximum capacity of tree data structure - periodicity=false) + initial_refinement_level = initial_refinement_level, + refinement_patches = refinement_patches, + n_cells_max = n_cells_max, # set maximum capacity of tree data structure + periodicity = false) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) ############################################################################### # semidiscretization Euler equations @@ -250,24 +244,37 @@ equations_euler = CompressibleEulerEquations2D(gamma) initial_condition_euler = VortexPairSetup.InitialCondition(vortex_pair) -sponge_layer_euler = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, 115*r0, -135*r0, 115*r0), - sponge_layer_max=(-115*r0, 135*r0, -115*r0, 135*r0), - reference_values=(rho, rho * c0^2 / gamma)) # (rho0, p0) +sponge_layer_euler = VortexPairSetup.SpongeLayer(sponge_layer_min = (-135 * r0, 115 * r0, + -135 * r0, 115 * r0), + sponge_layer_max = (-115 * r0, 135 * r0, + -115 * r0, 135 * r0), + reference_values = (rho, + rho * c0^2 / gamma)) # (rho0, p0) -boundary_condition_euler = VortexPairSetup.BoundaryCondition(rho, (rho * c0^2 / gamma) / (gamma-1)) +boundary_condition_euler = VortexPairSetup.BoundaryCondition(rho, + (rho * c0^2 / gamma) / + (gamma - 1)) -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition_euler, solver, - boundary_conditions=boundary_condition_euler, - source_terms=sponge_layer_euler) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition_euler, + solver, + boundary_conditions = boundary_condition_euler, + source_terms = sponge_layer_euler) ############################################################################### # semidiscretization acoustic perturbation equations -equations_acoustics = AcousticPerturbationEquations2D(v_mean_global=(13.0, 26.0), c_mean_global=39.0, - rho_mean_global=52.0) # global mean values will be overwritten - -sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, 100*r0, -135*r0, 100*r0), - sponge_layer_max=(-100*r0, 135*r0, -100*r0, 135*r0), - reference_values=(0.0,)) +equations_acoustics = AcousticPerturbationEquations2D(v_mean_global = (13.0, 26.0), + c_mean_global = 39.0, + rho_mean_global = 52.0) # global mean values will be overwritten + +sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min = (-135 * r0, + 100 * r0, + -135 * r0, + 100 * r0), + sponge_layer_max = (-100 * r0, + 135 * r0, + -100 * r0, + 135 * r0), + reference_values = (0.0,)) """ boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, @@ -276,24 +283,27 @@ sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, Boundary condition that uses a boundary state where the state variables are zero and the mean variables are the same as in `u_inner`. """ -function boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_zero(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - value = zero(eltype(u_inner)) - u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) + value = zero(eltype(u_inner)) + u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) - # 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 + # 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 + return flux end -semi_acoustics = SemidiscretizationHyperbolic(mesh, equations_acoustics, initial_condition_constant, - solver, boundary_conditions=boundary_condition_zero, - source_terms=sponge_layer_acoustics) +semi_acoustics = SemidiscretizationHyperbolic(mesh, equations_acoustics, + initial_condition_constant, + solver, + boundary_conditions = boundary_condition_zero, + source_terms = sponge_layer_acoustics) ############################################################################### # ODE solvers, callbacks etc. for averaging the flow field @@ -307,12 +317,12 @@ ode_averaging = semidiscretize(semi_euler, tspan1) summary_callback = SummaryCallback() analysis_interval = 5000 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) tspan_averaging = (50.0, 400.0) averaging_callback = AveragingCallback(semi_euler, tspan_averaging) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks_averaging = CallbackSet(summary_callback, alive_callback, averaging_callback, stepsize_callback) @@ -321,14 +331,13 @@ callbacks_averaging = CallbackSet(summary_callback, alive_callback, averaging_ca # run simulation for averaging the flow field # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol_averaging = solve(ode_averaging, 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_averaging); +sol_averaging = solve(ode_averaging, 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_averaging); # Print the timer summary summary_callback() - ############################################################################### # set up coupled semidiscretization @@ -337,13 +346,13 @@ source_region(x) = sum(abs2, x) < 6.0^2 # calculate sources within radius 6 arou weights(x) = sum(abs2, x) < 5.0^2 ? 1.0 : cospi(0.5 * (norm(x) - 5.0)) semi = SemidiscretizationEulerAcoustics(semi_acoustics, semi_euler, - source_region=source_region, weights=weights) + source_region = source_region, weights = weights) ############################################################################### # ODE solvers, callbacks etc. for the coupled simulation # Create ODE problem -tspan = (0.0, 7.0*T_a) +tspan = (0.0, 7.0 * T_a) ode = semidiscretize(semi, tspan) # We need an additional ODE for the pure flow problem ode_euler = semidiscretize(semi.semi_euler, tspan) @@ -351,28 +360,30 @@ ode_euler = semidiscretize(semi.semi_euler, tspan) # Set up coupling callback cfl_acoustics = 0.8 cfl_euler = 0.8 -euler_acoustics_coupling = EulerAcousticsCouplingCallback( - ode_euler, "out/averaging.h5", CarpenterKennedy2N54(williamson_condition=false), - cfl_acoustics, cfl_euler, callback=SaveRestartCallback(interval=2300, output_directory="out/euler/")) +euler_acoustics_coupling = EulerAcousticsCouplingCallback(ode_euler, "out/averaging.h5", + CarpenterKennedy2N54(williamson_condition = false), + cfl_acoustics, cfl_euler, + callback = SaveRestartCallback(interval = 2300, + output_directory = "out/euler/")) # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup # and resets the timers summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) output_directory = "out/" -save_solution = SaveSolutionCallback(interval=2300, output_directory=output_directory) -save_restart = SaveRestartCallback(interval=2300, output_directory=output_directory) +save_solution = SaveSolutionCallback(interval = 2300, output_directory = output_directory) +save_restart = SaveRestartCallback(interval = 2300, output_directory = output_directory) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback, save_solution, save_restart, euler_acoustics_coupling) -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); +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); # Print the timer summary -summary_callback() \ No newline at end of file +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl index d423b800fd..bc4859e576 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_eulermulti_convergence_es.jl b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl index 62c5bab51e..771343937a 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) 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); +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_eulermulti_ec.jl b/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl index 0715dfe35d..d912a280e4 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = 1.4, +equations = CompressibleEulerMulticomponentEquations2D(gammas = 1.4, gas_constants = 0.4) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 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) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +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); +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_eulermulti_es.jl b/examples/tree_2d_dgsem/elixir_eulermulti_es.jl index a3e5580b57..470e533ab8 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_es.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4, 0.4)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 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) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,30 +30,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_eulermulti_shock_bubble.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl index 38510446cb..f5ef51c108 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl @@ -5,7 +5,7 @@ using Trixi # semidiscretization of the compressible Euler multicomponent equations # 1) Dry Air 2) Helium + 28% Air -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), gas_constants = (0.287, 1.578)) """ @@ -16,124 +16,126 @@ A shock-bubble testcase for multicomponent Euler equations Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) """ -function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) - # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 - # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf - # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations - - # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving - delta = 0.03 - - # Region I - rho1_1 = delta - rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta - v1_1 = zero(delta) - v2_1 = zero(delta) - p_1 = 101325 - - # Region II - rho1_2 = 1.225-delta - rho2_2 = delta - v1_2 = zero(delta) - v2_2 = zero(delta) - p_2 = 101325 - - # Region III - rho1_3 = 1.6861 - delta - rho2_3 = delta - v1_3 = -113.5243 - v2_3 = zero(delta) - p_3 = 159060 - - # Set up Region I & II: - inicenter = SVector(zero(delta), zero(delta)) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - if (x[1] > 0.50) - # Set up Region III - rho1 = rho1_3 - rho2 = rho2_3 - v1 = v1_3 - v2 = v2_3 - p = p_3 - elseif (r < 0.25) - # Set up Region I - rho1 = rho1_1 - rho2 = rho2_1 - v1 = v1_1 - v2 = v2_1 - p = p_1 - else - # Set up Region II - rho1 = rho1_2 - rho2 = rho2_2 - v1 = v1_2 - v2 = v2_2 - p = p_2 - end - - return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{ + 5, + 2 + }) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) end initial_condition = initial_condition_shock_bubble -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_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.25, -2.225) -coordinates_max = ( 2.20, 2.225) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=1_000_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_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.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.01) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) -analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +summary_callback = SummaryCallback() -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.3) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 0.3) +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, - maxiters=1e5); -summary_callback() # print the timer summary \ No newline at end of file +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, + maxiters = 1e5); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 1c6cbef533..4a8a70b566 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -5,7 +5,7 @@ using Trixi # semidiscretization of the compressible Euler multicomponent equations # 1) Dry Air 2) Helium + 28% Air -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), gas_constants = (0.287, 1.578)) """ @@ -16,126 +16,130 @@ A shock-bubble testcase for multicomponent Euler equations Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) """ -function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) - # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 - # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf - # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations - - # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving - delta = 0.03 - - # Region I - rho1_1 = delta - rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta - v1_1 = zero(delta) - v2_1 = zero(delta) - p_1 = 101325 - - # Region II - rho1_2 = 1.225-delta - rho2_2 = delta - v1_2 = zero(delta) - v2_2 = zero(delta) - p_2 = 101325 - - # Region III - rho1_3 = 1.6861 - delta - rho2_3 = delta - v1_3 = -113.5243 - v2_3 = zero(delta) - p_3 = 159060 - - # Set up Region I & II: - inicenter = SVector(zero(delta), zero(delta)) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - if (x[1] > 0.50) - # Set up Region III - rho1 = rho1_3 - rho2 = rho2_3 - v1 = v1_3 - v2 = v2_3 - p = p_3 - elseif (r < 0.25) - # Set up Region I - rho1 = rho1_1 - rho2 = rho2_1 - v1 = v1_1 - v2 = v2_1 - p = p_1 - else - # Set up Region II - rho1 = rho1_2 - rho2 = rho2_2 - v1 = v1_2 - v2 = v2_2 - p = p_2 - end - - return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{ + 5, + 2 + }) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) end initial_condition = initial_condition_shock_bubble -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons=[(i+3 for i in eachcomponent(equations))...], - spec_entropy=false, - bar_states=true) + local_minmax_variables_cons = [ + (i + 3 for i in eachcomponent(equations))..., + ], + spec_entropy = false, + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (-2.25, -2.225) -coordinates_max = ( 2.20, 2.225) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=1_000_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) +coordinates_min = (-2.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.01) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) -analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +summary_callback = SummaryCallback() -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -save_solution = SaveSolutionCallback(interval=600, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.9) +save_solution = SaveSolutionCallback(interval = 600, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 0.9) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors=false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - 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 \ No newline at end of file +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index f817a91a58..5f6cdb1e9c 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -5,7 +5,7 @@ using Trixi # semidiscretization of the compressible Euler multicomponent equations # 1) Dry Air 2) Helium + 28% Air -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), gas_constants = (0.287, 1.578)) """ @@ -16,131 +16,136 @@ A shock-bubble testcase for multicomponent Euler equations Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) """ -function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) - # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 - # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf - # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations - - # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving - delta = 0.03 - - # Region I - rho1_1 = delta - rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta - v1_1 = zero(delta) - v2_1 = zero(delta) - p_1 = 101325 - - # Region II - rho1_2 = 1.225-delta - rho2_2 = delta - v1_2 = zero(delta) - v2_2 = zero(delta) - p_2 = 101325 - - # Region III - rho1_3 = 1.6861 - delta - rho2_3 = delta - v1_3 = -113.5243 - v2_3 = zero(delta) - p_3 = 159060 - - # Set up Region I & II: - inicenter = SVector(zero(delta), zero(delta)) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - if (x[1] > 0.50) - # Set up Region III - rho1 = rho1_3 - rho2 = rho2_3 - v1 = v1_3 - v2 = v2_3 - p = p_3 - elseif (r < 0.25) - # Set up Region I - rho1 = rho1_1 - rho2 = rho2_1 - v1 = v1_1 - v2 = v2_1 - p = p_1 - else - # Set up Region II - rho1 = rho1_2 - rho2 = rho2_2 - v1 = v1_2 - v2 = v2_2 - p = p_2 - end - - return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{ + 5, + 2 + }) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) end initial_condition = initial_condition_shock_bubble -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...], - positivity_variables_nonlinear=(), - positivity_correction_factor=0.1, - spec_entropy=false, - bar_states=false) + positivity_variables_cons = [ + (i + 3 for i in eachcomponent(equations))..., + ], + positivity_variables_nonlinear = (), + positivity_correction_factor = 0.1, + spec_entropy = false, + bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (-2.25, -2.225) -coordinates_max = ( 2.20, 2.225) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=1_000_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) +coordinates_min = (-2.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.01) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) -analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +summary_callback = SummaryCallback() -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.9) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 0.9) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) ############################################################################### # run the simulation output_directory = "out" stage_callbacks = (SubcellLimiterIDPCorrection(), - BoundsCheckCallback(save_errors=true, interval=100, output_directory=output_directory)) + BoundsCheckCallback(save_errors = true, interval = 100, + output_directory = output_directory)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - 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 \ No newline at end of file +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_hypdiff_godunov.jl b/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl index abf9735fd2..1700957d90 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl @@ -8,51 +8,50 @@ using Trixi equations = HyperbolicDiffusionEquations2D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - else - phi = sin(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q1 = 2*pi*cos(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q2 = 2*pi*sin(2.0*pi*x[1])*cos(2.0*pi*x[2]) - end - return SVector(phi, q1, q2) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + else + phi = sin(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q1 = 2 * pi * cos(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q2 = 2 * pi * sin(2.0 * pi * x[1]) * cos(2.0 * pi * x[2]) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -8 * equations.nu * pi^2 - - x1, x2 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - du1 = -C*tmp1*tmp2 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - - return SVector(du1, du2, du3) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -8 * equations.nu * pi^2 + + x1, x2 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + du1 = -C * tmp1 * tmp2 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + + return SVector(du1, du2, du3) end volume_flux = flux_central -solver = DGSEM(polydeg=4, surface_flux=flux_godunov, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) 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=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -63,30 +62,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_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); +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_hypdiff_harmonic_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index c144ef47a6..e70b91906b 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -7,44 +7,43 @@ using Trixi equations = HyperbolicDiffusionEquations2D() -@inline function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω - if t == 0.0 - phi = 1.0 - q1 = 1.0 - q2 = 1.0 - else - C = inv(sinh(pi)) - sinpi_x1, cospi_x1 = sincos(pi*x[1]) - sinpi_x2, cospi_x2 = sincos(pi*x[2]) - sinh_pix1 = sinh(pi*x[1]) - cosh_pix1 = cosh(pi*x[1]) - sinh_pix2 = sinh(pi*x[2]) - cosh_pix2 = cosh(pi*x[2]) - phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) - q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) - q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) - end - return SVector(phi, q1, q2) +@inline function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω + if t == 0.0 + phi = 1.0 + q1 = 1.0 + q2 = 1.0 + else + C = inv(sinh(pi)) + sinpi_x1, cospi_x1 = sincos(pi * x[1]) + sinpi_x2, cospi_x2 = sincos(pi * x[2]) + sinh_pix1 = sinh(pi * x[1]) + cosh_pix1 = cosh(pi * x[1]) + sinh_pix2 = sinh(pi * x[2]) + cosh_pix2 = cosh(pi * x[2]) + phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) + q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) + q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov) 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=30_000, - periodicity=false) - + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -55,30 +54,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_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); +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_hypdiff_lax_friedrichs.jl b/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl index d0d706981a..a1a0397a46 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl @@ -8,49 +8,48 @@ using Trixi equations = HyperbolicDiffusionEquations2D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - else - phi = sin(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q1 = 2*pi*cos(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q2 = 2*pi*sin(2.0*pi*x[1])*cos(2.0*pi*x[2]) - end - return SVector(phi, q1, q2) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + else + phi = sin(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q1 = 2 * pi * cos(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q2 = 2 * pi * sin(2.0 * pi * x[1]) * cos(2.0 * pi * x[2]) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -8 * equations.nu * pi^2 - - x1, x2 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - du1 = -C*tmp1*tmp2 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - - return SVector(du1, du2, du3) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -8 * equations.nu * pi^2 + + x1, x2 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + du1 = -C * tmp1 * tmp2 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + + return SVector(du1, du2, du3) end -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) 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=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -61,31 +60,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_hypdiff_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl index fc825660f1..1396481a3f 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -9,25 +9,23 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic # 1 => -x, 2 => +x, 3 => -y, 4 => +y as usual for orientations -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) 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=30_000, - periodicity=(false, true)) - + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_poisson_nonperiodic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_poisson_nonperiodic) ############################################################################### # ODE solvers, callbacks etc. @@ -38,30 +36,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_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); +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_kpp.jl b/examples/tree_2d_dgsem/elixir_kpp.jl index f3cbc1cb66..b48bde0d15 100644 --- a/examples/tree_2d_dgsem/elixir_kpp.jl +++ b/examples/tree_2d_dgsem/elixir_kpp.jl @@ -25,22 +25,25 @@ end @inline function Trixi.flux_ec(u_ll, u_rr, orientation::Integer, ::KPPEquation2D) # The tolerance of 1e-12 is based on experience and somewhat arbitrarily chosen if abs(u_ll[1] - u_rr[1]) < 1e-12 - return 0.5 * (flux(u_ll, orientation, KPPEquation2D()) + flux(u_rr, orientation, KPPEquation2D())) + return 0.5 * (flux(u_ll, orientation, KPPEquation2D()) + + flux(u_rr, orientation, KPPEquation2D())) else factor = 1.0 / (u_rr[1] - u_ll[1]) if orientation == 1 - return SVector(factor*(-cos(u_rr[1]) + cos(u_ll[1]))) + return SVector(factor * (-cos(u_rr[1]) + cos(u_ll[1]))) else - return SVector(factor*(sin(u_rr[1]) - sin(u_ll[1]))) + return SVector(factor * (sin(u_rr[1]) - sin(u_ll[1]))) end end end # Wavespeeds @inline wavespeed(::KPPEquation2D) = 1.0 -@inline Trixi.max_abs_speeds(u, equation::KPPEquation2D) = (wavespeed(equation), wavespeed(equation)) +@inline Trixi.max_abs_speeds(u, equation::KPPEquation2D) = (wavespeed(equation), + wavespeed(equation)) @inline Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equation::KPPEquation2D) = wavespeed(equation) -@inline Trixi.max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equation::KPPEquation2D) = wavespeed(equation) * norm(normal_direction) +@inline Trixi.max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equation::KPPEquation2D) = wavespeed(equation) * + norm(normal_direction) # Compute entropy: we use the square entropy @inline Trixi.entropy(u::Real, ::KPPEquation2D) = 0.5 * u^2 @@ -74,24 +77,25 @@ volume_flux = flux_ec polydeg = 3 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equation, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### # Set up the tree mesh (initially a Cartesian grid of [-2,2]^2) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - periodicity=true, - n_cells_max=500_000) + initial_refinement_level = 6, + periodicity = true, + n_cells_max = 500_000) ############################################################################### # Create the semi discretization object @@ -100,23 +104,24 @@ semi = SemidiscretizationHyperbolic(mesh, equation, initial_condition_kpp, solve ############################################################################### # Set up adaptive mesh refinement amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=first) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = first) max_refinement_level = 8 amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, shock_indicator, - base_level=2, - med_level=0, med_threshold=0.0003, - max_level=max_refinement_level, max_threshold=0.003, - max_threshold_secondary=shock_indicator.alpha_max) + base_level = 2, + med_level = 0, med_threshold = 0.0003, + max_level = max_refinement_level, + max_threshold = 0.003, + max_threshold_secondary = shock_indicator.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) ############################################################################### # ODE solvers, callbacks etc. @@ -125,14 +130,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_callback = AnalysisCallback(semi, interval=200) +analysis_callback = AnalysisCallback(semi, interval = 200) -alive_callback = AliveCallback(analysis_interval=200) +alive_callback = AliveCallback(analysis_interval = 200) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2cons) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -140,6 +145,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); ode_default_options()..., callback = callbacks) summary_callback() # Print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_lbm_constant.jl b/examples/tree_2d_dgsem/elixir_lbm_constant.jl index 40b16f41ef..5a4f3074e4 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_constant.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_constant.jl @@ -5,22 +5,20 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.1, Re=Inf) +equations = LatticeBoltzmannEquations2D(Ma = 0.1, Re = Inf) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 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,) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,19 +28,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -52,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_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); +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_lbm_couette.jl b/examples/tree_2d_dgsem/elixir_lbm_couette.jl index 6a33b2fb0e..1ba040405d 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_couette.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_couette.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.05, Re=2000) +equations = LatticeBoltzmannEquations2D(Ma = 0.05, Re = 2000) """ initial_condition_couette_unsteady(x, t, equations::LatticeBoltzmannEquations2D) @@ -16,19 +16,20 @@ incompressible Navier-Stokes equations. To be used in combination with this setup will converge to the state set in [`initial_condition_couette_steady`](@ref). """ function initial_condition_couette_unsteady(x, t, equations::LatticeBoltzmannEquations2D) - @unpack L, u0, rho0, nu = equations + @unpack L, u0, rho0, nu = equations - x1, x2 = x - v1 = u0*x2/L - for m in 1:100 - lambda_m = m * pi / L - v1 += 2 * u0 * (-1)^m/(lambda_m * L) * exp(-nu * lambda_m^2 * t) * sin(lambda_m * x2) - end + x1, x2 = x + v1 = u0 * x2 / L + for m in 1:100 + lambda_m = m * pi / L + v1 += 2 * u0 * (-1)^m / (lambda_m * L) * exp(-nu * lambda_m^2 * t) * + sin(lambda_m * x2) + end - rho = 1 - v2 = 0 + rho = 1 + v2 = 0 - return equilibrium_distribution(rho, v1, v2, equations) + return equilibrium_distribution(rho, v1, v2, equations) end initial_condition = initial_condition_couette_unsteady @@ -44,53 +45,49 @@ Moving *upper* wall boundary condition for a Couette flow setup. To be used in c function boundary_condition_couette(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, - surface_flux_function, equations) + return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, + surface_flux_function, equations) end function boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - @assert direction == 4 "moving wall assumed in +y direction" + @assert direction==4 "moving wall assumed in +y direction" - @unpack rho0, u0, weights, c_s = equations - cs_squared = c_s^2 + @unpack rho0, u0, weights, c_s = equations + cs_squared = c_s^2 - pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared - pdf2 = u_inner[2] # outgoing - pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared - pdf4 = u_inner[2] - pdf5 = u_inner[5] # outgoing - pdf6 = u_inner[6] # outgoing - pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared - pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared - pdf9 = u_inner[9] + pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared + pdf2 = u_inner[2] # outgoing + pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared + pdf4 = u_inner[2] + pdf5 = u_inner[5] # outgoing + pdf6 = u_inner[6] # outgoing + pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared + pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared + pdf9 = u_inner[9] - u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) + u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) - # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) - return surface_flux_function(u_inner, u_boundary, orientation, equations) + # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) + return surface_flux_function(u_inner, u_boundary, orientation, equations) end -boundary_conditions = ( - x_neg=boundary_condition_periodic, - x_pos=boundary_condition_periodic, - y_neg=boundary_condition_noslip_wall, - y_pos=boundary_condition_couette, - ) +boundary_conditions = (x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_noslip_wall, + y_pos = boundary_condition_couette) -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=(true, false), - n_cells_max=10_000,) - + initial_refinement_level = 3, + periodicity = (true, false), + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -101,26 +98,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Custom solution variables: normalize velocities by reference speed `u0` @inline function macroscopic_normalized(u, equations::LatticeBoltzmannEquations2D) - macroscopic = cons2macroscopic(u, equations) - rho, v1, v2, p = macroscopic + macroscopic = cons2macroscopic(u, equations) + rho, v1, v2, p = macroscopic - # Use `typeof(macroscopic)` to avoid having to explicitly add `using StaticArrays` - convert(typeof(macroscopic), (rho, v1/equations.u0, v2/equations.u0, p)) + # Use `typeof(macroscopic)` to avoid having to explicitly add `using StaticArrays` + convert(typeof(macroscopic), (rho, v1 / equations.u0, v2 / equations.u0, p)) +end +function Trixi.varnames(::typeof(macroscopic_normalized), + equations::LatticeBoltzmannEquations2D) + ("rho", "v1_normalized", "v2_normalized", "p") end -Trixi.varnames(::typeof(macroscopic_normalized), equations::LatticeBoltzmannEquations2D) = ("rho", "v1_normalized", "v2_normalized", "p") -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=macroscopic_normalized) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = macroscopic_normalized) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -130,11 +130,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_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); +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_lbm_lid_driven_cavity.jl b/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl index a34e784e7a..d00926cafa 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.1, Re=1000) +equations = LatticeBoltzmannEquations2D(Ma = 0.1, Re = 1000) """ initial_condition_lid_driven_cavity(x, t, equations::LatticeBoltzmannEquations2D) @@ -14,13 +14,13 @@ Initial state for a lid-driven cavity flow setup. To be used in combination with [`boundary_condition_lid_driven_cavity`](@ref) and [`boundary_condition_noslip_wall`](@ref). """ function initial_condition_lid_driven_cavity(x, t, equations::LatticeBoltzmannEquations2D) - @unpack L, u0, nu = equations + @unpack L, u0, nu = equations - rho = 1 - v1 = 0 - v2 = 0 + rho = 1 + v1 = 0 + v2 = 0 - return equilibrium_distribution(rho, v1, v2, equations) + return equilibrium_distribution(rho, v1, v2, equations) end initial_condition = initial_condition_lid_driven_cavity @@ -35,53 +35,49 @@ no-slip wall. To be used in combination with [`initial_condition_lid_driven_cavi function boundary_condition_lid_driven_cavity(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, - surface_flux_function, equations) + return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, + surface_flux_function, equations) end function boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - @assert direction == 4 "moving wall assumed in +y direction" + @assert direction==4 "moving wall assumed in +y direction" - @unpack rho0, u0, weights, c_s = equations - cs_squared = c_s^2 + @unpack rho0, u0, weights, c_s = equations + cs_squared = c_s^2 - pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared - pdf2 = u_inner[2] # outgoing - pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared - pdf4 = u_inner[2] - pdf5 = u_inner[5] # outgoing - pdf6 = u_inner[6] # outgoing - pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared - pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared - pdf9 = u_inner[9] + pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared + pdf2 = u_inner[2] # outgoing + pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared + pdf4 = u_inner[2] + pdf5 = u_inner[5] # outgoing + pdf6 = u_inner[6] # outgoing + pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared + pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared + pdf9 = u_inner[9] - u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) + u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) - # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) - return surface_flux_function(u_inner, u_boundary, orientation, equations) + # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) + return surface_flux_function(u_inner, u_boundary, orientation, equations) end -boundary_conditions = ( - x_neg=boundary_condition_noslip_wall, - x_pos=boundary_condition_noslip_wall, - y_neg=boundary_condition_noslip_wall, - y_pos=boundary_condition_lid_driven_cavity, - ) +boundary_conditions = (x_neg = boundary_condition_noslip_wall, + x_pos = boundary_condition_noslip_wall, + y_neg = boundary_condition_noslip_wall, + y_pos = boundary_condition_lid_driven_cavity) -solver = DGSEM(polydeg=5, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 5, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=10_000,) - + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -92,16 +88,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -111,11 +107,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_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); +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_linearizedeuler_convergence.jl b/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl index 14459fa4cb..93272833b7 100644 --- a/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl @@ -4,25 +4,25 @@ using Trixi ############################################################################### # semidiscretization of the linearized Euler equations -equations = LinearizedEulerEquations2D(v_mean_global=(0.0, 0.0), c_mean_global=1.0, rho_mean_global=1.0) +equations = LinearizedEulerEquations2D(v_mean_global = (0.0, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) + initial_refinement_level = 4, + n_cells_max = 30_000) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -37,28 +37,29 @@ summary_callback = SummaryCallback() analysis_interval = 100 # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=analysis_interval, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = analysis_interval, + solution_variables = cons2prim) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # print the timer summary summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl b/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl index 14fe201a29..fad03fab6e 100644 --- a/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl +++ b/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl @@ -5,33 +5,32 @@ using Trixi ############################################################################### # semidiscretization of the linearized Euler equations -equations = LinearizedEulerEquations2D(v_mean_global=(0.5, 0.0), c_mean_global=1.0, - rho_mean_global=1.0) +equations = LinearizedEulerEquations2D(v_mean_global = (0.5, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 5 and upwind flux as surface flux -solver = DGSEM(polydeg=5, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 5, surface_flux = flux_godunov) coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 4, + n_cells_max = 100_000, + periodicity = false) function initial_condition_gauss_wall(x, t, equations::LinearizedEulerEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - rho_prime = p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - return SVector(rho_prime, v1_prime, v2_prime, p_prime) + v1_prime = 0.0 + v2_prime = 0.0 + rho_prime = p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + return SVector(rho_prime, v1_prime, v2_prime, p_prime) end initial_condition = initial_condition_gauss_wall # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_wall) - + boundary_conditions = boundary_condition_wall) ############################################################################### # ODE solvers, callbacks etc. @@ -45,24 +44,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100) +save_solution = SaveSolutionCallback(interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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) +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) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl index d9e59160e7..377a07e947 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -4,25 +4,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,22 +31,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -56,11 +58,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhd_alfven_wave_mortar.jl b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl index 11dfeacde6..229360f266 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) -refinement_patches = ( - (type="box", coordinates_min=0.25 .* coordinates_max, - coordinates_max=0.75 .* coordinates_max), -) +refinement_patches = ((type = "box", coordinates_min = 0.25 .* coordinates_max, + coordinates_max = 0.75 .* coordinates_max),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -35,22 +33,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -62,7 +63,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_blast_wave.jl b/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl index af05fffaf5..a0909ca758 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl @@ -16,52 +16,50 @@ An MHD blast wave taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 - r = sqrt(x[1]^2 + x[2]^2) - f = (0.1 - r)/0.01 - if r <= 0.09 - p = 1000.0 - elseif r >= 0.1 - p = 0.1 - else - p = 0.1 + 999.9*f - end - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - B1 = 100.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 + r = sqrt(x[1]^2 + x[2]^2) + f = (0.1 - r) / 0.01 + if r <= 0.09 + p = 1000.0 + elseif r >= 0.1 + p = 0.1 + else + p = 0.1 + 999.9 * f + end + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + B1 = 100.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_central, flux_nonconservative_powell) +volume_flux = (flux_central, flux_nonconservative_powell) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -71,32 +69,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=7, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 7, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.8 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -109,7 +107,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_ec.jl b/examples/tree_2d_dgsem/elixir_mhd_ec.jl index 5873388f79..173d3ed448 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,18 @@ equations = IdealGlmMhdEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,19 +31,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -53,11 +52,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhd_orszag_tang.jl b/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl index 460b24e02b..7f26f270d6 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) """ @@ -16,44 +16,42 @@ The classical Orszag-Tang vortex test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_orszag_tang(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 5/3 - rho = 1.0 - v1 = -sin(2.0*pi*x[2]) - v2 = sin(2.0*pi*x[1]) - v3 = 0.0 - p = 1.0 / equations.gamma - B1 = -sin(2.0*pi*x[2]) / equations.gamma - B2 = sin(4.0*pi*x[1]) / equations.gamma - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 5/3 + rho = 1.0 + v1 = -sin(2.0 * pi * x[2]) + v2 = sin(2.0 * pi * x[1]) + v3 = 0.0 + p = 1.0 / equations.gamma + B1 = -sin(2.0 * pi * x[2]) / equations.gamma + B2 = sin(4.0 * pi * x[1]) / equations.gamma + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_orszag_tang surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_central, flux_nonconservative_powell) +volume_flux = (flux_central, flux_nonconservative_powell) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -63,32 +61,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.25 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -101,7 +99,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_rotor.jl b/examples/tree_2d_dgsem/elixir_mhd_rotor.jl index c6d880e9e9..3109b1ce30 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_rotor.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations equations = IdealGlmMhdEquations2D(1.4) @@ -16,59 +15,57 @@ The classical MHD rotor test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_rotor(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho = 10.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - else - rho = 1.0 + 9.0*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho = 10.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + else + rho = 1.0 + 9.0 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -78,32 +75,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.35 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -116,7 +113,7 @@ callbacks = CallbackSet(summary_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); +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_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 2e6429ad9b..84361ef4f8 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -17,59 +17,57 @@ An MHD blast wave modified from: This setup needs a positivity limiter for the density. """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 - r = sqrt(x[1]^2 + x[2]^2) - - pmax = 10.0 - pmin = 0.01 - rhomax = 1.0 - rhomin = 0.01 - if r <= 0.09 - p = pmax - rho = rhomax - elseif r >= 0.1 - p = pmin - rho = rhomin - else - p = pmin + (0.1 - r) * (pmax - pmin) / 0.01 - rho = rhomin + (0.1 - r) * (rhomax - rhomin) / 0.01 - end - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - B1 = 1.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 + r = sqrt(x[1]^2 + x[2]^2) + + pmax = 10.0 + pmin = 0.01 + rhomax = 1.0 + rhomin = 0.01 + if r <= 0.09 + p = pmax + rho = rhomax + elseif r >= 0.1 + p = pmin + rho = rhomin + else + p = pmin + (0.1 - r) * (pmax - pmin) / 0.01 + rho = rhomin + (0.1 - r) * (rhomax - rhomin) / 0.01 + end + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + B1 = 1.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell_local_symmetric) -volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) +volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_variables_nonlinear=[pressure], - positivity_correction_factor=0.1, - bar_states=false) + positivity_variables_cons = [1], + positivity_variables_nonlinear = [pressure], + positivity_correction_factor = 0.1, + bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -79,19 +77,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 0.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -104,7 +102,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_mhdmulti_convergence.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl index a7551f4893..4f1f8c5f2b 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5/3, 5/3, 5/3), - gas_constants = (2.08, 2.08, 2.08)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5 / 3, 5 / 3, 5 / 3), + gas_constants = (2.08, 2.08, 2.08)) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2), sqrt(2)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +54,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhdmulti_ec.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl index ec2f3c21cd..a7db9eeee9 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), - gas_constants = (1.0, 1.0)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), + gas_constants = (1.0, 1.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +53,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhdmulti_es.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl index 3cd9c621ae..fcaabdc7a5 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5/3, 5/3), - gas_constants = (0.2, 0.2)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5 / 3, 5 / 3), + gas_constants = (0.2, 0.2)) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +53,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhdmulti_rotor.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl index 55a4004f79..5ca21cc5e9 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl @@ -2,10 +2,9 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (1.0, 1.0)) """ @@ -14,62 +13,60 @@ equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), The classical MHD rotor test case adapted to two density components. """ function initial_condition_rotor(x, t, equations::IdealGlmMhdMulticomponentEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho1 = 10.0 - rho2 = 5.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho1 = 1.0 - rho2 = 0.5 - v1 = 0.0 - v2 = 0.0 - else - rho1 = 1.0 + 9.0*f - rho2 = 0.5 + 4.5*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(v1, v2, v3, p, B1, B2, B3, psi, rho1, rho2), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho1 = 10.0 + rho2 = 5.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho1 = 1.0 + rho2 = 0.5 + v1 = 0.0 + v2 = 0.0 + else + rho1 = 1.0 + 9.0 * f + rho2 = 0.5 + 4.5 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(v1, v2, v3, p, B1, B2, B3, psi, rho1, rho2), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.8, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.8, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -79,32 +76,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -117,7 +114,7 @@ callbacks = CallbackSet(summary_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); +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_navierstokes_convergence.jl b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl index b68e9e6c97..5755822485 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl @@ -8,163 +8,170 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=(true, false), - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = (true, false), + n_cells_max = 30_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ + - + - + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + - - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test @@ -175,23 +182,26 @@ velocity_bc_top_bottom = NoSlip() do x, t, equations return SVector(u[2], u[3]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_slip_wall, - y_pos = boundary_condition_slip_wall) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_top_bottom, - y_pos = boundary_condition_top_bottom) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_top_bottom, + y_pos = boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -201,16 +211,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl index 3314343ccc..7bd1ec0c64 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,27 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure - + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -45,15 +44,15 @@ boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity boundary_conditions = boundary_condition_slip_wall boundary_conditions_parabolic = (; x_neg = boundary_condition_cavity, - y_neg = boundary_condition_cavity, - y_pos = boundary_condition_lid, - x_pos = boundary_condition_cavity) + y_neg = boundary_condition_cavity, + y_pos = boundary_condition_lid, + x_pos = boundary_condition_cavity) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -63,17 +62,15 @@ tspan = (0.0, 25.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=100) +alive_callback = AliveCallback(alive_interval = 100) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - - diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl index 06e8f06d3c..4d92ea261e 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -7,11 +7,11 @@ using Trixi # TODO: parabolic; unify names of these accessor functions prandtl_number() = 0.72 -mu() = 1.0/3.0 * 10^(-5) # equivalent to Re = 30,000 +mu() = 1.0 / 3.0 * 10^(-5) # equivalent to Re = 30,000 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) """ A compressible version of the double shear layer initial condition. Adapted from @@ -22,32 +22,31 @@ Brown and Minion (1995). [DOI: 10.1006/jcph.1995.1205](https://doi.org/10.1006/jcph.1995.1205) """ function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) - # Shear layer parameters - k = 80 - delta = 0.05 - u0 = 1.0 - - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2] - 0.25)) : u0 * tanh(k*(0.75 -x[2])) - v2 = u0 * delta * sin(2*pi*(x[1]+ 0.25)) - p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Shear layer parameters + k = 80 + delta = 0.05 + u0 = 1.0 + + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = x[2] <= 0.5 ? u0 * tanh(k * (x[2] - 0.25)) : u0 * tanh(k * (0.75 - x[2])) + v2 = u0 * delta * sin(2 * pi * (x[1] + 0.25)) + p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_shear_layer volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - + initial_refinement_level = 4, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -61,26 +60,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 2000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # This uses velocity-based AMR @inline function v1(u, equations::CompressibleEulerEquations2D) - rho, rho_v1, _, _ = u - return rho_v1 / rho + rho, rho_v1, _, _ = u + return rho_v1 / rho end -amr_indicator = IndicatorLöhner(semi, variable=v1) +amr_indicator = IndicatorLöhner(semi, variable = v1) amr_controller = ControllerThreeLevel(semi, amr_indicator, base_level = 3, - med_level = 5, med_threshold=0.2, - max_level = 7, max_threshold=0.5) + med_level = 5, med_threshold = 0.2, + max_level = 7, max_threshold = 0.5) amr_callback = AMRCallback(semi, amr_controller, - interval=50, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 50, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -91,7 +90,7 @@ callbacks = CallbackSet(summary_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 \ No newline at end of file +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_navierstokes_taylor_green_vortex.jl b/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index c3cbc858f7..a3e38bf6d9 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,8 +10,8 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations2D) @@ -22,30 +22,30 @@ This forms the basis behind the 3D case found for instance in Simulation of the Compressible Taylor Green Vortex using High-Order Flux Reconstruction Schemes [DOI: 10.2514/6.2014-3210](https://doi.org/10.2514/6.2014-3210) """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations2D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) - v2 = -A * cos(x[1]) * sin(x[2]) - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/4.0 * A^2 * rho * (cos(2*x[1]) + cos(2*x[2])) - - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations2D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) + v2 = -A * cos(x[1]) * sin(x[2]) + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + 1.0 / 4.0 * A^2 * rho * (cos(2 * x[1]) + cos(2 * x[2])) + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - + initial_refinement_level = 4, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -59,11 +59,12 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,6 +74,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-9 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl index 7c60e35b03..349b374186 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.4) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) """ initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) @@ -21,29 +21,29 @@ boundary condition with the initial values. Due to the dry cells at the boundary effect of an outflow which can be seen in the simulation. """ function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values + # Set the background values - v1 = 0.0 - v2 = 0.0 + v1 = 0.0 + v2 = 0.0 - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) + 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 + # 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)))) + H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_conical_island @@ -53,19 +53,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -75,13 +76,13 @@ solver = DGSEM(basis, surface_flux, volume_integral) 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) + 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) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solver @@ -95,22 +96,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., 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 index eed0a350e7..bc528ae775 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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. @@ -16,17 +16,18 @@ 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)) +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) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -46,45 +47,48 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -93,15 +97,15 @@ end summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(dt=0.2, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(dt = 0.2, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -109,7 +113,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_parabolic_bowl.jl b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl index 03dcf01726..2008019cc3 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) @@ -28,27 +28,27 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) + a = 1.0 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v1 = -sigma * ω * sin(ω * t) + v2 = sigma * ω * cos(ω * t) + + b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_parabolic_bowl @@ -56,23 +56,23 @@ 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), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(7) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.6, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + 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) + 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 @@ -80,8 +80,8 @@ 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) + initial_refinement_level = 5, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -95,19 +95,20 @@ 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)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation @@ -115,6 +116,6 @@ stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterh callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., 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 index 6d4f6fe518..c92e885c16 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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)) +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 @@ -23,13 +23,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ 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) + 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) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +40,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +54,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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 index c3da957b76..f7544b1e32 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -15,8 +15,9 @@ 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)) +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 @@ -24,14 +25,14 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ 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) + 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) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -42,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -56,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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_twolayer_convergence.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl index 402361c882..f7c8ab3a24 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -5,7 +5,8 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test @@ -13,9 +14,9 @@ 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_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - +solver = DGSEM(polydeg = 3, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -23,13 +24,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=20_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 20_000, + periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +41,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +55,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, -save_everystep=false, callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index ba4bcd2577..1495e6d856 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -6,21 +6,24 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a bottom topography function # to test well-balancedness -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=9.81, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 9.81, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) # An initial condition with constant total water height, zero velocities and a bottom topography to # test well-balancedness function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + H_lower = 0.5 + H_upper = 0.6 + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? + 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + + -0.5)^2)) + 1) : 0.0) + + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_well_balanced @@ -30,8 +33,8 @@ initial_condition = initial_condition_well_balanced volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=3, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -39,9 +42,9 @@ solver = DGSEM(polydeg=3, surface_flux=surface_flux, coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -55,16 +58,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -72,7 +75,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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 index 23efdcb736..13023dfaba 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -6,21 +6,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations2D(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::ShallowWaterEquations2D) - # 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) + # 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 @@ -30,17 +30,17 @@ initial_condition = initial_condition_well_balancedness 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)) +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) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -61,30 +61,33 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -93,16 +96,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -110,7 +113,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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 index 66cd27f686..f50bd4e4f6 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl @@ -5,21 +5,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations2D(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::ShallowWaterEquations2D) - # 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) + # 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 @@ -31,8 +31,8 @@ boundary_condition = boundary_condition_slip_wall 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)) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -40,8 +40,8 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux, 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, + initial_refinement_level = 2, + n_cells_max = 10_000, periodicity = false) # create the semi discretization object @@ -64,30 +64,33 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -96,16 +99,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +116,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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 \ No newline at end of file +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index 6fede2fa4e..034411c2b5 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,7 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.812) +equations = ShallowWaterEquations2D(gravity_constant = 9.812) """ initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) @@ -23,28 +23,29 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations::ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations2D) + v1 = 0 + v2 = 0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -53,19 +54,20 @@ 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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -76,8 +78,8 @@ 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) + initial_refinement_level = 3, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -102,18 +104,20 @@ ode = semidiscretize(semi, tspan) 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]) + 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 - 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 ############################################################################### @@ -122,27 +126,27 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_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=2.0) +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,)) +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); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -157,34 +161,38 @@ summary_callback() # print the timer summary function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) h, _, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. + # 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 + 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)) + 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) +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 diff --git a/examples/tree_2d_fdsbp/elixir_advection_extended.jl b/examples/tree_2d_fdsbp/elixir_advection_extended.jl index 6e599d9f42..8716a9a6b7 100644 --- a/examples/tree_2d_fdsbp/elixir_advection_extended.jl +++ b/examples/tree_2d_fdsbp/elixir_advection_extended.jl @@ -13,22 +13,21 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=100) + derivative_order = 1, accuracy_order = 4, + xmin = 0.0, xmax = 1.0, N = 100) solver = FDSBP(D_SBP, - surface_integral=SurfaceIntegralStrongForm(flux_lax_friedrichs), - volume_integral=VolumeIntegralStrongForm()) + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 1, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,19 +37,18 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_convergence.jl b/examples/tree_2d_fdsbp/elixir_euler_convergence.jl index 2a6c291f0b..123be02bd1 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_convergence.jl @@ -13,23 +13,24 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = true) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, source_terms = source_terms_convergence_test) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,15 +41,15 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -58,6 +59,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl b/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl index e63343852a..4c41b84af3 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl @@ -9,42 +9,42 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_vanleer_haenel solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -54,27 +54,26 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(entropy, - energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, + energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, dt=1e-3, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, dt = 1e-3, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_vortex.jl b/examples/tree_2d_fdsbp/elixir_euler_vortex.jl index c1bee8f9c4..d0847cc801 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_vortex.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_vortex.jl @@ -19,62 +19,61 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - - cent = x - cent # distance to center point - - #cent=cross(iniaxis,cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude/(2*π)*exp(0.5*(1-r2)) # vel. perturbation - dtemp = -(equations.gamma-1)/(2*equations.gamma*rt)*du^2 # isentropic - rho = rho * (1+dtemp)^(1/(equations.gamma-1)) - vel = vel + du*cent - v1, v2 = vel - p = p * (1+dtemp)^(equations.gamma/(equations.gamma-1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + + cent = x - cent # distance to center point + + #cent=cross(iniaxis,cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -84,24 +83,23 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, dt=1e-3, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, dt = 1e-3, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_amr.jl b/examples/tree_3d_dgsem/elixir_advection_amr.jl index 67664eed56..19a9bd18a8 100644 --- a/examples/tree_3d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_amr.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,26 +28,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -61,7 +59,7 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_advection_basic.jl b/examples/tree_3d_dgsem/elixir_advection_basic.jl index da91a70fe6..3ea50423be 100644 --- a/examples/tree_3d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_3d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl index 0fab685b64..6a8f8d0259 100644 --- a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -11,27 +11,28 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) diffusivity() = 5.0e-4 equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=80_000) + initial_refinement_level = 4, + n_cells_max = 80_000) # Define initial condition -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation3D) - # Store translated coordinate for easy use of exact solution - x_trans = x - equation.advection_velocity * t - - nu = diffusivity() - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) - return SVector(scalar) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation3D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) end initial_condition = initial_condition_diffusive_convergence_test @@ -43,9 +44,8 @@ boundary_conditions_parabolic = boundary_condition_periodic semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -56,26 +56,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=3, - med_level=4, med_threshold=1.2, - max_level=5, max_threshold=1.45) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 3, + med_level = 4, med_threshold = 1.2, + max_level = 5, max_threshold = 1.45) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -87,7 +87,7 @@ callbacks = CallbackSet(summary_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 \ No newline at end of file +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_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl index 5dc6e6338a..4c30406680 100644 --- a/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -10,16 +10,16 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -0.5, -0.25) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 0.0, 0.5, 0.25) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (0.0, 0.5, 0.25) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Example setup taken from # - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). @@ -28,24 +28,24 @@ mesh = TreeMesh(coordinates_min, coordinates_max, # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_eriksson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_eriksson_johnson boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), - y_neg = BoundaryConditionDirichlet(initial_condition), - z_neg = boundary_condition_do_nothing, - y_pos = BoundaryConditionDirichlet(initial_condition), - x_pos = boundary_condition_do_nothing, - z_pos = boundary_condition_do_nothing) + y_neg = BoundaryConditionDirichlet(initial_condition), + z_neg = boundary_condition_do_nothing, + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing, + z_pos = boundary_condition_do_nothing) boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) @@ -53,9 +53,8 @@ boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -70,22 +69,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_extended.jl b/examples/tree_3d_dgsem/elixir_advection_extended.jl index d820f47f25..efc20c64f6 100644 --- a/examples/tree_3d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_3d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -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); +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); # Print the timer summary summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_mortar.jl b/examples/tree_3d_dgsem/elixir_advection_mortar.jl index 7b24f152b6..d27a19c7dc 100644 --- a/examples/tree_3d_dgsem/elixir_advection_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_advection_mortar.jl @@ -9,23 +9,21 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -1.0, -1.0), coordinates_max=(1.0, 1.0, 1.0)), - (type="box", coordinates_min=(0.0, -0.5, -0.5), coordinates_max=(0.5, 0.5, 0.5)), -) +coordinates_max = (1.0, 1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -1.0, -1.0), + coordinates_max = (1.0, 1.0, 1.0)), + (type = "box", coordinates_min = (0.0, -0.5, -0.5), + coordinates_max = (0.5, 0.5, 0.5))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000,) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -35,17 +33,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -53,11 +51,10 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_advection_restart.jl b/examples/tree_3d_dgsem/elixir_advection_restart.jl index b7835ed061..f81e013fc0 100644 --- a/examples/tree_3d_dgsem/elixir_advection_restart.jl +++ b/examples/tree_3d_dgsem/elixir_advection_restart.jl @@ -7,7 +7,6 @@ using Trixi trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl")) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -26,14 +25,13 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) - ############################################################################### # run the simulation diff --git a/examples/tree_3d_dgsem/elixir_euler_amr.jl b/examples/tree_3d_dgsem/elixir_euler_amr.jl index f226a6b446..9bd7f74c68 100644 --- a/examples/tree_3d_dgsem/elixir_euler_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_amr.jl @@ -14,30 +14,28 @@ A Gaussian pulse in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. """ function initial_condition_density_pulse(x, t, equations::CompressibleEulerEquations3D) - rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2))/2 - v1 = 1 - v2 = 1 - v3 = 1 - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - p = 1 - rho_e = p/(equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2 + v3^2) - return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) + rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2)) / 2 + v1 = 1 + v2 = 1 + v3 = 1 + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + p = 1 + rho_e = p / (equations.gamma - 1) + 1 / 2 * rho * (v1^2 + v2^2 + v3^2) + return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) end initial_condition = initial_condition_density_pulse -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -47,40 +45,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=1.05, - max_level=6, max_threshold=1.3) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 1.05, + max_level = 6, max_threshold = 1.3) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_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); +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_3d_dgsem/elixir_euler_blob_amr.jl b/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl index a8d112f5b0..0ce886620c 100644 --- a/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations3D(gamma) """ @@ -16,63 +16,65 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations3D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^3, 256^3 - # domain size is [-20.0,20.0]^3 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - rho = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh / 1.6 # crushing time - # determine background velocity - v1 = 2 * R * sqrt(Chi) / tau_cr - v2 = 0.0 - v3 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = v1 / Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p = c * c * rho / equations.gamma - # initial center of the blob - inicenter = [-15, 0, 0] - x_rel = x - inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2 + x_rel[3]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - rho = rho + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope *(r - R)) + 1))) - # velocity blob is zero - v1 = v1 - v1 * 0.5 * (1 + (tanh(slope *(r + R)) - (tanh(slope *(r - R)) + 1))) - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^3, 256^3 + # domain size is [-20.0,20.0]^3 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + rho = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + v1 = 2 * R * sqrt(Chi) / tau_cr + v2 = 0.0 + v3 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = v1 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p = c * c * rho / equations.gamma + # initial center of the blob + inicenter = [-15, 0, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2 + x_rel[3]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + rho = rho + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + v1 = v1 - v1 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_blob volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-20.0, -20.0, -20.0) -coordinates_max = ( 20.0, 20.0, 20.0) - -refinement_patches = ( - (type="box", coordinates_min=(-20.0, -10.0, -10.0), coordinates_max=(-10.0, 10.0, 10.0)), - (type="box", coordinates_min=(-20.0, -5.0, -5.0), coordinates_max=(-10.0, 5.0, 5.0)), - (type="box", coordinates_min=(-17.0, -2.0, -2.0), coordinates_max=(-13.0, 2.0, 2.0)), - (type="box", coordinates_min=(-17.0, -2.0, -2.0), coordinates_max=(-13.0, 2.0, 2.0)), -) +coordinates_max = (20.0, 20.0, 20.0) + +refinement_patches = ((type = "box", coordinates_min = (-20.0, -10.0, -10.0), + coordinates_max = (-10.0, 10.0, 10.0)), + (type = "box", coordinates_min = (-20.0, -5.0, -5.0), + coordinates_max = (-10.0, 5.0, 5.0)), + (type = "box", coordinates_min = (-17.0, -2.0, -2.0), + coordinates_max = (-13.0, 2.0, 2.0)), + (type = "box", coordinates_min = (-17.0, -2.0, -2.0), + coordinates_max = (-13.0, 2.0, 2.0))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=100_000,) + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -82,41 +84,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=Trixi.density) + variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 1, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=3, - adapt_initial_condition=false, - adapt_initial_condition_only_refine=true) + interval = 3, + adapt_initial_condition = false, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.7) +stepsize_callback = StepsizeCallback(cfl = 1.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(1.0e-4, 1.0e-4), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (1.0e-4, 1.0e-4), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, 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_3d_dgsem/elixir_euler_convergence.jl b/examples/tree_3d_dgsem/elixir_euler_convergence.jl index 2eeb280ae1..170b292a42 100644 --- a/examples/tree_3d_dgsem/elixir_euler_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_euler_convergence.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(2.0) initial_condition = initial_condition_eoc_test_coupled_euler_gravity -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_eoc_test_euler) - + source_terms = source_terms_eoc_test_euler) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) 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); +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_3d_dgsem/elixir_euler_convergence_pure_fv.jl b/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl index dbf5747784..4789b46dac 100644 --- a/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralPureLGLFiniteVolume(flux_hllc)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc)) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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_3d_dgsem/elixir_euler_density_pulse.jl b/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl index ee788321c6..cad8fc578c 100644 --- a/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl +++ b/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl @@ -14,33 +14,31 @@ A Gaussian pulse in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. """ function initial_condition_density_pulse(x, t, equations::CompressibleEulerEquations3D) - rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2))/2 - v1 = 1 - v2 = 1 - v3 = 1 - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - p = 1 - rho_e = p/(equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2 + v3^2) - return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) + rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2)) / 2 + v1 = 1 + v2 = 1 + v3 = 1 + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + p = 1 + rho_e = p / (equations.gamma - 1) + 1 / 2 * rho * (v1^2 + v2^2 + v3^2) + return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) end initial_condition = initial_condition_density_pulse volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,30 +48,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, 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); +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_3d_dgsem/elixir_euler_ec.jl b/examples/tree_3d_dgsem/elixir_euler_ec.jl index 08fd1b998d..88d7cbc7ba 100644 --- a/examples/tree_3d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_3d_dgsem/elixir_euler_ec.jl @@ -10,19 +10,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) 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); +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_3d_dgsem/elixir_euler_mortar.jl b/examples/tree_3d_dgsem/elixir_euler_mortar.jl index c9fc2dfed5..cf103dc26c 100644 --- a/examples/tree_3d_dgsem/elixir_euler_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_euler_mortar.jl @@ -8,22 +8,19 @@ using Trixi equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) -refinement_patches = ( - (type="box", coordinates_min=(0.5, 0.5, 0.5), coordinates_max=(1.5, 1.5, 1.5)), -) +refinement_patches = ((type = "box", coordinates_min = (0.5, 0.5, 0.5), + coordinates_max = (1.5, 1.5, 1.5)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +31,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +50,7 @@ callbacks = CallbackSet(summary_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); +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_3d_dgsem/elixir_euler_sedov_blast_wave.jl b/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl index 3641878149..87774ada26 100644 --- a/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -19,34 +19,34 @@ based on Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ function initial_condition_sedov_self_gravity(x, t, equations::CompressibleEulerEquations3D) - # Calculate radius as distance from origin - r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.25 # = 4.0 * smallest dx (for domain length=8 and max-ref=7) - E = 1.0 - p_inner = (equations.gamma - 1) * E / (4/3 * pi * r0^3) - p_ambient = 1e-5 # = true Sedov setup - - # Calculate primitive variables - # use a logistic function to transfer density value smoothly - L = 1.0 # maximum of function - x0 = 1.0 # center point of function - k = -50.0 # sharpness of transfer - logistic_function_rho = L/(1.0 + exp(-k*(r - x0))) - rho_ambient = 1e-5 - rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny - - # velocities are zero - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - - # use a logistic function to transfer pressure value smoothly - logistic_function_p = p_inner/(1.0 + exp(-k*(r - r0))) - p = max(logistic_function_p, p_ambient) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Calculate radius as distance from origin + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.25 # = 4.0 * smallest dx (for domain length=8 and max-ref=7) + E = 1.0 + p_inner = (equations.gamma - 1) * E / (4 / 3 * pi * r0^3) + p_ambient = 1e-5 # = true Sedov setup + + # Calculate primitive variables + # use a logistic function to transfer density value smoothly + L = 1.0 # maximum of function + x0 = 1.0 # center point of function + k = -50.0 # sharpness of transfer + logistic_function_rho = L / (1.0 + exp(-k * (r - x0))) + rho_ambient = 1e-5 + rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny + + # velocities are zero + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + + # use a logistic function to transfer pressure value smoothly + logistic_function_p = p_inner / (1.0 + exp(-k * (r - r0))) + p = max(logistic_function_p, p_ambient) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_sedov_self_gravity @@ -64,26 +64,26 @@ based on Should be used together with [`initial_condition_sedov_self_gravity`](@ref). """ function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, - surface_flux_function, - equations::CompressibleEulerEquations3D) - # velocities are zero, density/pressure are ambient values according to - # initial_condition_sedov_self_gravity - rho = 1e-5 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = 1e-5 - - u_boundary = prim2cons(SVector(rho, v1, v2, v3, p), equations) - - # 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 + surface_flux_function, + equations::CompressibleEulerEquations3D) + # velocities are zero, density/pressure are ambient values according to + # initial_condition_sedov_self_gravity + rho = 1e-5 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = 1e-5 + + u_boundary = prim2cons(SVector(rho, v1, v2, v3, p), equations) + + # 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 boundary_conditions = boundary_condition_sedov_self_gravity @@ -92,26 +92,24 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.7, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.7, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-4.0, -4.0, -4.0) -coordinates_max = ( 4.0, 4.0, 4.0) +coordinates_max = (4.0, 4.0, 4.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=1_000_000, - periodicity=false) - + initial_refinement_level = 2, + n_cells_max = 1_000_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -122,42 +120,41 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.0, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =7, max_threshold=0.0003) + base_level = 2, + max_level = 7, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.35) +stepsize_callback = StepsizeCallback(cfl = 0.35) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_3d_dgsem/elixir_euler_shockcapturing.jl b/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl index 3015f6c50a..0a90615016 100644 --- a/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl @@ -10,30 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_ranocha # OBS! Using a non-dissipative flux is only sensible to test EC, - # but not for real shock simulations +# but not for real shock simulations volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -43,27 +41,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) 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); +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_3d_dgsem/elixir_euler_shockcapturing_amr.jl b/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl index 3d338cd7f0..be31fbbc42 100644 --- a/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl @@ -10,30 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_ranocha # OBS! Using a non-dissipative flux is only sensible to test EC, - # but not for real shock simulations +# but not for real shock simulations volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -43,41 +41,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_smooth=false, - variable=density_pressure) + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =4, max_threshold=0.0003) + base_level = 2, + max_level = 4, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_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); +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_3d_dgsem/elixir_euler_source_terms.jl b/examples/tree_3d_dgsem/elixir_euler_source_terms.jl index 3445e9fc43..f0246c3049 100644 --- a/examples/tree_3d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_3d_dgsem/elixir_euler_source_terms.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) 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); +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_3d_dgsem/elixir_euler_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl index 693f9ce904..135ee673e4 100644 --- a/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl @@ -12,35 +12,37 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,27 +52,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) 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); +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_3d_dgsem/elixir_eulergravity_convergence.jl b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl index 6699ec9a4d..21ef661d0b 100644 --- a/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl @@ -15,12 +15,12 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -28,22 +28,21 @@ equations_gravity = HyperbolicDiffusionEquations3D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 - gravitational_constant=1.0, # aka G - cfl=1.5, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 + gravitational_constant = 1.0, # aka G + cfl = 1.5, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -52,20 +51,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -74,11 +73,10 @@ callbacks = CallbackSet(summary_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); +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 println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl b/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl index c7744ce23b..7bba154a92 100644 --- a/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl +++ b/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl @@ -8,53 +8,52 @@ using Trixi equations = HyperbolicDiffusionEquations3D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations3D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - q3 = 0.0 - else - phi = sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) - q1 = 2 * pi * cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) - q2 = 2 * pi * sin(2 * pi * x[1]) * cos(2 * pi * x[2]) * sin(2 * pi * x[3]) - q3 = 2 * pi * sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * x[3]) - end - return SVector(phi, q1, q2, q3) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + q3 = 0.0 + else + phi = sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) + q1 = 2 * pi * cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) + q2 = 2 * pi * sin(2 * pi * x[1]) * cos(2 * pi * x[2]) * sin(2 * pi * x[3]) + q3 = 2 * pi * sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * x[3]) + end + return SVector(phi, q1, q2, q3) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations3D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -12 * equations.nu * pi^2 - - x1, x2, x3 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - tmp3 = sinpi(2 * x3) - du1 = -C*tmp1*tmp2*tmp3 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - du4 = -inv_Tr * u[4] - - return SVector(du1, du2, du3, du4) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations3D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -12 * equations.nu * pi^2 + + x1, x2, x3 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + tmp3 = sinpi(2 * x3) + du1 = -C * tmp1 * tmp2 * tmp3 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + du4 = -inv_Tr * u[4] + + return SVector(du1, du2, du3, du4) end -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -65,20 +64,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.4) +stepsize_callback = StepsizeCallback(cfl = 2.4) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, @@ -89,6 +88,6 @@ callbacks = CallbackSet(summary_callback, steady_state_callback, # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_3d_dgsem/elixir_hypdiff_nonperiodic.jl b/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl index beefb22ea1..831e01519b 100644 --- a/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -8,27 +8,25 @@ using Trixi equations = HyperbolicDiffusionEquations3D() initial_condition = initial_condition_poisson_nonperiodic -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - z_neg=boundary_condition_periodic, - z_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=(false, true, true)) - + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = (false, true, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -39,31 +37,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 1.0e-5 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.8) +stepsize_callback = StepsizeCallback(cfl = 1.8) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + 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_3d_dgsem/elixir_lbm_constant.jl b/examples/tree_3d_dgsem/elixir_lbm_constant.jl index 269a0da2d5..ee38f62887 100644 --- a/examples/tree_3d_dgsem/elixir_lbm_constant.jl +++ b/examples/tree_3d_dgsem/elixir_lbm_constant.jl @@ -5,22 +5,20 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D3Q27 scheme -equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=Inf) +equations = LatticeBoltzmannEquations3D(Ma = 0.1, Re = Inf) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000,) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,19 +28,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -52,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_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); +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_3d_dgsem/elixir_lbm_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl index b3835eb128..0980ee56be 100644 --- a/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the Lattice-Boltzmann equations for the D3Q27 scheme L = 1.0 # reference length -equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=1600.0; L=L) +equations = LatticeBoltzmannEquations3D(Ma = 0.1, Re = 1600.0; L = L) """ initial_condition_taylor_green_vortex(x, t, equations::LatticeBoltzmannEquations3D) @@ -14,52 +14,51 @@ equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=1600.0; L=L) Initialize the flow field to the Taylor-Green vortex setup """ function initial_condition_taylor_green_vortex(x, t, equations::LatticeBoltzmannEquations3D) - @unpack u0, rho0, L = equations + @unpack u0, rho0, L = equations - v1 = u0 * sin(x[1] / L) * cos(x[2] / L) * cos(x[3] / L) - v2 = -u0 * cos(x[1] / L) * sin(x[2] / L) * cos(x[3] / L) - v3 = 0 - p0 = (pressure(rho0, equations) + - rho0 * u0^2 / 16 * (cos(2 * x[1] / L) + cos(2 * x[2] / L)) * (cos(2 * x[3] / L) + 2)) - rho = density(p0, equations) + v1 = u0 * sin(x[1] / L) * cos(x[2] / L) * cos(x[3] / L) + v2 = -u0 * cos(x[1] / L) * sin(x[2] / L) * cos(x[3] / L) + v3 = 0 + p0 = (pressure(rho0, equations) + + rho0 * u0^2 / 16 * (cos(2 * x[1] / L) + cos(2 * x[2] / L)) * + (cos(2 * x[3] / L) + 2)) + rho = density(p0, equations) - return equilibrium_distribution(rho, v1, v2, v3, equations) + return equilibrium_distribution(rho, v1, v2, v3, equations) end initial_condition = initial_condition_taylor_green_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) -coordinates_min = (-pi*L, -pi*L, -pi*L) -coordinates_max = ( pi*L, pi*L, pi*L) +coordinates_min = (-pi * L, -pi * L, -pi * L) +coordinates_max = (pi * L, pi * L, pi * L) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=300_000,) - + initial_refinement_level = 5, + n_cells_max = 300_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 20*equations.L/equations.u0) # Final time is `20` in non-dimensional time +tspan = (0.0, 20 * equations.L / equations.u0) # Final time is `20` in non-dimensional time ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 20 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(Trixi.energy_kinetic_nondimensional,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (Trixi.energy_kinetic_nondimensional,)) -alive_callback = AliveCallback(analysis_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=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=0.3) +stepsize_callback = StepsizeCallback(cfl = 0.3) collision_callback = LBMCollisionCallback() @@ -69,12 +68,11 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_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, - save_start=false, alias_u0=true); +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, + save_start = false, alias_u0 = true); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl index 191982bf2d..9aab5e5878 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,24 +5,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,18 +31,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -51,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl index e23f7ce546..3ce166a7fa 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl @@ -5,24 +5,22 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(-0.5, -0.5, -0.5), - coordinates_max=( 0.5, 0.5, 0.5)), -) +coordinates_max = (1.0, 1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (-0.5, -0.5, -0.5), + coordinates_max = (0.5, 0.5, 0.5)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000) + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -35,18 +33,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -54,11 +52,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_mhd_ec.jl b/examples/tree_3d_dgsem/elixir_mhd_ec.jl index 057ffcb031..1f0088e82c 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,18 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,19 +31,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -52,11 +51,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_mhd_ec_shockcapturing.jl b/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl index 6b4f6e310c..f8a72b6f45 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -10,25 +10,26 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -42,25 +43,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, glm_speed_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); +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_3d_dgsem/elixir_navierstokes_convergence.jl b/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl index ebb0137a1b..3ada9503c6 100644 --- a/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl @@ -8,213 +8,215 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=(true, false, true), - n_cells_max=50_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = (true, false, true), + n_cells_max = 50_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test @@ -222,30 +224,33 @@ initial_condition = initial_condition_navier_stokes_convergence_test # BC types velocity_bc_top_bottom = NoSlip() do x, t, equations u = initial_condition_navier_stokes_convergence_test(x, t, equations) - return SVector(u[2], u[3], u[4]) + return SVector(u[2], u[3], u[4]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_slip_wall, - y_pos = boundary_condition_slip_wall, - z_neg = boundary_condition_periodic, - z_pos = boundary_condition_periodic) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_top_bottom, - y_pos = boundary_condition_top_bottom, - z_neg = boundary_condition_periodic, - z_pos = boundary_condition_periodic) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_top_bottom, + y_pos = boundary_condition_top_bottom, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -255,16 +260,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index 5556831a59..65bd9aa133 100644 --- a/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,8 +10,8 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) @@ -22,31 +22,34 @@ The classical viscous Taylor-Green vortex, as found for instance in Simulation of the Compressible Taylor Green Vortex using High-Order Flux Reconstruction Schemes [DOI: 10.2514/6.2014-3210](https://doi.org/10.2514/6.2014-3210) """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -60,12 +63,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -75,6 +79,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_3d_fdsbp/elixir_advection_extended.jl b/examples/tree_3d_fdsbp/elixir_advection_extended.jl index 241e069864..22085a6351 100644 --- a/examples/tree_3d_fdsbp/elixir_advection_extended.jl +++ b/examples/tree_3d_fdsbp/elixir_advection_extended.jl @@ -13,22 +13,21 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=10) + derivative_order = 1, accuracy_order = 4, + xmin = 0.0, xmax = 1.0, N = 10) solver = FDSBP(D_SBP, - surface_integral=SurfaceIntegralStrongForm(flux_lax_friedrichs), - volume_integral=VolumeIntegralStrongForm()) + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 1, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,19 +37,18 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_3d_fdsbp/elixir_euler_convergence.jl b/examples/tree_3d_fdsbp/elixir_euler_convergence.jl index 6aafa1b5cc..aa5b231ee1 100644 --- a/examples/tree_3d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_3d_fdsbp/elixir_euler_convergence.jl @@ -11,24 +11,23 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -39,27 +38,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_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) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) 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); +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_3d_fdsbp/elixir_euler_taylor_green_vortex.jl b/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl index d2495cff5c..0354200ae4 100644 --- a/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl +++ b/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl @@ -14,40 +14,43 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=100_000) + initial_refinement_level = 2, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -57,28 +60,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, - energy_kinetic, - energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl index 2f8228dffb..8f8e867dca 100644 --- a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl +++ b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl @@ -6,16 +6,18 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.0, -0.5), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.0, -0.5), + c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 4 and (local) Lax-Friedrichs/Rusanov flux -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Create unstructured quadrilateral mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_five_circles_in_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -27,27 +29,26 @@ A Gaussian pulse, used in the `gauss_wall` example elixir in combination with [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. """ function initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) + prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_gauss_wall -boundary_conditions = Dict( :OuterCircle => boundary_condition_slip_wall, - :InnerCircle1 => boundary_condition_slip_wall, - :InnerCircle2 => boundary_condition_slip_wall, - :InnerCircle3 => boundary_condition_slip_wall, - :InnerCircle4 => boundary_condition_slip_wall, - :InnerCircle5 => boundary_condition_slip_wall ) +boundary_conditions = Dict(:OuterCircle => boundary_condition_slip_wall, + :InnerCircle1 => boundary_condition_slip_wall, + :InnerCircle2 => boundary_condition_slip_wall, + :InnerCircle3 => boundary_condition_slip_wall, + :InnerCircle4 => boundary_condition_slip_wall, + :InnerCircle5 => boundary_condition_slip_wall) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -61,10 +62,10 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=50, solution_variables=cons2state) +save_solution = SaveSolutionCallback(interval = 50, solution_variables = cons2state) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, save_solution) @@ -73,7 +74,7 @@ callbacks = CallbackSet(summary_callback, analysis_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-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl index 274978d48b..afef6c2c38 100644 --- a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl @@ -12,22 +12,24 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 6, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -40,22 +42,23 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_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); +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_euler_basic.jl b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl index 9fbea47a9d..cd6a199575 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl @@ -12,23 +12,24 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Slant => boundary_condition_convergence_test, - :Bezier => boundary_condition_convergence_test, - :Right => boundary_condition_convergence_test, - :Bottom => boundary_condition_convergence_test, - :Top => boundary_condition_convergence_test ) +boundary_conditions = Dict(:Slant => boundary_condition_convergence_test, + :Bezier => boundary_condition_convergence_test, + :Right => boundary_condition_convergence_test, + :Bottom => boundary_condition_convergence_test, + :Top => boundary_condition_convergence_test) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=8, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 8, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -37,8 +38,8 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -49,18 +50,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=50, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 50, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -72,7 +73,7 @@ callbacks = CallbackSet(summary_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); +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_euler_ec.jl b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl index 2725142fd1..0f53aa62a1 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl @@ -6,7 +6,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations2D(5/3) +equations = CompressibleEulerEquations2D(5 / 3) initial_condition = initial_condition_weak_blast_wave @@ -14,18 +14,19 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=6, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object @@ -41,15 +42,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -60,7 +61,7 @@ callbacks = CallbackSet(summary_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); +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_euler_free_stream.jl b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl index 36e119ab79..a2fec1a320 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl @@ -11,25 +11,26 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant boundary_condition_free_stream = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Body => boundary_condition_free_stream, - :Button1 => boundary_condition_free_stream, - :Button2 => boundary_condition_free_stream, - :Eye1 => boundary_condition_free_stream, - :Eye2 => boundary_condition_free_stream, - :Smile => boundary_condition_free_stream, - :Bowtie => boundary_condition_free_stream ) +boundary_conditions = Dict(:Body => boundary_condition_free_stream, + :Button1 => boundary_condition_free_stream, + :Button2 => boundary_condition_free_stream, + :Eye1 => boundary_condition_free_stream, + :Eye2 => boundary_condition_free_stream, + :Smile => boundary_condition_free_stream, + :Bowtie => boundary_condition_free_stream) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=flux_hll) +solver = DGSEM(polydeg = 6, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_gingerbread_man.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -38,7 +39,7 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -49,15 +50,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -65,7 +66,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_euler_periodic.jl b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl index 796c99987a..afd177f074 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl @@ -15,24 +15,25 @@ boundary_conditions = boundary_condition_periodic ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=FluxRotated(flux_hll)) +solver = DGSEM(polydeg = 6, surface_flux = FluxRotated(flux_hll)) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -43,14 +44,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_restart.jl b/examples/unstructured_2d_dgsem/elixir_euler_restart.jl index 6653f8662d..4d6af65b8a 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_restart.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_restart.jl @@ -7,7 +7,6 @@ using Trixi trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_basic.jl")) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,8 +17,8 @@ restart_filename = joinpath("out", "restart_000050.h5") mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) tspan = (load_time(restart_filename), 1.0) dt = load_dt(restart_filename) @@ -28,17 +27,15 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Get the last time index and work with that. load_timestep!(integrator, restart_filename) - ############################################################################### # run the simulation sol = solve!(integrator) summary_callback() # print the timer summary - diff --git a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl index 570a208469..e1cc093296 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,23 +43,25 @@ volume_flux = flux_ranocha polydeg = 6 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # create the semidiscretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -73,15 +75,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -92,7 +94,7 @@ callbacks = CallbackSet(summary_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); +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_euler_wall_bc.jl b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl index 5bfe1ae4e0..b2abefe7ee 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl @@ -10,40 +10,41 @@ equations = CompressibleEulerEquations2D(1.4) @inline function uniform_flow_state(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.0 - u_freestream = 0.3 - p_freestream = inv(equations.gamma) - - theta = pi / 90.0 # analogous with a two degree angle of attack - si, co = sincos(theta) - v1 = u_freestream * co - v2 = u_freestream * si - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.0 + u_freestream = 0.3 + p_freestream = inv(equations.gamma) + + theta = pi / 90.0 # analogous with a two degree angle of attack + si, co = sincos(theta) + v1 = u_freestream * co + v2 = u_freestream * si + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = uniform_flow_state boundary_condition_uniform_flow = BoundaryConditionDirichlet(uniform_flow_state) -boundary_conditions = Dict( :Bottom => boundary_condition_uniform_flow, - :Top => boundary_condition_uniform_flow, - :Right => boundary_condition_uniform_flow, - :Left => boundary_condition_uniform_flow, - :Circle => boundary_condition_slip_wall ) +boundary_conditions = Dict(:Bottom => boundary_condition_uniform_flow, + :Top => boundary_condition_uniform_flow, + :Right => boundary_condition_uniform_flow, + :Left => boundary_condition_uniform_flow, + :Circle => boundary_condition_slip_wall) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=4, surface_flux=flux_hll) +solver = DGSEM(polydeg = 4, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_box_around_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -52,7 +53,7 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -63,22 +64,23 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) +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); +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_mhd_alfven_wave.jl b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl index 6b31776b29..fdafed98c8 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,22 +5,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=7, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 7, surface_flux = (flux_hll, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # 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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -33,21 +34,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 0.9 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -56,11 +60,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_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); +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_mhd_ec.jl b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl index d75079bb8d..a40f92cac0 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl @@ -6,40 +6,42 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations2D(5/3) +equations = IdealGlmMhdEquations2D(5 / 3) function initial_condition_shifted_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) - # Shift blastwave to center of domain - inicenter = (sqrt(2)/2, sqrt(2)/2) - 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) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) - v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) - p = r > 0.5 ? 1.0 : 1.245 - - return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) + # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) + # Shift blastwave to center of domain + inicenter = (sqrt(2) / 2, sqrt(2) / 2) + 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) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) + p = r > 0.5 ? 1.0 : 1.245 + + return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) end initial_condition = initial_condition_shifted_weak_blast_wave # Get the DG approximation space volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=6, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # 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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -53,21 +55,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -79,7 +84,7 @@ callbacks = CallbackSet(summary_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); +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 index 044b2549b0..1148f25fae 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl @@ -7,47 +7,48 @@ using Trixi # semidiscretization of the shallow water equations with a continuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=1.0, H0=3.0) +equations = ShallowWaterEquations2D(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::ShallowWaterEquations2D) - # 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) + # 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 ) +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)) +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) +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) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks, etc. @@ -58,15 +59,15 @@ 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,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -74,6 +75,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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 index 138b256c08..8e9d396d82 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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. @@ -17,19 +17,21 @@ 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)) +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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -49,45 +51,48 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -96,15 +101,15 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -112,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_ec_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl index ee3650f3bb..94202b81df 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(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. @@ -17,17 +17,17 @@ 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) +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) ############################################################################### @@ -35,11 +35,12 @@ solver = DGSEM(basis, surface_flux, volume_integral) # 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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -59,45 +60,48 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -106,11 +110,11 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) @@ -118,7 +122,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_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); +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 index e0b64802ff..0766868840 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a periodic # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -16,23 +16,24 @@ initial_condition = initial_condition_convergence_test 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)) +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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,15 +44,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -59,7 +60,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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 index 65b0fcae46..6164f9d4a5 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl @@ -8,10 +8,8 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.875, - threshold_limiter=1e-12, threshold_wet=1e-14) - +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.875, + threshold_limiter = 1e-12, threshold_wet = 1e-14) """ initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) @@ -28,66 +26,68 @@ The initial conditions is taken from Section 6.3 of the paper: """ function initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) - # Set the background values - v1 = 0.0 - v2 = 0.0 + # 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 ) + 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) + 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 + # 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)))) + H = max(b, L / (1.0 + exp(-k * (x1 - x0)))) - # Avoid division by zero by adjusting the initial condition with a small dry state threshold - # that defaults to 500*eps() ≈ 1e-13 in double precision and is set in the constructor above - # for the ShallowWaterEquations struct. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # Avoid division by zero by adjusting the initial condition with a small dry state threshold + # that defaults to 500*eps() ≈ 1e-13 in double precision and is set in the constructor above + # for the ShallowWaterEquations struct. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_three_mounds function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::ShallowWaterEquations2D) - # Impulse and bottom from inside, height from external state - u_outer = SVector(equations.threshold_wet, u_inner[2], u_inner[3], u_inner[4]) + surface_flux_function, + equations::ShallowWaterEquations2D) + # Impulse and bottom from inside, height from external state + u_outer = SVector(equations.threshold_wet, u_inner[2], u_inner[3], u_inner[4]) - # calculate the boundary flux - flux = surface_flux_function(u_inner, u_outer, normal_direction, equations) + # calculate the boundary flux + flux = surface_flux_function(u_inner, u_outer, normal_direction, equations) - return flux + 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 ) +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), +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -96,8 +96,9 @@ solver = DGSEM(basis, surface_flux, volume_integral) 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) +isfile(default_meshfile) || + download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", + default_meshfile) meshfile = default_meshfile @@ -105,7 +106,7 @@ mesh = UnstructuredMesh2D(meshfile) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solver @@ -119,21 +120,21 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +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,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl index d9e71e4aa4..2cab68b1cb 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -7,7 +7,8 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a periodic # bottom topography function (set in the initial conditions) -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test @@ -16,23 +17,24 @@ initial_condition = initial_condition_convergence_test 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)) +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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semidiscretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,15 +45,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -59,7 +61,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl index 4295f93b34..9d70e9287c 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl @@ -7,62 +7,64 @@ using Trixi # Semidiscretization of the two-layer shallow water equations for a dam break test with a # discontinuous bottom topography function to test energy conservation -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=1.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, rho_upper = 0.9, + rho_lower = 1.0) # This test case uses a special work around to setup a truly discontinuous bottom topography # function and initial condition for this academic testcase of entropy conservation. First, a # dummy initial_condition_dam_break is introduced to create the semidiscretization. Then the initial # condition is reset with the true discontinuous values from initial_condition_discontinuous_dam_break. -function initial_condition_dam_break(x, t,equations::ShallowWaterTwoLayerEquations2D) - if x[1] < sqrt(2)/2 - H_upper = 1.0 - H_lower = 0.6 - b = 0.1 - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.0 - end - - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) +function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations2D) + if x[1] < sqrt(2) / 2 + H_upper = 1.0 + H_lower = 0.6 + b = 0.1 + else + H_upper = 0.9 + H_lower = 0.5 + b = 0.0 + end + + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_dam_break boundary_condition_constant = BoundaryConditionDirichlet(initial_condition_dam_break) - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux= (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the unstructured quad mesh from a file (downloads the file if not available locally) 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) +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=false) +mesh = UnstructuredMesh2D(mesh_file, periodicity = false) # Boundary conditions -boundary_condition = Dict(:Top => boundary_condition_slip_wall, - :Left => boundary_condition_slip_wall, - :Right => boundary_condition_slip_wall, +boundary_condition = Dict(:Top => boundary_condition_slip_wall, + :Left => boundary_condition_slip_wall, + :Right => boundary_condition_slip_wall, :Bottom => boundary_condition_slip_wall) # Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, - solver, boundary_conditions=boundary_condition) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver, boundary_conditions = boundary_condition) ############################################################################### # ODE solver @@ -79,58 +81,63 @@ ode = semidiscretize(semi, tspan) # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_discontinuous_dam_break(x, t, element_id, +function initial_condition_discontinuous_dam_break(x, t, element_id, equations::ShallowWaterTwoLayerEquations2D) - # Constant values - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Left side of discontinuity - IDs = [1, 2, 5, 6, 9, 10, 13, 14] - if element_id in IDs - H_upper = 1.0 - H_lower = 0.6 - b = 0.0 - # Right side of discontinuity - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.1 - end - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + # Constant values + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + + # Left side of discontinuity + IDs = [1, 2, 5, 6, 9, 10, 13, 14] + if element_id in IDs + H_upper = 1.0 + H_lower = 0.6 + b = 0.0 + # Right side of discontinuity + else + H_upper = 0.9 + H_lower = 0.5 + b = 0.1 + end + + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_dam_break(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_dam_break(x_node, first(tspan), element, + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end - ############################################################################### # Callbacks summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval,save_analysis=false, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -138,7 +145,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index 40bc9f2ab4..35b027c3a8 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -7,22 +7,25 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a discontinuous bottom # topography to test well-balancedness -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=1.0, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) # An initial condition with constant total water height, zero velocities and a bottom topography to # test well-balancedness function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Bottom Topography - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + H_lower = 0.5 + H_upper = 0.6 + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + + # Bottom Topography + b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? + 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + + -0.5)^2)) + 1) : 0.0) + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_well_balanced @@ -32,19 +35,20 @@ initial_condition = initial_condition_well_balanced volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -58,16 +62,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -75,7 +79,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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_wall_bc_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl index 4700724c52..76b9642d59 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl @@ -7,63 +7,66 @@ using Trixi # semidiscretization of the shallow water equations with a continuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.812, H0=2.0) +equations = ShallowWaterEquations2D(gravity_constant = 9.812, H0 = 2.0) function initial_condition_stone_throw(x, t, equations::ShallowWaterEquations2D) - # 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) + # 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 ) +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) +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) + 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) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +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) +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) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks, etc. @@ -74,15 +77,16 @@ 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)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -90,6 +94,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # 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); +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/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl index 645f985d10..bf4d0be682 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -7,21 +7,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.0) +equations = ShallowWaterEquations2D(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::ShallowWaterEquations2D) - # 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) + # 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 @@ -30,20 +30,21 @@ 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)) +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) +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) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -64,30 +65,33 @@ ode = semidiscretize(semi, tspan) # 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::ShallowWaterEquations2D) - # 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) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # 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 + 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 ############################################################################### @@ -96,16 +100,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # 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); +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/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 0722e77d73..527bcb0750 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -118,8 +118,6 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - # TODO: Revise Bounds Check for MCL - @unpack output_directory = callback mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f @@ -128,7 +126,7 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi if limiter.PressurePositivityLimiterKuzmin print(f, ", pressure_min") end - # No check for entropy limiting rn + # TODO: Bounds check for entropy limiting println(f) end @@ -192,21 +190,23 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterMCL) - @unpack idp_bounds_delta = limiter.cache - - # TODO: Revise bounds check for MCL + @unpack mcl_bounds_delta = limiter.cache println("─"^100) println("Maximum deviation from bounds:") println("─"^100) variables = varnames(cons2cons, semi.equations) for v in eachvariable(semi.equations) - println(variables[v], ":\n- lower bound: ", idp_bounds_delta[1, v], - "\n- upper bound: ", idp_bounds_delta[2, v]) + println(variables[v], ":\n- lower bound: ", mcl_bounds_delta[2, 1, v], + "\n- upper bound: ", mcl_bounds_delta[2, 2, v]) end if limiter.PressurePositivityLimiterKuzmin - println("pressure:\n- lower bound: ", - idp_bounds_delta[1, nvariables(semi.equations) + 1]) + println("pressure:\n- positivity: ", + mcl_bounds_delta[2, 1, nvariables(semi.equations) + 1]) + end + if limiter.SemiDiscEntropyLimiter + # TODO: Bounds check for entropy limiting + println("\nWARNING: No bounds check for the entropy limiter.") end println("─"^100 * "\n") diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 963f9a938a..cf47c0fc53 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -131,24 +131,21 @@ end time, iter, output_directory, save_errors) (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states - (; idp_bounds_delta) = limiter.cache + (; mcl_bounds_delta) = limiter.cache (; antidiffusive_flux1_L, antidiffusive_flux2_L) = cache.antidiffusive_fluxes - # TODO: Revise Bounds Check for MCL - n_vars = nvariables(equations) - deviation_min = zeros(eltype(u), n_vars + limiter.PressurePositivityLimiterKuzmin) - deviation_max = zeros(eltype(u), n_vars) - if limiter.DensityLimiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], - var_min[1, i, j, element] - u[1, i, j, element]) - deviation_max[1] = max(deviation_max[1], - u[1, i, j, element] - var_max[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + var_min[1, i, j, element] - + u[1, i, j, element]) + mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], + u[1, i, j, element] - + var_max[1, i, j, element]) end end @@ -162,34 +159,34 @@ end rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], - var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + var_min[1, i, j, element] - rho_limited) + mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], + rho_limited - var_max[1, i, j, element]) # +x rho_limited = bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] - deviation_min[1] = max(deviation_min[1], - var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + var_min[1, i, j, element] - rho_limited) + mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], + rho_limited - var_max[1, i, j, element]) # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], - var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + var_min[1, i, j, element] - rho_limited) + mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], + rho_limited - var_max[1, i, j, element]) # +y rho_limited = bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] - deviation_min[1] = max(deviation_min[1], - var_min[1, i, j, element] - rho_limited) - deviation_max[1] = max(deviation_max[1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + var_min[1, i, j, element] - rho_limited) + mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], + rho_limited - var_max[1, i, j, element]) end end end # limiter.DensityLimiter @@ -200,17 +197,20 @@ end for j in eachnode(solver), i in eachnode(solver) for v in 2:n_vars var_limited = u[v, i, j, element] / u[1, i, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], - var_limited - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited - + var_max[v, i, j, element]) end if limiter.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) end end end @@ -221,8 +221,8 @@ end # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(mcl_bounds_delta)) + error_pressure = zero(eltype(mcl_bounds_delta)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) # -x @@ -233,21 +233,22 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # +x rho_limited = bar_states1[1, i + 1, j, element] + @@ -257,21 +258,22 @@ end var_limited = bar_states1[v, i + 1, j, element] + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # -y rho_limited = bar_states2[1, i, j, element] - @@ -281,21 +283,22 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # +y rho_limited = bar_states2[1, i, j + 1, element] + @@ -305,21 +308,22 @@ end var_limited = bar_states2[v, i, j + 1, element] + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - - var_limited / rho_limited) - deviation_max[v] = max(deviation_max[v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end end end @@ -328,19 +332,20 @@ end for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) for v in 2:n_vars - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - - u[v, i, j, element]) - deviation_max[v] = max(deviation_max[v], - u[v, i, j, element] - - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + u[v, i, j, element]) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + u[v, i, j, element] - + var_max[v, i, j, element]) end if limiter.PressurePositivityLimiterKuzmin error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) end end end @@ -351,8 +356,8 @@ end # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(idp_bounds_delta)) - error_pressure = zero(eltype(idp_bounds_delta)) + var_limited = zero(eltype(mcl_bounds_delta)) + error_pressure = zero(eltype(mcl_bounds_delta)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) # -x @@ -363,19 +368,22 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], - var_limited - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # +x rho_limited = bar_states1[1, i + 1, j, element] + @@ -385,19 +393,22 @@ end var_limited = bar_states1[v, i + 1, j, element] + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], - var_limited - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # -y rho_limited = bar_states2[1, i, j, element] - @@ -407,19 +418,22 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], - var_limited - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end # +y rho_limited = bar_states2[1, i, j + 1, element] + @@ -429,19 +443,22 @@ end var_limited = bar_states2[v, i, j + 1, element] + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] - deviation_min[v] = max(deviation_min[v], - var_min[v, i, j, element] - var_limited) - deviation_max[v] = max(deviation_max[v], - var_limited - var_max[v, i, j, element]) + mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], + var_limited - + var_max[v, i, j, element]) if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.PressurePositivityLimiterKuzmin error_pressure -= var_limited * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) - error_pressure = zero(eltype(idp_bounds_delta)) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta)) end end end @@ -451,8 +468,9 @@ end for j in eachnode(solver), i in eachnode(solver) error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) end end @@ -477,8 +495,9 @@ end (bar_states1[4, i, j, element] - antidiffusive_flux1_L[4, i, j, element] / lambda1[i, j, element]) * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) # +x rho_limited = bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / @@ -494,8 +513,9 @@ end (bar_states1[4, i + 1, j, element] + antidiffusive_flux1_L[4, i + 1, j, element] / lambda1[i + 1, j, element]) * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / @@ -511,8 +531,9 @@ end (bar_states2[4, i, j, element] - antidiffusive_flux2_L[4, i, j, element] / lambda2[i, j, element]) * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) # +y rho_limited = bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / @@ -528,8 +549,9 @@ end (bar_states2[4, i, j + 1, element] + antidiffusive_flux2_L[4, i, j + 1, element] / lambda2[i, j + 1, element]) * rho_limited - deviation_min[n_vars + 1] = max(deviation_min[n_vars + 1], - error_pressure) + mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, + n_vars + 1], + error_pressure) end end end # limiter.PressurePositivityLimiterKuzmin @@ -538,7 +560,8 @@ end # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) - deviation_min[1] = max(deviation_min[1], -u[1, i, j, element]) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], + -u[1, i, j, element]) end end @@ -553,33 +576,35 @@ end rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) # +x rho_limited = (1 - beta) * bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) # -y rho_limited = (1 - beta) * bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) # +y rho_limited = (1 - beta) * bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] - deviation_min[1] = max(deviation_min[1], -rho_limited) + mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) end end end # limiter.DensityPositivityLimiter for v in eachvariable(equations) - idp_bounds_delta[1, v] = max(idp_bounds_delta[1, v], deviation_min[v]) - idp_bounds_delta[2, v] = max(idp_bounds_delta[2, v], deviation_max[v]) + mcl_bounds_delta[2, 1, v] = max(mcl_bounds_delta[2, 1, v], + mcl_bounds_delta[1, 1, v]) + mcl_bounds_delta[2, 2, v] = max(mcl_bounds_delta[2, 2, v], + mcl_bounds_delta[1, 2, v]) end if limiter.PressurePositivityLimiterKuzmin - idp_bounds_delta[1, n_vars + 1] = max(idp_bounds_delta[1, n_vars + 1], - deviation_min[n_vars + 1]) + mcl_bounds_delta[2, 1, n_vars + 1] = max(mcl_bounds_delta[2, 1, n_vars + 1], + mcl_bounds_delta[1, 1, n_vars + 1]) end if !save_errors @@ -588,13 +613,20 @@ end open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) for v in eachvariable(equations) - print(f, ", ", deviation_min[v], ", ", deviation_max[v]) + print(f, ", ", mcl_bounds_delta[1, 1, v], ", ", mcl_bounds_delta[1, 2, v]) end if limiter.PressurePositivityLimiterKuzmin - print(f, ", ", deviation_min[n_vars + 1]) + print(f, ", ", mcl_bounds_delta[1, 1, n_vars + 1]) end println(f) end + for v in eachvariable(equations) + mcl_bounds_delta[1, 1, v] = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta[1, 2, v] = zero(eltype(mcl_bounds_delta)) + end + if limiter.PressurePositivityLimiterKuzmin + mcl_bounds_delta[1, 1, n_vars + 1] = zero(eltype(mcl_bounds_delta)) + end return nothing end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 1c27a5d5dc..c724ada504 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -725,9 +725,11 @@ function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquat nvariables(equations), nnodes(basis)) - idp_bounds_delta = zeros(real(basis), 2, + # Memory for bounds checking routine with `BoundsCheckCallback`. + # [maximum since the last export / total maximum, min / max, variable] + mcl_bounds_delta = zeros(real(basis), 2, 2, nvariables(equations) + PressurePositivityLimiterKuzmin) - return (; subcell_limiter_coefficients, container_bar_states, idp_bounds_delta) + return (; subcell_limiter_coefficients, container_bar_states, mcl_bounds_delta) end end # @muladd diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 9944e45e12..77df1ba45b 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -525,6 +525,32 @@ end end end +@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[ + 0.35267161504176747, + 0.17218309138797958, + 0.17218307467125854, + 0.6236143054619037, + ], + linf=[ + 2.77484045816607, + 1.8281111268370718, + 1.8281110470490887, + 6.24263735888126, + ], + tspan=(0.0, 0.5), + surface_flux=flux_hlle) + # 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_euler_sedov_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), @@ -554,6 +580,7 @@ end end @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin + rm("out/deviations.txt", force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_MCL.jl"), l2=[ 0.4740321851943766, @@ -570,6 +597,10 @@ end tspan=(0.0, 1.0), initial_refinement_level=4, coverage_override=(maxiters = 6,)) + lines = readlines("out/deviations.txt") + @test lines[1] == + "# iter, simu_time, rho_min, rho_max, rho_v1_min, rho_v1_max, rho_v2_min, rho_v2_max, rho_e_min, rho_e_max, pressure_min" + @test startswith(lines[end], "349") || startswith(lines[end], "1") # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From 94d8a3eb6d37cee703eca58f841c78bdcd753956 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 6 Nov 2023 15:42:15 +0100 Subject: [PATCH 349/423] Remove doubled tests --- test/test_tree_2d_euler.jl | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 77df1ba45b..aeaaa71110 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -611,31 +611,6 @@ end end end -@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2=[ - 0.35267161504176747, - 0.17218309138797958, - 0.17218307467125854, - 0.6236143054619037, - ], - linf=[ - 2.77484045816607, - 1.8281111268370718, - 1.8281110470490887, - 6.24263735888126, - ], - tspan=(0.0, 0.5), - surface_flux=flux_hlle) - # 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) - end -end - @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), From f6836b05c8c16945e4e7f4d2491a29aaee74ccd6 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 16:23:30 +0100 Subject: [PATCH 350/423] Pass variable as strings instead of indices --- ...elixir_euler_convergence_wavingflag_IDP.jl | 4 +- .../elixir_euler_double_mach.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 4 +- .../elixir_euler_shock_upstream_sc_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 2 +- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_convergence_IDP.jl | 4 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 4 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_shockcapturing_subcell.jl | 2 +- .../elixir_euler_source_terms_sc_subcell.jl | 6 +-- ...ck_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...ubble_shockcapturing_subcell_positivity.jl | 4 +- .../elixir_mhd_shockcapturing_subcell.jl | 2 +- src/solvers/dgsem_tree/subcell_limiters.jl | 40 ++++++++++++++----- 16 files changed, 53 insertions(+), 31 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index 57c2d2a780..e7435e4712 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -14,8 +14,8 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], - positivity_variables_nonlinear = (pressure,), + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, spec_entropy = false, max_iterations_newton = 10, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index d306b70cb7..c855f448fd 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -22,7 +22,7 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], spec_entropy = true, positivity_correction_factor = 0.1, max_iterations_newton = 100, diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 639fb92875..6f81e38574 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -14,8 +14,8 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], - positivity_variables_nonlinear = (pressure,), + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, spec_entropy = false, smoothness_indicator = false, diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index def69ecc28..303cfa71de 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -37,7 +37,7 @@ polydeg = 5 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], spec_entropy = true, max_iterations_newton = 100, bar_states = true) diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 53c07261c3..1f88427d3e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -16,7 +16,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], spec_entropy = true, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 3bf4f230d4..47988bfef0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -42,7 +42,7 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], spec_entropy = true, bar_states = true, max_iterations_newton = 25) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index fab3a86e53..2307a6d139 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], math_entropy = true, bar_states = false, smoothness_indicator = true) diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index eccf13c6d2..66d6e77629 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -14,8 +14,8 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], - positivity_variables_nonlinear = (pressure,), + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, spec_entropy = false, max_iterations_newton = 10, diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 8f07b7ca92..5f482668cb 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -38,8 +38,8 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], - positivity_variables_nonlinear = (pressure,), + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], spec_entropy = false, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index b460b7a507..1848c71b6e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,7 +42,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], + local_minmax_variables_cons = ["rho"], spec_entropy = true, smoothness_indicator = false, bar_states = true) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index d8fce68592..0335597960 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], + positivity_variables_cons = ["rho"], positivity_correction_factor = 0.5, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 6d5281fcbc..5d9a90003d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -14,9 +14,9 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1], - positivity_variables_cons = [1], - positivity_variables_nonlinear = (pressure,), + local_minmax_variables_cons = ["rho"], + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], bar_states = true, smoothness_indicator = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 4a8a70b566..22e111c5a9 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -89,7 +89,7 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; local_minmax_variables_cons = [ - (i + 3 for i in eachcomponent(equations))..., + ("rho" * string(i) for i in eachcomponent(equations))..., ], spec_entropy = false, bar_states = true) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 5f6cdb1e9c..03670c4c6a 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -89,9 +89,9 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = [ - (i + 3 for i in eachcomponent(equations))..., + ("rho" * string(i) for i in eachcomponent(equations))..., ], - positivity_variables_nonlinear = (), + positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, spec_entropy = false, bar_states = false) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index 84361ef4f8..e1f60f7225 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -51,7 +51,7 @@ volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], + positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, bar_states = false) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 6a10f92b89..303f56950f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -22,7 +22,7 @@ end SubcellLimiterIDP(equations::AbstractEquations, basis; local_minmax_variables_cons = [], positivity_variables_cons = [], - positivity_variables_nonlinear = (), + positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, spec_entropy = false, math_entropy = false, @@ -40,6 +40,10 @@ including: - positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) - one-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) +Conservative variables to be limited are passed as a strings, e.g. `local_minmax_variables_cons = ["rho"]` +and `positivity_variables_nonlinear = ["rho"]`. For the non-linear variables the specific function is +passed, e.g. `positivity_variables_nonlinear = [pressure]`. + The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. The Newton-bisection method for the limiting of non-linear variables uses maximal `max_iterations_newton` @@ -90,7 +94,7 @@ end function SubcellLimiterIDP(equations::AbstractEquations, basis; local_minmax_variables_cons = [], positivity_variables_cons = [], - positivity_variables_nonlinear = (), + positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, spec_entropy = false, math_entropy = false, @@ -108,9 +112,19 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; error("Only one of the two can be selected: math_entropy/spec_entropy") end + variables = varnames(cons2cons, equations) + local_minmax_variables_cons_ = Vector{Int}(undef, length(local_minmax_variables_cons)) + positivity_variables_cons_ = Vector{Int}(undef, length(positivity_variables_cons)) + for (i, variable) in enumerate(local_minmax_variables_cons) + local_minmax_variables_cons_[i] = get_variable_index(variable, variables) + end + for (i, variable) in enumerate(positivity_variables_cons) + positivity_variables_cons_[i] = get_variable_index(variable, variables) + end + bound_keys = () if local_minmax - for v in local_minmax_variables_cons + for v in local_minmax_variables_cons_ v_string = string(v) bound_keys = (bound_keys..., Symbol(v_string, "_min"), Symbol(v_string, "_max")) @@ -122,8 +136,8 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; if math_entropy bound_keys = (bound_keys..., :math_entropy_max) end - for v in positivity_variables_cons - if !(v in local_minmax_variables_cons) + for v in positivity_variables_cons_ + if !(v in local_minmax_variables_cons_) bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end @@ -143,13 +157,12 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(positivity_variables_nonlinear), typeof(cache), typeof(IndicatorHG)}(local_minmax, - local_minmax_variables_cons, + local_minmax_variables_cons_, positivity, - positivity_variables_cons, + positivity_variables_cons_, positivity_variables_nonlinear, positivity_correction_factor, - spec_entropy, - math_entropy, + spec_entropy, math_entropy, bar_states, cache, max_iterations_newton, @@ -236,6 +249,15 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, return nothing end +@inline function get_variable_index(variable, variable_names) + for (i_, variable_) in enumerate(variable_names) + if variable == variable_ + return i_ + end + end + error("$variable is no valid variable.") +end + """ SubcellLimiterMCL(equations::AbstractEquations, basis; DensityLimiter = true, From 3f53816d6e5c36c87eb44b4cbcbb24cdc0d2d146 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 16:30:07 +0100 Subject: [PATCH 351/423] Update test to new passing structure --- test/test_unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 3d36fb3b44..d96d5b3e5f 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,7 +416,7 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ("variable",), 0.1, true, + indicator_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], ["variable"], 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) @test_nowarn show(stdout, indicator_idp) From 3afa4c1b6a3a331a2acc62433cff4e78f2532b08 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 16:58:28 +0100 Subject: [PATCH 352/423] Pass variables as strings instead of ints --- .../elixir_euler_blast_wave_sc_subcell.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- .../elixir_euler_shockcapturing_subcell.jl | 2 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 2 +- ...ubble_shockcapturing_subcell_positivity.jl | 2 +- .../elixir_mhd_shockcapturing_subcell.jl | 2 +- src/solvers/dgsem_tree/subcell_limiters.jl | 33 ++++++++++++++++--- test/test_unit.jl | 2 +- 8 files changed, 35 insertions(+), 12 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 8232639a80..209aa2ae35 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -41,7 +41,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1]) + local_minmax_variables_cons = ["rho"]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index a25ed5c9c2..c1ba3d9696 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,7 +42,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [1]) + local_minmax_variables_cons = ["rho"]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 3fea48b30d..282805a0e0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -39,7 +39,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], + positivity_variables_cons = ["rho"], positivity_correction_factor = 0.5) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 9079ff4cff..9c8754ab4d 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -89,7 +89,7 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; local_minmax_variables_cons = [ - (i + 3 for i in eachcomponent(equations))..., + ("rho" * string(i) for i in eachcomponent(equations))..., ]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 6241ca3093..6e321ca5e9 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -89,7 +89,7 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = [ - (i + 3 for i in eachcomponent(equations))..., + ("rho" * string(i) for i in eachcomponent(equations))..., ]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index b2cdff2ab5..fe9ad92467 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -51,7 +51,7 @@ volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [1], + positivity_variables_cons = ["rho"], positivity_correction_factor = 0.5) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 8269f0dd8d..228acdac4a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -23,6 +23,9 @@ including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) +Conservative variables to be limited are passed as a strings, e.g. `local_minmax_variables_cons = ["rho"]` +and `positivity_variables_nonlinear = ["rho"]`. + The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. @@ -59,16 +62,27 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) > 0) + variables = varnames(cons2cons, equations) + local_minmax_variables_cons_ = Vector{Int}(undef, + length(local_minmax_variables_cons)) + positivity_variables_cons_ = Vector{Int}(undef, length(positivity_variables_cons)) + for (i, variable) in enumerate(local_minmax_variables_cons) + local_minmax_variables_cons_[i] = get_variable_index(variable, variables) + end + for (i, variable) in enumerate(positivity_variables_cons) + positivity_variables_cons_[i] = get_variable_index(variable, variables) + end + bound_keys = () if local_minmax - for v in local_minmax_variables_cons + for v in local_minmax_variables_cons_ v_string = string(v) bound_keys = (bound_keys..., Symbol(v_string, "_min"), Symbol(v_string, "_max")) end end - for v in positivity_variables_cons - if !(v in local_minmax_variables_cons) + for v in positivity_variables_cons_ + if !(v in local_minmax_variables_cons_) bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end @@ -76,8 +90,8 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; cache = create_cache(SubcellLimiterIDP, equations, basis, bound_keys) SubcellLimiterIDP{typeof(positivity_correction_factor), - typeof(cache)}(local_minmax, local_minmax_variables_cons, - positivity, positivity_variables_cons, + typeof(cache)}(local_minmax, local_minmax_variables_cons_, + positivity, positivity_variables_cons_, positivity_correction_factor, cache) end @@ -138,4 +152,13 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, return nothing end + +@inline function get_variable_index(variable, variable_names) + for (i_, variable_) in enumerate(variable_names) + if variable == variable_ + return i_ + end + end + error("$variable is no valid variable.") +end end # @muladd diff --git a/test/test_unit.jl b/test/test_unit.jl index 4d7f8a6b85..9216e7d04e 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -414,7 +414,7 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], 0.1, "cache") + limiter_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], 0.1, "cache") @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test From de20a894014e271f31da1dc09faaf3b627aa60c7 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 16:58:58 +0100 Subject: [PATCH 353/423] Add `_nonperiodic` to elixir name --- ....jl => elixir_euler_blast_wave_sc_subcell_nonperiodic.jl} | 0 test/test_tree_2d_euler.jl | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename examples/tree_2d_dgsem/{elixir_euler_blast_wave_sc_subcell.jl => elixir_euler_blast_wave_sc_subcell_nonperiodic.jl} (100%) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl similarity index 100% rename from examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl rename to examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 28521ccfdf..24eae4d34d 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -396,8 +396,9 @@ end end end -@trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), +@trixi_testset "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ 0.3517507570120483, 0.19252291020146015, From 5b1378c49d2add89fb6c1a731ef8a1b49a6c2572 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 17:03:15 +0100 Subject: [PATCH 354/423] Format --- src/solvers/dgsem_tree/subcell_limiters.jl | 3 ++- test/test_unit.jl | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 303f56950f..f02828f20c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -113,7 +113,8 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end variables = varnames(cons2cons, equations) - local_minmax_variables_cons_ = Vector{Int}(undef, length(local_minmax_variables_cons)) + local_minmax_variables_cons_ = Vector{Int}(undef, + length(local_minmax_variables_cons)) positivity_variables_cons_ = Vector{Int}(undef, length(positivity_variables_cons)) for (i, variable) in enumerate(local_minmax_variables_cons) local_minmax_variables_cons_[i] = get_variable_index(variable, variables) diff --git a/test/test_unit.jl b/test/test_unit.jl index d96d5b3e5f..3c0e94e3ba 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,9 +416,9 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], ["variable"], 0.1, true, - true, true, "cache", 1, (1.0, 1.0), 1.0, true, - 1.0, nothing) + indicator_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], ["variable"], 0.1, + true, true, true, "cache", 1, (1.0, 1.0), 1.0, + true, 1.0, nothing) @test_nowarn show(stdout, indicator_idp) indicator_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, From ebedaba2dc5d84303c1caa4f52a3ba54b38082cf Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 18:30:55 +0100 Subject: [PATCH 355/423] Fix unit test --- test/test_unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 3c0e94e3ba..ea751d2ceb 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,7 +416,7 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], ["variable"], 0.1, + indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, true, true, true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) @test_nowarn show(stdout, indicator_idp) From fd3d531ca71fd023c807c4e1a81a194efeb2dfe0 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 7 Nov 2023 18:31:28 +0100 Subject: [PATCH 356/423] Fix unit test --- test/test_unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 9216e7d04e..4d7f8a6b85 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -414,7 +414,7 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, ["rho"], true, ["rho"], 0.1, "cache") + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], 0.1, "cache") @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test From 5e81530998d642f6053159765f3f99f0fb449867 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 8 Nov 2023 12:42:29 +0100 Subject: [PATCH 357/423] Implement suggestions --- ...ck_bubble_shockcapturing_subcell_minmax.jl | 5 ++- ...ubble_shockcapturing_subcell_positivity.jl | 5 ++- src/equations/equations.jl | 24 ++++++++++--- src/solvers/dgsem_tree/subcell_limiters.jl | 35 ++++++------------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 9c8754ab4d..3159a2066a 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -88,9 +88,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = [ - ("rho" * string(i) for i in eachcomponent(equations))..., - ]) + local_minmax_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 6e321ca5e9..7856c9bafb 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -88,9 +88,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = [ - ("rho" * string(i) for i in eachcomponent(equations))..., - ]) + positivity_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 0e77b92e04..bccb7c4614 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -42,6 +42,22 @@ Common choices of the `conversion_function` are [`cons2cons`](@ref) and """ function varnames end +""" + get_variable_index(variable, equations, conversion_function = cons2cons) + +Return the index of `variable` in `varnames(conversion_function, equations)` if available. +Otherwise, return an error. +""" +@inline function get_variable_index(variable, equations, + conversion_function = cons2cons) + index = findfirst(==(variable), varnames(conversion_function, equations)) + if isnothing(index) + error("$variable is no valid variable.") + end + + return index +end + # Add methods to show some information on systems of equations. function Base.show(io::IO, equations::AbstractEquations) # Since this is not performance-critical, we can use `@nospecialize` to reduce latency. @@ -211,8 +227,8 @@ end """ NonConservativeLocal() -Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". -When the argument `nonconservative_type` is of type `NonConservativeLocal`, +Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". +When the argument `nonconservative_type` is of type `NonConservativeLocal`, the function returns the local part of the non-conservative term. """ struct NonConservativeLocal end @@ -220,8 +236,8 @@ struct NonConservativeLocal end """ NonConservativeSymmetric() -Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". -When the argument `nonconservative_type` is of type `NonConservativeSymmetric`, +Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". +When the argument `nonconservative_type` is of type `NonConservativeSymmetric`, the function returns the symmetric part of the non-conservative term. """ struct NonConservativeSymmetric end diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 228acdac4a..055e7ce24a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -14,8 +14,8 @@ end """ SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], + local_minmax_variables_cons = String[], + positivity_variables_cons = String[], positivity_correction_factor = 0.1) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) @@ -23,8 +23,8 @@ including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) -Conservative variables to be limited are passed as a strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_nonlinear = ["rho"]`. +Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` +and `positivity_variables_cons = ["rho"]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. @@ -56,22 +56,16 @@ end # this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = [], - positivity_variables_cons = [], + local_minmax_variables_cons = String[], + positivity_variables_cons = String[], positivity_correction_factor = 0.1) local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) > 0) - variables = varnames(cons2cons, equations) - local_minmax_variables_cons_ = Vector{Int}(undef, - length(local_minmax_variables_cons)) - positivity_variables_cons_ = Vector{Int}(undef, length(positivity_variables_cons)) - for (i, variable) in enumerate(local_minmax_variables_cons) - local_minmax_variables_cons_[i] = get_variable_index(variable, variables) - end - for (i, variable) in enumerate(positivity_variables_cons) - positivity_variables_cons_[i] = get_variable_index(variable, variables) - end + local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, + equations) + positivity_variables_cons_ = get_variable_index.(positivity_variables_cons, + equations) bound_keys = () if local_minmax @@ -152,13 +146,4 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, return nothing end - -@inline function get_variable_index(variable, variable_names) - for (i_, variable_) in enumerate(variable_names) - if variable == variable_ - return i_ - end - end - error("$variable is no valid variable.") -end end # @muladd From f9ec72c4e808f9edcf72f882e5ed55dfc6d5cfef Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 8 Nov 2023 14:54:33 +0100 Subject: [PATCH 358/423] Clean up --- src/solvers/dgsem_tree/subcell_limiters.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 95dbd91894..b7d373a0ab 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -41,7 +41,7 @@ including: - One-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. For the non-linear variables the specific function is +and `positivity_variables_cons = ["rho"]`. For non-linear variables the specific functions are passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity @@ -83,8 +83,8 @@ struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, bar_states::Bool cache::Cache max_iterations_newton::Int - newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method - gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints + newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method + gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints smoothness_indicator::Bool threshold_smoothness_indicator::RealT IndicatorHG::Indicator @@ -170,7 +170,7 @@ end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - @unpack local_minmax, positivity, spec_entropy, math_entropy = limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter print(io, "SubcellLimiterIDP(") if !(local_minmax || positivity || spec_entropy || math_entropy) From 0a51a49a5cc2b97dfdecbc4ab798cf4e8d5ee18c Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 9 Nov 2023 12:45:00 +0100 Subject: [PATCH 359/423] Add missing comma in bounds check exportation --- src/callbacks_stage/subcell_bounds_check_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index cf47c0fc53..7ed3525dfc 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -93,7 +93,7 @@ if local_minmax for v in limiter.local_minmax_variables_cons v_string = string(v) - print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], + print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], ", ", idp_bounds_delta[Symbol(v_string, "_max")][1]) end end From 7e22f2578b4aa33f556c3ee8bc1b7aacb9195678 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 9 Nov 2023 14:44:34 +0100 Subject: [PATCH 360/423] Reduce allocations in `calc_variable_bounds!` for IDP --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index ed9c193725..8c7f3f8bfe 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -863,38 +863,39 @@ end # state variables if limiter.local_minmax - for index in limiter.local_minmax_variables_cons - var_min = variable_bounds[Symbol("$(index)_min")] - var_max = variable_bounds[Symbol("$(index)_max")] + for v in limiter.local_minmax_variables_cons + v_string = string(v) + var_min = variable_bounds[Symbol(v_string, "_min")] + var_max = variable_bounds[Symbol(v_string, "_max")] @threaded for element in eachelement(dg, cache) var_min[:, :, element] .= typemax(eltype(var_min)) var_max[:, :, element] .= typemin(eltype(var_max)) for j in eachnode(dg), i in eachnode(dg) var_min[i, j, element] = min(var_min[i, j, element], - u[index, i, j, element]) + u[v, i, j, element]) var_max[i, j, element] = max(var_max[i, j, element], - u[index, i, j, element]) + u[v, i, j, element]) # TODO: Add source term! # - xi direction var_min[i, j, element] = min(var_min[i, j, element], - bar_states1[index, i, j, element]) + bar_states1[v, i, j, element]) var_max[i, j, element] = max(var_max[i, j, element], - bar_states1[index, i, j, element]) + bar_states1[v, i, j, element]) # + xi direction var_min[i, j, element] = min(var_min[i, j, element], - bar_states1[index, i + 1, j, element]) + bar_states1[v, i + 1, j, element]) var_max[i, j, element] = max(var_max[i, j, element], - bar_states1[index, i + 1, j, element]) + bar_states1[v, i + 1, j, element]) # - eta direction var_min[i, j, element] = min(var_min[i, j, element], - bar_states2[index, i, j, element]) + bar_states2[v, i, j, element]) var_max[i, j, element] = max(var_max[i, j, element], - bar_states2[index, i, j, element]) + bar_states2[v, i, j, element]) # + eta direction var_min[i, j, element] = min(var_min[i, j, element], - bar_states2[index, i, j + 1, element]) + bar_states2[v, i, j + 1, element]) var_max[i, j, element] = max(var_max[i, j, element], - bar_states2[index, i, j + 1, element]) + bar_states2[v, i, j + 1, element]) end end end From ba2c20ba4bd3a354c5451ff97240ced97900d896 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 13 Nov 2023 14:21:36 +0100 Subject: [PATCH 361/423] Use thread parallelization for reset of alphas --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index f8ba8c2ce5..fc0e9636aa 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -36,7 +36,9 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE dt; kwargs...) @unpack alpha = limiter.cache.subcell_limiter_coefficients - alpha .= zero(eltype(alpha)) + @trixi_timeit timer() "reset alpha" @threaded for element in eachelement(dg, semi.cache) + alpha[.., element] .= zero(eltype(alpha)) + end if limiter.smoothness_indicator elements = semi.cache.element_ids_dgfv else From d854c50140494b0a987f926282c6ebdc5f4f78cd Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 13 Nov 2023 14:55:58 +0100 Subject: [PATCH 362/423] Reduce weird allocation when using thread parallelization --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 14 +++++++++---- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 20 ++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 8c7f3f8bfe..646b19391e 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -868,8 +868,10 @@ end var_min = variable_bounds[Symbol(v_string, "_min")] var_max = variable_bounds[Symbol(v_string, "_max")] @threaded for element in eachelement(dg, cache) - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) + for j in eachnode(dg), i in eachnode(dg) + var_min[i, j, element] = typemax(eltype(var_min)) + var_max[i, j, element] = typemin(eltype(var_max)) + end for j in eachnode(dg), i in eachnode(dg) var_min[i, j, element] = min(var_min[i, j, element], u[v, i, j, element]) @@ -904,7 +906,9 @@ end if limiter.spec_entropy s_min = variable_bounds[:spec_entropy_min] @threaded for element in eachelement(dg, cache) - s_min[:, :, element] .= typemax(eltype(s_min)) + for j in eachnode(dg), i in eachnode(dg) + s_min[i, j, element] = typemax(eltype(s_min)) + end for j in eachnode(dg), i in eachnode(dg) s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) @@ -933,7 +937,9 @@ end if limiter.math_entropy s_max = variable_bounds[:math_entropy_max] @threaded for element in eachelement(dg, cache) - s_max[:, :, element] .= typemin(eltype(s_max)) + for j in eachnode(dg), i in eachnode(dg) + s_max[i, j, element] = typemin(eltype(s_max)) + end for j in eachnode(dg), i in eachnode(dg) s = entropy_math(get_node_vars(u, equations, dg, i, j, element), equations) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index fc0e9636aa..0638344c4e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -75,10 +75,12 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE for j in 2:nnodes(dg), i in eachnode(dg) alpha2[i, j, element] = max(alpha[i, j - 1, element], alpha[i, j, element]) end - alpha1[1, :, element] .= zero(eltype(alpha1)) - alpha1[nnodes(dg) + 1, :, element] .= zero(eltype(alpha1)) - alpha2[:, 1, element] .= zero(eltype(alpha2)) - alpha2[:, nnodes(dg) + 1, element] .= zero(eltype(alpha2)) + for i in eachnode(dg) + alpha1[1, i, element] = zero(eltype(alpha1)) + alpha1[nnodes(dg) + 1, i, element] = zero(eltype(alpha1)) + alpha2[i, 1, element] = zero(eltype(alpha2)) + alpha2[i, nnodes(dg) + 1, element] = zero(eltype(alpha2)) + end end return nothing @@ -88,8 +90,10 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) - var_min[:, :, element] .= typemax(eltype(var_min)) - var_max[:, :, element] .= typemin(eltype(var_max)) + for j in eachnode(dg), i in eachnode(dg) + var_min[i, j, element] = typemax(eltype(var_min)) + var_max[i, j, element] = typemin(eltype(var_max)) + end # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) var = u[variable, i, j, element] @@ -189,7 +193,9 @@ end mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) - var_minmax[:, :, element] .= typeminmax(eltype(var_minmax)) + for j in eachnode(dg), i in eachnode(dg) + var_minmax[i, j, element] = typeminmax(eltype(var_minmax)) + end # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) From fca561421d71ae5a9c5f8d6e5216a031a38b2566 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 Nov 2023 14:32:26 +0100 Subject: [PATCH 363/423] Clean up branch with main --- src/solvers/dg.jl | 6 ------ src/solvers/dgsem_tree/dg_2d.jl | 1 - src/solvers/dgsem_tree/subcell_limiters.jl | 2 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 6 ++---- test/test_unit.jl | 8 +++----- 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 824e10c4f1..df427fb7ce 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -192,12 +192,6 @@ A subcell limiting volume integral type for DG methods based on subcell blending with a low-order FV method. Used with the limiters [`SubcellLimiterIDP`](@ref) and [`SubcellLimiterMCL`](@ref). -!!! note - Subcell limiting methods are not fully functional on non-conforming meshes. This is - mainly because the implementation assumes that low- and high-order schemes have the same - surface terms, which is not guaranteed for non-conforming meshes. The low-order scheme - with a high-order mortar is not invariant domain preserving. - !!! note Subcell limiting methods are not fully functional on non-conforming meshes. This is mainly because the implementation assumes that low- and high-order schemes have the same diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index fd990c6aab..6c953471fc 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -549,7 +549,6 @@ end return nothing end -# We pass the `surface_integral` argument solely for dispatch function prolong2interfaces!(cache, u, mesh::TreeMesh{2}, equations, surface_integral, dg::DG) @unpack interfaces = cache diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index b7d373a0ab..686f5360f3 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -239,7 +239,7 @@ end function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, ::VolumeIntegralSubcellLimiting, equations) - node_variables[:alpha_limiter] = limiter.cache.subcell_limiter_coefficients.alpha + node_variables[:limiting_coefficient] = limiter.cache.subcell_limiter_coefficients.alpha return nothing end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index de8ad2a7da..c948499930 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -36,10 +36,8 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE dt; kwargs...) @unpack alpha = limiter.cache.subcell_limiter_coefficients - @trixi_timeit timer() "reset alpha" @threaded for element in eachelement(dg, - semi.cache) - alpha[.., element] .= zero(eltype(alpha)) - end + @trixi_timeit timer() "reset alpha" reset_du!(alpha, dg, semi.cache) + if limiter.smoothness_indicator elements = semi.cache.element_ids_dgfv else diff --git a/test/test_unit.jl b/test/test_unit.jl index 94bdffdc92..014eb6f876 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -296,11 +296,9 @@ end end Trixi.move_connectivity!(c::MyContainer, first, last, destination) = c Trixi.delete_connectivity!(c::MyContainer, first, last) = c - function Trixi.reset_data_structures!(c::MyContainer) - (c.data = Vector{Int}(undef, - c.capacity + 1); - c) - end + Trixi.reset_data_structures!(c::MyContainer) = (c.data = Vector{Int}(undef, + c.capacity + 1); + c) function Base.:(==)(c1::MyContainer, c2::MyContainer) return (c1.capacity == c2.capacity && c1.length == c2.length && From e44272dcf174f9ed455182a193fcf513317926a7 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 Nov 2023 14:51:45 +0100 Subject: [PATCH 364/423] Remove deleted tests --- test/test_tree_2d_euler.jl | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 0d298c9573..2d2ae7c66d 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -559,25 +559,6 @@ end end end -@trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), - l2=[ - 0.0845430093623868, - 0.09271459184623232, - 0.09271459184623232, - 0.4377291875101709, - ], - linf=[ - 1.3608553480069898, - 1.6822884847136004, - 1.6822884847135997, - 4.2201475428867035, - ], - maxiters=30, - coverage_override=(maxiters = 6,)) -end - @trixi_testset "elixir_euler_positivity.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity.jl"), l2=[ @@ -791,18 +772,6 @@ end end end -@trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), - # This stuff is experimental and annoying to test. In the future, we plan - # to move it to another repository. Thus, we save developer time right now - # and do not run these tests anymore. - # l2 = [0.0009823702998067061, 0.004943231496200673, 0.0048604522073091815, 0.00496983530893294], - # linf = [0.00855717053383187, 0.02087422420794427, 0.017121993783086185, 0.02720703869972585], - maxiters=30, - coverage_override=(maxiters = 2,)) -end - @trixi_testset "elixir_euler_colliding_flow.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow.jl"), l2=[ From f1b276826e9bfe214e85dd8e35d6e277b2d226fc Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 Nov 2023 14:55:03 +0100 Subject: [PATCH 365/423] Change order of test as in main --- test/test_tree_2d_euler.jl | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 2d2ae7c66d..c3c2d658f4 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -470,35 +470,6 @@ end end end -@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2=[ - 0.352405949321075, - 0.17207721487429464, - 0.17207721487433883, - 0.6263024434020885, - ], - linf=[ - 2.760997358628186, - 1.8279186132509326, - 1.8279186132502805, - 6.251573757093399, - ], - tspan=(0.0, 0.5), - callbacks=CallbackSet(summary_callback, - analysis_callback, alive_callback, - stepsize_callback), - surface_flux=flux_hlle), - # 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_euler_sedov_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), @@ -559,6 +530,35 @@ end end end +@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[ + 0.352405949321075, + 0.17207721487429464, + 0.17207721487433883, + 0.6263024434020885, + ], + linf=[ + 2.760997358628186, + 1.8279186132509326, + 1.8279186132502805, + 6.251573757093399, + ], + tspan=(0.0, 0.5), + callbacks=CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback), + surface_flux=flux_hlle), + # 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_euler_positivity.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity.jl"), l2=[ From 062568c2dfa826235e3ef1e39c178388eb2cd0f1 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 Nov 2023 16:24:55 +0100 Subject: [PATCH 366/423] Add positivity limiting of non-linear variables --- ...kelvin_helmholtz_instability_sc_subcell.jl | 91 +++++++++ .../elixir_mhd_shockcapturing_subcell.jl | 7 +- src/callbacks_stage/subcell_bounds_check.jl | 8 + .../subcell_bounds_check_2d.jl | 17 ++ src/equations/compressible_euler_2d.jl | 19 ++ src/equations/ideal_glm_mhd_2d.jl | 21 ++ src/solvers/dgsem_tree/subcell_limiters.jl | 43 ++++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 181 ++++++++++++++++++ test/test_tree_2d_euler.jl | 26 +++ test/test_tree_2d_mhd.jl | 32 ++-- test/test_unit.jl | 3 +- 11 files changed, 422 insertions(+), 26 deletions(-) create mode 100644 examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl new file mode 100644 index 0000000000..1817672778 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -0,0 +1,91 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) + +A version of the classical Kelvin-Helmholtz instability based on +- Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) + A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations + of the Euler Equations + [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) +""" +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_kelvin_helmholtz_instability + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) + +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 5, + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.7) +ode = semidiscretize(semi, tspan) + +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, + solution_variables = cons2prim) + +save_restart = SaveRestartCallback(interval = 1000, + save_final_restart = true) + +stepsize_callback = StepsizeCallback(cfl = 0.7) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_restart, save_solution) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index fe9ad92467..74d0370647 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -22,7 +22,7 @@ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) r = sqrt(x[1]^2 + x[2]^2) pmax = 10.0 - pmin = 1.0 + pmin = 0.01 rhomax = 1.0 rhomin = 0.01 if r <= 0.09 @@ -52,7 +52,8 @@ basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], - positivity_correction_factor = 0.5) + positivity_variables_nonlinear = [pressure], + positivity_correction_factor = 0.1) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) @@ -84,7 +85,7 @@ save_solution = SaveSolutionCallback(interval = 100, save_final_solution = true, solution_variables = cons2prim) -cfl = 0.5 +cfl = 0.4 stepsize_callback = StepsizeCallback(cfl = cfl) glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index d7e30ab162..25662f8580 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -97,6 +97,9 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi end print(f, ", " * string(variables[v]) * "_min") end + for variable in limiter.positivity_variables_nonlinear + print(f, ", " * string(variable) * "_min") + end end println(f) end @@ -140,6 +143,11 @@ end println(string(variables[v]) * ":\n- positivity: ", idp_bounds_delta[Symbol(string(v), "_min")][2]) end + for variable in limiter.positivity_variables_nonlinear + variable_string = string(variable) + println(variable_string * ":\n- positivity: ", + idp_bounds_delta[Symbol(variable_string, "_min")][2]) + end end println("─"^100 * "\n") diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index d52eb6edb9..688d3281b9 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -48,6 +48,19 @@ end deviation[2] = max(deviation[2], deviation[1]) end + for variable in limiter.positivity_variables_nonlinear + key = Symbol(string(variable), "_min") + deviation = idp_bounds_delta[key] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + var = variable(get_node_vars(u, equations, solver, i, j, element), + equations) + deviation[1] = max(deviation[1], + variable_bounds[key][i, j, element] - var) + end + deviation[2] = max(deviation[2], deviation[1]) + end end if save_errors # Print to output file @@ -67,6 +80,10 @@ end print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) end + for variable in limiter.positivity_variables_nonlinear + print(f, ", ", + idp_bounds_delta[Symbol(string(variable), "_min")][1]) + end end println(f) end diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index a992f99eaf..f3d46da245 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1404,6 +1404,17 @@ end return SVector(w1, w2, w3, w4) end +# Transformation from conservative variables u to d(p)/d(u) +@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + + return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) +end + @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD # [DOI: 10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) @@ -1428,6 +1439,14 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end +@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end + # Convert primitive to conservative variables @inline function prim2cons(prim, equations::CompressibleEulerEquations2D) rho, v1, v2, p = prim diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 43d1991e34..dd80803e6a 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1062,6 +1062,19 @@ end return SVector(w1, w2, w3, w4, w5, w6, w7, w8, w9) end +# Transformation from conservative variables u to d(p)/d(u) +@inline function pressure(u, equations::IdealGlmMhdEquations2D, derivative::True) + rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_square = v1^2 + v2^2 + v3^2 + + return (equations.gamma - 1.0) * + SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) +end + # Convert entropy variables to conservative variables @inline function entropy2cons(w, equations::IdealGlmMhdEquations2D) w1, w2, w3, w4, w5, w6, w7, w8, w9 = w @@ -1089,6 +1102,14 @@ end return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end +@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end + # Convert primitive to conservative variables @inline function prim2cons(prim, equations::IdealGlmMhdEquations2D) rho, v1, v2, v3, p, B1, B2, B3, psi = prim diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 055e7ce24a..554c481017 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -16,18 +16,28 @@ end SubcellLimiterIDP(equations::AbstractEquations, basis; local_minmax_variables_cons = String[], positivity_variables_cons = String[], - positivity_correction_factor = 0.1) + positivity_variables_nonlinear = [], + positivity_correction_factor = 0.1, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations)) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) -- Positivity limiting for conservative variables (`positivity_variables_cons`) +- Positivity limiting for conservative variables (`positivity_variables_cons`) and non-linear variables +(`positivity_variables_nonlinear`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. +and `positivity_variables_cons = ["rho"]`. For non-linear variables the specific functions are +passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. +The limiting of non-linear variables uses a Newton-bisection method with a maximum of +`max_iterations_newton` iterations, relative and absolute tolerances of `newton_tolerances` +and a gamma constant of `gamma_constant_newton` (`gamma_constant_newton>=2*d`, +where `d = #dimensions`). !!! note This limiter and the correction callback [`SubcellLimiterIDPCorrection`](@ref) only work together. @@ -45,22 +55,32 @@ The bounds are calculated using the low-order FV solution. The positivity limite !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct SubcellLimiterIDP{RealT <: Real, Cache} <: AbstractSubcellLimiter +struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, Cache} <: + AbstractSubcellLimiter local_minmax::Bool local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables + positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables positivity_correction_factor::RealT cache::Cache + max_iterations_newton::Int + newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method + gamma_constant_newton::RealT # Constant for the subcell limiting of convex (nonlinear) constraints end # this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; local_minmax_variables_cons = String[], positivity_variables_cons = String[], - positivity_correction_factor = 0.1) + positivity_variables_nonlinear = [], + positivity_correction_factor = 0.1, + max_iterations_newton = 10, + newton_tolerances = (1.0e-12, 1.0e-14), + gamma_constant_newton = 2 * ndims(equations)) local_minmax = (length(local_minmax_variables_cons) > 0) - positivity = (length(positivity_variables_cons) > 0) + positivity = (length(positivity_variables_cons) + + length(positivity_variables_nonlinear) > 0) local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, equations) @@ -80,13 +100,20 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end + for variable in positivity_variables_nonlinear + bound_keys = (bound_keys..., Symbol(string(variable), "_min")) + end cache = create_cache(SubcellLimiterIDP, equations, basis, bound_keys) SubcellLimiterIDP{typeof(positivity_correction_factor), + typeof(positivity_variables_nonlinear), typeof(cache)}(local_minmax, local_minmax_variables_cons_, positivity, positivity_variables_cons_, - positivity_correction_factor, cache) + positivity_variables_nonlinear, + positivity_correction_factor, cache, + max_iterations_newton, newton_tolerances, + gamma_constant_newton) end function Base.show(io::IO, limiter::SubcellLimiterIDP) @@ -124,7 +151,7 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) ] end if positivity - string = "positivity for conservative variables $(limiter.positivity_variables_cons)" + string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index bc69e55f26..2ff8c9e8d0 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -229,6 +229,11 @@ end idp_positivity!(alpha, limiter, u, dt, semi, variable) end + # Nonlinear variables + for variable in limiter.positivity_variables_nonlinear + idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, variable) + end + return nothing end @@ -292,4 +297,180 @@ end return nothing end + +@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, variable) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + (; positivity_correction_factor) = limiter + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol(string(variable), "_min")] + + @threaded for element in eachelement(dg, semi.cache) + for j in eachnode(dg), i in eachnode(dg) + # Compute bound + u_local = get_node_vars(u, equations, dg, i, j, element) + var = variable(u_local, equations) + if var < 0 + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + end + var_min[i, j, element] = positivity_correction_factor * var + + # Perform Newton's bisection method to find new alpha + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, + variable, initial_check_nonnegative, + final_check_nonnegative, + dt, mesh, equations, dg, cache, limiter) + end + end + + return nothing +end + +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, + initial_check, final_check, dt, mesh, equations, + dg, cache, limiter) + (; inverse_weights) = dg.basis + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + inverse_jacobian = cache.elements.inverse_jacobian[element] + + (; gamma_constant_newton) = limiter + + # negative xi direction + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * + get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, + element) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) + + # positive xi direction + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * + inverse_weights[i] * + get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, + element) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) + + # negative eta direction + antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * + get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, + element) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) + + # positive eta direction + antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * + inverse_weights[j] * + get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, + element) + newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + equations, dt, limiter, antidiffusive_flux) + + return nothing +end + +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) + newton_reltol, newton_abstol = limiter.newton_tolerances + + beta = 1 - alpha[i, j, element] + + beta_L = 0 # alpha = 1 + beta_R = beta # No higher beta (lower alpha) than the current one + + u_curr = u + beta * dt * antidiffusive_flux + + # If state is valid, perform initial check and return if correction is not needed + if is_valid_state(u_curr, equations) + as = goal_function(variable, bound, u_curr, equations) + + initial_check(bound, as, newton_abstol) && return nothing + end + + # Newton iterations + for iter in 1:(limiter.max_iterations_newton) + beta_old = beta + + # If the state is valid, evaluate d(goal)/d(beta) + if is_valid_state(u_curr, equations) + dSdbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, + equations) + else # Otherwise, perform a bisection step + dSdbeta = 0 + end + + if dSdbeta != 0 + # Update beta with Newton's method + beta = beta - as / dSdbeta + end + + # Check bounds + if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0) || isnan(beta) + # Out of bounds, do a bisection step + beta = 0.5 * (beta_L + beta_R) + # Get new u + u_curr = u + beta * dt * antidiffusive_flux + + # If the state is invalid, finish bisection step without checking tolerance and iterate further + if !is_valid_state(u_curr, equations) + beta_R = beta + continue + end + + # Check new beta for condition and update bounds + as = goal_function(variable, bound, u_curr, equations) + if initial_check(bound, as, newton_abstol) + # New beta fulfills condition + beta_L = beta + else + # New beta does not fulfill condition + beta_R = beta + end + else + # Get new u + u_curr = u + beta * dt * antidiffusive_flux + + # If the state is invalid, redefine right bound without checking tolerance and iterate further + if !is_valid_state(u_curr, equations) + beta_R = beta + continue + end + + # Evaluate goal function + as = goal_function(variable, bound, u_curr, equations) + end + + # Check relative tolerance + if abs(beta_old - beta) <= newton_reltol + break + end + + # Check absolute tolerance + if final_check(bound, as, newton_abstol) + break + end + end + + new_alpha = 1 - beta + if alpha[i, j, element] > new_alpha + newton_abstol + error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") + else + alpha[i, j, element] = new_alpha + end + + return nothing +end + +# Initial checks +@inline initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 + +# Goal and d(Goal)d(u) function +@inline goal_function(variable, bound, u, equations) = bound - variable(u, equations) +@inline function dgoal_function(variable, u, dt, antidiffusive_flux, equations) + -dot(variable(u, equations, True()), dt * antidiffusive_flux) +end + +# Final checks +@inline function final_check_nonnegative(bound, goal, newton_abstol) + (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) +end end # @muladd diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 04a295537a..dff78694a4 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -581,6 +581,32 @@ end end end +@trixi_testset "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), + l2=[ + 0.05570313943221697, + 0.03298722119008495, + 0.05224470329798064, + 0.08011555326900793, + ], + linf=[ + 0.2409101307301882, + 0.16601896096921037, + 0.12356154796415487, + 0.2695166427148403, + ], + 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)) < 15000 + end +end + @trixi_testset "elixir_euler_colliding_flow.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow.jl"), l2=[ diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index 953c077c0a..1f8458075a 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -332,24 +332,28 @@ end @trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), - l2=[2.9974425783503109e-02, - 7.2849646345685956e-02, - 7.2488477174662239e-02, + l2=[ + 3.2064026219236076e-02, + 7.2461094392606618e-02, + 7.2380202888062711e-02, 0.0000000000000000e+00, - 1.2507971380965512e+00, - 1.8929505145499678e-02, - 1.2218606317164420e-02, + 8.6293936673145932e-01, + 8.4091669534557805e-03, + 5.2156364913231732e-03, 0.0000000000000000e+00, - 3.0154796910479838e-03], - linf=[3.2147382412340830e-01, - 1.3709471664007811e+00, - 1.3465154685288383e+00, + 2.0786952301129021e-04, + ], + linf=[ + 3.8778760255775635e-01, + 9.4666683953698927e-01, + 9.4618924645661928e-01, 0.0000000000000000e+00, - 1.6051257523415284e+01, - 3.0564266749926644e-01, - 2.3908016329805595e-01, + 1.0980297261521951e+01, + 1.0264404591009069e-01, + 1.0655686942176350e-01, 0.0000000000000000e+00, - 1.3711262178549158e-01], + 6.1013422157115546e-03, + ], tspan=(0.0, 0.003)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_unit.jl b/test/test_unit.jl index 0c5f2bf0a4..d0075e7ac9 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -414,7 +414,8 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], 0.1, "cache") + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, "cache", 1, + (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test From aa0e9e33cb1e29666e291d105c894b107d9df4a3 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:33:59 +0100 Subject: [PATCH 367/423] Rename MCL parameters (#119) --- ...elixir_euler_convergence_wavingflag_MCL.jl | 14 +- .../elixir_euler_double_mach_MCL.jl | 14 +- .../elixir_euler_free_stream_MCL.jl | 16 +- .../elixir_euler_shock_upstream_MCL.jl | 16 +- .../elixir_euler_astro_jet_MCL.jl | 12 +- .../elixir_euler_blast_wave_MCL.jl | 16 +- .../elixir_euler_convergence_MCL.jl | 14 +- ..._euler_kelvin_helmholtz_instability_MCL.jl | 16 +- .../elixir_euler_sedov_blast_wave_MCL.jl | 16 +- src/callbacks_stage/subcell_bounds_check.jl | 6 +- .../subcell_bounds_check_2d.jl | 60 +++---- src/callbacks_step/limiting_analysis.jl | 16 +- src/callbacks_step/limiting_analysis_2d.jl | 28 ++-- .../dgsem_tree/dg_2d_subcell_limiters.jl | 60 +++---- src/solvers/dgsem_tree/subcell_limiters.jl | 157 +++++++++--------- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 4 +- 16 files changed, 234 insertions(+), 231 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl index 20a20a9c20..7255781d3b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_MCL.jl @@ -14,13 +14,13 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = false, - DensityAlphaForAll = false, - SequentialLimiter = false, - ConservativeLimiter = false, - DensityPositivityLimiter = true, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = true, + density_limiter = false, + density_coefficient_for_all = false, + sequential_limiter = false, + conservative_limiter = false, + positivity_limiter_density = true, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = true, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index c7df12f27a..6a04b39ec4 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -22,13 +22,13 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - DensityPositivityLimiter = false, - PressurePositivityLimiterKuzmin = false, - SemiDiscEntropyLimiter = false, + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_density = false, + positivity_limiter_pressure = false, + entropy_limiter_semidiscrete = false, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg = volume_flux, diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 163cc6519a..623e69bcaa 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -14,14 +14,14 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = false, - DensityAlphaForAll = false, - SequentialLimiter = false, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = true, - SemiDiscEntropyLimiter = false, + density_limiter = false, + density_coefficient_for_all = false, + sequential_limiter = false, + conservative_limiter = false, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = true, + positivity_limiter_density = true, + entropy_limiter_semidiscrete = false, smoothness_indicator = false, Plotting = true) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index 06eaceb4f7..cc12990ab1 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -37,14 +37,14 @@ polydeg = 5 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = false, - DensityPositivityLimiter = false, - SemiDiscEntropyLimiter = false, + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_pressure = false, + positivity_limiter_pressure_exact = false, + positivity_limiter_density = false, + entropy_limiter_semidiscrete = false, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl index 69148f5bdb..b34ac71644 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_MCL.jl @@ -42,12 +42,12 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = true, - DensityAlphaForAll = true, - SequentialLimiter = true, - PressurePositivityLimiterKuzmin = true, - DensityPositivityLimiter = false, - SemiDiscEntropyLimiter = false, + density_limiter = true, + density_coefficient_for_all = true, + sequential_limiter = true, + positivity_limiter_pressure = true, + positivity_limiter_density = false, + entropy_limiter_semidiscrete = false, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index 3e90ef7da2..ba5f27d9f9 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -39,14 +39,14 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = true, - DensityAlphaForAll = true, - SequentialLimiter = false, - ConservativeLimiter = true, - DensityPositivityLimiter = true, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = false, - SemiDiscEntropyLimiter = true, + density_limiter = true, + density_coefficient_for_all = true, + sequential_limiter = false, + conservative_limiter = true, + positivity_limiter_density = true, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = false, + entropy_limiter_semidiscrete = true, smoothness_indicator = true, Plotting = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl index d82aed8ba3..02ebaa2b3c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_MCL.jl @@ -14,13 +14,13 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = false, - DensityAlphaForAll = false, - SequentialLimiter = false, - ConservativeLimiter = false, - DensityPositivityLimiter = true, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = true, + density_limiter = false, + density_coefficient_for_all = false, + sequential_limiter = false, + conservative_limiter = false, + positivity_limiter_density = true, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = true, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl index 548485a1ab..549054f41f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_MCL.jl @@ -38,14 +38,14 @@ polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = false, - DensityAlphaForAll = false, - SequentialLimiter = false, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = true, - SemiDiscEntropyLimiter = false, + density_limiter = false, + density_coefficient_for_all = false, + sequential_limiter = false, + conservative_limiter = false, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = true, + positivity_limiter_density = true, + entropy_limiter_semidiscrete = false, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index a5e7532854..51e42bf4a0 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -42,14 +42,14 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_mcl = SubcellLimiterMCL(equations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - DensityPositivityLimiter = false, - PressurePositivityLimiterKuzmin = true, - PressurePositivityLimiterKuzminExact = true, - SemiDiscEntropyLimiter = true, + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_density = false, + positivity_limiter_pressure = true, + positivity_limiter_pressure_exact = true, + entropy_limiter_semidiscrete = true, smoothness_indicator = false, Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 527bcb0750..16cf3abeee 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -123,7 +123,7 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time", join(", $(v)_min, $(v)_max" for v in varnames(cons2cons, semi.equations))) - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure print(f, ", pressure_min") end # TODO: Bounds check for entropy limiting @@ -200,11 +200,11 @@ end println(variables[v], ":\n- lower bound: ", mcl_bounds_delta[2, 1, v], "\n- upper bound: ", mcl_bounds_delta[2, 2, v]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure println("pressure:\n- positivity: ", mcl_bounds_delta[2, 1, nvariables(semi.equations) + 1]) end - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete # TODO: Bounds check for entropy limiting println("\nWARNING: No bounds check for the entropy limiter.") end diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 7ed3525dfc..b9406ab878 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -136,7 +136,7 @@ end n_vars = nvariables(equations) - if limiter.DensityLimiter + if limiter.density_limiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -189,9 +189,9 @@ end rho_limited - var_max[1, i, j, element]) end end - end # limiter.DensityLimiter + end # limiter.density_limiter - if limiter.SequentialLimiter + if limiter.sequential_limiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -204,7 +204,7 @@ end var_limited - var_max[v, i, j, element]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] @@ -239,11 +239,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited / rho_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -264,11 +264,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited / rho_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -289,11 +289,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited / rho_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -314,11 +314,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited / rho_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -327,7 +327,7 @@ end end end end - elseif limiter.ConservativeLimiter + elseif limiter.conservative_limiter # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -339,7 +339,7 @@ end u[v, i, j, element] - var_max[v, i, j, element]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] @@ -374,11 +374,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -399,11 +399,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -424,11 +424,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -449,11 +449,11 @@ end mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], var_limited - var_max[v, i, j, element]) - if limiter.PressurePositivityLimiterKuzmin && (v == 2 || v == 3) + if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, n_vars + 1], @@ -462,7 +462,7 @@ end end end end - elseif limiter.PressurePositivityLimiterKuzmin + elseif limiter.positivity_limiter_pressure # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -554,9 +554,9 @@ end error_pressure) end end - end # limiter.PressurePositivityLimiterKuzmin + end # limiter.positivity_limiter_pressure - if limiter.DensityPositivityLimiter + if limiter.positivity_limiter_density # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) @@ -566,7 +566,7 @@ end end # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - beta = limiter.DensityPositivityCorrectionFactor + beta = limiter.positivity_limiter_correction_factor # Checking the bounds for... # - density (rho): # beta * \bar{rho} <= \bar{rho}^{Lim} @@ -594,7 +594,7 @@ end mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) end end - end # limiter.DensityPositivityLimiter + end # limiter.positivity_limiter_density for v in eachvariable(equations) mcl_bounds_delta[2, 1, v] = max(mcl_bounds_delta[2, 1, v], @@ -602,7 +602,7 @@ end mcl_bounds_delta[2, 2, v] = max(mcl_bounds_delta[2, 2, v], mcl_bounds_delta[1, 2, v]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure mcl_bounds_delta[2, 1, n_vars + 1] = max(mcl_bounds_delta[2, 1, n_vars + 1], mcl_bounds_delta[1, 1, n_vars + 1]) end @@ -615,7 +615,7 @@ end for v in eachvariable(equations) print(f, ", ", mcl_bounds_delta[1, 1, v], ", ", mcl_bounds_delta[1, 2, v]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure print(f, ", ", mcl_bounds_delta[1, 1, n_vars + 1]) end println(f) @@ -624,7 +624,7 @@ end mcl_bounds_delta[1, 1, v] = zero(eltype(mcl_bounds_delta)) mcl_bounds_delta[1, 2, v] = zero(eltype(mcl_bounds_delta)) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure mcl_bounds_delta[1, 1, n_vars + 1] = zero(eltype(mcl_bounds_delta)) end diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index 55e48cbaf8..5bbf8c8b80 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -91,10 +91,10 @@ function initialize!(cb::DiscreteCallback{Condition, Affect!}, u_ode, t, integra open("$output_directory/$file", "a") do f print(f, "# iter, simu_time", join(", alpha_min_$v, alpha_avg_$v" for v in vars)) - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure print(f, ", alpha_min_pressure, alpha_avg_pressure") end - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete print(f, ", alpha_min_entropy, alpha_avg_entropy") end println(f) @@ -172,11 +172,11 @@ end print(f, ", ", minimum(view(alpha, v, ntuple(_ -> :, n_vars - 1)...))) print(f, ", ", alpha_min_avg[v]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure print(f, ", ", minimum(alpha_pressure), ", ", alpha_min_avg[n_vars + 1]) end - if limiter.SemiDiscEntropyLimiter - k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 + if limiter.entropy_limiter_semidiscrete + k = n_vars + limiter.positivity_limiter_pressure + 1 print(f, ", ", minimum(alpha_entropy), ", ", alpha_min_avg[k]) end println(f) @@ -187,12 +187,12 @@ end print(f, ", ", minimum(view(alpha_mean, v, ntuple(_ -> :, n_vars - 1)...))) print(f, ", ", alpha_mean_avg[v]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure print(f, ", ", minimum(alpha_mean_pressure), ", ", alpha_mean_avg[n_vars + 1]) end - if limiter.SemiDiscEntropyLimiter - k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 + if limiter.entropy_limiter_semidiscrete + k = n_vars + limiter.positivity_limiter_pressure + 1 print(f, ", ", minimum(alpha_mean_entropy), ", ", alpha_mean_avg[k]) end println(f) diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index a6b5c498c3..ef547c0196 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -47,11 +47,11 @@ function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter n_vars = nvariables(equations) alpha_avg = zeros(eltype(alpha), - n_vars + limiter.PressurePositivityLimiterKuzmin + - limiter.SemiDiscEntropyLimiter) + n_vars + limiter.positivity_limiter_pressure + + limiter.entropy_limiter_semidiscrete) alpha_mean_avg = zeros(eltype(alpha), - n_vars + limiter.PressurePositivityLimiterKuzmin + - limiter.SemiDiscEntropyLimiter) + n_vars + limiter.positivity_limiter_pressure + + limiter.entropy_limiter_semidiscrete) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -63,14 +63,14 @@ function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] end - if limiter.SemiDiscEntropyLimiter - k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 + if limiter.entropy_limiter_semidiscrete + k = n_vars + limiter.positivity_limiter_pressure + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * @@ -92,11 +92,11 @@ function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, n_vars = nvariables(equations) alpha_avg = zeros(eltype(alpha), - n_vars + limiter.PressurePositivityLimiterKuzmin + - limiter.SemiDiscEntropyLimiter) + n_vars + limiter.positivity_limiter_pressure + + limiter.entropy_limiter_semidiscrete) alpha_mean_avg = zeros(eltype(alpha), - n_vars + limiter.PressurePositivityLimiterKuzmin + - limiter.SemiDiscEntropyLimiter) + n_vars + limiter.positivity_limiter_pressure + + limiter.entropy_limiter_semidiscrete) total_volume = zero(eltype(alpha)) for element in eachelement(dg, cache) @@ -108,14 +108,14 @@ function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, alpha_mean_avg[v] += jacobian * weights[i] * weights[j] * alpha_mean[v, i, j, element] end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure alpha_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_pressure[i, j, element] alpha_mean_avg[n_vars + 1] += jacobian * weights[i] * weights[j] * alpha_mean_pressure[i, j, element] end - if limiter.SemiDiscEntropyLimiter - k = n_vars + limiter.PressurePositivityLimiterKuzmin + 1 + if limiter.entropy_limiter_semidiscrete + k = n_vars + limiter.positivity_limiter_pressure + 1 alpha_avg[k] += jacobian * weights[i] * weights[j] * alpha_entropy[i, j, element] alpha_mean_avg[k] += jacobian * weights[i] * weights[j] * diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 646b19391e..3783ead020 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -978,7 +978,7 @@ end var_max[v, :, :, element] .= typemin(eltype(var_max)) end - if limiter.DensityLimiter + if limiter.density_limiter for j in eachnode(dg), i in eachnode(dg) # Previous solution var_min[1, i, j, element] = min(var_min[1, i, j, element], @@ -1010,9 +1010,9 @@ end var_max[1, i, j, element] = max(var_max[1, i, j, element], bar_state_rho) end - end #limiter.DensityLimiter + end #limiter.density_limiter - if limiter.SequentialLimiter + if limiter.sequential_limiter for j in eachnode(dg), i in eachnode(dg) # Previous solution for v in 2:nvariables(equations) @@ -1057,7 +1057,7 @@ end bar_state_phi) end end - elseif limiter.ConservativeLimiter + elseif limiter.conservative_limiter for j in eachnode(dg), i in eachnode(dg) # Previous solution for v in 2:nvariables(equations) @@ -1119,11 +1119,11 @@ end for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha[:, i, j, element] .= one(eltype(alpha)) - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure alpha_mean_pressure[i, j, element] = zero(eltype(alpha_mean_pressure)) alpha_pressure[i, j, element] = one(eltype(alpha_pressure)) end - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete alpha_mean_entropy[i, j, element] = zero(eltype(alpha_mean_entropy)) alpha_entropy[i, j, element] = one(eltype(alpha_entropy)) end @@ -1137,7 +1137,7 @@ end # Therefore we make sure that the flux keeps its sign during limiting. # Density limiter - if limiter.DensityLimiter + if limiter.density_limiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1157,7 +1157,7 @@ end min(f_min, 0.0)) end - if limiter.Plotting || limiter.DensityAlphaForAll + if limiter.Plotting || limiter.density_coefficient_for_all if isapprox(antidiffusive_flux1_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1179,7 +1179,7 @@ end antidiffusive_flux1_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll + if limiter.density_coefficient_for_all for v in 2:nvariables(equations) antidiffusive_flux1_L[v, i, j, element] = coefficient * antidiffusive_flux1_L[v, @@ -1209,7 +1209,7 @@ end min(f_min, 0.0)) end - if limiter.Plotting || limiter.DensityAlphaForAll + if limiter.Plotting || limiter.density_coefficient_for_all if isapprox(antidiffusive_flux2_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1231,7 +1231,7 @@ end antidiffusive_flux2_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll + if limiter.density_coefficient_for_all for v in 2:nvariables(equations) antidiffusive_flux2_L[v, i, j, element] = coefficient * antidiffusive_flux2_L[v, @@ -1241,10 +1241,10 @@ end end end end - end # if limiter.DensityLimiter + end # if limiter.density_limiter # Sequential limiter - if limiter.SequentialLimiter + if limiter.sequential_limiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1348,7 +1348,7 @@ end end end # Conservative limiter - elseif limiter.ConservativeLimiter + elseif limiter.conservative_limiter for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] for v in 2:nvariables(equations) @@ -1428,11 +1428,11 @@ end antidiffusive_flux2_L[v, i, j, element] = flux_limited end end - end # limiter.SequentialLimiter and limiter.ConservativeLimiter + end # limiter.sequential_limiter and limiter.conservative_limiter # Density positivity limiter - if limiter.DensityPositivityLimiter - beta = limiter.DensityPositivityCorrectionFactor + if limiter.positivity_limiter_density + beta = limiter.positivity_limiter_correction_factor for j in eachnode(dg), i in 2:nnodes(dg) lambda = lambda1[i, j, element] bar_state_rho = bar_states1[1, i, j, element] @@ -1449,7 +1449,7 @@ end min(f_min, 0.0)) end - if limiter.Plotting || limiter.DensityAlphaForAll + if limiter.Plotting || limiter.density_coefficient_for_all if isapprox(antidiffusive_flux1_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1461,7 +1461,7 @@ end alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !limiter.DensityLimiter + if !limiter.density_limiter alpha_mean[1, i - 1, j, element] += coefficient alpha_mean[1, i, j, element] += coefficient end @@ -1470,7 +1470,7 @@ end antidiffusive_flux1_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll + if limiter.density_coefficient_for_all for v in 2:nvariables(equations) antidiffusive_flux1_L[v, i, j, element] = coefficient * antidiffusive_flux1_L[v, @@ -1497,7 +1497,7 @@ end min(f_min, 0.0)) end - if limiter.Plotting || limiter.DensityAlphaForAll + if limiter.Plotting || limiter.density_coefficient_for_all if isapprox(antidiffusive_flux2_L[1, i, j, element], 0.0, atol = eps()) coefficient = 1.0 # flux_limited is zero as well else @@ -1509,7 +1509,7 @@ end alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) - if !limiter.DensityLimiter + if !limiter.density_limiter alpha_mean[1, i, j - 1, element] += coefficient alpha_mean[1, i, j, element] += coefficient end @@ -1518,7 +1518,7 @@ end antidiffusive_flux2_L[1, i, j, element] = flux_limited #Limit all quantities with the same alpha - if limiter.DensityAlphaForAll + if limiter.density_coefficient_for_all for v in 2:nvariables(equations) antidiffusive_flux2_L[v, i, j, element] = coefficient * antidiffusive_flux2_L[v, @@ -1528,13 +1528,13 @@ end end end end - end #if limiter.DensityPositivityLimiter + end #if limiter.positivity_limiter_density # Divide alpha_mean by number of additions if limiter.Plotting @unpack alpha_mean = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 - if limiter.DensityLimiter || limiter.DensityPositivityLimiter + if limiter.density_limiter || limiter.positivity_limiter_density for i in eachnode(dg) alpha_mean[1, i, 1, element] += 1.0 alpha_mean[1, i, nnodes(dg), element] += 1.0 @@ -1545,7 +1545,7 @@ end alpha_mean[1, i, j, element] /= 4 end end - if limiter.SequentialLimiter || limiter.ConservativeLimiter + if limiter.sequential_limiter || limiter.conservative_limiter for v in 2:nvariables(equations) for i in eachnode(dg) alpha_mean[v, i, 1, element] += 1.0 @@ -1561,7 +1561,7 @@ end end # Limit pressure à la Kuzmin - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + @@ -1573,7 +1573,7 @@ end (bar_states1[1, i, j, element] * bar_states1[4, i, j, element] - 0.5 * bar_state_velocity) - if limiter.PressurePositivityLimiterKuzminExact + if limiter.positivity_limiter_pressure_exact # exact calculation of max(R_ij, R_ji) R_max = lambda1[i, j, element] * abs(bar_states1[2, i, j, element] * @@ -1628,7 +1628,7 @@ end (bar_states2[1, i, j, element] * bar_states2[4, i, j, element] - 0.5 * bar_state_velocity) - if limiter.PressurePositivityLimiterKuzminExact + if limiter.positivity_limiter_pressure_exact # exact calculation of max(R_ij, R_ji) R_max = lambda2[i, j, element] * abs(bar_states2[2, i, j, element] * @@ -1690,7 +1690,7 @@ end # Limit entropy # TODO: This is a very inefficient function. We compute the entropy four times at each node. # TODO: For now, this only works for Cartesian meshes. - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete for j in eachnode(dg), i in 2:nnodes(dg) antidiffusive_flux_local = get_node_vars(antidiffusive_flux1_L, equations, dg, diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 686f5360f3..9fac965192 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -246,32 +246,33 @@ end """ SubcellLimiterMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_pressure = false, + positivity_limiter_pressure_exact = true, + positivity_limiter_density = false, + positivity_limiter_correction_factor = 0.0, + entropy_limiter_semidiscrete = false, smoothness_indicator = false, threshold_smoothness_indicator = 0.1, variable_smoothness_indicator = density_pressure, Plotting = true) Subcell monolithic convex limiting (MCL) used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- local two-sided limiting for `cons(1)` (`DensityLimiter`) -- transfer amount of `DensityLimiter` to all quantities (`DensityAlphaForAll`) -- local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`SequentialLimiter`) -- local two-sided limiting for conservative variables (`ConservativeLimiter`) -- positivity limiting for `cons(1)` (`DensityPositivityLimiter`) and pressure (`PressurePositivityLimiterKuzmin`) -- semidiscrete entropy fix (`SemiDiscEntropyLimiter`) - -The pressure positivity limiting preserves a sharp version (`PressurePositivityLimiterKuzminExact`) -and a more cautious one. The density positivity limiter uses a `DensityPositivityCorrectionFactor` -such that `u^new >= positivity_correction_factor * u^FV`. All additional analyses for plotting routines -can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). +- local two-sided limiting for `cons(1)` (`density_limiter`) +- transfer amount of `density_limiter` to all quantities (`density_coefficient_for_all`) +- local two-sided limiting for variables `phi:=cons(i)/cons(1)` (`sequential_limiter`) +- local two-sided limiting for conservative variables (`conservative_limiter`) +- positivity limiting for `cons(1)` (`positivity_limiter_density`) +- positivity limiting pressure à la Kuzmin (`positivity_limiter_pressure`) +- semidiscrete entropy fix (`entropy_limiter_semidiscrete`) + +The pressure positivity limiting preserves a sharp version (`positivity_limiter_pressure_exact`) +and a more cautious one. The density positivity limiter uses a `positivity_limiter_correction_factor` +such that `u^new >= positivity_limiter_correction_factor * u^FV`. All additional analyses for plotting +routines can be disabled via `Plotting=false` (see `save_alpha` and `update_alpha_max_avg!`). A hard-switch [`IndicatorHennemannGassner`](@ref) can be activated (`smoothness_indicator`) with `variable_smoothness_indicator`, which disables subcell blending for element-wise @@ -291,41 +292,41 @@ indicator values <= `threshold_smoothness_indicator`. """ struct SubcellLimiterMCL{RealT <: Real, Cache, Indicator} <: AbstractSubcellLimiter cache::Cache - DensityLimiter::Bool # Impose local maximum/minimum for cons(1) based on bar states - DensityAlphaForAll::Bool # Use the cons(1) blending coefficient for all quantities - SequentialLimiter::Bool # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states - ConservativeLimiter::Bool # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states - PressurePositivityLimiterKuzmin::Bool # Impose positivity for pressure â la Kuzmin - PressurePositivityLimiterKuzminExact::Bool # Only for PressurePositivityLimiterKuzmin=true: Use the exact calculation of alpha - DensityPositivityLimiter::Bool # Impose positivity for cons(1) - DensityPositivityCorrectionFactor::RealT # Correction Factor for DensityPositivityLimiter in [0,1) - SemiDiscEntropyLimiter::Bool # synchronized semidiscrete entropy fix - smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner - threshold_smoothness_indicator::RealT # threshold for smoothness indicator + density_limiter::Bool # Impose local maximum/minimum for cons(1) based on bar states + density_coefficient_for_all::Bool # Use the cons(1) blending coefficient for all quantities + sequential_limiter::Bool # Impose local maximum/minimum for variables phi:=cons(i)/cons(1) i 2:nvariables based on bar states + conservative_limiter::Bool # Impose local maximum/minimum for conservative variables 2:nvariables based on bar states + positivity_limiter_pressure::Bool # Impose positivity for pressure la Kuzmin + positivity_limiter_pressure_exact::Bool # Only for positivity_limiter_pressure=true: Use the sharp calculation of factor + positivity_limiter_density::Bool # Impose positivity for cons(1) + positivity_limiter_correction_factor::RealT # Correction Factor for positivity_limiter_density in [0,1) + entropy_limiter_semidiscrete::Bool # synchronized semidiscrete entropy fix + smoothness_indicator::Bool # activates smoothness indicator: IndicatorHennemannGassner + threshold_smoothness_indicator::RealT # threshold for smoothness indicator IndicatorHG::Indicator Plotting::Bool end # this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterMCL(equations::AbstractEquations, basis; - DensityLimiter = true, - DensityAlphaForAll = false, - SequentialLimiter = true, - ConservativeLimiter = false, - PressurePositivityLimiterKuzmin = false, - PressurePositivityLimiterKuzminExact = true, - DensityPositivityLimiter = false, - DensityPositivityCorrectionFactor = 0.0, - SemiDiscEntropyLimiter = false, + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_pressure = false, + positivity_limiter_pressure_exact = true, + positivity_limiter_density = false, + positivity_limiter_correction_factor = 0.0, + entropy_limiter_semidiscrete = false, smoothness_indicator = false, threshold_smoothness_indicator = 0.1, variable_smoothness_indicator = density_pressure, Plotting = true) - if SequentialLimiter && ConservativeLimiter - error("Only one of the two can be selected: SequentialLimiter/ConservativeLimiter") + if sequential_limiter && conservative_limiter + error("Only one of the two can be selected: sequential_limiter/conservative_limiter") end cache = create_cache(SubcellLimiterMCL, equations, basis, - PressurePositivityLimiterKuzmin) + positivity_limiter_pressure) if smoothness_indicator IndicatorHG = IndicatorHennemannGassner(equations, basis, alpha_smooth = false, variable = variable_smoothness_indicator) @@ -334,13 +335,13 @@ function SubcellLimiterMCL(equations::AbstractEquations, basis; end SubcellLimiterMCL{typeof(threshold_smoothness_indicator), typeof(cache), typeof(IndicatorHG)}(cache, - DensityLimiter, DensityAlphaForAll, - SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzmin, - PressurePositivityLimiterKuzminExact, - DensityPositivityLimiter, - DensityPositivityCorrectionFactor, - SemiDiscEntropyLimiter, + density_limiter, density_coefficient_for_all, + sequential_limiter, conservative_limiter, + positivity_limiter_pressure, + positivity_limiter_pressure_exact, + positivity_limiter_density, + positivity_limiter_correction_factor, + entropy_limiter_semidiscrete, smoothness_indicator, threshold_smoothness_indicator, IndicatorHG, Plotting) @@ -350,20 +351,20 @@ function Base.show(io::IO, limiter::SubcellLimiterMCL) @nospecialize limiter # reduce precompilation time print(io, "SubcellLimiterMCL(") - limiter.DensityLimiter && print(io, "; dens") - limiter.DensityAlphaForAll && print(io, "; dens alpha ∀") - limiter.SequentialLimiter && print(io, "; seq") - limiter.ConservativeLimiter && print(io, "; cons") - if limiter.PressurePositivityLimiterKuzmin + limiter.density_limiter && print(io, "; dens") + limiter.density_coefficient_for_all && print(io, "; dens alpha ∀") + limiter.sequential_limiter && print(io, "; seq") + limiter.conservative_limiter && print(io, "; cons") + if limiter.positivity_limiter_pressure print(io, - "; $(limiter.PressurePositivityLimiterKuzminExact ? "pres (Kuzmin ex)" : "pres (Kuzmin)")") + "; $(limiter.positivity_limiter_pressure_exact ? "pres (sharp)" : "pres (cautious)")") end - limiter.DensityPositivityLimiter && print(io, "; dens pos") - if limiter.DensityPositivityCorrectionFactor != 0 + limiter.positivity_limiter_density && print(io, "; dens pos") + if limiter.positivity_limiter_correction_factor != 0 print(io, - " with correction factor $(limiter.DensityPositivityCorrectionFactor)") + " with correction factor $(limiter.positivity_limiter_correction_factor)") end - limiter.SemiDiscEntropyLimiter && print(io, "; semid. entropy") + limiter.entropy_limiter_semidiscrete && print(io, "; semid. entropy") limiter.smoothness_indicator && print(io, "; Smoothness indicator: ", limiter.IndicatorHG, " with threshold ", limiter.threshold_smoothness_indicator) @@ -372,34 +373,36 @@ end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) @nospecialize limiter # reduce precompilation time - @unpack DensityLimiter, DensityAlphaForAll, SequentialLimiter, ConservativeLimiter, - PressurePositivityLimiterKuzminExact, DensityPositivityLimiter, SemiDiscEntropyLimiter = limiter + @unpack density_limiter, density_coefficient_for_all, sequential_limiter, conservative_limiter, + positivity_limiter_pressure_exact, positivity_limiter_density, entropy_limiter_semidiscrete = limiter if get(io, :compact, false) show(io, limiter) else setup = ["limiter" => ""] - DensityLimiter && (setup = [setup..., "" => "DensityLimiter"]) - DensityAlphaForAll && (setup = [setup..., "" => "DensityAlphaForAll"]) - SequentialLimiter && (setup = [setup..., "" => "SequentialLimiter"]) - ConservativeLimiter && (setup = [setup..., "" => "ConservativeLimiter"]) - if limiter.PressurePositivityLimiterKuzmin + density_limiter && (setup = [setup..., "" => "Density Limiter"]) + density_coefficient_for_all && + (setup = [setup..., "" => "Transfer density coefficient to all quantities"]) + sequential_limiter && (setup = [setup..., "" => "Sequential Limiter"]) + conservative_limiter && (setup = [setup..., "" => "Conservative Limiter"]) + if limiter.positivity_limiter_pressure setup = [ setup..., - "" => "PressurePositivityLimiterKuzmin $(PressurePositivityLimiterKuzminExact ? "(exact)" : "")", + "" => "$(positivity_limiter_pressure_exact ? "(Sharp)" : "(Cautious)") positivity limiter for Pressure à la Kuzmin", ] end - if DensityPositivityLimiter - if limiter.DensityPositivityCorrectionFactor != 0.0 + if positivity_limiter_density + if limiter.positivity_limiter_correction_factor != 0.0 setup = [ setup..., - "" => "DensityPositivityLimiter with correction factor $(limiter.DensityPositivityCorrectionFactor)", + "" => "Positivity Limiter for Density with correction factor $(limiter.positivity_limiter_correction_factor)", ] else - setup = [setup..., "" => "DensityPositivityLimiter"] + setup = [setup..., "" => "Positivity Limiter for Density"] end end - SemiDiscEntropyLimiter && (setup = [setup..., "" => "SemiDiscEntropyLimiter"]) + entropy_limiter_semidiscrete && + (setup = [setup..., "" => "Semidiscrete Entropy Limiter"]) if limiter.smoothness_indicator setup = [ setup..., @@ -422,12 +425,12 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, node_variables[s] = alpha[v, ntuple(_ -> :, size(alpha, 2) + 1)...] end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure @unpack alpha_pressure = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_pressure] = alpha_pressure end - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete @unpack alpha_entropy = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_entropy] = alpha_entropy end @@ -438,12 +441,12 @@ function get_node_variables!(node_variables, limiter::SubcellLimiterMCL, node_variables[s] = copy(alpha_mean[v, ntuple(_ -> :, size(alpha, 2) + 1)...]) end - if limiter.PressurePositivityLimiterKuzmin + if limiter.positivity_limiter_pressure @unpack alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_mean_pressure] = alpha_mean_pressure end - if limiter.SemiDiscEntropyLimiter + if limiter.entropy_limiter_semidiscrete @unpack alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients node_variables[:alpha_mean_entropy] = alpha_mean_entropy end diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index c948499930..06e682e922 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -725,7 +725,7 @@ end # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, PressurePositivityLimiterKuzmin) + basis::LobattoLegendreBasis, positivity_limiter_pressure) subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterMCL2D{real(basis) }(0, nvariables(equations), @@ -737,7 +737,7 @@ function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquat # Memory for bounds checking routine with `BoundsCheckCallback`. # [maximum since the last export / total maximum, min / max, variable] mcl_bounds_delta = zeros(real(basis), 2, 2, - nvariables(equations) + PressurePositivityLimiterKuzmin) + nvariables(equations) + positivity_limiter_pressure) return (; subcell_limiter_coefficients, container_bar_states, mcl_bounds_delta) end From 849b09e6241dbc8732c5f8ecc49808490788401b Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 16 Nov 2023 12:17:44 +0100 Subject: [PATCH 368/423] Revise derivative function call; Add default derivative version --- src/equations/compressible_euler_2d.jl | 3 ++- src/equations/equations.jl | 6 ++++++ src/equations/ideal_glm_mhd_2d.jl | 3 ++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index f3d46da245..ca10fbac66 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1405,7 +1405,8 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function pressure(u, equations::CompressibleEulerEquations2D, derivative::True) +@inline function variable_derivative(::typeof(pressure), + u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho diff --git a/src/equations/equations.jl b/src/equations/equations.jl index ba2ad1cd1c..fd8e858ae0 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -369,6 +369,12 @@ of the correct length `nvariables(equations)`. """ function energy_internal end +# Default implementation of derivation for `variable`. Used for subcell limiting. +# Implementing a derivative function for a specific function improves the performance. +@inline function variable_derivative(variable, u, equations) + return ForwardDiff.gradient(x -> variable(x, equations), u) +end + #################################################################################################### # Include files with actual implementations for different systems of equations. diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index dd80803e6a..e486b5532b 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1063,7 +1063,8 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function pressure(u, equations::IdealGlmMhdEquations2D, derivative::True) +@inline function variable_derivative(::typeof(pressure), + u, equations::IdealGlmMhdEquations2D) rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u v1 = rho_v1 / rho diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 2ff8c9e8d0..e362d71cac 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -466,7 +466,7 @@ end # Goal and d(Goal)d(u) function @inline goal_function(variable, bound, u, equations) = bound - variable(u, equations) @inline function dgoal_function(variable, u, dt, antidiffusive_flux, equations) - -dot(variable(u, equations, True()), dt * antidiffusive_flux) + -dot(variable_derivative(variable, u, equations), dt * antidiffusive_flux) end # Final checks From 2c75e383e768df60613a5b07605fcafebee24e82 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 16 Nov 2023 16:32:59 +0100 Subject: [PATCH 369/423] Adapt test to actually test pos limiter for nonlinear variables --- test/test_tree_2d_euler.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index dff78694a4..9315ae4d28 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -585,18 +585,18 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl"), l2=[ - 0.05570313943221697, - 0.03298722119008495, - 0.05224470329798064, - 0.08011555326900793, + 0.42185634563805724, + 0.1686471269704017, + 0.18240674916968103, + 0.17858250604280654, ], linf=[ - 0.2409101307301882, - 0.16601896096921037, - 0.12356154796415487, - 0.2695166427148403, + 1.7012978064377158, + 0.7149714986746726, + 0.5822547982757897, + 0.7300051017382696, ], - tspan=(0.0, 0.2)) + tspan=(0.0, 2.0)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From bf69564e35851b037d86e921368bc1d0d6b18ecd Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 16 Nov 2023 17:07:51 +0100 Subject: [PATCH 370/423] Add unit test to test default implementation of variable_derivative --- test/test_unit.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/test_unit.jl b/test/test_unit.jl index d0075e7ac9..6888f62a61 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1105,6 +1105,26 @@ end end end +@testset "Consistency check for variable_derivative routine" begin + # Set up conservative variables, equations + u = [ + 0.5011914484393387, + 0.8829127712445113, + 0.43024132987932817, + 0.7560616633050348, + ] + + equations = CompressibleEulerEquations2D(1.4) + + # Define wrapper function for pressure in order to call default implementation + function pressure_test(u, equations) + return pressure(u, equations) + end + + @test Trixi.variable_derivative(pressure_test, u, equations) ≈ + Trixi.variable_derivative(pressure, u, equations) +end + @testset "Equivalent Fluxes" begin # Set up equations and dummy conservative variables state # Burgers' Equation From e50b5a89a3a6351fc683ad2ea7303c24030eb505 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 16 Nov 2023 22:38:19 +0100 Subject: [PATCH 371/423] Clean up some stuff --- src/solvers/dgsem_tree/subcell_limiters.jl | 32 ++++++++++++---------- test/test_unit.jl | 16 +++++------ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 9fac965192..a967cc035e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -176,11 +176,11 @@ function Base.show(io::IO, limiter::SubcellLimiterIDP) if !(local_minmax || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else - print(io, "limiter=(") - local_minmax && print(io, "min/max limiting, ") - positivity && print(io, "positivity, ") - spec_entropy && print(io, "specific entropy, ") - math_entropy && print(io, "mathematical entropy, ") + print(io, "Limiter=(") + local_minmax && print(io, "Local min/max, ") + positivity && print(io, "Positivity, ") + spec_entropy && print(io, "Specific entropy, ") + math_entropy && print(io, "Mathematical entropy, ") print(io, "), ") end limiter.smoothness_indicator && @@ -199,32 +199,36 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) show(io, limiter) else if !(local_minmax || positivity || spec_entropy || math_entropy) - setup = ["limiter" => "No limiter selected => pure DG method"] + setup = ["Limiter" => "No limiter selected => pure DG method"] else - setup = ["limiter" => ""] + setup = ["Limiter" => ""] if local_minmax setup = [ setup..., - "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", + "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_minmax_variables_cons)", ] end if positivity - string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" + string = "Positivity limiting for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., - "" => " positivity correction factor = $(limiter.positivity_correction_factor)", + "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", ] end if spec_entropy - setup = [setup..., "" => "local minimum bound for specific entropy"] + setup = [setup..., "" => "Local minimum limiting for specific entropy"] end if math_entropy - setup = [setup..., "" => "local maximum bound for mathematical entropy"] + setup = [ + setup..., + "" => "Local maximum limiting for mathematical entropy", + ] end setup = [ setup..., - "Local bounds" => (limiter.bar_states ? "Bar States" : "FV solution"), + "Local bounds with" => (limiter.bar_states ? "Bar States" : + "FV solution"), ] if limiter.smoothness_indicator setup = [ @@ -232,8 +236,8 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", ] end - summary_box(io, "SubcellLimiterIDP", setup) end + summary_box(io, "SubcellLimiterIDP", setup) end end diff --git a/test/test_unit.jl b/test/test_unit.jl index 014eb6f876..224d04f41c 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -414,14 +414,14 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - indicator_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, - true, true, true, "cache", 1, (1.0, 1.0), 1.0, - true, 1.0, nothing) - @test_nowarn show(stdout, indicator_idp) - - indicator_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, - 1.0, true, true, 1.0, nothing, true) - @test_nowarn show(stdout, indicator_mcl) + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, true, true, + true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, + nothing) + @test_nowarn show(stdout, limiter_idp) + + limiter_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, + 1.0, true, true, 1.0, nothing, true) + @test_nowarn show(stdout, limiter_mcl) # TODO: TrixiShallowWater: move unit test indicator_hg_swe = IndicatorHennemannGassnerShallowWater(1.0, 0.0, true, "variable", From 0c9b36f3b9aa31c0ef5ff2c53a1b6df7b3c1b0c9 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 17 Nov 2023 14:09:57 +0100 Subject: [PATCH 372/423] Merge changes from `subcell-limiting-positivty-cons-structured` --- .../subcell_limiter_idp_correction_2d.jl | 83 +++--- src/equations/ideal_glm_mhd_1d.jl | 142 ++++++++++ .../dg_2d_subcell_limiters.jl | 16 +- .../dgsem_structured/subcell_limiters_2d.jl | 9 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 3 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 265 +++++++++++------- test/Project.toml | 2 +- test/test_aqua.jl | 4 +- test/test_tree_1d_mhd.jl | 24 ++ test/test_unit.jl | 1 + 10 files changed, 381 insertions(+), 168 deletions(-) diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index 95a841b406..f7c6fd5582 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -6,9 +6,6 @@ #! format: noindent function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes - @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else @@ -21,27 +18,8 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) inverse_jacobian = -cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, - element) - alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, - j, element) - alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, - element) - alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2_L, equations, dg, i, - j + 1, element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * - (inverse_weights[i] * - (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * - (alpha_flux2_jp1[v] - alpha_flux2[v])) - end + perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, cache, + i, j, element) end end @@ -49,10 +27,6 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) end function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes - @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients - if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else @@ -64,30 +38,41 @@ function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, # Sign switch as in apply_jacobian! inverse_jacobian = -cache.elements.inverse_jacobian[i, j, element] - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, - element) - alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, - j, element) - alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, - element) - alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2_L, equations, dg, i, - j + 1, element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * - (inverse_weights[i] * - (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * - (alpha_flux2_jp1[v] - alpha_flux2[v])) - end + perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, cache, + i, j, element) end end return nothing end + +# Function barrier to dispatch outer function by mesh type +@inline function perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, + cache, i, j, element) + (; inverse_weights) = dg.basis + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; alpha1, alpha2) = dg.volume_integral.limiter.cache.subcell_limiter_coefficients + + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1 - alpha1[i, j, element]) * + get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) + alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * + get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, + element) + alpha_flux2 = (1 - alpha2[i, j, element]) * + get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) + alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * + get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, + element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * + (inverse_weights[i] * + (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * + (alpha_flux2_jp1[v] - alpha_flux2[v])) + end + + return nothing +end end # @muladd diff --git a/src/equations/ideal_glm_mhd_1d.jl b/src/equations/ideal_glm_mhd_1d.jl index 85030e8a5a..a465571989 100644 --- a/src/equations/ideal_glm_mhd_1d.jl +++ b/src/equations/ideal_glm_mhd_1d.jl @@ -259,6 +259,148 @@ Hindenlang and Gassner (2019), extending [`flux_ranocha`](@ref) to the MHD equat return SVector(f1, f2, f3, f4, f5, f6, f7, f8) end +""" + flux_hllc(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D) + +- Li (2005) +An HLLC Riemann solver for magneto-hydrodynamics +[DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020). +""" +function flux_hllc(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations1D) + # Unpack left and right states + rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr = cons2prim(u_rr, equations) + + # Conserved variables + rho_v1_ll = u_ll[2] + rho_v2_ll = u_ll[3] + rho_v3_ll = u_ll[4] + + rho_v1_rr = u_rr[2] + rho_v2_rr = u_rr[3] + rho_v3_rr = u_rr[4] + + # Obtain left and right fluxes + f_ll = flux(u_ll, orientation, equations) + f_rr = flux(u_rr, orientation, equations) + + SsL, SsR = min_max_speed_naive(u_ll, u_rr, orientation, equations) + sMu_L = SsL - v1_ll + sMu_R = SsR - v1_rr + if SsL >= 0 + f1 = f_ll[1] + f2 = f_ll[2] + f3 = f_ll[3] + f4 = f_ll[4] + f5 = f_ll[5] + f6 = f_ll[6] + f7 = f_ll[7] + f8 = f_ll[8] + elseif SsR <= 0 + f1 = f_rr[1] + f2 = f_rr[2] + f3 = f_rr[3] + f4 = f_rr[4] + f5 = f_rr[5] + f6 = f_rr[6] + f7 = f_rr[7] + f8 = f_rr[8] + else + # Compute the "HLLC-speed", eq. (14) from paper mentioned above + #= + SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_ll - p_rr - B1_ll^2 + B1_rr^2 ) / + (rho_rr * sMu_R - rho_ll * sMu_L) + =# + # Simplification for 1D: B1 is constant + SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_ll - p_rr) / + (rho_rr * sMu_R - rho_ll * sMu_L) + + Sdiff = SsR - SsL + + # Compute HLL values for vStar, BStar + # These correspond to eq. (28) and (30) from the referenced paper + # and the classic HLL intermediate state given by (2) + rho_HLL = (SsR * rho_rr - SsL * rho_ll - (f_rr[1] - f_ll[1])) / Sdiff + + v1Star = (SsR * rho_v1_rr - SsL * rho_v1_ll - (f_rr[2] - f_ll[2])) / + (Sdiff * rho_HLL) + v2Star = (SsR * rho_v2_rr - SsL * rho_v2_ll - (f_rr[3] - f_ll[3])) / + (Sdiff * rho_HLL) + v3Star = (SsR * rho_v3_rr - SsL * rho_v3_ll - (f_rr[4] - f_ll[4])) / + (Sdiff * rho_HLL) + + #B1Star = (SsR * B1_rr - SsL * B1_ll - (f_rr[6] - f_ll[6])) / Sdiff + # 1D B1 = constant => B1_ll = B1_rr = B1Star + B1Star = B1_ll + + B2Star = (SsR * B2_rr - SsL * B2_ll - (f_rr[7] - f_ll[7])) / Sdiff + B3Star = (SsR * B3_rr - SsL * B3_ll - (f_rr[8] - f_ll[8])) / Sdiff + if SsL <= SStar + SdiffStar = SsL - SStar + + densStar = rho_ll * sMu_L / SdiffStar # (19) + + mom_1_Star = densStar * SStar # (20) + mom_2_Star = densStar * v2_ll - + (B1Star * B2Star - B1_ll * B2_ll) / SdiffStar # (21) + mom_3_Star = densStar * v3_ll - + (B1Star * B3Star - B1_ll * B3_ll) / SdiffStar # (22) + + #pstar = rho_ll * sMu_L * (SStar - v1_ll) + p_ll - B1_ll^2 + B1Star^2 # (17) + # 1D B1 = constant => B1_ll = B1_rr = B1Star + pstar = rho_ll * sMu_L * (SStar - v1_ll) + p_ll # (17) + + enerStar = u_ll[5] * sMu_L / SdiffStar + + (pstar * SStar - p_ll * v1_ll - (B1Star * + (B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) - + B1_ll * (B1_ll * v1_ll + B2_ll * v2_ll + B3_ll * v3_ll))) / + SdiffStar # (23) + + # Classic HLLC update (32) + f1 = f_ll[1] + SsL * (densStar - u_ll[1]) + f2 = f_ll[2] + SsL * (mom_1_Star - u_ll[2]) + f3 = f_ll[3] + SsL * (mom_2_Star - u_ll[3]) + f4 = f_ll[4] + SsL * (mom_3_Star - u_ll[4]) + f5 = f_ll[5] + SsL * (enerStar - u_ll[5]) + f6 = f_ll[6] + SsL * (B1Star - u_ll[6]) + f7 = f_ll[7] + SsL * (B2Star - u_ll[7]) + f8 = f_ll[8] + SsL * (B3Star - u_ll[8]) + else # SStar <= Ssr + SdiffStar = SsR - SStar + + densStar = rho_rr * sMu_R / SdiffStar # (19) + + mom_1_Star = densStar * SStar # (20) + mom_2_Star = densStar * v2_rr - + (B1Star * B2Star - B1_rr * B2_rr) / SdiffStar # (21) + mom_3_Star = densStar * v3_rr - + (B1Star * B3Star - B1_rr * B3_rr) / SdiffStar # (22) + + #pstar = rho_rr * sMu_R * (SStar - v1_rr) + p_rr - B1_rr^2 + B1Star^2 # (17) + # 1D B1 = constant => B1_ll = B1_rr = B1Star + pstar = rho_rr * sMu_R * (SStar - v1_rr) + p_rr # (17) + + enerStar = u_rr[5] * sMu_R / SdiffStar + + (pstar * SStar - p_rr * v1_rr - (B1Star * + (B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) - + B1_rr * (B1_rr * v1_rr + B2_rr * v2_rr + B3_rr * v3_rr))) / + SdiffStar # (23) + + # Classic HLLC update (32) + f1 = f_rr[1] + SsR * (densStar - u_rr[1]) + f2 = f_rr[2] + SsR * (mom_1_Star - u_rr[2]) + f3 = f_rr[3] + SsR * (mom_2_Star - u_rr[3]) + f4 = f_rr[4] + SsR * (mom_3_Star - u_rr[4]) + f5 = f_rr[5] + SsR * (enerStar - u_rr[5]) + f6 = f_rr[6] + SsR * (B1Star - u_rr[6]) + f7 = f_rr[7] + SsR * (B2Star - u_rr[7]) + f8 = f_rr[8] + SsR * (B3Star - u_rr[8]) + end + end + return SVector(f1, f2, f3, f4, f5, f6, f7, f8) +end + # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation @inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D) diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 8d0894f251..46953feb14 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -5,13 +5,17 @@ @muladd begin #! format: noindent +# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element +# (**without non-conservative terms**). +# +# See also `flux_differencing_kernel!`. @inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::StructuredMesh{2}, nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) - @unpack contravariant_vectors = cache.elements - @unpack weights, derivative_split = dg.basis - @unpack flux_temp_threaded = cache + (; contravariant_vectors) = cache.elements + (; weights, derivative_split) = dg.basis + (; flux_temp_threaded) = cache flux_temp = flux_temp_threaded[Threads.threadid()] @@ -112,10 +116,10 @@ end if limiter isa SubcellLimiterIDP && !limiter.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states - @unpack contravariant_vectors = cache.elements + (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states + (; contravariant_vectors) = cache.elements - @unpack normal_direction_xi, normal_direction_eta = limiter.cache.container_bar_states + (; normal_direction_xi, normal_direction_eta) = limiter.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) diff --git a/src/solvers/dgsem_structured/subcell_limiters_2d.jl b/src/solvers/dgsem_structured/subcell_limiters_2d.jl index 52fbb6b53c..c5c21c34ff 100644 --- a/src/solvers/dgsem_structured/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_structured/subcell_limiters_2d.jl @@ -8,8 +8,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, mesh::StructuredMesh{2}) _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack contravariant_vectors = cache.elements + (; boundary_conditions) = semi + (; contravariant_vectors) = cache.elements + # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids @@ -130,8 +131,8 @@ end function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, semi, mesh::StructuredMesh{2}) _, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack boundary_conditions = semi - @unpack contravariant_vectors = cache.elements + (; boundary_conditions) = semi + (; contravariant_vectors) = cache.elements # Calc bounds at interfaces and periodic boundaries for element in eachelement(dg, cache) # Get neighboring element ids diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 3783ead020..2c6ab93a6f 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -123,8 +123,7 @@ function calc_volume_integral!(du, u, end end -@inline function subcell_limiting_kernel!(du, u, - element, +@inline function subcell_limiting_kernel!(du, u, element, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, nonconservative_terms, equations, volume_integral, limiter::SubcellLimiterIDP, diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 06e682e922..153fa59957 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -330,17 +330,18 @@ end end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) + mesh, _, _, _ = mesh_equations_solver_cache(semi) + for variable in limiter.local_minmax_variables_cons - idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable) + idp_local_minmax!(alpha, limiter, u, t, dt, semi, mesh, elements, variable) end return nothing end -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements, variable) - mesh, _, dg, cache = mesh_equations_solver_cache(semi) - (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - (; inverse_weights) = dg.basis +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, + elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients variable_string = string(variable) @@ -351,60 +352,90 @@ end end @threaded for element in elements - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, variable, + var_min, var_max, i, j, element) end + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, + mesh::StructuredMesh{2}, elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + variable_string = string(variable) + var_min = variable_bounds[Symbol(variable_string, "_min")] + var_max = variable_bounds[Symbol(variable_string, "_max")] + if !limiter.bar_states + calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) + end + + @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end - var = u[variable, i, j, element] - # Real Zalesak type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pp and Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1_R[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1_L[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2_R[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2_L[variable, i, j + 1, element] - - Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + - max(0, val_flux2_local) + max(0, val_flux2_local_jp1) - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - Pp = inverse_jacobian * Pp - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / - (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) - Qm = abs(Qm) / - (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, variable, + var_min, var_max, i, j, element) end end return nothing end +# Function barrier to dispatch outer function by mesh type +@inline function idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, + variable, var_min, var_max, i, j, element) + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + + var = u[variable, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pp and Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1_R[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1_L[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2_R[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2_L[variable, i, j + 1, element] + + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / + (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / + (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) + + return nothing +end + @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -450,9 +481,11 @@ end end @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) + mesh, _, _, _ = mesh_equations_solver_cache(semi) + # Conservative variables for variable in limiter.positivity_variables_cons - idp_positivity!(alpha, limiter, u, dt, semi, elements, variable) + idp_positivity!(alpha, limiter, u, dt, semi, mesh, elements, variable) end # Nonlinear variables @@ -463,73 +496,96 @@ end return nothing end -@inline function idp_positivity!(alpha, limiter, u, dt, semi, elements, variable) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - (; inverse_weights) = dg.basis - (; positivity_correction_factor) = limiter +@inline function idp_positivity!(alpha, limiter, u, dt, semi, mesh::TreeMesh{2}, + elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in elements - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - end + inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end + idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, cache, + variable, var_min, i, j, element) + end + end - var = u[variable, i, j, element] - if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") - end + return nothing +end - # Compute bound - if limiter.local_minmax && - variable in limiter.local_minmax_variables_cons && - var_min[i, j, element] >= positivity_correction_factor * var - # Local limiting is more restrictive that positivity limiting - # => Skip positivity limiting for this node - continue - end - var_min[i, j, element] = positivity_correction_factor * var +@inline function idp_positivity!(alpha, limiter, u, dt, semi, mesh::StructuredMesh{2}, + elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) - # Real one-sided Zalesak-type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1_R[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1_L[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2_R[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2_L[variable, i, j + 1, element] - - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) - - # Calculate alpha - alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol(string(variable), "_min")] + + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, cache, + variable, var_min, i, j, element) end end return nothing end +# Function barrier to dispatch outer function by mesh type +@inline function idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, + cache, variable, var_min, i, j, element) + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + (; positivity_correction_factor) = limiter + + var = u[variable, i, j, element] + if var < 0 + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + end + + # Compute bound + if limiter.local_minmax && + variable in limiter.local_minmax_variables_cons && + var_min[i, j, element] >= positivity_correction_factor * var + # Local limiting is more restrictive that positivity limiting + # => Skip positivity limiting for this node + return nothing + end + var_min[i, j, element] = positivity_correction_factor * var + + # Real one-sided Zalesak-type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1_R[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1_L[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2_R[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2_L[variable, i, j + 1, element] + + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) + + # Calculate alpha + alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) + + return nothing +end + @inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @@ -564,6 +620,7 @@ end dg, cache, limiter) @unpack inverse_weights = dg.basis @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + # TODO: Pass inverse_jacobian for the correct mesh type if mesh isa TreeMesh inverse_jacobian = cache.elements.inverse_jacobian[element] else # mesh isa StructuredMesh diff --git a/test/Project.toml b/test/Project.toml index fcb96b9e48..ecae0ac090 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -12,7 +12,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] -Aqua = "0.7" +Aqua = "0.8" CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" Downloads = "1" ForwardDiff = "0.10" diff --git a/test/test_aqua.jl b/test/test_aqua.jl index 9f57791406..93457caba2 100644 --- a/test/test_aqua.jl +++ b/test/test_aqua.jl @@ -11,8 +11,8 @@ include("test_trixi.jl") ambiguities = false, # exceptions necessary for adding a new method `StartUpDG.estimate_h` # in src/solvers/dgmulti/sbp.jl - piracy = (treat_as_own = [Trixi.StartUpDG.RefElemData, - Trixi.StartUpDG.MeshData],)) + piracies = (treat_as_own = [Trixi.StartUpDG.RefElemData, + Trixi.StartUpDG.MeshData],)) end end #module diff --git a/test/test_tree_1d_mhd.jl b/test/test_tree_1d_mhd.jl index b34bdf0660..447572eee8 100644 --- a/test/test_tree_1d_mhd.jl +++ b/test/test_tree_1d_mhd.jl @@ -206,6 +206,30 @@ end end end +@trixi_testset "elixir_mhd_torrilhon_shock_tube.jl (HLLC)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_torrilhon_shock_tube.jl"), + surface_flux=flux_hllc, + l2=[ + 0.4574266553239646, 0.4794143154876439, 0.3407079689595056, + 0.44797768430829343, 0.9206916204424165, + 1.3216517820475193e-16, 0.2889748702415378, + 0.25529778018020927, + ], + linf=[ + 1.217943947570543, 0.8868438459815245, 0.878215340656725, + 0.9710882819266371, 1.6742759645320984, + 2.220446049250313e-16, 0.704710220504591, 0.6562122176458641, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + @trixi_testset "elixir_mhd_ryujones_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ryujones_shock_tube.jl"), l2=[ diff --git a/test/test_unit.jl b/test/test_unit.jl index 224d04f41c..d4c11da635 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -964,6 +964,7 @@ end for u in u_values @test flux_hlle(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hllc(u, u, 1, equations) ≈ flux(u, 1, equations) end equations = IdealGlmMhdEquations2D(1.4, 5.0) #= c_h =# From 5af578fce744341c14ac88ae39159afb81d3b66c Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 17 Nov 2023 14:16:36 +0100 Subject: [PATCH 373/423] Add comments --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 153fa59957..9d6074998b 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -329,6 +329,9 @@ end return nothing end +############################################################################### +# Local minimum/maximum limiting + @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) mesh, _, _, _ = mesh_equations_solver_cache(semi) @@ -436,6 +439,9 @@ end return nothing end +############################################################################### +# Local minimum limiting of specific entropy + @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -458,6 +464,9 @@ end return nothing end +############################################################################### +# Local maximum limiting of mathematical entropy + @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -480,6 +489,9 @@ end return nothing end +############################################################################### +# Global positivity limiting + @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) mesh, _, _, _ = mesh_equations_solver_cache(semi) @@ -496,6 +508,9 @@ end return nothing end +############################################################################### +# Global positivity limiting of conservative variables + @inline function idp_positivity!(alpha, limiter, u, dt, semi, mesh::TreeMesh{2}, elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) @@ -586,6 +601,9 @@ end return nothing end +############################################################################### +# Global positivity limiting of non-linear variables + @inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) @@ -615,6 +633,9 @@ end return nothing end +############################################################################### +# Newton-bisection method + @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, initial_check, final_check, dt, mesh, equations, dg, cache, limiter) From e09ed2879594d584370c1ecdf8b3022de03621b2 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 10:25:31 +0100 Subject: [PATCH 374/423] Extract inner code of entropy limiters due to dispatching --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 198 +++++++++++++----- 1 file changed, 143 insertions(+), 55 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9d6074998b..116658cea9 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -5,6 +5,10 @@ @muladd begin #! format: noindent +############################################################################### +# IDP Limiting +############################################################################### + # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, bound_keys, bar_states) @@ -35,6 +39,8 @@ end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, dt; kwargs...) + mesh, _, _, _ = mesh_equations_solver_cache(semi) + @unpack alpha = limiter.cache.subcell_limiter_coefficients @trixi_timeit timer() "reset alpha" reset_du!(alpha, dg, semi.cache) @@ -55,13 +61,11 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE end if limiter.spec_entropy @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, - dt, - semi, elements) + dt, semi, mesh, elements) end if limiter.math_entropy @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, - dt, - semi, elements) + dt, semi, mesh, elements) end # Calculate alpha1 and alpha2 @@ -84,6 +88,9 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE return nothing end +############################################################################### +# Calculation of local bounds using low-order FV solution + @inline function calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @@ -442,8 +449,9 @@ end ############################################################################### # Local minimum limiting of specific entropy -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, elements) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, + elements) + _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_min = variable_bounds[:spec_entropy_min] if !limiter.bar_states @@ -452,12 +460,37 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in elements + inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, + newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, + i, j, element, dt, equations, dg, cache, limiter, entropy_spec, initial_check_entropy_spec, - final_check_standard, - dt, mesh, equations, dg, cache, limiter) + final_check_standard) + end + end + + return nothing +end + +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, + mesh::StructuredMesh{2}, elements) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_min = variable_bounds[:spec_entropy_min] + if !limiter.bar_states + calc_bounds_onesided!(s_min, min, typemax, entropy_spec, u, t, semi) + end + + # Perform Newton's bisection method to find new alpha + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + inverse_jacobian = cache.elements.inverse_jacobian[element] + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, + i, j, element, dt, equations, dg, cache, limiter, + entropy_spec, initial_check_entropy_spec, + final_check_standard) end end @@ -467,8 +500,34 @@ end ############################################################################### # Local maximum limiting of mathematical entropy -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, elements) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, + elements) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_max = variable_bounds[:math_entropy_max] + if !limiter.bar_states + calc_bounds_onesided!(s_max, max, typemin, entropy_math, u, t, semi) + end + + # Perform Newton's bisection method to find new alpha + @threaded for element in elements + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, + i, j, element, dt, equations, dg, cache, limiter, + entropy_math, initial_check_entropy_math, + final_check_standard) + end + end + + return nothing +end + +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, + mesh::StructuredMesh{2}, + elements) + _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_max = variable_bounds[:math_entropy_max] if !limiter.bar_states @@ -478,11 +537,12 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) + inverse_jacobian = cache.elements.inverse_jacobian[element] u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, + newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, + i, j, element, dt, equations, dg, cache, limiter, entropy_math, initial_check_entropy_math, - final_check_standard, - dt, mesh, equations, dg, cache, limiter) + final_check_standard) end end @@ -496,13 +556,13 @@ end mesh, _, _, _ = mesh_equations_solver_cache(semi) # Conservative variables - for variable in limiter.positivity_variables_cons + @trixi_timeit timer() "conservative variables" for variable in limiter.positivity_variables_cons idp_positivity!(alpha, limiter, u, dt, semi, mesh, elements, variable) end # Nonlinear variables - for variable in limiter.positivity_variables_nonlinear - idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, variable) + @trixi_timeit timer() "non-linear variables" for variable in limiter.positivity_variables_nonlinear + idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, mesh, elements, variable) end return nothing @@ -604,87 +664,111 @@ end ############################################################################### # Global positivity limiting of non-linear variables -@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, - variable) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - (; positivity_correction_factor) = limiter +@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, + mesh::TreeMesh{2}, elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in elements + inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - # Compute bound - u_local = get_node_vars(u, equations, dg, i, j, element) - var = variable(u_local, equations) - if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") - end - var_min[i, j, element] = positivity_correction_factor * var + idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, dt, + semi, dg, cache, variable, var_min, + i, j, element) + end + end + + return nothing +end + +@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, + mesh::StructuredMesh{2}, elements, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol(string(variable), "_min")] - # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, - variable, initial_check_nonnegative, - final_check_nonnegative, - dt, mesh, equations, dg, cache, limiter) + @threaded for element in elements + for j in eachnode(dg), i in eachnode(dg) + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, dt, + semi, dg, cache, variable, var_min, + i, j, element) end end return nothing end +# Function barrier to dispatch outer function by mesh type +@inline function idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, + dt, semi, dg, cache, variable, var_min, + i, j, element) + _, equations, _, _ = mesh_equations_solver_cache(semi) + + u_local = get_node_vars(u, equations, dg, i, j, element) + var = variable(u_local, equations) + if var < 0 + error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + end + var_min[i, j, element] = limiter.positivity_correction_factor * var + + # Perform Newton's bisection method to find new alpha + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, inverse_jacobian, i, j, + element, dt, equations, dg, cache, limiter, variable, + initial_check_nonnegative, final_check_nonnegative) + + return nothing +end + ############################################################################### # Newton-bisection method -@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, - initial_check, final_check, dt, mesh, equations, - dg, cache, limiter) - @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes - # TODO: Pass inverse_jacobian for the correct mesh type - if mesh isa TreeMesh - inverse_jacobian = cache.elements.inverse_jacobian[element] - else # mesh isa StructuredMesh - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - end +@inline function newton_loops_alpha!(alpha, bound, u, inverse_jacobian, i, j, element, + dt, equations, dg, cache, limiter, + variable, initial_check, final_check) + (; inverse_weights) = dg.basis + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - @unpack gamma_constant_newton = limiter + (; gamma_constant_newton) = limiter # negative xi direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, equations, dt, limiter, + antidiffusive_flux, variable, initial_check, final_check) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, equations, dt, limiter, + antidiffusive_flux, variable, initial_check, final_check) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, equations, dt, limiter, + antidiffusive_flux, variable, initial_check, final_check) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, equations, dt, limiter, + antidiffusive_flux, variable, initial_check, final_check) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, - final_check, equations, dt, limiter, antidiffusive_flux) +@inline function newton_loop!(alpha, bound, u, i, j, element, equations, dt, limiter, + antidiffusive_flux, variable, initial_check, final_check) newton_reltol, newton_abstol = limiter.newton_tolerances beta = 1 - alpha[i, j, element] @@ -801,6 +885,10 @@ end (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end +############################################################################### +# Monolithic Convex Limiting +############################################################################### + # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, positivity_limiter_pressure) From 3a206222a3a86f6b21b09742761a0a1be4774767 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 10:30:22 +0100 Subject: [PATCH 375/423] Fix blast wave test --- test/test_tree_2d_euler.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index c3c2d658f4..b98890814c 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -365,16 +365,16 @@ end @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), l2=[ - 0.30785002807815187, - 0.1759956703391451, - 0.1759417566220675, - 0.6141201710105174, + 0.30785094769124677, + 0.17599603017990473, + 0.17594201496603085, + 0.614120201076276, ], linf=[ - 1.2971792413978331, - 1.1057407237412735, - 1.1057665512872346, - 2.436409926521213, + 1.2971828380703805, + 1.1057475500114755, + 1.105770653844522, + 2.4364101844067916 ], tspan=(0.0, 0.5), initial_refinement_level=4, From 1aa2eaf1e8f8d7cc91968c3fa306b3091d506b31 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 10:33:29 +0100 Subject: [PATCH 376/423] Format --- test/test_tree_2d_euler.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index b98890814c..d2fec9b63b 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -374,7 +374,7 @@ end 1.2971828380703805, 1.1057475500114755, 1.105770653844522, - 2.4364101844067916 + 2.4364101844067916, ], tspan=(0.0, 0.5), initial_refinement_level=4, From 4830bbbbbeebee25276c203a2378a5380c4f9da1 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 12:02:29 +0100 Subject: [PATCH 377/423] Fix entropy limiter for StructuredMesh --- .../elixir_euler_shock_upstream_sc_subcell.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 7 +++---- test/test_structured_2d.jl | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 303cfa71de..3bfa027197 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -96,7 +96,7 @@ mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" -cells_per_dimension = (24, 36) +cells_per_dimension = (8, 12) mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string = mapping_as_string, periodicity = false) @@ -107,7 +107,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 10.0) +tspan = (0.0, 2.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 116658cea9..01764a3996 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -485,7 +485,7 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[element] + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, @@ -525,8 +525,7 @@ end end @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, - mesh::StructuredMesh{2}, - elements) + mesh::StructuredMesh{2}, elements) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_max = variable_bounds[:math_entropy_max] @@ -537,7 +536,7 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[element] + inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 405709242c..622d6daf2e 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -664,7 +664,6 @@ end 10.06523457762742, 51.00903155017642, ], - cells_per_dimension=(8, 12), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From af19dbf3a7706ad248cc1ca5968dc0d2e8c328c4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 12:34:53 +0100 Subject: [PATCH 378/423] Fix typo --- src/solvers/dgsem_tree/subcell_limiters.jl | 6 +++--- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index a967cc035e..dc1bf13772 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -37,16 +37,16 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) -- Positivity limiting for conservative (`positivity_variables_cons`) and non-linear variables (`positivity_variables_nonlinear`) +- Positivity limiting for conservative (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) - One-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. For non-linear variables the specific functions are +and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. -The Newton-bisection method for the limiting of non-linear variables uses maximal `max_iterations_newton` +The Newton-bisection method for the limiting of nonlinear variables uses maximal `max_iterations_newton` iterations, tolerances `newton_tolerances` and the gamma constant `gamma_constant_newton` (gamma_constant_newton>=2*d, where d=#dimensions). diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 01764a3996..c37276c580 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -555,13 +555,22 @@ end mesh, _, _, _ = mesh_equations_solver_cache(semi) # Conservative variables - @trixi_timeit timer() "conservative variables" for variable in limiter.positivity_variables_cons - idp_positivity!(alpha, limiter, u, dt, semi, mesh, elements, variable) + for variable in limiter.positivity_variables_cons + @trixi_timeit timer() "conservative variables" idp_positivity!(alpha, limiter, + u, dt, semi, + mesh, elements, + variable) end # Nonlinear variables - @trixi_timeit timer() "non-linear variables" for variable in limiter.positivity_variables_nonlinear - idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, mesh, elements, variable) + for variable in limiter.positivity_variables_nonlinear + @trixi_timeit timer() "nonlinear variables" idp_positivity_nonlinear!(alpha, + limiter, + u, dt, + semi, + mesh, + elements, + variable) end return nothing @@ -661,7 +670,7 @@ end end ############################################################################### -# Global positivity limiting of non-linear variables +# Global positivity limiting of nonlinear variables @inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, mesh::TreeMesh{2}, elements, variable) From 36b2481b2049313f24a10b8cd3231e3cd8ba73e3 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 20 Nov 2023 13:14:42 +0100 Subject: [PATCH 379/423] Clean up comments and code --- src/solvers/dgsem_tree/subcell_limiters.jl | 18 ++++----- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 38 +++++++++++++++---- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 554c481017..86d70e3853 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -25,16 +25,16 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) -- Positivity limiting for conservative variables (`positivity_variables_cons`) and non-linear variables +- Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. For non-linear variables the specific functions are +and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. -The limiting of non-linear variables uses a Newton-bisection method with a maximum of +The limiting of nonlinear variables uses a Newton-bisection method with a maximum of `max_iterations_newton` iterations, relative and absolute tolerances of `newton_tolerances` and a gamma constant of `gamma_constant_newton` (`gamma_constant_newton>=2*d`, where `d = #dimensions`). @@ -124,9 +124,9 @@ function Base.show(io::IO, limiter::SubcellLimiterIDP) if !(local_minmax || positivity) print(io, "No limiter selected => pure DG method") else - print(io, "limiter=(") - local_minmax && print(io, "min/max limiting, ") - positivity && print(io, "positivity") + print(io, "Limiter=(") + local_minmax && print(io, "Local min/max, ") + positivity && print(io, "Positivity, ") print(io, "), ") end print(io, "Local bounds with FV solution") @@ -147,15 +147,15 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) if local_minmax setup = [ setup..., - "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", + "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_minmax_variables_cons)", ] end if positivity - string = "positivity for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" + string = "Positivity limiting for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" setup = [setup..., "" => string] setup = [ setup..., - "" => " positivity correction factor = $(limiter.positivity_correction_factor)", + "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", ] end setup = [ diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index e362d71cac..1b6e8d318e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -5,6 +5,10 @@ @muladd begin #! format: noindent +############################################################################### +# IDP Limiting +############################################################################### + # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, basis::LobattoLegendreBasis, bound_keys) @@ -56,6 +60,9 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE return nothing end +############################################################################### +# Calculation of local bounds using low-order FV solution + @inline function calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @@ -154,6 +161,9 @@ end return nothing end +############################################################################### +# Local minimum/maximum limiting + @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi) for variable in limiter.local_minmax_variables_cons idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) @@ -223,20 +233,32 @@ end return nothing end +############################################################################### +# Global positivity limiting + @inline function idp_positivity!(alpha, limiter, u, dt, semi) # Conservative variables for variable in limiter.positivity_variables_cons - idp_positivity!(alpha, limiter, u, dt, semi, variable) + @trixi_timeit timer() "conservative variables" idp_positivity!(alpha, limiter, + u, dt, semi, + variable) end # Nonlinear variables for variable in limiter.positivity_variables_nonlinear - idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, variable) + @trixi_timeit timer() "nonlinear variables" idp_positivity_nonlinear!(alpha, + limiter, + u, dt, + semi, + variable) end return nothing end +############################################################################### +# Global positivity limiting of conservative variables + @inline function idp_positivity!(alpha, limiter, u, dt, semi, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes @@ -299,13 +321,14 @@ end end @inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, variable) - mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + _, equations, dg, cache = mesh_equations_solver_cache(semi) (; positivity_correction_factor) = limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in eachelement(dg, semi.cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) # Compute bound u_local = get_node_vars(u, equations, dg, i, j, element) @@ -318,8 +341,8 @@ end # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, variable, initial_check_nonnegative, - final_check_nonnegative, - dt, mesh, equations, dg, cache, limiter) + final_check_nonnegative, inverse_jacobian, + dt, equations, dg, cache, limiter) end end @@ -327,11 +350,10 @@ end end @inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, - initial_check, final_check, dt, mesh, equations, - dg, cache, limiter) + initial_check, final_check, inverse_jacobian, dt, + equations, dg, cache, limiter) (; inverse_weights) = dg.basis (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - inverse_jacobian = cache.elements.inverse_jacobian[element] (; gamma_constant_newton) = limiter From dbc79a7bd122bfdb45462da9c96e38bfd3b2093a Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 22 Nov 2023 16:10:42 +0100 Subject: [PATCH 380/423] Add approved changes from P4estMesh PR --- .../elixir_euler_free_stream_MCL.jl | 2 +- .../elixir_euler_free_stream_sc_subcell.jl | 7 +- .../elixir_euler_shock_upstream_MCL.jl | 4 +- src/callbacks_step/stepsize_dg2d.jl | 2 +- src/equations/compressible_euler_2d.jl | 53 +++------ src/equations/equations.jl | 6 +- .../dg_2d_subcell_limiters.jl | 15 ++- src/time_integration/methods_SSP.jl | 6 +- test/test_structured_2d.jl | 111 +++++++++--------- 9 files changed, 103 insertions(+), 103 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl index 623e69bcaa..62d03abc6e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -51,7 +51,7 @@ function mapping(xi_, eta_) return SVector(x, y) end -cells_per_dimension = (32, 32) +cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 6f81e38574..e67130f881 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -18,10 +18,7 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, spec_entropy = false, - smoothness_indicator = false, - bar_states = true, - max_iterations_newton = 10, - newton_tolerances = (1.0e-12, 1.0e-14)) + bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, @@ -49,7 +46,7 @@ function mapping(xi_, eta_) return SVector(x, y) end -cells_per_dimension = (32, 32) +cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl index cc12990ab1..2f2bc26f21 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_MCL.jl @@ -101,7 +101,7 @@ mapping_as_string = "a = sqrt(5.9^2 - 3.85^2); alpha = acos(3.85 / 5.9); l = (pi "f4(s) = SVector(0.0, -(a - 1.0) * 0.5 * (s + 1.0) + a); " * "faces = (f1, f2, f3, f4); mapping = Trixi.transfinite_mapping(faces)" -cells_per_dimension = (24, 36) +cells_per_dimension = (8, 12) mesh = StructuredMesh(cells_per_dimension, mapping_bow, mapping_as_string = mapping_as_string, periodicity = false) @@ -112,7 +112,7 @@ semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 10.0) +tspan = (0.0, 2.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 1bf7402ae7..f66686ff36 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -43,7 +43,7 @@ function max_dt(u, t, mesh::TreeMesh{2}, return 2 / (nnodes(dg) * max_scaled_speed) end -@inline function max_dt(u, t, mesh::Union{TreeMesh, StructuredMesh}, +@inline function max_dt(u, t, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, constant_speed::False, equations, semi, dg::DG, cache, limiter::Union{SubcellLimiterIDP, SubcellLimiterMCL}) @unpack inverse_weights = dg.basis diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index f008958f22..7488f172bb 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -394,9 +394,11 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end +# TODO: Add docstring when about to merge. @inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, orientation::Integer, - direction, x, t, equations) + direction, x, t, + equations::CompressibleEulerEquations2D) # Get inverse of density srho = 1 / u_inner[1] @@ -412,44 +414,16 @@ end vn = factor * u_inner[3] * srho end - # get pressure and Mach from state - p = pressure(u_inner, equations) - a = sqrt(equations.gamma * p * srho) - normalMachNo = abs(vn / a) - - if vn < 0 # inflow - if normalMachNo < 1.0 - # subsonic inflow: All variables from outside but pressure - cons = outer_boundary_value_function(x, t, equations) - - prim = cons2prim(cons, equations) - prim = SVector(view(prim, 1:3)..., p) - cons = prim2cons(prim, equations) - else - # supersonic inflow: All variables from outside - cons = outer_boundary_value_function(x, t, equations) - end - else # outflow - if normalMachNo < 1.0 - # subsonic outflow: All variables from inside but pressure - cons = outer_boundary_value_function(x, t, equations) - - prim = cons2prim(u_inner, equations) - prim = SVector(view(prim, 1:3)..., pressure(cons, equations)) - cons = prim2cons(prim, equations) - else - # supersonic outflow: All variables from inside - cons = u_inner - end - end - - return cons + return characteristic_boundary_value_function_inner(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations) end @inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, normal_direction::AbstractVector, - direction, x, t, equations) + direction, x, t, + equations::CompressibleEulerEquations2D) # Get inverse of density srho = 1 / u_inner[1] @@ -459,10 +433,19 @@ end else # u_boundary is "left" of boundary, u_inner is "right" of boundary factor = -1 end - vn = factor * + vn = factor * srho * (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) / norm(normal_direction) + return characteristic_boundary_value_function_inner(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations) +end + +# Inner function to distinguish between different mesh types. +@inline function characteristic_boundary_value_function_inner(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations::CompressibleEulerEquations2D) # get pressure and Mach from state p = pressure(u_inner, equations) a = sqrt(equations.gamma * p * srho) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index e88ba97d79..516f22ff33 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -203,6 +203,10 @@ end """ BoundaryConditionCharacteristic(outer_boundary_value_function) +Characteristic-based boundary condition. + +!!! warning "Experimental code" + This numerical flux is experimental and may change in any future release. """ struct BoundaryConditionCharacteristic{B, C} outer_boundary_value_function::B @@ -215,7 +219,7 @@ function BoundaryConditionCharacteristic(outer_boundary_value_function) characteristic_boundary_value_function) end -# Dirichlet-type boundary condition for use with TreeMesh or StructuredMesh +# Characteristic-based boundary condition for use with TreeMesh or StructuredMesh @inline function (boundary_condition::BoundaryConditionCharacteristic)(u_inner, orientation_or_normal, direction, diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 46953feb14..4db5d5a3bf 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -117,8 +117,6 @@ end return nothing end (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states - (; contravariant_vectors) = cache.elements - (; normal_direction_xi, normal_direction_eta) = limiter.cache.container_bar_states # Calc lambdas and bar states inside elements @@ -166,6 +164,19 @@ end end end + calc_lambdas_bar_states_interface!(u, t, limiter, boundary_conditions, mesh, + equations, + dg, cache; calc_bar_states = calc_bar_states) + + return nothing +end + +@inline function calc_lambdas_bar_states_interface!(u, t, limiter, boundary_conditions, + mesh::StructuredMesh{2}, equations, + dg, cache; calc_bar_states = true) + (; contravariant_vectors) = cache.elements + (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states + # Calc lambdas and bar states at interfaces and periodic boundaries @threaded for element in eachelement(dg, cache) # Get neighboring element ids diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 3aacd4a5da..7443e6ed26 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -271,10 +271,10 @@ end function calc_normal_directions!(container_bar_states, mesh::StructuredMesh, equations, dg, cache) - @unpack weights, derivative_matrix = dg.basis - @unpack contravariant_vectors = cache.elements + (; weights, derivative_matrix) = dg.basis + (; contravariant_vectors) = cache.elements - @unpack normal_direction_xi, normal_direction_eta = container_bar_states + (; normal_direction_xi, normal_direction_eta) = container_bar_states @threaded for element in eachelement(dg, cache) for j in eachnode(dg) normal_direction = get_contravariant_vector(1, contravariant_vectors, 1, j, diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index e317783f95..ea2477e6df 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -539,19 +539,18 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_sc_subcell.jl"), l2=[ - 2.6224749465938795e-14, - 1.6175366858083413e-14, - 2.358782725951525e-14, - 5.910156539173304e-14, + 1.4663777294625118e-15, + 2.320054900530864e-14, + 3.487555722563465e-14, + 2.008802099296406e-14, ], linf=[ - 1.1546319456101628e-14, - 1.084687895058778e-13, - 1.7050250100680842e-13, - 2.0250467969162855e-13, + 2.3092638912203256e-14, + 2.0623780461193064e-13, + 2.6795232699328153e-13, + 2.362554596402333e-13, ], - atol=1.0e-13, - cells_per_dimension=(8, 8)) + atol=7.0e-13) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -565,19 +564,18 @@ end @trixi_testset "elixir_euler_free_stream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_MCL.jl"), l2=[ - 3.532639560334565e-14, - 1.4787576718355913e-14, - 2.109573923923632e-14, - 2.54649935281524e-14, + 8.457600308458635e-16, + 2.185478357408446e-14, + 3.14987670823871e-14, + 1.6817763381190492e-14, ], linf=[ - 7.993605777301127e-15, - 1.1611545058798356e-13, - 1.7619239400801234e-13, - 2.007283228522283e-13, + 2.1316282072803006e-14, + 2.0759782781709646e-13, + 2.4705237855471296e-13, + 2.255973186038318e-13, ], - atol=1.0e-13, - cells_per_dimension=(8, 8)) + atol=7.0e-13) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -617,34 +615,42 @@ end @trixi_testset "elixir_euler_double_mach.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), l2=[ - 0.8955457632754655, - 6.8117495933240235, - 3.2697118944675716, - 77.5174041919109, + 0.8895735118233061, + 6.7732502383794655, + 3.2537120458330913, + 77.15211199077615, ], linf=[ - 10.16165871096883, - 133.2522870057006, - 38.23157147773949, - 1470.3950960145828, + 10.595204890391603, + 133.14647204580373, + 39.59427444784427, + 1467.649170200717, ], initial_refinement_level=3, 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)) < 10000 + end end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ - 0.9266313242695542, - 7.071517579972717, - 3.2627078543492787, - 80.24631724351916, + 0.9230564188859353, + 7.048067525695328, + 3.2513897966486693, + 80.02373234685636, ], linf=[ - 14.244598580563007, - 138.4745277257612, - 38.69633620234036, - 1574.6686216469134, + 13.994085024959638, + 138.49691741864086, + 38.68709126443809, + 1574.7770582279284, ], initial_refinement_level=3, tspan=(0.0, 0.05)) @@ -662,16 +668,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2=[ - 1.2351468819080416, - 1.1269856428294935, - 1.7239124305681928, - 11.715260007491556, + 1.2351650580585378, + 1.1268555757641623, + 1.723421391322672, + 11.715156856828612, ], linf=[ - 5.385493056976312, - 6.575446146030286, - 10.06523457762742, - 51.00903155017642, + 5.3783629857817825, + 6.562416423223851, + 10.008377369949162, + 51.24533429408666, ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -687,18 +693,17 @@ end @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), l2=[ - 1.2607430289877726, - 1.1565837325291355, - 1.7791790302458714, - 11.891223800389232, + 1.2607430289878367, + 1.1565837325291748, + 1.779179030245946, + 11.891223800389836, ], linf=[ - 5.68876088477983, - 8.165554425950146, - 10.859100194836538, - 50.25822408989214, + 5.68876088478026, + 8.16555442595031, + 10.859100194836678, + 50.258224089906975, ], - cells_per_dimension=(8, 12), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From 9c0a288c62c5a403af6ca6c5de500d0b6a901c0f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 22 Nov 2023 18:30:57 +0100 Subject: [PATCH 381/423] Clean up routine `get_boundary_outer_state` --- .../elixir_euler_double_mach.jl | 90 ++++++++++++++++++- .../elixir_euler_double_mach_MCL.jl | 90 ++++++++++++++++++- src/equations/compressible_euler_2d.jl | 65 -------------- .../dgsem_tree/dg_2d_subcell_limiters.jl | 56 +++++------- 4 files changed, 197 insertions(+), 104 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index c855f448fd..8ad6138e63 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -7,11 +7,97 @@ using Trixi gamma = 1.4 equations = CompressibleEulerEquations2D(gamma) -initial_condition = Trixi.initial_condition_double_mach_reflection +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_double_mach_reflection boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (y_neg = Trixi.boundary_condition_mixed_dirichlet_wall, +# Special mixed boundary condition type for the :y_neg of the domain. +# It is charachteristic-based when x < 1/6 and a slip wall when x >= 1/6 +# Note: Only for StructuredMesh +@inline function boundary_condition_mixed_characteristic_wall(u_inner, + normal_direction::AbstractVector, + direction, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + # From the BoundaryConditionCharacteristic + # get the external state of the solution + u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + direction, x, t, + equations) + # Calculate boundary flux + flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, + surface_flux_function, equations) + end + + return flux +end + +# Note: Only for StructuredMesh +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + equations, + dg, indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + direction, x, t, + equations) + + else # if x[1] >= 1 / 6 # boundary_condition_slip_wall + u_rotate = Trixi.rotate_to_x(u_inner, normal_direction, equations) + + u_outer = SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + end + return u_outer +end + +boundary_conditions = (y_neg = boundary_condition_mixed_characteristic_wall, y_pos = boundary_condition_inflow_outflow, x_pos = boundary_condition_inflow_outflow, x_neg = boundary_condition_inflow_outflow) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 6a04b39ec4..e49d3a658c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -7,11 +7,97 @@ using Trixi gamma = 1.4 equations = CompressibleEulerEquations2D(gamma) -initial_condition = Trixi.initial_condition_double_mach_reflection +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_double_mach_reflection boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) -boundary_conditions = (y_neg = Trixi.boundary_condition_mixed_dirichlet_wall, +# Special mixed boundary condition type for the :y_neg of the domain. +# It is charachteristic-based when x < 1/6 and a slip wall when x >= 1/6 +# Note: Only for StructuredMesh +@inline function boundary_condition_mixed_characteristic_wall(u_inner, + normal_direction::AbstractVector, + direction, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + # From the BoundaryConditionCharacteristic + # get the external state of the solution + u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + direction, x, t, + equations) + # Calculate boundary flux + flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, + surface_flux_function, equations) + end + + return flux +end + +# Note: Only for StructuredMesh +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + equations, + dg, indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + direction, x, t, + equations) + + else # if x[1] >= 1 / 6 # boundary_condition_slip_wall + u_rotate = Trixi.rotate_to_x(u_inner, normal_direction, equations) + + u_outer = SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) + end + return u_outer +end + +boundary_conditions = (y_neg = boundary_condition_mixed_characteristic_wall, y_pos = boundary_condition_inflow_outflow, x_pos = boundary_condition_inflow_outflow, x_neg = boundary_condition_inflow_outflow) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 7488f172bb..8d42a507a5 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -480,71 +480,6 @@ end return cons end -""" - initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - -Compressible Euler setup for a double Mach reflection problem. -Involves strong shock interactions as well as steady / unsteady flow structures. -Also exercises special boundary conditions along the bottom of the domain that is a mixture of -Dirichlet and slip wall. -See Section IV c on the paper below for details. - -- Paul Woodward and Phillip Colella (1984) - The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. - [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) -""" -@inline function initial_condition_double_mach_reflection(x, t, - equations::CompressibleEulerEquations2D) - if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) - phi = pi / 6 - sin_phi, cos_phi = sincos(phi) - - rho = 8.0 - v1 = 8.25 * cos_phi - v2 = -8.25 * sin_phi - p = 116.5 - else - rho = 1.4 - v1 = 0.0 - v2 = 0.0 - p = 1.0 - end - - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) -end - -# Special mixed boundary condition type for the :Bottom of the domain. -# It is charachteristic when x < 1/6 and a slip wall when x >= 1/6 -@inline function boundary_condition_mixed_dirichlet_wall(u_inner, - normal_direction::AbstractVector, - direction, - x, t, surface_flux_function, - equations::CompressibleEulerEquations2D) - # Note: Only for StructuredMesh - if x[1] < 1 / 6 - # # From the BoundaryConditionDirichlet - # # get the external value of the solution - # u_boundary = initial_condition_double_mach_reflection(x, t, equations) - - # From the BoundaryConditionCharacteristic - # get the external state of the solution - u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, - u_inner, - normal_direction, - direction, x, t, - equations) - # Calculate boundary flux - flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) - else # x[1] >= 1 / 6 - # Use the free slip wall BC otherwise - flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, - surface_flux_function, equations) - end - - return flux -end - # Calculate 2D flux for a single point @inline function flux(u, orientation::Integer, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 2c6ab93a6f..ac121b8ab7 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -1813,44 +1813,30 @@ end return nothing end +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_slip_wall), + orientation::Integer, direction, + equations, dg, indices...) + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) +end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, + direction, equations, dg, indices...) + u_rotate = rotate_to_x(u_inner, normal_direction, equations) + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_rotate[2], + u_inner[3] - 2.0 * u_rotate[3], + u_inner[4]) +end + +# Default implementation of `get_boundary_outer_state` returns inner value. @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation_or_normal, direction, equations, dg, indices...) - if boundary_condition == boundary_condition_slip_wall #boundary_condition_reflecting_euler_wall - if orientation_or_normal isa AbstractArray - u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], - u_inner[4]) - else # orientation_or_normal isa Integer - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) - end - elseif boundary_condition == boundary_condition_mixed_dirichlet_wall - x = get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) - if x[1] < 1 / 6 # BoundaryConditionCharacteristic - u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, - u_inner, - orientation_or_normal, - direction, x, t, - equations) - - return u_outer - else # x[1] >= 1 / 6 # boundary_condition_slip_wall - if orientation_or_normal isa AbstractArray - u_rotate = rotate_to_x(u_inner, orientation_or_normal, equations) - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], - u_inner[4]) - else # orientation_or_normal isa Integer - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) - end - end - end - + error("rr") return u_inner end From 1d945823b12bc6b8c0c25ccf4cce5983e6e61f62 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 22 Nov 2023 18:32:18 +0100 Subject: [PATCH 382/423] Format --- examples/structured_2d_dgsem/elixir_euler_double_mach.jl | 8 ++++---- .../structured_2d_dgsem/elixir_euler_double_mach_MCL.jl | 8 ++++---- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 8ad6138e63..1b268422e1 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -74,10 +74,10 @@ end # Note: Only for StructuredMesh @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, - equations, - dg, indices...) + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + equations, + dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index e49d3a658c..ad537b4968 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -74,10 +74,10 @@ end # Note: Only for StructuredMesh @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, - equations, - dg, indices...) + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + equations, + dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index ac121b8ab7..83c741efc1 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -1836,7 +1836,6 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, orientation_or_normal, direction, equations, dg, indices...) - error("rr") return u_inner end From 4e7f685a017d889cca6c9779f89a9a9f4c1463e2 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 23 Nov 2023 09:20:56 +0100 Subject: [PATCH 383/423] Fix test --- test/test_structured_2d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 78d4cd8ea0..50f032e9e0 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -701,8 +701,8 @@ end 11.715156856828612, ], linf=[ - 5.3783629857817825, - 6.562416423223851, + 5.378363125399197, + 6.5624165241817245, 10.008377369949162, 51.24533429408666, ], From 73e26c4a1ab7ce1322a5c91965a414ad8c3d7868 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Thu, 23 Nov 2023 11:15:35 +0100 Subject: [PATCH 384/423] Speed up bar states bounds calculation of entropies (#120) * Speed up bar states bounds calculation of entropies * Format * Implement suggestions --- .../dgsem_tree/dg_2d_subcell_limiters.jl | 129 ++++++++++-------- 1 file changed, 72 insertions(+), 57 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 83c741efc1..fe751a2688 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -83,7 +83,7 @@ function calc_volume_integral!(du, u, cache) if limiter.smoothness_indicator - @unpack element_ids_dg, element_ids_dgfv = cache + (; element_ids_dg, element_ids_dgfv) = cache # Calculate element-wise blending factors α alpha_element = @trixi_timeit timer() "element-wise blending factors" limiter.IndicatorHG(u, mesh, @@ -178,11 +178,11 @@ end nonconservative_terms::False, equations, volume_integral, limiter::SubcellLimiterMCL, dg::DGSEM, cache) - @unpack inverse_weights = dg.basis - @unpack volume_flux_dg, volume_flux_fv = volume_integral + (; inverse_weights) = dg.basis + (; volume_flux_dg, volume_flux_fv) = volume_integral # high-order DG fluxes - @unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache + (; fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded) = cache fhat1_L = fhat1_L_threaded[Threads.threadid()] fhat1_R = fhat1_R_threaded[Threads.threadid()] fhat2_L = fhat2_L_threaded[Threads.threadid()] @@ -192,7 +192,7 @@ end cache) # low-order FV fluxes - @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache + (; fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded) = cache fstar1_L = fstar1_L_threaded[Threads.threadid()] fstar2_L = fstar2_L_threaded[Threads.threadid()] fstar1_R = fstar1_R_threaded[Threads.threadid()] @@ -212,7 +212,7 @@ end limiter, dg, element, cache, fstar1_L, fstar2_L) - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) du[v, i, j, element] += inverse_weights[i] * @@ -582,7 +582,7 @@ end u, mesh, nonconservative_terms::False, equations, limiter::SubcellLimiterMCL, dg, element, cache) - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -619,7 +619,7 @@ end u, mesh, nonconservative_terms::True, equations, limiter::SubcellLimiterMCL, dg, element, cache) - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) @@ -658,7 +658,7 @@ end if limiter isa SubcellLimiterIDP && !limiter.bar_states return nothing end - @unpack lambda1, lambda2, bar_states1, bar_states2 = limiter.cache.container_bar_states + (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states # Calc lambdas and bar states inside elements @threaded for element in eachelement(dg, cache) @@ -857,8 +857,8 @@ end if !limiter.bar_states return nothing end - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - @unpack bar_states1, bar_states2 = limiter.cache.container_bar_states + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + (; bar_states1, bar_states2) = limiter.cache.container_bar_states # state variables if limiter.local_minmax @@ -908,27 +908,34 @@ end for j in eachnode(dg), i in eachnode(dg) s_min[i, j, element] = typemax(eltype(s_min)) end + # FV solution at node (i, j) for j in eachnode(dg), i in eachnode(dg) s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), equations) s_min[i, j, element] = min(s_min[i, j, element], s) - # TODO: Add source? - # - xi direction + # TODO: Add source term! + end + # xi direction: subcell face between (i-1, j) and (i, j) + for j in eachnode(dg), i in 1:(nnodes(dg) + 1) s = entropy_spec(get_node_vars(bar_states1, equations, dg, i, j, element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # + xi direction - s = entropy_spec(get_node_vars(bar_states1, equations, dg, i + 1, j, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # - eta direction + if i <= nnodes(dg) + s_min[i, j, element] = min(s_min[i, j, element], s) + end + if i > 1 + s_min[i - 1, j, element] = min(s_min[i - 1, j, element], s) + end + end + # eta direction: subcell face between (i, j-1) and (i, j) + for j in 1:(nnodes(dg) + 1), i in eachnode(dg) s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j, element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # + eta direction - s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j + 1, - element), equations) - s_min[i, j, element] = min(s_min[i, j, element], s) + if j <= nnodes(dg) + s_min[i, j, element] = min(s_min[i, j, element], s) + end + if j > 1 + s_min[i, j - 1, element] = min(s_min[i, j - 1, element], s) + end end end end @@ -939,26 +946,34 @@ end for j in eachnode(dg), i in eachnode(dg) s_max[i, j, element] = typemin(eltype(s_max)) end + # FV solution at node (i, j) for j in eachnode(dg), i in eachnode(dg) s = entropy_math(get_node_vars(u, equations, dg, i, j, element), equations) s_max[i, j, element] = max(s_max[i, j, element], s) - # - xi direction + # TODO: Add source term! + end + # xi direction: subcell face between (i-1, j) and (i, j) + for j in eachnode(dg), i in 1:(nnodes(dg) + 1) s = entropy_math(get_node_vars(bar_states1, equations, dg, i, j, element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # + xi direction - s = entropy_math(get_node_vars(bar_states1, equations, dg, i + 1, j, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # - eta direction + if i <= nnodes(dg) + s_max[i, j, element] = max(s_max[i, j, element], s) + end + if i > 1 + s_max[i - 1, j, element] = max(s_max[i - 1, j, element], s) + end + end + # eta direction: subcell face between (i, j-1) and (i, j) + for j in 1:(nnodes(dg) + 1), i in eachnode(dg) s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j, element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # + eta direction - s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j + 1, - element), equations) - s_max[i, j, element] = max(s_max[i, j, element], s) + if j <= nnodes(dg) + s_max[i, j, element] = max(s_max[i, j, element], s) + end + if j > 1 + s_max[i, j - 1, element] = max(s_max[i, j - 1, element], s) + end end end end @@ -968,8 +983,8 @@ end @inline function calc_variable_bounds!(u, mesh, nonconservative_terms, equations, limiter::SubcellLimiterMCL, dg, cache) - @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients - @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states + (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients + (; bar_states1, bar_states2) = limiter.cache.container_bar_states @threaded for element in eachelement(dg, cache) for v in eachvariable(equations) @@ -1108,13 +1123,13 @@ end equations, limiter, dg, element, cache, fstar1, fstar2) - @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes - @unpack var_min, var_max = limiter.cache.subcell_limiter_coefficients - @unpack bar_states1, bar_states2, lambda1, lambda2 = limiter.cache.container_bar_states + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients + (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states if limiter.Plotting - @unpack alpha, alpha_pressure, alpha_entropy, - alpha_mean, alpha_mean_pressure, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_pressure, alpha_entropy, alpha_mean, + alpha_mean_pressure, alpha_mean_entropy) = limiter.cache.subcell_limiter_coefficients for j in eachnode(dg), i in eachnode(dg) alpha_mean[:, i, j, element] .= zero(eltype(alpha_mean)) alpha[:, i, j, element] .= one(eltype(alpha)) @@ -1167,7 +1182,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1219,7 +1234,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1282,7 +1297,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1333,7 +1348,7 @@ end (g_limited + sign(g_limited) * eps()) / (g + sign(g_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1377,7 +1392,7 @@ end (antidiffusive_flux1_L[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[v, i - 1, j, element] = min(alpha[v, i - 1, j, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1417,7 +1432,7 @@ end (antidiffusive_flux2_L[v, i, j, element] + sign(flux_limited) * eps())) end - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[v, i, j - 1, element] = min(alpha[v, i, j - 1, element], coefficient) alpha[v, i, j, element] = min(alpha[v, i, j, element], coefficient) @@ -1456,7 +1471,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[1, i - 1, j, element] = min(alpha[1, i - 1, j, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1504,7 +1519,7 @@ end end if limiter.Plotting - @unpack alpha, alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha, alpha_mean) = limiter.cache.subcell_limiter_coefficients alpha[1, i, j - 1, element] = min(alpha[1, i, j - 1, element], coefficient) alpha[1, i, j, element] = min(alpha[1, i, j, element], coefficient) @@ -1531,7 +1546,7 @@ end # Divide alpha_mean by number of additions if limiter.Plotting - @unpack alpha_mean = limiter.cache.subcell_limiter_coefficients + (; alpha_mean) = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 if limiter.density_limiter || limiter.positivity_limiter_density for i in eachnode(dg) @@ -1561,7 +1576,7 @@ end # Limit pressure à la Kuzmin if limiter.positivity_limiter_pressure - @unpack alpha_pressure, alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients + (; alpha_pressure, alpha_mean_pressure) = limiter.cache.subcell_limiter_coefficients for j in eachnode(dg), i in 2:nnodes(dg) bar_state_velocity = bar_states1[2, i, j, element]^2 + bar_states1[3, i, j, element]^2 @@ -1672,7 +1687,7 @@ end end end if limiter.Plotting - @unpack alpha_mean_pressure = limiter.cache.subcell_limiter_coefficients + (; alpha_mean_pressure) = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_pressure[i, 1, element] += 1.0 @@ -1729,7 +1744,7 @@ end end end if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients + (; alpha_entropy, alpha_mean_entropy) = limiter.cache.subcell_limiter_coefficients alpha_entropy[i - 1, j, element] = min(alpha_entropy[i - 1, j, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1777,7 +1792,7 @@ end end end if limiter.Plotting - @unpack alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients + (; alpha_entropy, alpha_mean_entropy) = limiter.cache.subcell_limiter_coefficients alpha_entropy[i, j - 1, element] = min(alpha_entropy[i, j - 1, element], alpha) alpha_entropy[i, j, element] = min(alpha_entropy[i, j, element], alpha) @@ -1786,7 +1801,7 @@ end end end if limiter.Plotting - @unpack alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients + (; alpha_mean_entropy) = limiter.cache.subcell_limiter_coefficients # Interfaces contribute with 1.0 for i in eachnode(dg) alpha_mean_entropy[i, 1, element] += 1.0 From bcfc1e952c5e408e55c7c394b966afcc234e11a4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 28 Nov 2023 17:22:43 +0100 Subject: [PATCH 385/423] Fix normalization for Charactersitics and slip wall --- .../elixir_euler_double_mach.jl | 15 ++++--- .../elixir_euler_double_mach_MCL.jl | 15 ++++--- .../dg_2d_subcell_limiters.jl | 2 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 45 ++++++++++++------- src/time_integration/methods_SSP.jl | 4 +- test/test_structured_2d.jl | 32 ++++++------- 6 files changed, 64 insertions(+), 49 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 1b268422e1..d854ab45f7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -76,22 +76,23 @@ end @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, - equations, + equations::CompressibleEulerEquations2D, dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, u_inner, - normal_direction, - direction, x, t, - equations) + normal_direction / + norm(normal_direction), + direction, x, t, equations) else # if x[1] >= 1 / 6 # boundary_condition_slip_wall - u_rotate = Trixi.rotate_to_x(u_inner, normal_direction, equations) + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction u_outer = SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], u_inner[4]) end return u_outer diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index ad537b4968..f5abd10ca8 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -76,22 +76,23 @@ end @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, - equations, + equations::CompressibleEulerEquations2D, dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, u_inner, - normal_direction, - direction, x, t, - equations) + normal_direction / + norm(normal_direction), + direction, x, t, equations) else # if x[1] >= 1 / 6 # boundary_condition_slip_wall - u_rotate = Trixi.rotate_to_x(u_inner, normal_direction, equations) + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction u_outer = SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], u_inner[4]) end return u_outer diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 4db5d5a3bf..d1044db1d4 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -109,7 +109,7 @@ return nothing end -@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh, +@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh{2}, nonconservative_terms, equations, limiter, dg, cache, boundary_conditions; calc_bar_states = true) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index fe751a2688..ce4b5440e8 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -1831,29 +1831,25 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_slip_wall), orientation::Integer, direction, - equations, dg, indices...) + equations::CompressibleEulerEquations2D, + dg, indices...) return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_slip_wall), - normal_direction::AbstractVector, - direction, equations, dg, indices...) - u_rotate = rotate_to_x(u_inner, normal_direction, equations) + normal_direction::AbstractVector, direction, + equations::CompressibleEulerEquations2D, + dg, indices...) + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction return SVector(u_inner[1], - u_inner[2] - 2.0 * u_rotate[2], - u_inner[3] - 2.0 * u_rotate[3], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], u_inner[4]) end -# Default implementation of `get_boundary_outer_state` returns inner value. -@inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition, - orientation_or_normal, direction, equations, - dg, indices...) - return u_inner -end - @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, orientation_or_normal, direction, equations, @@ -1868,13 +1864,30 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionCharacteristic, - orientation_or_normal, direction, equations, + orientation::Integer, direction, equations, dg, indices...) - @unpack node_coordinates = cache.elements + (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, - u_inner, orientation_or_normal, + u_inner, orientation, + direction, x, t, equations) + + return u_outer +end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::BoundaryConditionCharacteristic, + normal_direction::AbstractVector, direction, + equations, dg, indices...) + (; node_coordinates) = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + + u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, + normal_direction / + norm(normal_direction), direction, x, t, equations) return u_outer diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 7443e6ed26..bc5e46e193 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -269,8 +269,8 @@ function calc_normal_directions!(container_bar_states, mesh::TreeMesh, equations nothing end -function calc_normal_directions!(container_bar_states, mesh::StructuredMesh, equations, - dg, cache) +function calc_normal_directions!(container_bar_states, mesh::StructuredMesh{2}, + equations, dg, cache) (; weights, derivative_matrix) = dg.basis (; contravariant_vectors) = cache.elements diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 50f032e9e0..8061d62705 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -695,16 +695,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2=[ - 1.2351650580585378, - 1.1268555757641623, - 1.723421391322672, - 11.715156856828612, + 1.2360964282793594, + 1.1280398030799386, + 1.7267648591561005, + 11.7190241252948, ], linf=[ - 5.378363125399197, - 6.5624165241817245, - 10.008377369949162, - 51.24533429408666, + 5.393863681425582, + 6.476830142076269, + 10.13110957325047, + 49.922573759404, ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -720,16 +720,16 @@ end @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), l2=[ - 1.2607430289878367, - 1.1565837325291748, - 1.779179030245946, - 11.891223800389836, + 1.2655219565562812, + 1.1981291403309833, + 1.7964926709729876, + 11.968876601483794, ], linf=[ - 5.68876088478026, - 8.16555442595031, - 10.859100194836678, - 50.258224089906975, + 5.675285252773072, + 10.063582862371597, + 12.3837111905078, + 51.34700027665198, ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations From 60a0fbf7564ace51bf86a6d3ca9e7f4337dc9b99 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 28 Nov 2023 18:18:15 +0100 Subject: [PATCH 386/423] Fix elixirs and tests --- .../elixir_euler_double_mach.jl | 1 + .../elixir_euler_double_mach_MCL.jl | 1 + test/test_structured_2d.jl | 32 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index d854ab45f7..2df2489d29 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -1,6 +1,7 @@ using OrdinaryDiffEq using Trixi +using LinearAlgebra: norm # for use in get_boundary_outer_state ############################################################################### # semidiscretization of the compressible Euler equations diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index f5abd10ca8..21f5f2dc3b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -1,6 +1,7 @@ using OrdinaryDiffEq using Trixi +using LinearAlgebra: norm # for use in get_boundary_outer_state ############################################################################### # semidiscretization of the compressible Euler equations diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 8061d62705..dff333c2bb 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -642,16 +642,16 @@ end @trixi_testset "elixir_euler_double_mach.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), l2=[ - 0.8895735118233061, - 6.7732502383794655, - 3.2537120458330913, - 77.15211199077615, + 0.8892711012596337, + 6.768939095393111, + 3.2588878985646255, + 77.16322087232443, ], linf=[ - 10.595204890391603, - 133.14647204580373, - 39.59427444784427, - 1467.649170200717, + 10.740469658192428, + 133.31243847865667, + 38.66587124337752, + 1470.9225424937222, ], initial_refinement_level=3, tspan=(0.0, 0.05)) @@ -668,16 +668,16 @@ end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ - 0.9230564188859353, - 7.048067525695328, - 3.2513897966486693, - 80.02373234685636, + 0.9199296340616842, + 7.054039186151105, + 3.3554396452157937, + 79.79580531230015, ], linf=[ - 13.994085024959638, - 138.49691741864086, - 38.68709126443809, - 1574.7770582279284, + 14.104646332033838, + 133.18960630718664, + 39.607867526776694, + 1476.9124768351937, ], initial_refinement_level=3, tspan=(0.0, 0.05)) From 66476eb515b54e6a5cfb097c73fe436553f8ebee Mon Sep 17 00:00:00 2001 From: bennibolm Date: Sun, 3 Dec 2023 13:00:39 +0100 Subject: [PATCH 387/423] Add verified changes from P4estMesh PR --- .../elixir_euler_double_mach.jl | 13 +++-- .../elixir_euler_double_mach_MCL.jl | 13 +++-- src/equations/equations.jl | 7 +-- .../dg_2d_subcell_limiters.jl | 14 +++--- .../dgsem_structured/subcell_limiters_2d.jl | 28 ++++++----- .../dgsem_tree/dg_2d_subcell_limiters.jl | 49 +++++++------------ src/solvers/dgsem_tree/subcell_limiters_2d.jl | 17 ++++--- 7 files changed, 74 insertions(+), 67 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 2df2489d29..8153d2634b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -63,7 +63,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond direction, x, t, equations) # Calculate boundary flux - flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + 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 + flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + end else # x[1] >= 1 / 6 # Use the free slip wall BC otherwise flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, @@ -77,14 +82,14 @@ end @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, + mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, u_inner, - normal_direction / - norm(normal_direction), + normal_direction, direction, x, t, equations) else # if x[1] >= 1 / 6 # boundary_condition_slip_wall @@ -120,7 +125,7 @@ volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -initial_refinement_level = 6 +initial_refinement_level = 4 cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) coordinates_min = (0.0, 0.0) coordinates_max = (4.0, 1.0) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 21f5f2dc3b..e85c263429 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -63,7 +63,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond direction, x, t, equations) # Calculate boundary flux - flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + 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 + flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) + end else # x[1] >= 1 / 6 # Use the free slip wall BC otherwise flux = boundary_condition_slip_wall(u_inner, normal_direction, direction, x, t, @@ -77,14 +82,14 @@ end @inline function Trixi.get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, + mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, dg, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, u_inner, - normal_direction / - norm(normal_direction), + normal_direction, direction, x, t, equations) else # if x[1] >= 1 / 6 # boundary_condition_slip_wall @@ -123,7 +128,7 @@ volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -initial_refinement_level = 6 +initial_refinement_level = 4 cells_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) coordinates_min = (0.0, 0.0) coordinates_max = (4.0, 1.0) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 516f22ff33..31d1c8a818 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -226,9 +226,10 @@ end x, t, surface_flux_function, equations) - u_boundary = characteristic_boundary_value_function(boundary_condition.outer_boundary_value_function, - u_inner, orientation_or_normal, - direction, x, t, equations) + u_boundary = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, + orientation_or_normal, + direction, x, t, equations) # Calculate boundary flux if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index d1044db1d4..c6f3dcc1f1 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -245,7 +245,8 @@ end u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) + mesh, equations, dg, + 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) @@ -270,8 +271,8 @@ end u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) + mesh, equations, dg, + nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) @@ -301,7 +302,8 @@ end u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) + mesh, equations, dg, + i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) @@ -326,8 +328,8 @@ end u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) + mesh, equations, dg, + i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) diff --git a/src/solvers/dgsem_structured/subcell_limiters_2d.jl b/src/solvers/dgsem_structured/subcell_limiters_2d.jl index c5c21c34ff..83a979a16a 100644 --- a/src/solvers/dgsem_structured/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_structured/subcell_limiters_2d.jl @@ -61,7 +61,8 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) + mesh, equations, dg, + 1, j, element) var_outer = u_outer[variable] var_min[1, j, element] = min(var_min[1, j, element], var_outer) @@ -77,8 +78,8 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) + mesh, equations, dg, + nnodes(dg), j, element) var_outer = u_outer[variable] var_min[nnodes(dg), j, element] = min(var_min[nnodes(dg), j, element], @@ -97,7 +98,8 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) + mesh, equations, dg, + i, 1, element) var_outer = u_outer[variable] var_min[i, 1, element] = min(var_min[i, 1, element], var_outer) @@ -113,8 +115,8 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) + mesh, equations, dg, + i, nnodes(dg), element) var_outer = u_outer[variable] var_min[i, nnodes(dg), element] = min(var_min[i, nnodes(dg), element], @@ -180,7 +182,8 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem u_inner = get_node_vars(u, equations, dg, 1, j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], Ja1, 1, - equations, dg, 1, j, element) + mesh, equations, dg, + 1, j, element) var_outer = variable(u_outer, equations) var_minmax[1, j, element] = minmax(var_minmax[1, j, element], var_outer) @@ -195,8 +198,8 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], Ja1, 2, - equations, dg, nnodes(dg), j, - element) + mesh, equations, dg, + nnodes(dg), j, element) var_outer = variable(u_outer, equations) var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), j, @@ -214,7 +217,8 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem u_inner = get_node_vars(u, equations, dg, i, 1, element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], Ja2, 3, - equations, dg, i, 1, element) + mesh, equations, dg, + i, 1, element) var_outer = variable(u_outer, equations) var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], var_outer) @@ -229,8 +233,8 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], Ja2, 4, - equations, dg, i, nnodes(dg), - element) + mesh, equations, dg, + i, nnodes(dg), element) var_outer = variable(u_outer, equations) var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, nnodes(dg), diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index ce4b5440e8..aff68284b4 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -651,7 +651,7 @@ end return nothing end -@inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh, +@inline function calc_lambdas_bar_states!(u, t, mesh::TreeMesh{2}, nonconservative_terms, equations, limiter, dg, cache, boundary_conditions; calc_bar_states = true) @@ -761,7 +761,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], orientation, 1, - equations, dg, 1, j, element) + mesh, equations, dg, + 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -781,8 +782,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], orientation, 2, - equations, dg, nnodes(dg), j, - element) + mesh, equations, dg, + nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, @@ -807,7 +808,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], orientation, 3, - equations, dg, i, 1, element) + mesh, equations, dg, + i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -827,8 +829,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], orientation, 4, - equations, dg, i, nnodes(dg), - element) + mesh, equations, dg, + i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, @@ -1831,7 +1833,7 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_slip_wall), orientation::Integer, direction, - equations::CompressibleEulerEquations2D, + mesh, equations::CompressibleEulerEquations2D, dg, indices...) return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) end @@ -1839,7 +1841,7 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::typeof(boundary_condition_slip_wall), normal_direction::AbstractVector, direction, - equations::CompressibleEulerEquations2D, + mesh, equations::CompressibleEulerEquations2D, dg, indices...) factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction @@ -1852,9 +1854,9 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionDirichlet, - orientation_or_normal, direction, equations, - dg, indices...) - @unpack node_coordinates = cache.elements + orientation_or_normal, direction, mesh, + equations, dg, indices...) + (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) u_outer = boundary_condition.boundary_value_function(x, t, equations) @@ -1864,30 +1866,15 @@ end @inline function get_boundary_outer_state(u_inner, cache, t, boundary_condition::BoundaryConditionCharacteristic, - orientation::Integer, direction, equations, + orientation_or_normal, direction, + mesh::Union{TreeMesh, StructuredMesh}, + equations, dg, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, - u_inner, orientation, - direction, x, t, equations) - - return u_outer -end - -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::BoundaryConditionCharacteristic, - normal_direction::AbstractVector, direction, - equations, dg, indices...) - (; node_coordinates) = cache.elements - - x = get_node_coords(node_coordinates, equations, dg, indices...) - - u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, - u_inner, - normal_direction / - norm(normal_direction), + u_inner, orientation_or_normal, direction, x, t, equations) return u_outer diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index c37276c580..8168ce6ab5 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -182,7 +182,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[boundary_index], orientation, boundary_index, - equations, dg, index..., element) + mesh, equations, dg, + index..., element) var_outer = u_outer[variable] var_min[index..., element] = min(var_min[index..., element], var_outer) @@ -280,7 +281,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[1], orientation, 1, - equations, dg, 1, j, element) + mesh, equations, dg, + 1, j, element) var_outer = variable(u_outer, equations) var_minmax[1, j, element] = minmax(var_minmax[1, j, element], @@ -292,8 +294,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[2], orientation, 2, - equations, dg, nnodes(dg), j, - element) + mesh, equations, dg, + nnodes(dg), j, element) var_outer = variable(u_outer, equations) var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), @@ -308,7 +310,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[3], orientation, 3, - equations, dg, i, 1, element) + mesh, equations, dg, + i, 1, element) var_outer = variable(u_outer, equations) var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], @@ -320,8 +323,8 @@ end u_outer = get_boundary_outer_state(u_inner, cache, t, boundary_conditions[4], orientation, 4, - equations, dg, i, nnodes(dg), - element) + mesh, equations, dg, + i, nnodes(dg), element) var_outer = variable(u_outer, equations) var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, From 8ebce9d10869df4c27b1a9a90da13ea0cc4e572b Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 4 Dec 2023 10:34:50 +0100 Subject: [PATCH 388/423] Fix bug --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 82a3439013..431780dab8 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -11,7 +11,7 @@ # this method is used when the limiter is constructed as for shock-capturing volume integrals function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, bound_keys) + basis::LobattoLegendreBasis, bound_keys, bar_states) subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis)}(0, nnodes(basis), bound_keys) From 15abed3bbf2121f967a87b253ecc8d72247af0a4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 4 Dec 2023 10:36:49 +0100 Subject: [PATCH 389/423] Adapt tests to reduce compilation time --- test/test_structured_2d.jl | 70 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index dff333c2bb..8cacad848d 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -642,18 +642,18 @@ end @trixi_testset "elixir_euler_double_mach.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), l2=[ - 0.8892711012596337, - 6.768939095393111, - 3.2588878985646255, - 77.16322087232443, + 0.87417841433288, + 6.669726935171785, + 3.4980245896465387, + 76.33557073534843, ], linf=[ - 10.740469658192428, - 133.31243847865667, - 38.66587124337752, - 1470.9225424937222, + 11.428353671462515, + 142.73486852796972, + 38.91639544578682, + 1651.7541392659086, ], - initial_refinement_level=3, + initial_refinement_level=2, tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -668,18 +668,18 @@ end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ - 0.9199296340616842, - 7.054039186151105, - 3.3554396452157937, - 79.79580531230015, + 0.8887316108902574, + 6.644244699117507, + 3.449004719354504, + 76.27064751067829, ], linf=[ - 14.104646332033838, - 133.18960630718664, - 39.607867526776694, - 1476.9124768351937, + 11.047531144845593, + 121.9664993888814, + 35.74266955717666, + 1370.2362649787694, ], - initial_refinement_level=3, + initial_refinement_level=2, tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -695,17 +695,18 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_sc_subcell.jl"), l2=[ - 1.2360964282793594, - 1.1280398030799386, - 1.7267648591561005, - 11.7190241252948, + 1.2251169601680385, + 1.1492245175358053, + 1.6159494561956207, + 11.595399424356522, ], linf=[ - 5.393863681425582, - 6.476830142076269, - 10.13110957325047, - 49.922573759404, + 5.510615373248864, + 6.031732951057033, + 7.75523532462757, + 50.34978438323783, ], + cells_per_dimension = (4, 6), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -720,17 +721,18 @@ end @trixi_testset "elixir_euler_shock_upstream_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shock_upstream_MCL.jl"), l2=[ - 1.2655219565562812, - 1.1981291403309833, - 1.7964926709729876, - 11.968876601483794, + 1.251060277251583, + 1.113113246031922, + 1.6514902305846646, + 11.691342485806103, ], linf=[ - 5.675285252773072, - 10.063582862371597, - 12.3837111905078, - 51.34700027665198, + 5.893750268397502, + 5.620631940554678, + 9.523570698421638, + 50.004005679063496, ], + cells_per_dimension = (4, 6), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From 647ead58ec33add29d7a911af9073847bb9cbf59 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 4 Dec 2023 10:39:54 +0100 Subject: [PATCH 390/423] Format --- test/test_structured_2d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 8cacad848d..0bd5247c83 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -706,7 +706,7 @@ end 7.75523532462757, 50.34978438323783, ], - cells_per_dimension = (4, 6), + cells_per_dimension=(4, 6), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -732,7 +732,7 @@ end 9.523570698421638, 50.004005679063496, ], - cells_per_dimension = (4, 6), + cells_per_dimension=(4, 6), tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From 1a09eaa1a707e6e77fa84591dd44e13eaf1f5b90 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Tue, 5 Dec 2023 10:47:08 +0100 Subject: [PATCH 391/423] Add support for P4estMesh to `subcell-limiting` (#121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for P4estMesh to `subcell-limiting` * Add elixir with supersonic flow * Extract inner code of `characteristic_boundary_value_function` * Add support for `BoundaryConditionDirichlet` for P4estMesh * Fix calculation of `vn` * Remove default routine for `get_boundary_outer_state` * Revise calculation of bar states * Fix allocations with `foreach(enumerate(...))` * Fix normalization in `get_boundary_outer_state` * Add TODO note for future * Remove unnecessary code; format * Adapt test errors after normalizing normal vectors * Add dispatch for equations * Fix normalization; Is done inside boundary_value_function * Fix bug in calculation of bar state at interfaces for P4estMesh * Add mesh as parameter of `get_boundary_outer_state` - Fixes bug that P4estMesh calls the right `characteristic_boundary_state` routine * Add p4est double mach elixir * Fix error * Remove comment * Add test for supersonic flow * fmt * Add comments * Update src/equations/compressible_euler_2d.jl Co-authored-by: Andrés Rueda-Ramírez * fmt * Fix error --------- Co-authored-by: Andrés Rueda-Ramírez --- .../elixir_euler_double_mach.jl | 167 ++++++++++++ .../elixir_euler_free_stream_sc_subcell.jl | 91 +++++++ ...ir_euler_supersonic_cylinder_sc_subcell.jl | 152 +++++++++++ .../elixir_euler_double_mach.jl | 1 - .../elixir_euler_double_mach_MCL.jl | 1 - src/auxiliary/auxiliary.jl | 17 ++ .../subcell_limiter_idp_correction_2d.jl | 3 +- src/callbacks_step/stepsize_dg2d.jl | 9 +- src/equations/compressible_euler_2d.jl | 41 ++- src/equations/equations.jl | 16 ++ src/solvers/dgsem_p4est/dg.jl | 3 + .../dgsem_p4est/dg_2d_subcell_limiters.jl | 212 +++++++++++++++ .../dgsem_p4est/subcell_limiters_2d.jl | 250 ++++++++++++++++++ .../dg_2d_subcell_limiters.jl | 7 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 27 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 15 +- src/time_integration/methods_SSP.jl | 3 +- test/test_p4est_2d.jl | 81 ++++++ 18 files changed, 1066 insertions(+), 30 deletions(-) create mode 100644 examples/p4est_2d_dgsem/elixir_euler_double_mach.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl create mode 100644 src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl create mode 100644 src/solvers/dgsem_p4est/subcell_limiters_2d.jl diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl new file mode 100644 index 0000000000..949bc40e64 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl @@ -0,0 +1,167 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_double_mach_reflection + +boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + +# Special mixed boundary condition type for the :y_neg of the domain. +# It is charachteristic-based when x < 1/6 and a slip wall when x >= 1/6 +# Note: Only for P4estMesh +@inline function boundary_condition_mixed_characteristic_wall(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + # From the BoundaryConditionCharacteristic + # get the external state of the solution + u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + x, t, + equations) + # Calculate boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, + surface_flux_function, equations) + end + + return flux +end + +# Note: Only for P4estMesh +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + mesh::P4estMesh{2}, + equations::CompressibleEulerEquations2D, + dg, indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + x, t, equations) + + else # if x[1] >= 1 / 6 # boundary_condition_slip_wall + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction + + u_outer = SVector(u_inner[1], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], + u_inner[4]) + end + return u_outer +end + +boundary_conditions = Dict(:y_neg => boundary_condition_mixed_characteristic_wall, + :y_pos => boundary_condition_inflow_outflow, + :x_pos => boundary_condition_inflow_outflow, + :x_neg => boundary_condition_inflow_outflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 4 +basis = LobattoLegendreBasis(polydeg) + +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons = ["rho"], + spec_entropy = true, + positivity_correction_factor = 0.1, + max_iterations_newton = 100, + bar_states = true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +initial_refinement_level = 4 +trees_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) +coordinates_min = (0.0, 0.0) +coordinates_max = (4.0, 1.0) +mesh = P4estMesh(trees_per_dimension, polydeg = polydeg, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 0, + periodicity = false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl new file mode 100644 index 0000000000..9d67ad76ce --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -0,0 +1,91 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_constant + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], + positivity_correction_factor = 0.1, + spec_entropy = false, + bar_states = true) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. +# This particular mesh is unstructured in the yz-plane, but extruded in x-direction. +# Apply the warping mapping in the yz-plane to get a curved 2D mesh that is extruded +# in x-direction to ensure free stream preservation on a non-conforming mesh. +# See https://doi.org/10.1007/s10915-018-00897-9, Section 6. + +# Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D +function mapping(xi_, eta_) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) + + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) + + return SVector(x, y) +end + +trees_per_dimension = (16, 16) + +# Create P4estMesh with 16 x 16 trees and 16 x 16 elements +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + mapping = mapping, + initial_refinement_level = 0, periodicity = true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 10000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl new file mode 100644 index 0000000000..8b6b93e0ac --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl @@ -0,0 +1,152 @@ +# Channel flow around a cylinder at Mach 3 +# +# Boundary conditions are supersonic Mach 3 inflow at the left portion of the domain +# and supersonic outflow at the right portion of the domain. The top and bottom of the +# channel as well as the cylinder are treated as Euler slip wall boundaries. +# This flow results in strong shock reflections / interactions as well as Kelvin-Helmholtz +# instabilities at later times as two Mach stems form above and below the cylinder. +# +# For complete details on the problem setup see Section 5.7 of the paper: +# - Jean-Luc Guermond, Murtazo Nazarov, Bojan Popov, and Ignacio Tomas (2018) +# Second-Order Invariant Domain Preserving Approximation of the Euler Equations using Convex Limiting. +# [DOI: 10.1137/17M1149961](https://doi.org/10.1137/17M1149961) +# +# Keywords: supersonic flow, shock capturing, AMR, unstructured curved mesh, positivity preservation, compressible Euler, 2D + +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +@inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_mach3_flow + +# Supersonic inflow boundary condition. +# Calculate the boundary flux entirely from the external solution state, i.e., set +# external solution state values for everything entering the domain. +@inline function boundary_condition_supersonic_inflow(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach3_flow(x, t, equations) + flux = Trixi.flux(u_boundary, normal_direction, equations) + + return flux +end + +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_supersonic_inflow), + normal_direction::AbstractVector, direction, + mesh::P4estMesh{2}, equations, dg, + indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + + return initial_condition_mach3_flow(x, t, equations) +end + +# Supersonic outflow boundary condition. +# Calculate the boundary flux entirely from the internal solution state. Analogous to supersonic inflow +# except all the solution state values are set from the internal solution as everything leaves the domain +@inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, + surface_flux_function, + equations::CompressibleEulerEquations2D) + flux = Trixi.flux(u_inner, normal_direction, equations) + + return flux +end + +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_outflow), + orientation_or_normal, direction, + mesh::P4estMesh{2}, equations, dg, + indices...) + return u_inner +end + +# boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + +# boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, +# :Circle => boundary_condition_slip_wall, +# :Top => boundary_condition_slip_wall, +# :Right => boundary_condition_inflow_outflow, +# :Left => boundary_condition_inflow_outflow) + +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Circle => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_supersonic_inflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons = ["rho"], + positivity_variables_nonlinear = [pressure], + spec_entropy = false, + bar_states = false) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + 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_mesh_file = joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = P4estMesh{2}(mesh_file, initial_refinement_level = 0) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers + +tspan = (0.0, 2.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, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.4) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 8153d2634b..c40d79e3cc 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi -using LinearAlgebra: norm # for use in get_boundary_outer_state ############################################################################### # semidiscretization of the compressible Euler equations diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index e85c263429..e56392f9b2 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi -using LinearAlgebra: norm # for use in get_boundary_outer_state ############################################################################### # semidiscretization of the compressible Euler equations diff --git a/src/auxiliary/auxiliary.jl b/src/auxiliary/auxiliary.jl index 1f7d30d6aa..ac3ff63ade 100644 --- a/src/auxiliary/auxiliary.jl +++ b/src/auxiliary/auxiliary.jl @@ -345,4 +345,21 @@ function register_error_hints() return nothing end + +# Same as `foreach(enumerate(something))`, but without allocations. +# +# Note that compile times may increase if this is used with big tuples. +# TODO: Add comment in the respective PR (here and where it is used: `dg_p4est/dg_2d_subcell_limiters.jl`) +@inline foreach_enumerate(func, collection) = foreach_enumerate(func, collection, 1) +@inline foreach_enumerate(func, collection::Tuple{}, index) = nothing + +@inline function foreach_enumerate(func, collection, index) + element = first(collection) + remaining_collection = Base.tail(collection) + + func((index, element)) + + # Process remaining collection + foreach_enumerate(func, remaining_collection, index + 1) +end end # @muladd diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index f7c6fd5582..4ab1357de6 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -26,7 +26,8 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) return nothing end -function perform_idp_correction!(u, dt, mesh::StructuredMesh{2}, equations, dg, cache) +function perform_idp_correction!(u, dt, mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + equations, dg, cache) if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index f66686ff36..92c21d65e1 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -43,7 +43,7 @@ function max_dt(u, t, mesh::TreeMesh{2}, return 2 / (nnodes(dg) * max_scaled_speed) end -@inline function max_dt(u, t, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, +@inline function max_dt(u, t, mesh::Union{TreeMesh{2}, StructuredMesh{2}, P4estMesh{2}}, constant_speed::False, equations, semi, dg::DG, cache, limiter::Union{SubcellLimiterIDP, SubcellLimiterMCL}) @unpack inverse_weights = dg.basis @@ -75,7 +75,7 @@ end J = 1 / cache.elements.inverse_jacobian[element] end for j in eachnode(dg), i in eachnode(dg) - if mesh isa StructuredMesh{2} + if (mesh isa StructuredMesh{2}) || (mesh isa P4estMesh{2}) J = 1 / cache.elements.inverse_jacobian[i, j, element] end denom = inverse_weights[i] * @@ -114,8 +114,9 @@ end return 2 / (nnodes(dg) * max_scaled_speed) end -@inline function max_dt_RK(u, t, mesh::StructuredMesh{2}, constant_speed, equations, - dg::DG, cache, limiter, element_ids_dg) +@inline function max_dt_RK(u, t, mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + constant_speed, equations, dg::DG, cache, limiter, + element_ids_dg) @unpack contravariant_vectors, inverse_jacobian = cache.elements max_scaled_speed = nextfloat(zero(t)) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 8d42a507a5..88e136f996 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -395,6 +395,7 @@ Should be used together with [`StructuredMesh`](@ref). end # TODO: Add docstring when about to merge. +# Using with TreeMesh{2} @inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, orientation::Integer, direction, x, t, @@ -414,11 +415,12 @@ end vn = factor * u_inner[3] * srho end - return characteristic_boundary_value_function_inner(outer_boundary_value_function, - u_inner, srho, vn, x, t, - equations) + return calc_characteristic_boundary_value_function(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations) end +# Using with StructuredMesh{2} @inline function characteristic_boundary_value_function(outer_boundary_value_function, u_inner, normal_direction::AbstractVector, @@ -437,15 +439,34 @@ end (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) / norm(normal_direction) - return characteristic_boundary_value_function_inner(outer_boundary_value_function, - u_inner, srho, vn, x, t, - equations) + return calc_characteristic_boundary_value_function(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations) end -# Inner function to distinguish between different mesh types. -@inline function characteristic_boundary_value_function_inner(outer_boundary_value_function, - u_inner, srho, vn, x, t, - equations::CompressibleEulerEquations2D) +# Using with P4estMesh{2} +@inline function characteristic_boundary_value_function(outer_boundary_value_function, + u_inner, + normal_direction::AbstractVector, + x, t, + equations::CompressibleEulerEquations2D) + # Get inverse of density + srho = 1 / u_inner[1] + + # Get normal velocity + vn = srho * (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) / + norm(normal_direction) + + return calc_characteristic_boundary_value_function(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations) +end + +# Function to compute the outer state of the characteristics-based boundary condition. +# This function is called by all mesh types. +@inline function calc_characteristic_boundary_value_function(outer_boundary_value_function, + u_inner, srho, vn, x, t, + equations::CompressibleEulerEquations2D) # get pressure and Mach from state p = pressure(u_inner, equations) a = sqrt(equations.gamma * p * srho) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 31d1c8a818..6d6e3e92a9 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -243,6 +243,22 @@ end return flux end +# Characteristic-based boundary condition for use with P4estMesh +@inline function (boundary_condition::BoundaryConditionCharacteristic)(u_inner, + normal_direction, + x, t, + surface_flux_function, + equations) + u_boundary = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, normal_direction, + x, t, equations) + + # Calculate boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + + return flux +end + # operator types used for dispatch on parabolic boundary fluxes struct Gradient end struct Divergence end diff --git a/src/solvers/dgsem_p4est/dg.jl b/src/solvers/dgsem_p4est/dg.jl index ec50627d3e..ad3b071749 100644 --- a/src/solvers/dgsem_p4est/dg.jl +++ b/src/solvers/dgsem_p4est/dg.jl @@ -52,4 +52,7 @@ include("dg_2d_parabolic.jl") include("dg_3d.jl") include("dg_3d_parabolic.jl") include("dg_parallel.jl") + +include("subcell_limiters_2d.jl") +include("dg_2d_subcell_limiters.jl") end # @muladd diff --git a/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl new file mode 100644 index 0000000000..f8a5ea24ec --- /dev/null +++ b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl @@ -0,0 +1,212 @@ +# 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 + +@inline function calc_lambdas_bar_states_interface!(u, t, limiter, boundary_conditions, + mesh::P4estMesh{2}, equations, + dg, cache; calc_bar_states = true) + (; contravariant_vectors) = cache.elements + (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states + + (; neighbor_ids, node_indices) = cache.interfaces + index_range = eachnode(dg) + + # Calc lambdas and bar states at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get element and side index information on the primary element + primary_element = neighbor_ids[1, interface] + primary_indices = node_indices[1, interface] + primary_direction = indices2direction(primary_indices) + + # Get element and side index information on the secondary element + secondary_element = neighbor_ids[2, interface] + secondary_indices = node_indices[2, interface] + secondary_direction = indices2direction(secondary_indices) + + # Create the local i,j indexing + i_primary_start, i_primary_step = index_to_start_step_2d(primary_indices[1], + index_range) + j_primary_start, j_primary_step = index_to_start_step_2d(primary_indices[2], + index_range) + i_secondary_start, i_secondary_step = index_to_start_step_2d(secondary_indices[1], + index_range) + j_secondary_start, j_secondary_step = index_to_start_step_2d(secondary_indices[2], + index_range) + + i_primary = i_primary_start - i_primary_step + j_primary = j_primary_start - j_primary_step + i_secondary = i_secondary_start - i_secondary_step + j_secondary = j_secondary_start - j_secondary_step + + for node in eachnode(dg) + # Increment primary element indices + i_primary += i_primary_step + j_primary += j_primary_step + i_secondary += i_secondary_step + j_secondary += j_secondary_step + + # Get the normal direction on the primary element. + # Contravariant vectors at interfaces in negative coordinate direction + # are pointing inwards. This is handled by `get_normal_direction`. + normal_direction = get_normal_direction(primary_direction, + contravariant_vectors, i_primary, + j_primary, primary_element) + + u_primary = get_node_vars(u, equations, dg, i_primary, j_primary, + primary_element) + u_secondary = get_node_vars(u, equations, dg, i_secondary, j_secondary, + secondary_element) + + lambda = max_abs_speed_naive(u_primary, u_secondary, normal_direction, + equations) + if primary_direction == 1 + lambda1[i_primary, j_primary, primary_element] = lambda + elseif primary_direction == 2 + lambda1[i_primary + 1, j_primary, primary_element] = lambda + elseif primary_direction == 3 + lambda2[i_primary, j_primary, primary_element] = lambda + else # primary_direction == 4 + lambda2[i_primary, j_primary + 1, primary_element] = lambda + end + if secondary_direction == 1 + lambda1[i_secondary, j_secondary, secondary_element] = lambda + elseif secondary_direction == 2 + lambda1[i_secondary + 1, j_secondary, secondary_element] = lambda + elseif secondary_direction == 3 + lambda2[i_secondary, j_secondary, secondary_element] = lambda + else # secondary_direction == 4 + lambda2[i_secondary, j_secondary + 1, secondary_element] = lambda + end + + !calc_bar_states && continue + + flux_primary = flux(u_primary, normal_direction, equations) + flux_secondary = flux(u_secondary, normal_direction, equations) + + bar_state = 0.5 * (u_primary + u_secondary) - + 0.5 * (flux_secondary - flux_primary) / lambda + if primary_direction == 1 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_primary, j_primary, primary_element) + elseif primary_direction == 2 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_primary + 1, j_primary, primary_element) + elseif primary_direction == 3 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_primary, j_primary, primary_element) + else # primary_direction == 4 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_primary, j_primary + 1, primary_element) + end + if secondary_direction == 1 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_secondary, j_secondary, secondary_element) + elseif secondary_direction == 2 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_secondary + 1, j_secondary, secondary_element) + elseif secondary_direction == 3 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_secondary, j_secondary, secondary_element) + else # secondary_direction == 4 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_secondary, j_secondary + 1, secondary_element) + end + end + end + + calc_lambdas_bar_states_boundary!(u, t, limiter, boundary_conditions, + mesh, equations, dg, cache; + calc_bar_states = calc_bar_states) + + return nothing +end + +@inline function calc_lambdas_bar_states_boundary!(u, t, limiter, + boundary_conditions::BoundaryConditionPeriodic, + mesh::P4estMesh{2}, equations, dg, + cache; calc_bar_states = true) + return nothing +end + +# Calc lambdas and bar states at physical boundaries +@inline function calc_lambdas_bar_states_boundary!(u, t, limiter, boundary_conditions, + mesh::P4estMesh{2}, equations, dg, + cache; calc_bar_states = true) + (; boundary_condition_types, boundary_indices) = boundary_conditions + (; contravariant_vectors) = cache.elements + + (; lambda1, lambda2, bar_states1, bar_states2) = limiter.cache.container_bar_states + + (; boundaries) = cache + index_range = eachnode(dg) + + # Allocation-free version of `foreach(enumerate((...))` + foreach_enumerate(boundary_condition_types) do (i, boundary_condition) + for boundary in boundary_indices[i] + element = boundaries.neighbor_ids[boundary] + node_indices = boundaries.node_indices[boundary] + direction = indices2direction(node_indices) + + i_node_start, i_node_step = index_to_start_step_2d(node_indices[1], + index_range) + j_node_start, j_node_step = index_to_start_step_2d(node_indices[2], + index_range) + + i_node = i_node_start - i_node_step + j_node = j_node_start - j_node_step + for node in eachnode(dg) + i_node += i_node_step + j_node += j_node_step + + normal_direction = get_normal_direction(direction, + contravariant_vectors, + i_node, j_node, element) + + u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_condition, normal_direction, + direction, mesh, equations, dg, + i_node, j_node, element) + + lambda = max_abs_speed_naive(u_inner, u_outer, normal_direction, + equations) + if direction == 1 + lambda1[i_node, j_node, element] = lambda + elseif direction == 2 + lambda1[i_node + 1, j_node, element] = lambda + elseif direction == 3 + lambda2[i_node, j_node, element] = lambda + else # direction == 4 + lambda2[i_node, j_node + 1, element] = lambda + end + + !calc_bar_states && continue + + flux_inner = flux(u_inner, normal_direction, equations) + flux_outer = flux(u_outer, normal_direction, equations) + + bar_state = 0.5 * (u_inner + u_outer) - + 0.5 * (flux_outer - flux_inner) / lambda + if direction == 1 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_node, j_node, element) + elseif direction == 2 + set_node_vars!(bar_states1, bar_state, equations, dg, + i_node + 1, j_node, element) + elseif direction == 3 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_node, j_node, element) + else # direction == 4 + set_node_vars!(bar_states2, bar_state, equations, dg, + i_node, j_node + 1, element) + end + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_p4est/subcell_limiters_2d.jl b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl new file mode 100644 index 0000000000..d014a7b038 --- /dev/null +++ b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl @@ -0,0 +1,250 @@ +# 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 calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, + mesh::P4estMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; boundary_conditions) = semi + + (; neighbor_ids, node_indices) = cache.interfaces + index_range = eachnode(dg) + + for interface in eachinterface(dg, cache) + # Get element and side index information on the primary element + primary_element = neighbor_ids[1, interface] + primary_indices = node_indices[1, interface] + + # Get element and side index information on the secondary element + secondary_element = neighbor_ids[2, interface] + secondary_indices = node_indices[2, interface] + + # Create the local i,j indexing + i_primary_start, i_primary_step = index_to_start_step_2d(primary_indices[1], + index_range) + j_primary_start, j_primary_step = index_to_start_step_2d(primary_indices[2], + index_range) + i_secondary_start, i_secondary_step = index_to_start_step_2d(secondary_indices[1], + index_range) + j_secondary_start, j_secondary_step = index_to_start_step_2d(secondary_indices[2], + index_range) + + i_primary = i_primary_start + j_primary = j_primary_start + i_secondary = i_secondary_start + j_secondary = j_secondary_start + + for node in eachnode(dg) + var_primary = u[variable, i_primary, j_primary, primary_element] + var_secondary = u[variable, i_secondary, j_secondary, secondary_element] + + var_min[i_primary, j_primary, primary_element] = min(var_min[i_primary, + j_primary, + primary_element], + var_secondary) + var_max[i_primary, j_primary, primary_element] = max(var_max[i_primary, + j_primary, + primary_element], + var_secondary) + + var_min[i_secondary, j_secondary, secondary_element] = min(var_min[i_secondary, + j_secondary, + secondary_element], + var_primary) + var_max[i_secondary, j_secondary, secondary_element] = max(var_max[i_secondary, + j_secondary, + secondary_element], + var_primary) + + # Increment primary element indices + i_primary += i_primary_step + j_primary += j_primary_step + i_secondary += i_secondary_step + j_secondary += j_secondary_step + end + end + + calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) + + return nothing +end + +@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, + boundary_conditions::BoundaryConditionPeriodic, + mesh, equations, dg, cache) + return nothing +end + +@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) + (; boundary_condition_types, boundary_indices) = boundary_conditions + (; contravariant_vectors) = cache.elements + + (; boundaries) = cache + index_range = eachnode(dg) + + foreach(enumerate(boundary_condition_types)) do (i, boundary_condition) + for boundary in boundary_indices[i] + element = boundaries.neighbor_ids[boundary] + node_indices = boundaries.node_indices[boundary] + direction = indices2direction(node_indices) + + i_node_start, i_node_step = index_to_start_step_2d(node_indices[1], + index_range) + j_node_start, j_node_step = index_to_start_step_2d(node_indices[2], + index_range) + + i_node = i_node_start + j_node = j_node_start + for i in eachnode(dg) + normal_direction = get_normal_direction(direction, + contravariant_vectors, + i_node, j_node, element) + + u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) + + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_condition, normal_direction, + direction, mesh, equations, dg, + i_node, j_node, element) + var_outer = u_outer[variable] + + var_min[i_node, j_node, element] = min(var_min[i_node, j_node, element], + var_outer) + var_max[i_node, j_node, element] = max(var_max[i_node, j_node, element], + var_outer) + + i_node += i_node_step + j_node += j_node_step + end + end + end + + return nothing +end + +function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, semi, + mesh::P4estMesh{2}) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; boundary_conditions) = semi + + (; neighbor_ids, node_indices) = cache.interfaces + index_range = eachnode(dg) + index_end = last(index_range) + + for interface in eachinterface(dg, cache) + # Get element and side index information on the primary element + primary_element = neighbor_ids[1, interface] + primary_indices = node_indices[1, interface] + + # Get element and side index information on the secondary element + secondary_element = neighbor_ids[2, interface] + secondary_indices = node_indices[2, interface] + + # Create the local i,j indexing + i_primary_start, i_primary_step = index_to_start_step_2d(primary_indices[1], + index_range) + j_primary_start, j_primary_step = index_to_start_step_2d(primary_indices[2], + index_range) + i_secondary_start, i_secondary_step = index_to_start_step_2d(secondary_indices[1], + index_range) + j_secondary_start, j_secondary_step = index_to_start_step_2d(secondary_indices[2], + index_range) + + i_primary = i_primary_start + j_primary = j_primary_start + i_secondary = i_secondary_start + j_secondary = j_secondary_start + + for node in eachnode(dg) + var_primary = variable(get_node_vars(u, equations, dg, i_primary, j_primary, + primary_element), equations) + var_secondary = variable(get_node_vars(u, equations, dg, i_secondary, + j_secondary, secondary_element), + equations) + + var_minmax[i_primary, j_primary, primary_element] = minmax(var_minmax[i_primary, + j_primary, + primary_element], + var_secondary) + var_minmax[i_secondary, j_secondary, secondary_element] = minmax(var_minmax[i_secondary, + j_secondary, + secondary_element], + var_primary) + + # Increment primary element indices + i_primary += i_primary_step + j_primary += j_primary_step + i_secondary += i_secondary_step + j_secondary += j_secondary_step + end + end + + calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) + + return nothing +end + +@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, + t, + boundary_conditions::BoundaryConditionPeriodic, + mesh, equations, dg, cache) + return nothing +end + +@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, + t, boundary_conditions, + mesh, equations, dg, cache) + (; boundary_condition_types, boundary_indices) = boundary_conditions + (; contravariant_vectors) = cache.elements + + (; boundaries) = cache + index_range = eachnode(dg) + + foreach(enumerate(boundary_condition_types)) do (i, boundary_condition) + for boundary in boundary_indices[i] + element = boundaries.neighbor_ids[boundary] + node_indices = boundaries.node_indices[boundary] + direction = indices2direction(node_indices) + + i_node_start, i_node_step = index_to_start_step_2d(node_indices[1], + index_range) + j_node_start, j_node_step = index_to_start_step_2d(node_indices[2], + index_range) + + i_node = i_node_start + j_node = j_node_start + for node in eachnode(dg) + normal_direction = get_normal_direction(direction, + contravariant_vectors, + i_node, j_node, element) + + u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) + + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_condition, normal_direction, + direction, mesh, equations, dg, + i_node, j_node, element) + var_outer = variable(u_outer, equations) + + var_minmax[i_node, j_node, element] = minmax(var_minmax[i_node, j_node, + element], + var_outer) + + i_node += i_node_step + j_node += j_node_step + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index c6f3dcc1f1..3a1a560214 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -10,8 +10,8 @@ # # See also `flux_differencing_kernel!`. @inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, - mesh::StructuredMesh{2}, nonconservative_terms::False, - equations, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) (; contravariant_vectors) = cache.elements (; weights, derivative_split) = dg.basis @@ -109,7 +109,8 @@ return nothing end -@inline function calc_lambdas_bar_states!(u, t, mesh::StructuredMesh{2}, +@inline function calc_lambdas_bar_states!(u, t, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, nonconservative_terms, equations, limiter, dg, cache, boundary_conditions; calc_bar_states = true) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index aff68284b4..c1afd67306 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -5,8 +5,9 @@ @muladd begin #! format: noindent -function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, - volume_integral::VolumeIntegralSubcellLimiting, dg::DG, uEltype) +function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}, P4estMesh{2}}, + equations, volume_integral::VolumeIntegralSubcellLimiting, + dg::DG, uEltype) cache = create_cache(mesh, equations, VolumeIntegralPureLGLFiniteVolume(volume_integral.volume_flux_fv), dg, uEltype) @@ -61,7 +62,8 @@ function create_cache(mesh::Union{TreeMesh{2}, StructuredMesh{2}}, equations, end function calc_volume_integral!(du, u, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, nonconservative_terms, equations, volume_integral::VolumeIntegralSubcellLimiting, dg::DGSEM, cache, t, boundary_conditions) @@ -124,7 +126,8 @@ function calc_volume_integral!(du, u, end @inline function subcell_limiting_kernel!(du, u, element, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, nonconservative_terms, equations, volume_integral, limiter::SubcellLimiterIDP, dg::DGSEM, cache) @@ -1879,4 +1882,20 @@ end return u_outer end + +@inline function get_boundary_outer_state(u_inner, cache, t, + boundary_condition::BoundaryConditionCharacteristic, + normal_direction::AbstractVector, direction, + mesh::P4estMesh, equations, dg, indices...) + (; node_coordinates) = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + + u_outer = boundary_condition.boundary_value_function(boundary_condition.outer_boundary_value_function, + u_inner, + normal_direction, + x, t, equations) + + return u_outer +end end # @muladd diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 431780dab8..5a37ab7739 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -375,7 +375,8 @@ end end @inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, - mesh::StructuredMesh{2}, elements, variable) + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -476,7 +477,8 @@ end end @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, - mesh::StructuredMesh{2}, elements) + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_min = variable_bounds[:spec_entropy_min] @@ -527,7 +529,8 @@ end end @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, - mesh::StructuredMesh{2}, elements) + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_max = variable_bounds[:math_entropy_max] @@ -599,7 +602,8 @@ end return nothing end -@inline function idp_positivity!(alpha, limiter, u, dt, semi, mesh::StructuredMesh{2}, +@inline function idp_positivity!(alpha, limiter, u, dt, semi, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) @@ -694,7 +698,8 @@ end end @inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, - mesh::StructuredMesh{2}, elements, variable) + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index bc5e46e193..e73e475a73 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -269,7 +269,8 @@ function calc_normal_directions!(container_bar_states, mesh::TreeMesh, equations nothing end -function calc_normal_directions!(container_bar_states, mesh::StructuredMesh{2}, +function calc_normal_directions!(container_bar_states, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, equations, dg, cache) (; weights, derivative_matrix) = dg.basis (; contravariant_vectors) = cache.elements diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index db34aecc16..d967b945a2 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -153,6 +153,32 @@ end end end +@trixi_testset "elixir_euler_free_stream_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_free_stream_sc_subcell.jl"), + l2=[ + 1.4663777294625118e-15, + 2.320054900530864e-14, + 3.487555722563465e-14, + 2.008802099296406e-14, + ], + linf=[ + 2.3092638912203256e-14, + 2.0623780461193064e-13, + 2.6795232699328153e-13, + 2.362554596402333e-13, + ], + atol=2.0e-12,) + # 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)) < 15000 + end +end + @trixi_testset "elixir_euler_shockcapturing_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), l2=[ @@ -337,6 +363,32 @@ end end end +@trixi_testset "elixir_euler_double_mach.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), + l2=[ + 0.8741784143331414, + 6.669726935141086, + 3.4980245896042237, + 76.33557073504075, + ], + linf=[ + 11.428353668952052, + 142.73486850872337, + 38.91639544604301, + 1651.7541390872523, + ], + initial_refinement_level=1, + 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)) < 15000 + end +end + @trixi_testset "elixir_euler_supersonic_cylinder.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder.jl"), l2=[ @@ -365,6 +417,35 @@ end end end +@trixi_testset "elixir_euler_supersonic_cylinder_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_supersonic_cylinder_sc_subcell.jl"), + l2=[ + 0.01733051773398731, + 0.038254257166961285, + 0.018157981470786955, + 0.12176639664229769, + ], + linf=[ + 1.3534563960399795, + 2.861333164923601, + 2.248472479406512, + 9.797432332463623, + ], + tspan=(0.0, 0.001), + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # 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)) < 15000 + end + end +end + @trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), l2=[ From 8803e4d96b2d339026f2b2007f1c01961d0fa8bd Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 6 Dec 2023 10:20:39 +0100 Subject: [PATCH 392/423] Add entropy limiting to elixir --- ...lixir_euler_supersonic_cylinder_sc_subcell.jl | 3 ++- test/test_p4est_2d.jl | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl index 8b6b93e0ac..de0a0116ec 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl @@ -98,7 +98,8 @@ basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], - spec_entropy = false, + spec_entropy = true, + max_iterations_newton = 100, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index d967b945a2..c763a2781d 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -421,16 +421,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder_sc_subcell.jl"), l2=[ - 0.01733051773398731, - 0.038254257166961285, - 0.018157981470786955, - 0.12176639664229769, + 0.015519026585326362, + 0.03624624063147592, + 0.015856390554735263, + 0.11035405581567337, ], linf=[ - 1.3534563960399795, - 2.861333164923601, - 2.248472479406512, - 9.797432332463623, + 1.034507228088565, + 2.7694272511829157, + 1.760899156958975, + 7.7689019494557865, ], tspan=(0.0, 0.001), skip_coverage=true) From aeb5025d0cd771993598d523dfa7c29face42a01 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 6 Dec 2023 11:30:07 +0100 Subject: [PATCH 393/423] Add elixirs and tests for MCL on P4estMesh --- .../elixir_euler_double_mach_MCL.jl | 170 ++++++++++++++++++ .../elixir_euler_free_stream_MCL.jl | 94 ++++++++++ .../elixir_euler_supersonic_cylinder_MCL.jl | 156 ++++++++++++++++ .../dgsem_tree/dg_2d_subcell_limiters.jl | 3 +- test/test_p4est_2d.jl | 81 +++++++++ 5 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_free_stream_MCL.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl new file mode 100644 index 0000000000..45f7d12f60 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -0,0 +1,170 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) + +Compressible Euler setup for a double Mach reflection problem. +Involves strong shock interactions as well as steady / unsteady flow structures. +Also exercises special boundary conditions along the bottom of the domain that is a mixture of +Dirichlet and slip wall. +See Section IV c on the paper below for details. + +- Paul Woodward and Phillip Colella (1984) + The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. + [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) +""" +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_double_mach_reflection + +boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + +# Special mixed boundary condition type for the :y_neg of the domain. +# It is charachteristic-based when x < 1/6 and a slip wall when x >= 1/6 +# Note: Only for P4estMesh +@inline function boundary_condition_mixed_characteristic_wall(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + # From the BoundaryConditionCharacteristic + # get the external state of the solution + u_boundary = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + x, t, + equations) + # Calculate boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, + surface_flux_function, equations) + end + + return flux +end + +# Note: Only for P4estMesh +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), + normal_direction::AbstractVector, direction, + mesh::P4estMesh{2}, + equations::CompressibleEulerEquations2D, + dg, indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + if x[1] < 1 / 6 # BoundaryConditionCharacteristic + u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, + u_inner, + normal_direction, + x, t, equations) + + else # if x[1] >= 1 / 6 # boundary_condition_slip_wall + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction + + u_outer = SVector(u_inner[1], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], + u_inner[4]) + end + return u_outer +end + +boundary_conditions = Dict(:y_neg => boundary_condition_mixed_characteristic_wall, + :y_pos => boundary_condition_inflow_outflow, + :x_pos => boundary_condition_inflow_outflow, + :x_neg => boundary_condition_inflow_outflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 4 +basis = LobattoLegendreBasis(polydeg) + +limiter_mcl = SubcellLimiterMCL(equations, basis; + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_density = false, + positivity_limiter_pressure = false, + entropy_limiter_semidiscrete = false, + Plotting = true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +initial_refinement_level = 4 +trees_per_dimension = (4 * 2^initial_refinement_level, 2^initial_refinement_level) +coordinates_min = (0.0, 0.0) +coordinates_max = (4.0, 1.0) +mesh = P4estMesh(trees_per_dimension, polydeg = polydeg, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 0, + periodicity = false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +stage_callbacks = (BoundsCheckCallback(save_errors = false),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream_MCL.jl new file mode 100644 index 0000000000..135744f0e4 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream_MCL.jl @@ -0,0 +1,94 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_constant + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_mcl = SubcellLimiterMCL(equations, basis; + density_limiter = true, + density_coefficient_for_all = false, + sequential_limiter = true, + conservative_limiter = false, + positivity_limiter_density = false, + positivity_limiter_pressure = false, + entropy_limiter_semidiscrete = false, + Plotting = true) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. +# This particular mesh is unstructured in the yz-plane, but extruded in x-direction. +# Apply the warping mapping in the yz-plane to get a curved 2D mesh that is extruded +# in x-direction to ensure free stream preservation on a non-conforming mesh. +# See https://doi.org/10.1007/s10915-018-00897-9, Section 6. + +# Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D +function mapping(xi_, eta_) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) + + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) + + return SVector(x, y) +end + +trees_per_dimension = (16, 16) + +# Create P4estMesh with 16 x 16 trees and 16 x 16 elements +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + mapping = mapping, + initial_refinement_level = 0, periodicity = true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 10000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +############################################################################### +# run the simulation + +stage_callbacks = (BoundsCheckCallback(save_errors = false),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl new file mode 100644 index 0000000000..75b65fe1f2 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl @@ -0,0 +1,156 @@ +# Channel flow around a cylinder at Mach 3 +# +# Boundary conditions are supersonic Mach 3 inflow at the left portion of the domain +# and supersonic outflow at the right portion of the domain. The top and bottom of the +# channel as well as the cylinder are treated as Euler slip wall boundaries. +# This flow results in strong shock reflections / interactions as well as Kelvin-Helmholtz +# instabilities at later times as two Mach stems form above and below the cylinder. +# +# For complete details on the problem setup see Section 5.7 of the paper: +# - Jean-Luc Guermond, Murtazo Nazarov, Bojan Popov, and Ignacio Tomas (2018) +# Second-Order Invariant Domain Preserving Approximation of the Euler Equations using Convex Limiting. +# [DOI: 10.1137/17M1149961](https://doi.org/10.1137/17M1149961) +# +# Keywords: supersonic flow, shock capturing, AMR, unstructured curved mesh, positivity preservation, compressible Euler, 2D + +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +@inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_mach3_flow + +# Supersonic inflow boundary condition. +# Calculate the boundary flux entirely from the external solution state, i.e., set +# external solution state values for everything entering the domain. +@inline function boundary_condition_supersonic_inflow(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach3_flow(x, t, equations) + flux = Trixi.flux(u_boundary, normal_direction, equations) + + return flux +end + +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_supersonic_inflow), + normal_direction::AbstractVector, direction, + mesh::P4estMesh{2}, equations, dg, + indices...) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) + + return initial_condition_mach3_flow(x, t, equations) +end + +# Supersonic outflow boundary condition. +# Calculate the boundary flux entirely from the internal solution state. Analogous to supersonic inflow +# except all the solution state values are set from the internal solution as everything leaves the domain +@inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, + surface_flux_function, + equations::CompressibleEulerEquations2D) + flux = Trixi.flux(u_inner, normal_direction, equations) + + return flux +end + +@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, + boundary_condition::typeof(boundary_condition_outflow), + orientation_or_normal, direction, + mesh::P4estMesh{2}, equations, dg, + indices...) + return u_inner +end + +# boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_condition) + +# boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, +# :Circle => boundary_condition_slip_wall, +# :Top => boundary_condition_slip_wall, +# :Right => boundary_condition_inflow_outflow, +# :Left => boundary_condition_inflow_outflow) + +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Circle => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_supersonic_inflow) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_mcl = SubcellLimiterMCL(equations, basis; + density_limiter = true, + density_coefficient_for_all = true, + sequential_limiter = false, + conservative_limiter = false, + positivity_limiter_density = true, + positivity_limiter_pressure = true, + entropy_limiter_semidiscrete = false, + Plotting = true) +volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; + 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_mesh_file = joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = P4estMesh{2}(mesh_file, initial_refinement_level = 0) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers + +tspan = (0.0, 2.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, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.9) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) + +stage_callbacks = (BoundsCheckCallback(save_errors = false),) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index c1afd67306..36a860438b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -177,7 +177,8 @@ end @inline function subcell_limiting_kernel!(du, u, element, - mesh::Union{TreeMesh{2}, StructuredMesh{2}}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, nonconservative_terms::False, equations, volume_integral, limiter::SubcellLimiterMCL, dg::DGSEM, cache) diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index c763a2781d..a9803299fd 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -179,6 +179,32 @@ end end end +@trixi_testset "elixir_euler_free_stream_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_MCL.jl"), + l2=[ + 1.5395023651392628e-16, + 5.707276922805213e-15, + 6.656058585297407e-15, + 5.171129126439075e-15, + ], + linf=[ + 2.886579864025407e-15, + 5.384581669432009e-14, + 9.997558336749535e-14, + 6.217248937900877e-14, + ], + trees_per_dimension=(8, 8), + atol=2.0e-12,) + # 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)) < 15000 + end +end + @trixi_testset "elixir_euler_shockcapturing_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), l2=[ @@ -389,6 +415,32 @@ end end end +@trixi_testset "elixir_euler_double_mach_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), + l2=[ + 0.8887316275665456, + 6.644244953884144, + 3.449004719784639, + 76.2706476520857, + ], + linf=[ + 11.047531178706233, + 121.96650277677226, + 35.74266968217143, + 1370.2362955295619, + ], + initial_refinement_level=1, + 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)) < 10000 + end +end + @trixi_testset "elixir_euler_supersonic_cylinder.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder.jl"), l2=[ @@ -446,6 +498,35 @@ end end end +@trixi_testset "elixir_euler_supersonic_cylinder_MCL.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_supersonic_cylinder_MCL.jl"), + l2=[ + 0.01719185099537115, + 0.037755715231922615, + 0.018219844214522288, + 0.1211329583241979, + ], + linf=[ + 1.36377851955985337, + 2.886724226405783, + 2.271954486109792, + 9.900660307619413, + ], + tspan=(0.0, 0.001), + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # 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)) < 15000 + end + end +end + @trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), l2=[ From 1431449d947e00ef3c6ca7a25a630e0d61494b80 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 6 Dec 2023 13:51:04 +0100 Subject: [PATCH 394/423] Fix test --- test/test_p4est_2d.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index a9803299fd..478d7d1d4c 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -418,16 +418,16 @@ end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ - 0.8887316275665456, - 6.644244953884144, + 0.8887316108902814, + 6.644244699117552, 3.449004719784639, 76.2706476520857, ], linf=[ 11.047531178706233, - 121.96650277677226, + 121.96649938887894, 35.74266968217143, - 1370.2362955295619, + 1370.2362649787465, ], initial_refinement_level=1, tspan=(0.0, 0.05)) @@ -437,7 +437,7 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end From 2702bb8ae9422701bf7279d46f25fb1a9bdeb0fa Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 7 Dec 2023 16:48:16 +0100 Subject: [PATCH 395/423] Rename Newton-bisection variables --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index fee22e188a..788d32344a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -402,9 +402,9 @@ end # If state is valid, perform initial check and return if correction is not needed if is_valid_state(u_curr, equations) - as = goal_function(variable, bound, u_curr, equations) + goal = goal_function(variable, bound, u_curr, equations) - initial_check(bound, as, newton_abstol) && return nothing + initial_check(bound, goal, newton_abstol) && return nothing end # Newton iterations @@ -413,19 +413,19 @@ end # If the state is valid, evaluate d(goal)/d(beta) if is_valid_state(u_curr, equations) - dSdbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, - equations) + dgoal_dbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, + equations) else # Otherwise, perform a bisection step - dSdbeta = 0 + dgoal_dbeta = 0 end - if dSdbeta != 0 + if dgoal_dbeta != 0 # Update beta with Newton's method - beta = beta - as / dSdbeta + beta = beta - goal / dgoal_dbeta end # Check bounds - if (beta < beta_L) || (beta > beta_R) || (dSdbeta == 0) || isnan(beta) + if (beta < beta_L) || (beta > beta_R) || (dgoal_dbeta == 0) || isnan(beta) # Out of bounds, do a bisection step beta = 0.5 * (beta_L + beta_R) # Get new u @@ -438,8 +438,8 @@ end end # Check new beta for condition and update bounds - as = goal_function(variable, bound, u_curr, equations) - if initial_check(bound, as, newton_abstol) + goal = goal_function(variable, bound, u_curr, equations) + if initial_check(bound, goal, newton_abstol) # New beta fulfills condition beta_L = beta else @@ -457,7 +457,7 @@ end end # Evaluate goal function - as = goal_function(variable, bound, u_curr, equations) + goal = goal_function(variable, bound, u_curr, equations) end # Check relative tolerance @@ -466,7 +466,7 @@ end end # Check absolute tolerance - if final_check(bound, as, newton_abstol) + if final_check(bound, goal, newton_abstol) break end end From 5ec5adee3d248bb255868a32b9790ea717a42c2f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 13 Dec 2023 12:59:26 +0100 Subject: [PATCH 396/423] Implement suggestions --- src/solvers/dgsem_tree/subcell_limiters.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 86d70e3853..fb52272e2e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -36,8 +36,8 @@ The bounds are calculated using the low-order FV solution. The positivity limite `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. The limiting of nonlinear variables uses a Newton-bisection method with a maximum of `max_iterations_newton` iterations, relative and absolute tolerances of `newton_tolerances` -and a gamma constant of `gamma_constant_newton` (`gamma_constant_newton>=2*d`, -where `d = #dimensions`). +and a provisional update constant `gamma_constant_newton` (`gamma_constant_newton>=2*d`, +where `d = #dimensions`). See equation (20) of Pazner (2020) and equation (30) of Rueda-Ramírez et al. (2022). !!! note This limiter and the correction callback [`SubcellLimiterIDPCorrection`](@ref) only work together. diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 788d32344a..98d2a3296c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -238,9 +238,12 @@ end @inline function idp_positivity!(alpha, limiter, u, dt, semi) # Conservative variables for variable in limiter.positivity_variables_cons - @trixi_timeit timer() "conservative variables" idp_positivity!(alpha, limiter, - u, dt, semi, - variable) + @trixi_timeit timer() "conservative variables" idp_positivity_conservative!(alpha, + limiter, + u, + dt, + semi, + variable) end # Nonlinear variables @@ -258,7 +261,7 @@ end ############################################################################### # Global positivity limiting of conservative variables -@inline function idp_positivity!(alpha, limiter, u, dt, semi, variable) +@inline function idp_positivity_conservative!(alpha, limiter, u, dt, semi, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes (; inverse_weights) = dg.basis From 944ec3c570fb6c637ce5e073ed74f89765568bae Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 21 Dec 2023 20:15:42 +0100 Subject: [PATCH 397/423] fmt --- test/test_tree_2d_eulermulti.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 5974e9938f..323d88c01e 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -97,22 +97,22 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), - l2=[ - 76.59096367977872, - 1.9879932386864356, - 59851.34515039375, - 0.18710988181124935, - 0.010631432251136084, - ], - linf=[ - 212.71245739310544, - 27.399221359958894, - 158389.9681231281, - 0.6524718882809865, - 0.10630137919864985, - ], - initial_refinement_level=3, - tspan=(0.0, 0.001)) + l2=[ + 76.59096367977872, + 1.9879932386864356, + 59851.34515039375, + 0.18710988181124935, + 0.010631432251136084, + ], + linf=[ + 212.71245739310544, + 27.399221359958894, + 158389.9681231281, + 0.6524718882809865, + 0.10630137919864985, + ], + initial_refinement_level=3, + tspan=(0.0, 0.001)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From bcd1c9909f1c685213ef952cbda68288e7d0fa1d Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 12:16:53 +0100 Subject: [PATCH 398/423] Fix variable_derivative routines for entropies --- src/equations/compressible_euler_2d.jl | 55 +++++++++++++++----------- src/equations/ideal_glm_mhd_2d.jl | 45 ++++++++++----------- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 9cd76701b5..75fae0afa7 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1529,7 +1529,6 @@ end return SVector(w1, w2, w3, w4) end -@inline entropy_math(u, equations, derivative::True) = cons2entropy(u, equations) # Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) @inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) @@ -1556,19 +1555,6 @@ end return SVector(w1, w2, w3, w4) end -@inline entropy_spec(u, equations, derivative::True) = cons2entropy_spec(u, equations) - -# Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::CompressibleEulerEquations2D) - rho, rho_v1, rho_v2, rho_e = u - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v_square = v1^2 + v2^2 - - return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) -end @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD @@ -1594,14 +1580,6 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end -@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 - return false - end - return true -end - # Convert primitive to conservative variables @inline function prim2cons(prim, equations::CompressibleEulerEquations2D) rho, v1, v2, p = prim @@ -1622,6 +1600,18 @@ end return p end +# Transformation from conservative variables u to d(p)/d(u) +@inline function variable_derivative(::typeof(pressure), + u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + + return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) +end + @inline function density_pressure(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u rho_times_p = (equations.gamma - 1) * (rho * rho_e - 0.5 * (rho_v1^2 + rho_v2^2)) @@ -1671,6 +1661,12 @@ end return S end +# Transformation from conservative variables u to d(s)/d(u) +@inline function variable_derivative(::typeof(entropy_math), + u, equations::CompressibleEulerEquations2D) + return cons2entropy(u, equations) +end + # Calculate specific entropy for conservative variable u @inline function entropy_spec(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u @@ -1684,6 +1680,12 @@ end return s end +# Transformation from conservative variables u to d(s)/d(u) +@inline function variable_derivative(::typeof(entropy_spec), + u, equations::CompressibleEulerEquations2D) + return cons2entropy_spec(u, equations) +end + # Default entropy is the mathematical entropy @inline function entropy(cons, equations::CompressibleEulerEquations2D) entropy_math(cons, equations) @@ -1702,4 +1704,13 @@ end @inline function energy_internal(cons, equations::CompressibleEulerEquations2D) return energy_total(cons, equations) - energy_kinetic(cons, equations) end + +# State validation for subcell limiting using Newton-bisection method +@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end end # @muladd diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index e486b5532b..b1371ba38b 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1062,20 +1062,6 @@ end return SVector(w1, w2, w3, w4, w5, w6, w7, w8, w9) end -# Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::IdealGlmMhdEquations2D) - rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v_square = v1^2 + v2^2 + v3^2 - - return (equations.gamma - 1.0) * - SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) -end - # Convert entropy variables to conservative variables @inline function entropy2cons(w, equations::IdealGlmMhdEquations2D) w1, w2, w3, w4, w5, w6, w7, w8, w9 = w @@ -1103,14 +1089,6 @@ end return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end -@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 - return false - end - return true -end - # Convert primitive to conservative variables @inline function prim2cons(prim, equations::IdealGlmMhdEquations2D) rho, v1, v2, v3, p, B1, B2, B3, psi = prim @@ -1140,6 +1118,20 @@ end return p end +# Transformation from conservative variables u to d(p)/d(u) +@inline function variable_derivative(::typeof(pressure), + u, equations::IdealGlmMhdEquations2D) + rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_square = v1^2 + v2^2 + v3^2 + + return (equations.gamma - 1.0) * + SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) +end + @inline function density_pressure(u, equations::IdealGlmMhdEquations2D) rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u p = (equations.gamma - 1) * (rho_e - 0.5 * (rho_v1^2 + rho_v2^2 + rho_v3^2) / rho @@ -1406,6 +1398,15 @@ end cons[9]^2 / 2) end +# State validation for subcell limiting using Newton-bisection method +@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end + # Calculate the cross helicity (\vec{v}⋅\vec{B}) for a conservative state `cons' @inline function cross_helicity(cons, ::IdealGlmMhdEquations2D) return (cons[2] * cons[6] + cons[3] * cons[7] + cons[4] * cons[8]) / cons[1] From ccdc34edf591ac5bab10fb4b2011c86da6b3b6ac Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 12:27:40 +0100 Subject: [PATCH 399/423] Relocate functions --- src/equations/compressible_euler_2d.jl | 41 +++++++++++------------ src/equations/ideal_glm_mhd_2d.jl | 45 +++++++++++++------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index ca10fbac66..47916283a1 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1404,18 +1404,6 @@ end return SVector(w1, w2, w3, w4) end -# Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::CompressibleEulerEquations2D) - rho, rho_v1, rho_v2, rho_e = u - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v_square = v1^2 + v2^2 - - return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) -end - @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD # [DOI: 10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) @@ -1440,14 +1428,6 @@ end return SVector(rho, rho_v1, rho_v2, rho_e) end -@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 - return false - end - return true -end - # Convert primitive to conservative variables @inline function prim2cons(prim, equations::CompressibleEulerEquations2D) rho, v1, v2, p = prim @@ -1468,6 +1448,18 @@ end return p end +# Transformation from conservative variables u to d(p)/d(u) +@inline function variable_derivative(::typeof(pressure), + u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + + return (equations.gamma - 1.0) * SVector(0.5 * v_square, -v1, -v2, 1.0) +end + @inline function density_pressure(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u rho_times_p = (equations.gamma - 1) * (rho * rho_e - 0.5 * (rho_v1^2 + rho_v2^2)) @@ -1535,4 +1527,13 @@ end @inline function energy_internal(cons, equations::CompressibleEulerEquations2D) return energy_total(cons, equations) - energy_kinetic(cons, equations) end + +# State validation for subcell limiting using Newton-bisection method +@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end end # @muladd diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index e486b5532b..b1371ba38b 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -1062,20 +1062,6 @@ end return SVector(w1, w2, w3, w4, w5, w6, w7, w8, w9) end -# Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::IdealGlmMhdEquations2D) - rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v_square = v1^2 + v2^2 + v3^2 - - return (equations.gamma - 1.0) * - SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) -end - # Convert entropy variables to conservative variables @inline function entropy2cons(w, equations::IdealGlmMhdEquations2D) w1, w2, w3, w4, w5, w6, w7, w8, w9 = w @@ -1103,14 +1089,6 @@ end return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end -@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 - return false - end - return true -end - # Convert primitive to conservative variables @inline function prim2cons(prim, equations::IdealGlmMhdEquations2D) rho, v1, v2, v3, p, B1, B2, B3, psi = prim @@ -1140,6 +1118,20 @@ end return p end +# Transformation from conservative variables u to d(p)/d(u) +@inline function variable_derivative(::typeof(pressure), + u, equations::IdealGlmMhdEquations2D) + rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_square = v1^2 + v2^2 + v3^2 + + return (equations.gamma - 1.0) * + SVector(0.5 * v_square, -v1, -v2, -v3, 1.0, -B1, -B2, -B3, -psi) +end + @inline function density_pressure(u, equations::IdealGlmMhdEquations2D) rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u p = (equations.gamma - 1) * (rho_e - 0.5 * (rho_v1^2 + rho_v2^2 + rho_v3^2) / rho @@ -1406,6 +1398,15 @@ end cons[9]^2 / 2) end +# State validation for subcell limiting using Newton-bisection method +@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) + p = pressure(cons, equations) + if cons[1] <= 0.0 || p <= 0.0 + return false + end + return true +end + # Calculate the cross helicity (\vec{v}⋅\vec{B}) for a conservative state `cons' @inline function cross_helicity(cons, ::IdealGlmMhdEquations2D) return (cons[2] * cons[6] + cons[3] * cons[7] + cons[4] * cons[8]) / cons[1] From 91e5239375b164cf61e1a83c3ee192328e91e8fa Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 13:51:23 +0100 Subject: [PATCH 400/423] Add entropy limiters --- ...euler_blast_wave_sc_subcell_nonperiodic.jl | 3 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 3 +- src/callbacks_stage/subcell_bounds_check.jl | 18 +- .../subcell_bounds_check_2d.jl | 32 +++- src/equations/compressible_euler_2d.jl | 52 ++++++ src/solvers/dgsem_tree/subcell_limiters.jl | 43 ++++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 169 +++++++++++++++++- test/test_tree_2d_euler.jl | 32 ++-- test/test_unit.jl | 4 +- 9 files changed, 325 insertions(+), 31 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index 209aa2ae35..6ff381b896 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -41,7 +41,8 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"]) + local_minmax_variables_cons = ["rho"], + math_entropy = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index c1ba3d9696..64cae96315 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,7 +42,8 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"]) + local_minmax_variables_cons = ["rho"], + spec_entropy = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 25662f8580..04fe084eff 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -77,7 +77,7 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - (; local_minmax, positivity) = limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter (; output_directory) = callback variables = varnames(cons2cons, semi.equations) @@ -90,6 +90,12 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi print(f, ", " * variable_string * "_min, " * variable_string * "_max") end end + if spec_entropy + print(f, ", specEntr_min") + end + if math_entropy + print(f, ", mathEntr_max") + end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons @@ -120,7 +126,7 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - (; local_minmax, positivity) = limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter (; idp_bounds_delta) = limiter.cache variables = varnames(cons2cons, semi.equations) @@ -135,6 +141,14 @@ end println("-upper bound: ", idp_bounds_delta[Symbol(v_string, "_max")][2]) end end + if spec_entropy + println("spec. entropy:\n- lower bound: ", + idp_bounds_delta[:spec_entropy_min][2]) + end + if math_entropy + println("math. entropy:\n- upper bound: ", + idp_bounds_delta[:math_entropy_max][2]) + end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 688d3281b9..06e5663e12 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -8,7 +8,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors) - (; local_minmax, positivity) = solver.volume_integral.limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta) = limiter.cache @@ -32,6 +32,30 @@ deviation_max[2] = max(deviation_max[2], deviation_max[1]) end end + if spec_entropy + key = :spec_entropy_min + deviation = idp_bounds_delta[key] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), + equations) + deviation[1] = max(deviation[1], variable_bounds[key][i, j, element] - s) + end + deviation[2] = max(deviation[2], deviation[1]) + end + if math_entropy + key = :math_entropy_max + deviation = idp_bounds_delta[key] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + s = entropy_math(get_node_vars(u, equations, solver, i, j, element), + equations) + deviation[1] = max(deviation[1], s - variable_bounds[key][i, j, element]) + end + deviation[2] = max(deviation[2], deviation[1]) + end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons @@ -73,6 +97,12 @@ idp_bounds_delta[Symbol(v_string, "_max")][1]) end end + if spec_entropy + print(f, ", ", idp_bounds_delta[:spec_entropy_min][1]) + end + if math_entropy + print(f, ", ", idp_bounds_delta[:math_entropy_max][1]) + end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 47916283a1..d660f6f0db 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1404,6 +1404,33 @@ end return SVector(w1, w2, w3, w4) end +# Transformation from conservative variables u to entropy vector dSdu, +# S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) +@inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + inv_rho_gammap1 = (1 / rho)^(equations.gamma + 1.0) + + # The derivative vector for the modified specific entropy of Guermond et al. + w1 = inv_rho_gammap1 * + (0.5 * rho * (equations.gamma + 1.0) * v_square - equations.gamma * rho_e) + w2 = -rho_v1 * inv_rho_gammap1 + w3 = -rho_v2 * inv_rho_gammap1 + w4 = (1 / rho)^equations.gamma + + # The derivative vector for other specific entropy + # sp = 1.0/(gammam1 * (rho_e - 0.5 * rho * v_square) + # w1 = gammam1 * 0.5 * v_square * sp - gamma / rho + # w2 = -gammam1 * v1 * sp + # w3 = -gammam1 * v2 * sp + # w4 = gammam1 * sp + + return SVector(w1, w2, w3, w4) +end + @inline function entropy2cons(w, equations::CompressibleEulerEquations2D) # See Hughes, Franca, Mallet (1986) A new finite element formulation for CFD # [DOI: 10.1016/0045-7825(86)90127-1](https://doi.org/10.1016/0045-7825(86)90127-1) @@ -1509,6 +1536,31 @@ end return S end +# Transformation from conservative variables u to d(s)/d(u) +@inline function variable_derivative(::typeof(entropy_math), + u, equations::CompressibleEulerEquations2D) + return cons2entropy(u, equations) +end + +# Calculate specific entropy for conservative variable u +@inline function entropy_spec(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, rho_v2, rho_e = u + + # Modified specific entropy from Guermond et al. (2019) + s = (rho_e - 0.5 * (rho_v1^2 + rho_v2^2) / rho) * (1 / rho)^equations.gamma + + # Other specific entropy + # rho_sp = rho/((equations.gamma - 1.0) * (rho_e - 0.5 * rho * v_square)) + # s = log(p) - (equaions.gamma + 1) * log(rho) + return s +end + +# Transformation from conservative variables u to d(s)/d(u) +@inline function variable_derivative(::typeof(entropy_spec), + u, equations::CompressibleEulerEquations2D) + return cons2entropy_spec(u, equations) +end + # Default entropy is the mathematical entropy @inline function entropy(cons, equations::CompressibleEulerEquations2D) entropy_math(cons, equations) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index fb52272e2e..db44385384 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -18,6 +18,8 @@ end positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) @@ -27,6 +29,7 @@ including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) +- One-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are @@ -63,6 +66,8 @@ struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, Cache} <: positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables positivity_correction_factor::RealT + spec_entropy::Bool + math_entropy::Bool cache::Cache max_iterations_newton::Int newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method @@ -75,12 +80,17 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, + spec_entropy = false, + math_entropy = false, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) + if math_entropy && spec_entropy + error("Only one of the two can be selected: math_entropy/spec_entropy") + end local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, equations) @@ -95,6 +105,12 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; Symbol(v_string, "_max")) end end + if spec_entropy + bound_keys = (bound_keys..., :spec_entropy_min) + end + if math_entropy + bound_keys = (bound_keys..., :math_entropy_max) + end for v in positivity_variables_cons_ if !(v in local_minmax_variables_cons_) bound_keys = (bound_keys..., Symbol(string(v), "_min")) @@ -111,22 +127,26 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; typeof(cache)}(local_minmax, local_minmax_variables_cons_, positivity, positivity_variables_cons_, positivity_variables_nonlinear, - positivity_correction_factor, cache, + positivity_correction_factor, + spec_entropy, math_entropy, + cache, max_iterations_newton, newton_tolerances, gamma_constant_newton) end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity) = limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter print(io, "SubcellLimiterIDP(") - if !(local_minmax || positivity) + if !(local_minmax || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else print(io, "Limiter=(") local_minmax && print(io, "Local min/max, ") positivity && print(io, "Positivity, ") + spec_entropy && print(io, "Specific entropy, ") + math_entropy && print(io, "Mathematical entropy, ") print(io, "), ") end print(io, "Local bounds with FV solution") @@ -135,15 +155,15 @@ end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity) = limiter + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter if get(io, :compact, false) show(io, limiter) else - if !(local_minmax || positivity) - setup = ["limiter" => "No limiter selected => pure DG method"] + if !(local_minmax || positivity || spec_entropy || math_entropy) + setup = ["Limiter" => "No limiter selected => pure DG method"] else - setup = ["limiter" => ""] + setup = ["Limiter" => ""] if local_minmax setup = [ setup..., @@ -158,6 +178,15 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", ] end + if spec_entropy + setup = [setup..., "" => "Local minimum limiting for specific entropy"] + end + if math_entropy + setup = [ + setup..., + "" => "Local maximum limiting for mathematical entropy", + ] + end setup = [ setup..., "Local bounds" => "FV solution", diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 98d2a3296c..edc2a2182a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -40,6 +40,14 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) end + if limiter.spec_entropy + @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, dt, + semi) + end + if limiter.math_entropy + @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, dt, + semi) + end # Calculate alpha1 and alpha2 @unpack alpha1, alpha2 = limiter.cache.subcell_limiter_coefficients @@ -160,6 +168,105 @@ end return nothing end +@inline function calc_bounds_onesided!(var_minmax, minmax, typeminmax, variable, u, t, + semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + var_minmax[i, j, element] = typeminmax(eltype(var_minmax)) + end + + # Calculate bounds at Gauss-Lobatto nodes using u + for j in eachnode(dg), i in eachnode(dg) + var = variable(get_node_vars(u, equations, dg, i, j, element), equations) + var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) + + if i > 1 + var_minmax[i - 1, j, element] = minmax(var_minmax[i - 1, j, element], + var) + end + if i < nnodes(dg) + var_minmax[i + 1, j, element] = minmax(var_minmax[i + 1, j, element], + var) + end + if j > 1 + var_minmax[i, j - 1, element] = minmax(var_minmax[i, j - 1, element], + var) + end + if j < nnodes(dg) + var_minmax[i, j + 1, element] = minmax(var_minmax[i, j + 1, element], + var) + end + end + end + + # Values at element boundary + calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) +end + +@inline function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, + semi, mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; boundary_conditions) = semi + # Calc bounds at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) + end + var_left = variable(get_node_vars(u, equations, dg, index_left..., left), + equations) + var_right = variable(get_node_vars(u, equations, dg, index_right..., right), + equations) + + var_minmax[index_right..., right] = minmax(var_minmax[index_right..., + right], var_left) + var_minmax[index_left..., left] = minmax(var_minmax[index_left..., left], + var_right) + end + end + + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + for i in eachnode(dg) + if neighbor_side == 2 # Element is on the right, boundary on the left + index = (1, i) + boundary_index = 1 + else # Element is on the left, boundary on the right + index = (nnodes(dg), i) + boundary_index = 2 + end + if orientation == 2 + index = reverse(index) + boundary_index += 2 + end + u_outer = get_boundary_outer_state(boundary_conditions[boundary_index], + cache, t, equations, dg, + index..., element) + var_outer = variable(u_outer, equations) + + var_minmax[index..., element] = minmax(var_minmax[index..., element], + var_outer) + end + end + + return nothing +end + ############################################################################### # Local minimum/maximum limiting @@ -232,6 +339,54 @@ end return nothing end +############################################################################## +# Local minimum limiting of specific entropy + +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_min = variable_bounds[:spec_entropy_min] + calc_bounds_onesided!(s_min, min, typemax, entropy_spec, u, t, semi) + + # Perform Newton's bisection method to find new alpha + @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, + entropy_spec, initial_check_entropy_spec, + final_check_nonnegative, inverse_jacobian, + dt, equations, dg, cache, limiter) + end + end + + return nothing +end + +############################################################################### +# Local maximum limiting of mathematical entropy + +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + s_max = variable_bounds[:math_entropy_max] + calc_bounds_onesided!(s_max, max, typemin, entropy_math, u, t, semi) + + # Perform Newton's bisection method to find new alpha + @threaded for element in eachelement(dg, cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, + entropy_math, initial_check_entropy_math, + final_check_nonnegative, inverse_jacobian, + dt, equations, dg, cache, limiter) + end + end + + return nothing +end + ############################################################################### # Global positivity limiting @@ -485,6 +640,14 @@ end end # Initial checks +@inline function initial_check_entropy_spec(bound, goal, newton_abstol) + goal <= max(newton_abstol, abs(bound) * newton_abstol) +end + +@inline function initial_check_entropy_math(bound, goal, newton_abstol) + goal >= -max(newton_abstol, abs(bound) * newton_abstol) +end + @inline initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 # Goal and d(Goal)d(u) function @@ -493,7 +656,11 @@ end -dot(variable_derivative(variable, u, equations), dt * antidiffusive_flux) end -# Final checks +# Final check +@inline function final_check_standard(bound, goal, newton_abstol) + abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) +end + @inline function final_check_nonnegative(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 06b2da681c..cb9be39b38 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -317,16 +317,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ - 0.3517507570120483, - 0.19252291020146015, - 0.19249751956580294, - 0.618717827188004, + 0.3221133847370183, + 0.1798445067477554, + 0.17983199781537987, + 0.6136848341801259, ], linf=[ - 1.6699566795772216, - 1.3608007992899402, - 1.361864507190922, - 2.44022884092527, + 1.3433576692371516, + 1.1747340428151851, + 1.1744175397224497, + 2.4215287080587955, ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -371,16 +371,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ - 0.4328635350273501, - 0.15011135840723572, - 0.15011135840723572, - 0.616129927549474, + 0.41446162783024115, + 0.14606475224088192, + 0.14607706259100364, + 0.6168364393501943, ], linf=[ - 1.6145297181778906, - 0.8614006163026988, - 0.8614006163026972, - 6.450225090647602, + 1.5717827990209163, + 0.7963182071213032, + 0.7956862000276138, + 6.456116489970984, ], tspan=(0.0, 1.0), initial_refinement_level=4, diff --git a/test/test_unit.jl b/test/test_unit.jl index 8b91f0875c..16d94fabe9 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,8 +416,8 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, "cache", 1, - (1.0, 1.0), 1.0) + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, true, true, + "cache", 1, (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test From 927d783004ba319eb9e746c89d80087c3cab00a4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 14:48:33 +0100 Subject: [PATCH 401/423] Update test errors after adding entropy limiting --- test/test_tree_2d_euler.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index cb9be39b38..1bb7cf89ea 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -317,16 +317,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ - 0.3221133847370183, - 0.1798445067477554, - 0.17983199781537987, - 0.6136848341801259, + 0.32211638619244837, + 0.17984613698288662, + 0.1798341339489921, + 0.6136855864874968, ], linf=[ - 1.3433576692371516, - 1.1747340428151851, - 1.1744175397224497, - 2.4215287080587955, + 1.343528359596545, + 1.174708306029737, + 1.174481988232382, + 2.42152874599586, ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -371,16 +371,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ - 0.41446162783024115, - 0.14606475224088192, - 0.14607706259100364, - 0.6168364393501943, + 0.4144617475432438, + 0.14606478267219714, + 0.1460770935963815, + 0.6168365992433479, ], linf=[ - 1.5717827990209163, - 0.7963182071213032, - 0.7956862000276138, - 6.456116489970984, + 1.5717829602926576, + 0.7963192532954594, + 0.7956878517936237, + 6.4561186367550825, ], tspan=(0.0, 1.0), initial_refinement_level=4, From 40b8d93a6a75eb9b63559a702576778b5259fb6c Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 14:51:37 +0100 Subject: [PATCH 402/423] Use `calc_onesided_boundary` from `subcell-limiting-entropies` --- src/equations/compressible_euler_2d.jl | 3 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 110 ++++++------------ 2 files changed, 35 insertions(+), 78 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 75fae0afa7..2b437675e9 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1530,7 +1530,8 @@ end return SVector(w1, w2, w3, w4) end -# Transformation from conservative variables u to entropy vector dSdu, S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) +# Transformation from conservative variables u to entropy vector dSdu, +# S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) @inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 67958fbd4b..dbdc2afda8 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -241,29 +241,22 @@ end right = cache.interfaces.neighbor_ids[2, interface] orientation = cache.interfaces.orientations[interface] - - if orientation == 1 - for j in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, nnodes(dg), j, - left), equations) - var_right = variable(get_node_vars(u, equations, dg, 1, j, right), - equations) - - var_minmax[1, j, right] = minmax(var_minmax[1, j, right], var_left) - var_minmax[nnodes(dg), j, left] = minmax(var_minmax[nnodes(dg), j, - left], var_right) - end - else # orientation == 2 - for i in eachnode(dg) - var_left = variable(get_node_vars(u, equations, dg, i, nnodes(dg), - left), equations) - var_right = variable(get_node_vars(u, equations, dg, i, 1, right), - equations) - - var_minmax[i, 1, right] = minmax(var_minmax[i, 1, right], var_left) - var_minmax[i, nnodes(dg), left] = minmax(var_minmax[i, nnodes(dg), - left], var_right) + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) end + var_left = variable(get_node_vars(u, equations, dg, index_left..., left), + equations) + var_right = variable(get_node_vars(u, equations, dg, index_right..., right), + equations) + + var_minmax[index_right..., right] = minmax(var_minmax[index_right..., + right], var_left) + var_minmax[index_left..., left] = minmax(var_minmax[index_left..., left], + var_right) end end @@ -273,65 +266,28 @@ end orientation = cache.boundaries.orientations[boundary] neighbor_side = cache.boundaries.neighbor_sides[boundary] - if orientation == 1 + for i in eachnode(dg) if neighbor_side == 2 # Element is on the right, boundary on the left - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[1], - orientation, 1, - mesh, equations, dg, - 1, j, element) - var_outer = variable(u_outer, equations) - - var_minmax[1, j, element] = minmax(var_minmax[1, j, element], - var_outer) - end + index = (1, i) + boundary_index = 1 else # Element is on the left, boundary on the right - for j in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[2], - orientation, 2, - mesh, equations, dg, - nnodes(dg), j, element) - var_outer = variable(u_outer, equations) - - var_minmax[nnodes(dg), j, element] = minmax(var_minmax[nnodes(dg), - j, element], - var_outer) - end + index = (nnodes(dg), i) + boundary_index = 2 end - else # orientation == 2 - if neighbor_side == 2 # Element is on the right, boundary on the left - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[3], - orientation, 3, - mesh, equations, dg, - i, 1, element) - var_outer = variable(u_outer, equations) - - var_minmax[i, 1, element] = minmax(var_minmax[i, 1, element], - var_outer) - end - else # Element is on the left, boundary on the right - for i in eachnode(dg) - u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_conditions[4], - orientation, 4, - mesh, equations, dg, - i, nnodes(dg), element) - var_outer = variable(u_outer, equations) - - var_minmax[i, nnodes(dg), element] = minmax(var_minmax[i, - nnodes(dg), - element], - var_outer) - end + if orientation == 2 + index = reverse(index) + boundary_index += 2 end + u_inner = get_node_vars(u, equations, dg, index..., element) + u_outer = get_boundary_outer_state(u_inner, cache, t, + boundary_conditions[boundary_index], + orientation, boundary_index, + mesh, equations, dg, + index..., element) + var_outer = variable(u_outer, equations) + + var_minmax[index..., element] = minmax(var_minmax[index..., element], + var_outer) end end From 8a516a331e09ea233ff7f2949b92a4a384c9d19a Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 22 Dec 2023 15:39:55 +0100 Subject: [PATCH 403/423] Adapt elixir --- ...ir_euler_blast_wave_sc_subcell_nonperiodic.jl | 1 + test/test_tree_2d_euler.jl | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index 78a931f627..9d44eae485 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -42,6 +42,7 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; local_minmax_variables_cons = ["rho"], + math_entropy = true, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index caf73ff3f0..89213979d9 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -393,16 +393,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ - 0.3517507570120483, - 0.19252291020146015, - 0.19249751956580294, - 0.618717827188004, + 0.32211638619244837, + 0.17984613698288662, + 0.1798341339489921, + 0.6136855864874968, ], linf=[ - 1.6699566795772216, - 1.3608007992899402, - 1.361864507190922, - 2.44022884092527, + 1.343528359596545, + 1.174708306029737, + 1.174481988232382, + 2.42152874599586, ], tspan=(0.0, 0.5), initial_refinement_level=4, From 896c0a77ac75a5e9124ed47386de2eae2ef0529e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 30 Jan 2024 18:08:09 +0100 Subject: [PATCH 404/423] Fix allocations with multithreaded --- src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 36a860438b..52dc6813c3 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -993,9 +993,9 @@ end (; bar_states1, bar_states2) = limiter.cache.container_bar_states @threaded for element in eachelement(dg, cache) - for v in eachvariable(equations) - var_min[v, :, :, element] .= typemax(eltype(var_min)) - var_max[v, :, :, element] .= typemin(eltype(var_max)) + for j in eachnode(dg), i in eachnode(dg), v in eachvariable(equations) + var_min[v, i, j, element] = typemax(eltype(var_min)) + var_max[v, i, j, element] = typemin(eltype(var_max)) end if limiter.density_limiter From 485f4477bc2fff84db33e1873e2f38d1e86d6dc4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 30 Jan 2024 18:46:32 +0100 Subject: [PATCH 405/423] Split mcl_bounds_delta into global and local --- src/callbacks_stage/subcell_bounds_check.jl | 8 +- .../subcell_bounds_check_2d.jl | 329 +++++++++--------- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 10 +- 3 files changed, 183 insertions(+), 164 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 16cf3abeee..340ef0287b 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -190,19 +190,19 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterMCL) - @unpack mcl_bounds_delta = limiter.cache + @unpack mcl_bounds_delta_global = limiter.cache println("─"^100) println("Maximum deviation from bounds:") println("─"^100) variables = varnames(cons2cons, semi.equations) for v in eachvariable(semi.equations) - println(variables[v], ":\n- lower bound: ", mcl_bounds_delta[2, 1, v], - "\n- upper bound: ", mcl_bounds_delta[2, 2, v]) + println(variables[v], ":\n- lower bound: ", mcl_bounds_delta_global[1, v], + "\n- upper bound: ", mcl_bounds_delta_global[2, v]) end if limiter.positivity_limiter_pressure println("pressure:\n- positivity: ", - mcl_bounds_delta[2, 1, nvariables(semi.equations) + 1]) + mcl_bounds_delta_global[1, nvariables(semi.equations) + 1]) end if limiter.entropy_limiter_semidiscrete # TODO: Bounds check for entropy limiting diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index b9406ab878..70c8741da8 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -131,7 +131,7 @@ end time, iter, output_directory, save_errors) (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states - (; mcl_bounds_delta) = limiter.cache + (; mcl_bounds_delta_local, mcl_bounds_delta_global) = limiter.cache (; antidiffusive_flux1_L, antidiffusive_flux2_L) = cache.antidiffusive_fluxes n_vars = nvariables(equations) @@ -140,12 +140,12 @@ end # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - var_min[1, i, j, element] - - u[1, i, j, element]) - mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], - u[1, i, j, element] - - var_max[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + var_min[1, i, j, element] - + u[1, i, j, element]) + mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], + u[1, i, j, element] - + var_max[1, i, j, element]) end end @@ -159,34 +159,42 @@ end rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - var_min[1, i, j, element] - rho_limited) - mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + var_min[1, i, j, element] - + rho_limited) + mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], + rho_limited - + var_max[1, i, j, element]) # +x rho_limited = bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - var_min[1, i, j, element] - rho_limited) - mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + var_min[1, i, j, element] - + rho_limited) + mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], + rho_limited - + var_max[1, i, j, element]) # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - var_min[1, i, j, element] - rho_limited) - mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + var_min[1, i, j, element] - + rho_limited) + mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], + rho_limited - + var_max[1, i, j, element]) # +y rho_limited = bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - var_min[1, i, j, element] - rho_limited) - mcl_bounds_delta[1, 2, 1] = max(mcl_bounds_delta[1, 2, 1], - rho_limited - var_max[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + var_min[1, i, j, element] - + rho_limited) + mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], + rho_limited - + var_max[1, i, j, element]) end end end # limiter.density_limiter @@ -197,20 +205,20 @@ end for j in eachnode(solver), i in eachnode(solver) for v in 2:n_vars var_limited = u[v, i, j, element] / u[1, i, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited - + var_max[v, i, j, element]) end if limiter.positivity_limiter_pressure error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) end end end @@ -221,8 +229,8 @@ end # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(mcl_bounds_delta)) - error_pressure = zero(eltype(mcl_bounds_delta)) + var_limited = zero(eltype(mcl_bounds_delta_local)) + error_pressure = zero(eltype(mcl_bounds_delta_local)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) # -x @@ -233,22 +241,22 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited / rho_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +x rho_limited = bar_states1[1, i + 1, j, element] + @@ -258,22 +266,22 @@ end var_limited = bar_states1[v, i + 1, j, element] + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited / rho_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # -y rho_limited = bar_states2[1, i, j, element] - @@ -283,22 +291,22 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited / rho_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +y rho_limited = bar_states2[1, i, j + 1, element] + @@ -308,22 +316,22 @@ end var_limited = bar_states2[v, i, j + 1, element] + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited / rho_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited / rho_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited / rho_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited / rho_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end end end @@ -332,20 +340,20 @@ end for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) for v in 2:n_vars - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - u[v, i, j, element]) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - u[v, i, j, element] - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + u[v, i, j, element]) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + u[v, i, j, element] - + var_max[v, i, j, element]) end if limiter.positivity_limiter_pressure error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) end end end @@ -356,8 +364,8 @@ end # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} # - pressure (p): # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(mcl_bounds_delta)) - error_pressure = zero(eltype(mcl_bounds_delta)) + var_limited = zero(eltype(mcl_bounds_delta_local)) + error_pressure = zero(eltype(mcl_bounds_delta_local)) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) # -x @@ -368,22 +376,22 @@ end var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1_L[v, i, j, element] / lambda1[i, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +x rho_limited = bar_states1[1, i + 1, j, element] + @@ -393,22 +401,22 @@ end var_limited = bar_states1[v, i + 1, j, element] + antidiffusive_flux1_L[v, i + 1, j, element] / lambda1[i + 1, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # -y rho_limited = bar_states2[1, i, j, element] - @@ -418,22 +426,22 @@ end var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2_L[v, i, j, element] / lambda2[i, j, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +y rho_limited = bar_states2[1, i, j + 1, element] + @@ -443,22 +451,22 @@ end var_limited = bar_states2[v, i, j + 1, element] + antidiffusive_flux2_L[v, i, j + 1, element] / lambda2[i, j + 1, element] - mcl_bounds_delta[1, 1, v] = max(mcl_bounds_delta[1, 1, v], - var_min[v, i, j, element] - - var_limited) - mcl_bounds_delta[1, 2, v] = max(mcl_bounds_delta[1, 2, v], - var_limited - - var_max[v, i, j, element]) + mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], + var_min[v, i, j, element] - + var_limited) + mcl_bounds_delta_local[2, v] = max(mcl_bounds_delta_local[2, v], + var_limited - + var_max[v, i, j, element]) if limiter.positivity_limiter_pressure && (v == 2 || v == 3) error_pressure += 0.5 * var_limited^2 end end if limiter.positivity_limiter_pressure error_pressure -= var_limited * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) - error_pressure = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) + error_pressure = zero(eltype(mcl_bounds_delta_local)) end end end @@ -468,9 +476,9 @@ end for j in eachnode(solver), i in eachnode(solver) error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) end end @@ -495,9 +503,9 @@ end (bar_states1[4, i, j, element] - antidiffusive_flux1_L[4, i, j, element] / lambda1[i, j, element]) * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) # +x rho_limited = bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / @@ -513,9 +521,9 @@ end (bar_states1[4, i + 1, j, element] + antidiffusive_flux1_L[4, i + 1, j, element] / lambda1[i + 1, j, element]) * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) # -y rho_limited = bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / @@ -531,9 +539,9 @@ end (bar_states2[4, i, j, element] - antidiffusive_flux2_L[4, i, j, element] / lambda2[i, j, element]) * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) # +y rho_limited = bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / @@ -549,9 +557,9 @@ end (bar_states2[4, i, j + 1, element] + antidiffusive_flux2_L[4, i, j + 1, element] / lambda2[i, j + 1, element]) * rho_limited - mcl_bounds_delta[1, 1, n_vars + 1] = max(mcl_bounds_delta[1, 1, - n_vars + 1], - error_pressure) + mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, + n_vars + 1], + error_pressure) end end end # limiter.positivity_limiter_pressure @@ -560,8 +568,8 @@ end # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], - -u[1, i, j, element]) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + -u[1, i, j, element]) end end @@ -576,35 +584,41 @@ end rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / lambda1[i, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + -rho_limited) # +x rho_limited = (1 - beta) * bar_states1[1, i + 1, j, element] + antidiffusive_flux1_L[1, i + 1, j, element] / lambda1[i + 1, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + -rho_limited) # -y rho_limited = (1 - beta) * bar_states2[1, i, j, element] - antidiffusive_flux2_L[1, i, j, element] / lambda2[i, j, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + -rho_limited) # +y rho_limited = (1 - beta) * bar_states2[1, i, j + 1, element] + antidiffusive_flux2_L[1, i, j + 1, element] / lambda2[i, j + 1, element] - mcl_bounds_delta[1, 1, 1] = max(mcl_bounds_delta[1, 1, 1], -rho_limited) + mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], + -rho_limited) end end end # limiter.positivity_limiter_density for v in eachvariable(equations) - mcl_bounds_delta[2, 1, v] = max(mcl_bounds_delta[2, 1, v], - mcl_bounds_delta[1, 1, v]) - mcl_bounds_delta[2, 2, v] = max(mcl_bounds_delta[2, 2, v], - mcl_bounds_delta[1, 2, v]) + mcl_bounds_delta_global[1, v] = max(mcl_bounds_delta_global[1, v], + mcl_bounds_delta_local[1, v]) + mcl_bounds_delta_global[2, v] = max(mcl_bounds_delta_global[2, v], + mcl_bounds_delta_local[2, v]) end if limiter.positivity_limiter_pressure - mcl_bounds_delta[2, 1, n_vars + 1] = max(mcl_bounds_delta[2, 1, n_vars + 1], - mcl_bounds_delta[1, 1, n_vars + 1]) + mcl_bounds_delta_global[1, n_vars + 1] = max(mcl_bounds_delta_global[1, + n_vars + 1], + mcl_bounds_delta_local[1, + n_vars + 1]) end if !save_errors @@ -613,19 +627,20 @@ end open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) for v in eachvariable(equations) - print(f, ", ", mcl_bounds_delta[1, 1, v], ", ", mcl_bounds_delta[1, 2, v]) + print(f, ", ", mcl_bounds_delta_local[1, v], ", ", + mcl_bounds_delta_local[2, v]) end if limiter.positivity_limiter_pressure - print(f, ", ", mcl_bounds_delta[1, 1, n_vars + 1]) + print(f, ", ", mcl_bounds_delta_local[1, n_vars + 1]) end println(f) end for v in eachvariable(equations) - mcl_bounds_delta[1, 1, v] = zero(eltype(mcl_bounds_delta)) - mcl_bounds_delta[1, 2, v] = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, v] = zero(eltype(mcl_bounds_delta_local)) + mcl_bounds_delta_local[2, v] = zero(eltype(mcl_bounds_delta_local)) end if limiter.positivity_limiter_pressure - mcl_bounds_delta[1, 1, n_vars + 1] = zero(eltype(mcl_bounds_delta)) + mcl_bounds_delta_local[1, n_vars + 1] = zero(eltype(mcl_bounds_delta_local)) end return nothing diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index dbdc2afda8..262fef1354 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -877,9 +877,13 @@ function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquat # Memory for bounds checking routine with `BoundsCheckCallback`. # [maximum since the last export / total maximum, min / max, variable] - mcl_bounds_delta = zeros(real(basis), 2, 2, - nvariables(equations) + positivity_limiter_pressure) + mcl_bounds_delta_local = zeros(real(basis), 2, + nvariables(equations) + positivity_limiter_pressure) - return (; subcell_limiter_coefficients, container_bar_states, mcl_bounds_delta) + mcl_bounds_delta_global = zeros(real(basis), 2, + nvariables(equations) + positivity_limiter_pressure) + + return (; subcell_limiter_coefficients, container_bar_states, + mcl_bounds_delta_local, mcl_bounds_delta_global) end end # @muladd From 41587ccbe24f42ebd0f2d91a0834ecf47f82bf6a Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 30 Jan 2024 18:48:36 +0100 Subject: [PATCH 406/423] Add comment --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 262fef1354..3acbaae679 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -876,10 +876,12 @@ function create_cache(limiter::Type{SubcellLimiterMCL}, equations::AbstractEquat nnodes(basis)) # Memory for bounds checking routine with `BoundsCheckCallback`. - # [maximum since the last export / total maximum, min / max, variable] + # Local variable contains the maximum deviation since the last export. + # [min / max, variable] mcl_bounds_delta_local = zeros(real(basis), 2, nvariables(equations) + positivity_limiter_pressure) - + # Global variable contains the total maximum deviation. + # [min / max, variable] mcl_bounds_delta_global = zeros(real(basis), 2, nvariables(equations) + positivity_limiter_pressure) From 2c61390ec65c127ad94a15ead3583be30146a496 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:17:40 +0100 Subject: [PATCH 407/423] Outsource code for saving bounds errors (#122) --- src/callbacks_stage/subcell_bounds_check.jl | 36 +++++--- .../subcell_bounds_check_2d.jl | 91 +++++++++++-------- 2 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 340ef0287b..05fd3ae78e 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -42,23 +42,35 @@ function (callback::BoundsCheckCallback)(u_ode, integrator, stage) (stage == length(alg.c)) && (iter % callback.interval == 0 || integrator.finalstep) @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, - solver.volume_integral, t, - iter + 1, - callback.output_directory, - save_errors) + solver.volume_integral) + + if save_errors + @trixi_timeit timer() "check_bounds" save_bounds_check_errors(callback.output_directory, + t, iter + 1, + equations, + solver.volume_integral) + end +end + +@inline function check_bounds(u, mesh, equations, solver, cache, + volume_integral::AbstractVolumeIntegral) + return nothing +end + +@inline function check_bounds(u, mesh, equations, solver, cache, + volume_integral::VolumeIntegralSubcellLimiting) + check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter) end -function check_bounds(u, mesh, equations, solver, cache, - volume_integral::AbstractVolumeIntegral, t, iter, - output_directory, save_errors) +@inline function save_bounds_check_errors(output_directory, t, iter, equations, + volume_integral::AbstractVolumeIntegral) return nothing end -function check_bounds(u, mesh, equations, solver, cache, - volume_integral::VolumeIntegralSubcellLimiting, t, iter, - output_directory, save_errors) - check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter, t, iter, - output_directory, save_errors) +@inline function save_bounds_check_errors(output_directory, t, iter, equations, + volume_integral::VolumeIntegralSubcellLimiting) + save_bounds_check_errors(output_directory, t, iter, equations, + volume_integral.limiter) end function init_callback(callback::BoundsCheckCallback, semi) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 70c8741da8..849fd4cd0a 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -6,8 +6,7 @@ #! format: noindent @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, - limiter::SubcellLimiterIDP, - time, iter, output_directory, save_errors) + limiter::SubcellLimiterIDP) (; local_minmax, positivity, spec_entropy, math_entropy) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta) = limiter.cache @@ -86,49 +85,56 @@ deviation[2] = max(deviation[2], deviation[1]) end end - if save_errors - # Print to output file - open("$output_directory/deviations.txt", "a") do f - print(f, iter, ", ", time) - if local_minmax - for v in limiter.local_minmax_variables_cons - v_string = string(v) - print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], ", ", - idp_bounds_delta[Symbol(v_string, "_max")][1]) - end - end - if spec_entropy - print(f, ", ", idp_bounds_delta[:spec_entropy_min][1]) - end - if math_entropy - print(f, ", ", idp_bounds_delta[:math_entropy_max][1]) + + return nothing +end + +@inline function save_bounds_check_errors(output_directory, time, iter, equations, + limiter::SubcellLimiterIDP) + (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; idp_bounds_delta) = limiter.cache + + # Print errors to output file + open("$output_directory/deviations.txt", "a") do f + print(f, iter, ", ", time) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], ", ", + idp_bounds_delta[Symbol(v_string, "_max")][1]) end - if positivity - for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons - continue - end - print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) - end - for variable in limiter.positivity_variables_nonlinear - print(f, ", ", - idp_bounds_delta[Symbol(string(variable), "_min")][1]) + end + if spec_entropy + print(f, ", ", idp_bounds_delta[:spec_entropy_min][1]) + end + if math_entropy + print(f, ", ", idp_bounds_delta[:math_entropy_max][1]) + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue end + print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) + end + for variable in limiter.positivity_variables_nonlinear + print(f, ", ", + idp_bounds_delta[Symbol(string(variable), "_min")][1]) end - println(f) - end - # Reset first entries of idp_bounds_delta - for (key, _) in idp_bounds_delta - idp_bounds_delta[key][1] = zero(eltype(idp_bounds_delta[key][1])) end + println(f) + end + + # Reset first entries of idp_bounds_delta + for (key, _) in idp_bounds_delta + idp_bounds_delta[key][1] = zero(eltype(idp_bounds_delta[key][1])) end return nothing end @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, - limiter::SubcellLimiterMCL, - time, iter, output_directory, save_errors) + limiter::SubcellLimiterMCL) (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states (; mcl_bounds_delta_local, mcl_bounds_delta_global) = limiter.cache @@ -621,9 +627,16 @@ end n_vars + 1]) end - if !save_errors - return nothing - end + return nothing +end + +@inline function save_bounds_check_errors(output_directory, time, iter, equations, + limiter::SubcellLimiterMCL) + (; mcl_bounds_delta_local) = limiter.cache + + n_vars = nvariables(equations) + + # Print errors to output file open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) for v in eachvariable(equations) @@ -635,6 +648,8 @@ end end println(f) end + + # Reset mcl_bounds_delta_local for v in eachvariable(equations) mcl_bounds_delta_local[1, v] = zero(eltype(mcl_bounds_delta_local)) mcl_bounds_delta_local[2, v] = zero(eltype(mcl_bounds_delta_local)) From e51644ee559e96dcd867c193c18ce92dfc0443e1 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Fri, 2 Feb 2024 10:52:41 +0100 Subject: [PATCH 408/423] Cancel some `for` loops for clarity and better parallelization capability (#123) * Cancel some for loops for clarity and better parallelisation capability * Fix last commit * Fix again * Move calculation of rho_limited * Update comments --- .../subcell_bounds_check_2d.jl | 115 ++++++++---------- 1 file changed, 49 insertions(+), 66 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 758c6a80a9..a2441e0bcd 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -173,24 +173,21 @@ end n_vars = nvariables(equations) if limiter.density_limiter - # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) + # New solution u^{n+1} mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], var_min[1, i, j, element] - u[1, i, j, element]) mcl_bounds_delta_local[2, 1] = max(mcl_bounds_delta_local[2, 1], u[1, i, j, element] - var_max[1, i, j, element]) - end - end - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - density (rho): - # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # \bar{rho}^{min} <= \bar{rho}^{Lim} <= \bar{rho}^{max} + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / @@ -236,9 +233,9 @@ end end # limiter.density_limiter if limiter.sequential_limiter - # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) + # New solution u^{n+1} for v in 2:n_vars var_limited = u[v, i, j, element] / u[1, i, j, element] mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], @@ -256,19 +253,15 @@ end n_vars + 1], error_pressure) end - end - end - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - velocities and energy (phi): - # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(mcl_bounds_delta_local)) - error_pressure = zero(eltype(mcl_bounds_delta_local)) - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - velocities and total energy (phi): + # \bar{phi}^{min} <= \bar{phi}^{Lim} / \bar{rho}^{Lim} <= \bar{phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(mcl_bounds_delta_local)) + error_pressure = zero(eltype(mcl_bounds_delta_local)) # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / @@ -372,9 +365,9 @@ end end end elseif limiter.conservative_limiter - # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) + # New solution u^{n+1} for v in 2:n_vars mcl_bounds_delta_local[1, v] = max(mcl_bounds_delta_local[1, v], var_min[v, i, j, element] - @@ -391,23 +384,16 @@ end n_vars + 1], error_pressure) end - end - end - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - conservative variables (phi): - # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - var_limited = zero(eltype(mcl_bounds_delta_local)) - error_pressure = zero(eltype(mcl_bounds_delta_local)) - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - conservative variables (noted as rho*phi): + # \bar{rho*phi}^{min} <= \bar{rho*phi}^{Lim} <= \bar{rho*phi}^{max} + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + var_limited = zero(eltype(mcl_bounds_delta_local)) + error_pressure = zero(eltype(mcl_bounds_delta_local)) # -x - rho_limited = bar_states1[1, i, j, element] - - antidiffusive_flux1_L[1, i, j, element] / - lambda1[i, j, element] for v in 2:n_vars var_limited = bar_states1[v, i, j, element] - antidiffusive_flux1_L[v, i, j, element] / @@ -423,6 +409,9 @@ end end end if limiter.positivity_limiter_pressure + rho_limited = bar_states1[1, i, j, element] - + antidiffusive_flux1_L[1, i, j, element] / + lambda1[i, j, element] error_pressure -= var_limited * rho_limited mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, n_vars + 1], @@ -430,9 +419,6 @@ end error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +x - rho_limited = bar_states1[1, i + 1, j, element] + - antidiffusive_flux1_L[1, i + 1, j, element] / - lambda1[i + 1, j, element] for v in 2:n_vars var_limited = bar_states1[v, i + 1, j, element] + antidiffusive_flux1_L[v, i + 1, j, element] / @@ -448,6 +434,9 @@ end end end if limiter.positivity_limiter_pressure + rho_limited = bar_states1[1, i + 1, j, element] + + antidiffusive_flux1_L[1, i + 1, j, element] / + lambda1[i + 1, j, element] error_pressure -= var_limited * rho_limited mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, n_vars + 1], @@ -455,9 +444,6 @@ end error_pressure = zero(eltype(mcl_bounds_delta_local)) end # -y - rho_limited = bar_states2[1, i, j, element] - - antidiffusive_flux2_L[1, i, j, element] / - lambda2[i, j, element] for v in 2:n_vars var_limited = bar_states2[v, i, j, element] - antidiffusive_flux2_L[v, i, j, element] / @@ -473,6 +459,9 @@ end end end if limiter.positivity_limiter_pressure + rho_limited = bar_states2[1, i, j, element] - + antidiffusive_flux2_L[1, i, j, element] / + lambda2[i, j, element] error_pressure -= var_limited * rho_limited mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, n_vars + 1], @@ -480,9 +469,6 @@ end error_pressure = zero(eltype(mcl_bounds_delta_local)) end # +y - rho_limited = bar_states2[1, i, j + 1, element] + - antidiffusive_flux2_L[1, i, j + 1, element] / - lambda2[i, j + 1, element] for v in 2:n_vars var_limited = bar_states2[v, i, j + 1, element] + antidiffusive_flux2_L[v, i, j + 1, element] / @@ -498,6 +484,9 @@ end end end if limiter.positivity_limiter_pressure + rho_limited = bar_states2[1, i, j + 1, element] + + antidiffusive_flux2_L[1, i, j + 1, element] / + lambda2[i, j + 1, element] error_pressure -= var_limited * rho_limited mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, n_vars + 1], @@ -507,23 +496,20 @@ end end end elseif limiter.positivity_limiter_pressure - # New solution u^{n+1} for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) + # New solution u^{n+1} error_pressure = 0.5 * (u[2, i, j, element]^2 + u[3, i, j, element]^2) - u[1, i, j, element] * u[4, i, j, element] mcl_bounds_delta_local[1, n_vars + 1] = max(mcl_bounds_delta_local[1, n_vars + 1], error_pressure) - end - end - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - # Checking the bounds for... - # - pressure (p): - # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - pressure (p): + # \bar{rho}^{Lim} \bar{rho * E}^{Lim} >= |\bar{rho * v}^{Lim}|^2 / 2 + # -x rho_limited = bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / @@ -601,21 +587,18 @@ end end # limiter.positivity_limiter_pressure if limiter.positivity_limiter_density - # New solution u^{n+1} + beta = limiter.positivity_limiter_correction_factor for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) + # New solution u^{n+1} mcl_bounds_delta_local[1, 1] = max(mcl_bounds_delta_local[1, 1], -u[1, i, j, element]) - end - end - # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ - beta = limiter.positivity_limiter_correction_factor - # Checking the bounds for... - # - density (rho): - # beta * \bar{rho} <= \bar{rho}^{Lim} - for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) + # Limited bar states \bar{u}^{Lim} = \bar{u} + Δf^{Lim} / λ + # Checking the bounds for... + # - density (rho): + # beta * \bar{rho} <= \bar{rho}^{Lim} + # -x rho_limited = (1 - beta) * bar_states1[1, i, j, element] - antidiffusive_flux1_L[1, i, j, element] / From be7bcb95a7d557bb680536d7f0f8f0b092606b15 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 5 Feb 2024 12:27:54 +0100 Subject: [PATCH 409/423] Merge branch 'main' --- .github/workflows/SpellCheck.yml | 2 +- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 2 +- NEWS.md | 1 + Project.toml | 2 + .../elixir_2d_euler_vortex_unstructured.jl | 9 +- docs/make.jl | 1 + docs/src/multi-physics_coupling.md | 46 ++ examples/dgmulti_2d/elixir_euler_hohqmesh.jl | 9 +- .../elixir_advection_amr_unstructured_flag.jl | 7 +- .../elixir_advection_unstructured_flag.jl | 7 +- .../elixir_euler_blast_wave_amr.jl | 7 +- .../elixir_euler_double_mach_amr.jl | 8 +- .../elixir_euler_forward_step_amr.jl | 8 +- .../elixir_euler_free_stream.jl | 7 +- ...e_terms_nonconforming_unstructured_flag.jl | 7 +- .../elixir_euler_supersonic_cylinder.jl | 8 +- .../elixir_euler_wall_bc_amr.jl | 8 +- examples/p4est_2d_dgsem/elixir_mhd_rotor.jl | 7 +- ...lixir_advection_amr_unstructured_curved.jl | 7 +- .../elixir_advection_unstructured_curved.jl | 7 +- examples/p4est_3d_dgsem/elixir_euler_ec.jl | 7 +- .../elixir_euler_free_stream.jl | 7 +- .../elixir_euler_free_stream_extruded.jl | 7 +- ...terms_nonconforming_unstructured_curved.jl | 7 +- ...euler_source_terms_nonperiodic_hohqmesh.jl | 8 +- .../elixir_advection_coupled.jl | 191 ++++-- .../elixir_shallowwater_well_balanced.jl | 1 - .../elixir_advection_amr_unstructured_flag.jl | 7 +- .../elixir_advection_unstructured_flag.jl | 7 +- .../elixir_euler_free_stream.jl | 7 +- ...e_terms_nonconforming_unstructured_flag.jl | 7 +- examples/t8code_2d_dgsem/elixir_mhd_rotor.jl | 7 +- ...lixir_advection_amr_unstructured_curved.jl | 9 +- .../elixir_advection_unstructured_curved.jl | 7 +- examples/t8code_3d_dgsem/elixir_euler_ec.jl | 7 +- .../elixir_euler_free_stream.jl | 7 +- .../elixir_euler_free_stream_extruded.jl | 7 +- ...terms_nonconforming_unstructured_curved.jl | 7 +- ...kelvin_helmholtz_instability_sc_subcell.jl | 1 + .../elixir_mhd_shockcapturing_subcell.jl | 1 + .../elixir_acoustics_gauss_wall.jl | 8 +- .../elixir_advection_basic.jl | 9 +- .../elixir_euler_basic.jl | 9 +- .../unstructured_2d_dgsem/elixir_euler_ec.jl | 9 +- .../elixir_euler_free_stream.jl | 9 +- .../elixir_euler_periodic.jl | 9 +- .../elixir_euler_sedov.jl | 7 +- .../elixir_euler_wall_bc.jl | 9 +- .../elixir_mhd_alfven_wave.jl | 8 +- .../unstructured_2d_dgsem/elixir_mhd_ec.jl | 8 +- .../elixir_shallowwater_dirichlet.jl | 8 +- .../elixir_shallowwater_ec.jl | 8 +- .../elixir_shallowwater_ec_shockcapturing.jl | 8 +- .../elixir_shallowwater_source_terms.jl | 8 +- ...ixir_shallowwater_three_mound_dam_break.jl | 13 +- ...lixir_shallowwater_twolayer_convergence.jl | 8 +- .../elixir_shallowwater_twolayer_dam_break.jl | 8 +- ...xir_shallowwater_twolayer_well_balanced.jl | 8 +- ...xir_shallowwater_wall_bc_shockcapturing.jl | 9 +- .../elixir_shallowwater_well_balanced.jl | 9 +- .../elixir_advection_basic.jl | 9 +- .../elixir_euler_free_stream.jl | 9 +- .../elixir_euler_source_terms.jl | 9 +- src/Trixi.jl | 1 + src/auxiliary/auxiliary.jl | 23 + src/auxiliary/t8code.jl | 235 +------ src/callbacks_step/amr.jl | 40 +- src/callbacks_step/amr_dg.jl | 11 +- src/callbacks_step/amr_dg2d.jl | 7 +- src/callbacks_step/amr_dg3d.jl | 7 +- src/callbacks_step/analysis_dg2d_parallel.jl | 6 +- src/callbacks_step/analysis_dg3d_parallel.jl | 6 +- src/callbacks_step/stepsize_dg2d.jl | 32 + src/callbacks_step/stepsize_dg3d.jl | 32 + src/equations/compressible_euler_2d.jl | 12 +- src/equations/equations.jl | 6 +- src/equations/ideal_glm_mhd_2d.jl | 16 +- src/meshes/p4est_mesh.jl | 4 + src/meshes/t8code_mesh.jl | 585 ++++++++++++++++-- .../semidiscretization_coupled.jl | 191 ++++-- .../dgsem_p4est/containers_parallel.jl | 6 +- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 176 ++++-- src/solvers/dgsem_p4est/dg_2d_parallel.jl | 21 +- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 137 ++-- src/solvers/dgsem_p4est/dg_3d_parallel.jl | 23 +- src/solvers/dgsem_p4est/dg_parallel.jl | 9 +- src/solvers/dgsem_t8code/containers.jl | 13 +- src/solvers/dgsem_t8code/containers_2d.jl | 3 +- src/solvers/dgsem_t8code/containers_3d.jl | 3 +- .../dgsem_t8code/containers_parallel.jl | 65 ++ src/solvers/dgsem_t8code/dg.jl | 7 +- src/solvers/dgsem_t8code/dg_parallel.jl | 135 ++++ src/solvers/dgsem_tree/dg_2d_parabolic.jl | 18 - src/solvers/dgsem_tree/dg_2d_parallel.jl | 3 +- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 18 - src/solvers/dgsem_tree/subcell_limiters.jl | 21 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 77 +-- test/test_mpi.jl | 6 +- test/test_mpi_p4est_2d.jl | 63 ++ test/test_mpi_p4est_3d.jl | 81 +++ test/test_mpi_t8code_2d.jl | 142 +++++ test/test_mpi_t8code_3d.jl | 180 ++++++ test/test_mpi_tree.jl | 3 +- test/test_parabolic_2d.jl | 16 +- test/test_parabolic_3d.jl | 28 +- test/test_structured_2d.jl | 28 +- test/test_t8code_2d.jl | 7 +- test/test_threaded.jl | 2 + test/test_unit.jl | 6 +- 110 files changed, 2210 insertions(+), 971 deletions(-) create mode 100644 docs/src/multi-physics_coupling.md create mode 100644 src/solvers/dgsem_t8code/containers_parallel.jl create mode 100644 src/solvers/dgsem_t8code/dg_parallel.jl create mode 100644 test/test_mpi_t8code_2d.jl create mode 100644 test/test_mpi_t8code_3d.jl diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml index a780e97515..b242b6e811 100644 --- a/.github/workflows/SpellCheck.yml +++ b/.github/workflows/SpellCheck.yml @@ -10,4 +10,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v4 - name: Check spelling - uses: crate-ci/typos@v1.16.26 + uses: crate-ci/typos@v1.18.0 diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6aa4809c1c..4531c3aee0 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -26,7 +26,7 @@ jobs: version: ${{ matrix.version }} arch: ${{ matrix.arch }} show-versioninfo: true - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: cache-name: cache-artifacts with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f287cc5feb..2e388366fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,7 @@ jobs: - uses: julia-actions/julia-processcoverage@v1 with: directories: src,examples,ext - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: file: ./lcov.info flags: unittests diff --git a/NEWS.md b/NEWS.md index 3a3a504a91..02a723fca4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,7 @@ for human readability. - `flux_hllc` on non-cartesian meshes for `CompressibleEulerEquations{2,3}D` - Different boundary conditions for quad/hex meshes in Abaqus format, even if not generated by HOHQMesh, can now be digested by Trixi in 2D and 3D. +- Subcell (positivity) limiting support for nonlinear variables in 2D for `TreeMesh` ## Changes when updating to v0.6 from v0.5.x diff --git a/Project.toml b/Project.toml index 0bbdec206d..e99b08e0e8 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" @@ -57,6 +58,7 @@ ConstructionBase = "1.3" DataStructures = "0.18.15" DiffEqBase = "6 - 6.143" DiffEqCallbacks = "2.25" +Downloads = "1.6" EllipsisNotation = "1.0" FillArrays = "0.13.2, 1" ForwardDiff = "0.10.18" diff --git a/benchmark/elixir_2d_euler_vortex_unstructured.jl b/benchmark/elixir_2d_euler_vortex_unstructured.jl index 082b6648ab..43e4b6559d 100644 --- a/benchmark/elixir_2d_euler_vortex_unstructured.jl +++ b/benchmark/elixir_2d_euler_vortex_unstructured.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -49,11 +48,9 @@ end initial_condition = initial_condition_isentropic_vortex solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) -default_mesh_file = joinpath(@__DIR__, "mesh_uniform_cartesian.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/ranocha/f4ea19ba3b62348968c971db43d7798b/raw/a506abb9479c020920cf6068c142670fc1a9aadc/mesh_uniform_cartesian.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/ranocha/f4ea19ba3b62348968c971db43d7798b/raw/a506abb9479c020920cf6068c142670fc1a9aadc/mesh_uniform_cartesian.mesh", + joinpath(@__DIR__, "mesh_uniform_cartesian.mesh")) + mesh = UnstructuredMesh2D(mesh_file, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/docs/make.jl b/docs/make.jl index dee87371bd..7fce3b31e2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -108,6 +108,7 @@ makedocs( ], "Time integration" => "time_integration.md", "Callbacks" => "callbacks.md", + "Coupling" => "multi-physics_coupling.md" ], "Advanced topics & developers" => [ "Conventions" =>"conventions.md", diff --git a/docs/src/multi-physics_coupling.md b/docs/src/multi-physics_coupling.md new file mode 100644 index 0000000000..eec92bc21d --- /dev/null +++ b/docs/src/multi-physics_coupling.md @@ -0,0 +1,46 @@ +# [Multi-physics coupling](@id multi-physics-coupling) +A complex simulation can consist of different spatial domains in which +different equations are being solved, different numerical methods being used +or the grid structure is different. +One example would be a fluid in a tank and an extended hot plate attached to it. +We would then like to solve the Navier-Stokes equations in the fluid domain +and the heat conduction equations in the plate. +The coupling would happen at the interface through the exchange of thermal energy. + + +## Converter coupling +It may happen that the two systems to be coupled do not share any variables, but +share some of the physics. +In such a situation, the same physics is just represented in a different form and with +a different set of variables. +This is the case, for instance assuming two domains, if there is a fluid system in one domain +and a Vlasov system in the other domain. +In that case we would have variables representing distribution functions of +the Vlasov system on one side and variables representing the mechanical quantities, like density, +of the fluid system. +To translate the fields from one description to the other one needs to use +converter functions. +These functions need to be hand tailored by the user in the elixir file where each +pair of coupled systems requires two coupling functions, one for each direction. + +In the general case, we have a system $A$ with $m$ variables +$u_{A,i}, \: i = 1, \dots, m$ and another +system $B$ with $n$ variables $u_{B,j}, \: j = 1, \dots, n$. +We then define two coupling functions, one that transforms $u_A$ into $u_B$ +and one that goes the other way. + +In their minimal form they take the position vector $x$, state vector $u$ +and the equations of the two coupled systems +and return the transformed variables. +By passing the equations we can make use of their parameters, if they are required. +Examples can be seen in `examples/structured_2d_dgsem/elixir_advection_coupled.jl`. + + +## Warning about binary compatibility +Currently the coordinate values on the nodes can differ by machine precision when +simulating the mesh and when splitting the mesh in multiple domains. +This is an issue coming from the coordinate interpolation on the nodes. +As a result, running a simulation in a single system and in two coupled domains +may result in a difference of the order of the machine precision. +While this is not an issue for most practical problems, it is best to keep this in mind when comparing test runs. + diff --git a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl index f534b5bc8a..9b14a5c682 100644 --- a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl +++ b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -30,12 +29,8 @@ dg = DGMulti(polydeg = 8, element_type = Quad(), approximation_type = SBP(), ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh")) mesh = DGMultiMesh(dg, mesh_file) diff --git a/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl index 0a50b3644f..4bfb2d3e37 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -31,10 +30,8 @@ Trixi.validate_faces(faces) mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping_flag, diff --git a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl index 37fcc547f6..1ab96925fe 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -29,10 +28,8 @@ Trixi.validate_faces(faces) mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping_flag, diff --git a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl index 0ca4fdc2eb..5db5f74a68 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -50,10 +49,8 @@ volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; solver = DGSEM(basis, surface_flux, volume_integral) # Unstructured mesh with 48 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + joinpath(@__DIR__, "square_unstructured_1.inp")) mesh = P4estMesh{2}(mesh_file, polydeg = 3, initial_refinement_level = 1) diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl index 92928146d7..fbc11e8918 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -99,11 +98,8 @@ 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__, "abaqus_double_mach.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", + joinpath(@__DIR__, "abaqus_double_mach.inp")) mesh = P4estMesh{2}(mesh_file) diff --git a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl index 0ec9fc222f..654efd5e20 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -104,11 +103,8 @@ 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__, "abaqus_forward_step.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", + joinpath(@__DIR__, "abaqus_forward_step.inp")) mesh = P4estMesh{2}(mesh_file) diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl index 38307a7d78..ab11dc1156 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -31,10 +30,8 @@ end # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 48 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + joinpath(@__DIR__, "square_unstructured_1.inp")) # Map the unstructured mesh with the mapping above mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping, initial_refinement_level = 1) diff --git a/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl index 09d018309a..084fd699b8 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -31,10 +30,8 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping_flag, diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl index 36c5624ba9..76ee96d476 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl @@ -13,7 +13,6 @@ # # Keywords: supersonic flow, shock capturing, AMR, unstructured curved mesh, positivity preservation, compressible Euler, 2D -using Downloads: download using OrdinaryDiffEq using Trixi @@ -82,11 +81,8 @@ 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__, "abaqus_cylinder_in_channel.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp")) mesh = P4estMesh{2}(mesh_file) diff --git a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl index 8b8d05bade..75e60d0c78 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -39,11 +38,8 @@ solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the unstructured quad mesh from a file (downloads the file if not available locally) -default_mesh_file = joinpath(@__DIR__, "abaqus_gingerbread_man.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", + joinpath(@__DIR__, "abaqus_gingerbread_man.inp")) mesh = P4estMesh{2}(mesh_file) diff --git a/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl index 380db48735..089e82580c 100644 --- a/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -69,10 +68,8 @@ function mapping_twist(xi, eta) return SVector(x, y) end -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) mesh = P4estMesh{2}(mesh_file, polydeg = 4, diff --git a/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl index cd280cf5bf..33afd2e030 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -49,10 +48,8 @@ function mapping(xi, eta, zeta) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). mesh = P4estMesh{3}(mesh_file, polydeg = 2, diff --git a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl index 6df9ac0b16..83adcbf6a6 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -46,10 +45,8 @@ function mapping(xi, eta, zeta) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) mesh = P4estMesh{3}(mesh_file, polydeg = 3, mapping = mapping, diff --git a/examples/p4est_3d_dgsem/elixir_euler_ec.jl b/examples/p4est_3d_dgsem/elixir_euler_ec.jl index d9d774a7ff..9169854505 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_ec.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_ec.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -46,10 +45,8 @@ function mapping(xi_, eta_, zeta_) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) mesh = P4estMesh{3}(mesh_file, polydeg = 5, mapping = mapping, diff --git a/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl index 24a781ca59..6406a38186 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -47,10 +46,8 @@ function mapping(xi_, eta_, zeta_) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). mesh = P4estMesh{3}(mesh_file, polydeg = 2, diff --git a/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl index f56fe3a429..08307a449a 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -36,10 +35,8 @@ function mapping(xi, eta_, zeta_) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) mesh = P4estMesh{3}(mesh_file, polydeg = 3, mapping = mapping, diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl index 0de22eaea4..e7ca0cad4b 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -49,10 +48,8 @@ function mapping(xi, eta, zeta) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). mesh = P4estMesh{3}(mesh_file, polydeg = 2, diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl index 0fa3a28fe8..7d81d6739b 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -19,11 +18,8 @@ boundary_conditions = Dict(:Bottom => boundary_condition, solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Unstructured 3D half circle mesh from HOHQMesh -default_mesh_file = joinpath(@__DIR__, "abaqus_half_circle_3d.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", + joinpath(@__DIR__, "abaqus_half_circle_3d.inp")) mesh = P4estMesh{3}(mesh_file, initial_refinement_level = 0) diff --git a/examples/structured_2d_dgsem/elixir_advection_coupled.jl b/examples/structured_2d_dgsem/elixir_advection_coupled.jl index 2a56d23f4c..43b68f21b0 100644 --- a/examples/structured_2d_dgsem/elixir_advection_coupled.jl +++ b/examples/structured_2d_dgsem/elixir_advection_coupled.jl @@ -2,31 +2,38 @@ using OrdinaryDiffEq using Trixi ############################################################################### -# Coupled semidiscretization of two linear advection systems, which are connected periodically +# Coupled semidiscretization of four linear advection systems using converter functions such that +# they are also coupled across the domain boundaries to generate a periodic system. # -# In this elixir, we have a square domain that is divided into a left half and a right half. On each -# half of the domain, a completely independent SemidiscretizationHyperbolic is created for the -# linear advection equations. The two systems are coupled in the x-direction and have periodic -# boundaries in the y-direction. For a high-level overview, see also the figure below: +# In this elixir, we have a square domain that is divided into a upper-left, lower-left, +# upper-right and lower-right quarter. On each quarter +# of the domain, a completely independent SemidiscretizationHyperbolic is created for the +# linear advection equations. The four systems are coupled in the x and y-direction. +# For a high-level overview, see also the figure below: # # (-1, 1) ( 1, 1) # ┌────────────────────┬────────────────────┐ -# │ ↑ periodic ↑ │ ↑ periodic ↑ │ -# │ │ │ +# │ ↑ coupled ↑ │ ↑ coupled ↑ │ # │ │ │ # │ ========= │ ========= │ # │ system #1 │ system #2 │ # │ ========= │ ========= │ # │ │ │ +# │<-- coupled │<-- coupled │ +# │ coupled -->│ coupled -->│ # │ │ │ +# │ ↓ coupled ↓ │ ↓ coupled ↓ │ +# ├────────────────────┼────────────────────┤ +# │ ↑ coupled ↑ │ ↑ coupled ↑ │ # │ │ │ +# │ ========= │ ========= │ +# │ system #3 │ system #4 │ +# │ ========= │ ========= │ # │ │ │ -# │ coupled -->│<-- coupled │ -# │ │ │ -# │<-- coupled │ coupled -->│ -# │ │ │ +# │<-- coupled │<-- coupled │ +# │ coupled -->│ coupled -->│ # │ │ │ -# │ ↓ periodic ↓ │ ↓ periodic ↓ │ +# │ ↓ coupled ↓ │ ↓ coupled ↓ │ # └────────────────────┴────────────────────┘ # (-1, -1) ( 1, -1) @@ -36,60 +43,135 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) -# First mesh is the left half of a [-1,1]^2 square -coordinates_min1 = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +# This will be the number of elements for each quarter/semidiscretization. +cells_per_dimension = (8, 8) + +########### +# system #1 +########### + +coordinates_min1 = (-1.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max1 = (0.0, 1.0) # maximum coordinates (max(x), max(y)) -# Define identical resolution as a variable such that it is easier to change from `trixi_include` -cells_per_dimension = (8, 16) +mesh1 = StructuredMesh(cells_per_dimension, coordinates_min1, coordinates_max1) -cells_per_dimension1 = cells_per_dimension +# Define the coupling functions +coupling_function12 = (x, u, equations_other, equations_own) -> u +coupling_function13 = (x, u, equations_other, equations_own) -> u -mesh1 = StructuredMesh(cells_per_dimension1, coordinates_min1, coordinates_max1) +# Define the coupling boundary conditions and the system it is coupled to. +boundary_conditions_x_neg1 = BoundaryConditionCoupled(2, (:end, :i_forward), Float64, + coupling_function12) +boundary_conditions_x_pos1 = BoundaryConditionCoupled(2, (:begin, :i_forward), Float64, + coupling_function12) +boundary_conditions_y_neg1 = BoundaryConditionCoupled(3, (:i_forward, :end), Float64, + coupling_function13) +boundary_conditions_y_pos1 = BoundaryConditionCoupled(3, (:i_forward, :begin), Float64, + coupling_function13) # A semidiscretization collects data structures and functions for the spatial discretization semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, solver, - boundary_conditions = ( - # Connect left boundary with right boundary of right mesh - x_neg = BoundaryConditionCoupled(2, - (:end, - :i_forward), - Float64), - # Connect right boundary with left boundary of right mesh - x_pos = BoundaryConditionCoupled(2, - (:begin, - :i_forward), - Float64), - y_neg = boundary_condition_periodic, - y_pos = boundary_condition_periodic)) - -# Second mesh is the right half of a [-1,1]^2 square -coordinates_min2 = (0.0, -1.0) # minimum coordinates (min(x), min(y)) + boundary_conditions = (x_neg = boundary_conditions_x_neg1, + x_pos = boundary_conditions_x_pos1, + y_neg = boundary_conditions_y_neg1, + y_pos = boundary_conditions_y_pos1)) + +########### +# system #2 +########### + +coordinates_min2 = (0.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max2 = (1.0, 1.0) # maximum coordinates (max(x), max(y)) -cells_per_dimension2 = cells_per_dimension +mesh2 = StructuredMesh(cells_per_dimension, coordinates_min2, coordinates_max2) -mesh2 = StructuredMesh(cells_per_dimension2, coordinates_min2, coordinates_max2) +# Define the coupling functions +coupling_function21 = (x, u, equations_other, equations_own) -> u +coupling_function24 = (x, u, equations_other, equations_own) -> u +# Define the coupling boundary conditions and the system it is coupled to. +boundary_conditions_x_neg2 = BoundaryConditionCoupled(1, (:end, :i_forward), Float64, + coupling_function21) +boundary_conditions_x_pos2 = BoundaryConditionCoupled(1, (:begin, :i_forward), Float64, + coupling_function21) +boundary_conditions_y_neg2 = BoundaryConditionCoupled(4, (:i_forward, :end), Float64, + coupling_function24) +boundary_conditions_y_pos2 = BoundaryConditionCoupled(4, (:i_forward, :begin), Float64, + coupling_function24) + +# A semidiscretization collects data structures and functions for the spatial discretization semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, solver, - boundary_conditions = ( - # Connect left boundary with right boundary of left mesh - x_neg = BoundaryConditionCoupled(1, - (:end, - :i_forward), - Float64), - # Connect right boundary with left boundary of left mesh - x_pos = BoundaryConditionCoupled(1, - (:begin, - :i_forward), - Float64), - y_neg = boundary_condition_periodic, - y_pos = boundary_condition_periodic)) - -# Create a semidiscretization that bundles semi1 and semi2 -semi = SemidiscretizationCoupled(semi1, semi2) + boundary_conditions = (x_neg = boundary_conditions_x_neg2, + x_pos = boundary_conditions_x_pos2, + y_neg = boundary_conditions_y_neg2, + y_pos = boundary_conditions_y_pos2)) + +########### +# system #3 +########### + +coordinates_min3 = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max3 = (0.0, 0.0) # maximum coordinates (max(x), max(y)) + +mesh3 = StructuredMesh(cells_per_dimension, coordinates_min3, coordinates_max3) + +# Define the coupling functions +coupling_function34 = (x, u, equations_other, equations_own) -> u +coupling_function31 = (x, u, equations_other, equations_own) -> u + +# Define the coupling boundary conditions and the system it is coupled to. +boundary_conditions_x_neg3 = BoundaryConditionCoupled(4, (:end, :i_forward), Float64, + coupling_function34) +boundary_conditions_x_pos3 = BoundaryConditionCoupled(4, (:begin, :i_forward), Float64, + coupling_function34) +boundary_conditions_y_neg3 = BoundaryConditionCoupled(1, (:i_forward, :end), Float64, + coupling_function31) +boundary_conditions_y_pos3 = BoundaryConditionCoupled(1, (:i_forward, :begin), Float64, + coupling_function31) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi3 = SemidiscretizationHyperbolic(mesh3, equations, initial_condition_convergence_test, + solver, + boundary_conditions = (x_neg = boundary_conditions_x_neg3, + x_pos = boundary_conditions_x_pos3, + y_neg = boundary_conditions_y_neg3, + y_pos = boundary_conditions_y_pos3)) + +########### +# system #4 +########### + +coordinates_min4 = (0.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max4 = (1.0, 0.0) # maximum coordinates (max(x), max(y)) + +mesh4 = StructuredMesh(cells_per_dimension, coordinates_min4, coordinates_max4) + +# Define the coupling functions +coupling_function43 = (x, u, equations_other, equations_own) -> u +coupling_function42 = (x, u, equations_other, equations_own) -> u + +# Define the coupling boundary conditions and the system it is coupled to. +boundary_conditions_x_neg4 = BoundaryConditionCoupled(3, (:end, :i_forward), Float64, + coupling_function43) +boundary_conditions_x_pos4 = BoundaryConditionCoupled(3, (:begin, :i_forward), Float64, + coupling_function43) +boundary_conditions_y_neg4 = BoundaryConditionCoupled(2, (:i_forward, :end), Float64, + coupling_function42) +boundary_conditions_y_pos4 = BoundaryConditionCoupled(2, (:i_forward, :begin), Float64, + coupling_function42) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi4 = SemidiscretizationHyperbolic(mesh4, equations, initial_condition_convergence_test, + solver, + boundary_conditions = (x_neg = boundary_conditions_x_neg4, + x_pos = boundary_conditions_x_pos4, + y_neg = boundary_conditions_y_neg4, + y_pos = boundary_conditions_y_pos4)) + +# Create a semidiscretization that bundles all the semidiscretizations. +semi = SemidiscretizationCoupled(semi1, semi2, semi3, semi4) ############################################################################### # ODE solvers, callbacks etc. @@ -104,7 +186,10 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_callback1 = AnalysisCallback(semi1, interval = 100) analysis_callback2 = AnalysisCallback(semi2, interval = 100) -analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2) +analysis_callback3 = AnalysisCallback(semi3, interval = 100) +analysis_callback4 = AnalysisCallback(semi4, interval = 100) +analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2, + analysis_callback3, analysis_callback4) # The SaveSolutionCallback allows to save the solution to a file in regular intervals save_solution = SaveSolutionCallback(interval = 100, diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl index 61dd252fd8..a6a56aa807 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi diff --git a/examples/t8code_2d_dgsem/elixir_advection_amr_unstructured_flag.jl b/examples/t8code_2d_dgsem/elixir_advection_amr_unstructured_flag.jl index f285d24fc6..0923e32848 100644 --- a/examples/t8code_2d_dgsem/elixir_advection_amr_unstructured_flag.jl +++ b/examples/t8code_2d_dgsem/elixir_advection_amr_unstructured_flag.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -31,10 +30,8 @@ Trixi.validate_faces(faces) mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_2d_dgsem/elixir_advection_unstructured_flag.jl b/examples/t8code_2d_dgsem/elixir_advection_unstructured_flag.jl index 5ba1ab1548..ba8f1b59b8 100644 --- a/examples/t8code_2d_dgsem/elixir_advection_unstructured_flag.jl +++ b/examples/t8code_2d_dgsem/elixir_advection_unstructured_flag.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -28,10 +27,8 @@ Trixi.validate_faces(faces) mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n. -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_2d_dgsem/elixir_euler_free_stream.jl b/examples/t8code_2d_dgsem/elixir_euler_free_stream.jl index 37d15f3856..5e6c4193c5 100644 --- a/examples/t8code_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/t8code_2d_dgsem/elixir_euler_free_stream.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -30,10 +29,8 @@ end # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 48 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + joinpath(@__DIR__, "square_unstructured_1.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl b/examples/t8code_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl index bcc1abc560..e496eb7672 100644 --- a/examples/t8code_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl +++ b/examples/t8code_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -30,10 +29,8 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_2d_dgsem/elixir_mhd_rotor.jl b/examples/t8code_2d_dgsem/elixir_mhd_rotor.jl index adb154948f..ff2e40ae60 100644 --- a/examples/t8code_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/t8code_2d_dgsem/elixir_mhd_rotor.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -68,10 +67,8 @@ function mapping_twist(xi, eta) return SVector(x, y) end -mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + joinpath(@__DIR__, "square_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_advection_amr_unstructured_curved.jl b/examples/t8code_3d_dgsem/elixir_advection_amr_unstructured_curved.jl index 617736afbd..e7c0f4b731 100644 --- a/examples/t8code_3d_dgsem/elixir_advection_amr_unstructured_curved.jl +++ b/examples/t8code_3d_dgsem/elixir_advection_amr_unstructured_curved.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -47,11 +46,9 @@ function mapping(xi, eta, zeta) return SVector(5 * x, 5 * y, 5 * z) end -# Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +# Unstructured mesh with 48 cells of the cube domain [-1, 1]^3. +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connectivity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_advection_unstructured_curved.jl b/examples/t8code_3d_dgsem/elixir_advection_unstructured_curved.jl index df358435c9..ee27ee117f 100644 --- a/examples/t8code_3d_dgsem/elixir_advection_unstructured_curved.jl +++ b/examples/t8code_3d_dgsem/elixir_advection_unstructured_curved.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -45,10 +44,8 @@ function mapping(xi, eta, zeta) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connectivity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_euler_ec.jl b/examples/t8code_3d_dgsem/elixir_euler_ec.jl index 07745c3ac5..b720bfcd37 100644 --- a/examples/t8code_3d_dgsem/elixir_euler_ec.jl +++ b/examples/t8code_3d_dgsem/elixir_euler_ec.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -45,10 +44,8 @@ function mapping(xi_, eta_, zeta_) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connectivity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_euler_free_stream.jl b/examples/t8code_3d_dgsem/elixir_euler_free_stream.jl index e135d46481..b70a6091ad 100644 --- a/examples/t8code_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/t8code_3d_dgsem/elixir_euler_free_stream.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -46,10 +45,8 @@ function mapping(xi_, eta_, zeta_) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connectivity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_euler_free_stream_extruded.jl b/examples/t8code_3d_dgsem/elixir_euler_free_stream_extruded.jl index d129b59826..6ae38d20b5 100644 --- a/examples/t8code_3d_dgsem/elixir_euler_free_stream_extruded.jl +++ b/examples/t8code_3d_dgsem/elixir_euler_free_stream_extruded.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -35,10 +34,8 @@ function mapping(xi, eta_, zeta_) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + joinpath(@__DIR__, "cube_unstructured_2.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/t8code_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl b/examples/t8code_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl index d4664522be..6856be36ea 100644 --- a/examples/t8code_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl +++ b/examples/t8code_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl @@ -1,4 +1,3 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -48,10 +47,8 @@ function mapping(xi, eta, zeta) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 -mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || - download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +mesh_file = Trixi.download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + joinpath(@__DIR__, "cube_unstructured_1.inp")) # INP mesh files are only support by p4est. Hence, we # create a p4est connecvity object first from which diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 5f482668cb..5630b51c29 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -42,6 +42,7 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_nonlinear = [pressure], spec_entropy = false, bar_states = true) + volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl index e1f60f7225..a4dedc2d69 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -55,6 +55,7 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, bar_states = false) + volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl index 8f8e867dca..9741430d11 100644 --- a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl +++ b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -14,11 +13,8 @@ equations = AcousticPerturbationEquations2D(v_mean_global = (0.0, -0.5), solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Create unstructured quadrilateral mesh from a file -default_mesh_file = joinpath(@__DIR__, "mesh_five_circles_in_circle.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", + joinpath(@__DIR__, "mesh_five_circles_in_circle.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl index afef6c2c38..c0ee453344 100644 --- a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -16,12 +15,8 @@ solver = DGSEM(polydeg = 6, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_basic.jl b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl index cd6a199575..f8976120d5 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -25,12 +24,8 @@ solver = DGSEM(polydeg = 8, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_ec.jl b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl index 0f53aa62a1..58b4d9a1dd 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -19,12 +18,8 @@ solver = DGSEM(polydeg = 6, surface_flux = flux_ranocha, ############################################################################### # Get the curved quad mesh from a file - -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl index a2fec1a320..f266a3de0b 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -26,12 +25,8 @@ solver = DGSEM(polydeg = 6, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_gingerbread_man.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", + joinpath(@__DIR__, "mesh_gingerbread_man.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl index afd177f074..e640001ad7 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -19,12 +18,8 @@ solver = DGSEM(polydeg = 6, surface_flux = FluxRotated(flux_hll)) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl index e1cc093296..06053273b7 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl @@ -55,11 +55,8 @@ solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, volume_integral = volume_integral) # Get the curved quad mesh from a file -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl index b2abefe7ee..65e5eb51ce 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -40,12 +39,8 @@ solver = DGSEM(polydeg = 4, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file - -default_mesh_file = joinpath(@__DIR__, "mesh_box_around_circle.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", + joinpath(@__DIR__, "mesh_box_around_circle.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl index 3ed3e828ca..0c7152a6ea 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -17,12 +16,9 @@ solver = DGSEM(polydeg = 7, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # 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 = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) -mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl index a40f92cac0..805934e305 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -35,11 +34,8 @@ solver = DGSEM(polydeg = 6, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl index 1148f25fae..df1a69192c 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -38,11 +37,8 @@ solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjord # 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + joinpath(@__DIR__, "mesh_outer_circle.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl index 8e9d396d82..9122fb8287 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -25,11 +24,8 @@ solver = DGSEM(polydeg = 6, # 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl index 94202b81df..98408db5a7 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -34,11 +33,8 @@ 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl index 0766868840..a7aa580895 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -23,11 +22,8 @@ solver = DGSEM(polydeg = 6, surface_flux = surface_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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) 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 index 6164f9d4a5..df321aad26 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -93,16 +92,10 @@ solver = DGSEM(basis, surface_flux, volume_integral) ############################################################################### # Get the unstructured quad mesh from a file (downloads the file if not available locally) +mesh_file = Trixi.download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", + joinpath(@__DIR__, "mesh_three_mound.mesh")) -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) +mesh = UnstructuredMesh2D(mesh_file) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl index 0b86095663..fcc08b6f99 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -24,11 +23,8 @@ solver = DGSEM(polydeg = 6, surface_flux = surface_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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl index 4ad5f7e320..821f31c52a 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -48,11 +47,8 @@ solver = DGSEM(polydeg = 6, surface_flux = surface_flux, ############################################################################### # 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = false) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index 6a727df250..ca1f54595b 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -42,11 +41,8 @@ solver = DGSEM(polydeg = 6, surface_flux = surface_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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl index 76b9642d59..f115113ed2 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -55,12 +54,8 @@ solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, ############################################################################### # 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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + joinpath(@__DIR__, "mesh_outer_circle.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl index bf4d0be682..6bad3a77f0 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -36,13 +35,9 @@ solver = DGSEM(polydeg = 6, surface_flux = surface_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_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl b/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl index c181203e7a..fe7e708f3b 100644 --- a/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl +++ b/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -21,12 +20,8 @@ solver = FDSBP(D_SBP, ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl b/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl index 7ada50c0c6..25a81c16bf 100644 --- a/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl +++ b/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -33,12 +32,8 @@ solver = FDSBP(D_SBP, ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_gingerbread_man.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", + joinpath(@__DIR__, "mesh_gingerbread_man.mesh")) mesh = UnstructuredMesh2D(mesh_file) diff --git a/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl b/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl index edcd221bf5..5f11d41ad5 100644 --- a/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl +++ b/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl @@ -1,5 +1,4 @@ -using Downloads: download using OrdinaryDiffEq using Trixi @@ -22,12 +21,8 @@ solver = FDSBP(D_SBP, ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) - -default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh")) mesh = UnstructuredMesh2D(mesh_file, periodicity = true) diff --git a/src/Trixi.jl b/src/Trixi.jl index e4fba96b51..83e6176808 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -39,6 +39,7 @@ import SciMLBase: get_du, get_tmp_cache, u_modified!, get_proposed_dt, set_proposed_dt!, terminate!, remake, add_tstop!, has_tstop, first_tstop +using Downloads: Downloads using CodeTracking: CodeTracking using ConstructionBase: ConstructionBase using DiffEqCallbacks: PeriodicCallback, PeriodicCallbackAffect diff --git a/src/auxiliary/auxiliary.jl b/src/auxiliary/auxiliary.jl index ac3ff63ade..e487699bcd 100644 --- a/src/auxiliary/auxiliary.jl +++ b/src/auxiliary/auxiliary.jl @@ -346,6 +346,29 @@ function register_error_hints() return nothing end +""" + Trixi.download(src_url, file_path) + +Download a file from given `src_url` to given `file_path` if +`file_path` is not already a file. This function just returns +`file_path`. +This is a small wrapper of `Downloads.download(src_url, file_path)` +that avoids race conditions when multiple MPI ranks are used. +""" +function download(src_url, file_path) + # Note that `mpi_isroot()` is also `true` if running + # in serial (without MPI). + if mpi_isroot() + isfile(file_path) || Downloads.download(src_url, file_path) + end + + if mpi_isparallel() + MPI.Barrier(mpi_comm()) + end + + return file_path +end + # Same as `foreach(enumerate(something))`, but without allocations. # # Note that compile times may increase if this is used with big tuples. diff --git a/src/auxiliary/t8code.jl b/src/auxiliary/t8code.jl index db01476bb8..7c1399fc80 100644 --- a/src/auxiliary/t8code.jl +++ b/src/auxiliary/t8code.jl @@ -46,230 +46,6 @@ function init_t8code() return nothing end -function trixi_t8_unref_forest(forest) - t8_forest_unref(Ref(forest)) -end - -function t8_free(ptr) - T8code.Libt8.sc_free(t8_get_package_id(), ptr) -end - -function trixi_t8_count_interfaces(forest) - # Check that forest is a committed, that is valid and usable, forest. - @assert t8_forest_is_committed(forest) != 0 - - # Get the number of local elements of forest. - num_local_elements = t8_forest_get_local_num_elements(forest) - # Get the number of ghost elements of forest. - num_ghost_elements = t8_forest_get_num_ghosts(forest) - # Get the number of trees that have elements of this process. - num_local_trees = t8_forest_get_num_local_trees(forest) - - current_index = t8_locidx_t(0) - - local_num_conform = 0 - local_num_mortars = 0 - local_num_boundary = 0 - - for itree in 0:(num_local_trees - 1) - tree_class = t8_forest_get_tree_class(forest, itree) - eclass_scheme = t8_forest_get_eclass_scheme(forest, tree_class) - - # Get the number of elements of this tree. - num_elements_in_tree = t8_forest_get_tree_num_elements(forest, itree) - - for ielement in 0:(num_elements_in_tree - 1) - element = t8_forest_get_element_in_tree(forest, itree, ielement) - - level = t8_element_level(eclass_scheme, element) - - num_faces = t8_element_num_faces(eclass_scheme, element) - - for iface in 0:(num_faces - 1) - pelement_indices_ref = Ref{Ptr{t8_locidx_t}}() - pneighbor_leafs_ref = Ref{Ptr{Ptr{t8_element}}}() - pneigh_scheme_ref = Ref{Ptr{t8_eclass_scheme}}() - - dual_faces_ref = Ref{Ptr{Cint}}() - num_neighbors_ref = Ref{Cint}() - - forest_is_balanced = Cint(1) - - t8_forest_leaf_face_neighbors(forest, itree, element, - pneighbor_leafs_ref, iface, dual_faces_ref, - num_neighbors_ref, - pelement_indices_ref, pneigh_scheme_ref, - forest_is_balanced) - - num_neighbors = num_neighbors_ref[] - neighbor_ielements = unsafe_wrap(Array, pelement_indices_ref[], - num_neighbors) - neighbor_leafs = unsafe_wrap(Array, pneighbor_leafs_ref[], num_neighbors) - neighbor_scheme = pneigh_scheme_ref[] - - if num_neighbors > 0 - neighbor_level = t8_element_level(neighbor_scheme, neighbor_leafs[1]) - - # Conforming interface: The second condition ensures we only visit the interface once. - if level == neighbor_level && current_index <= neighbor_ielements[1] - local_num_conform += 1 - elseif level < neighbor_level - local_num_mortars += 1 - end - else - local_num_boundary += 1 - end - - t8_free(dual_faces_ref[]) - t8_free(pneighbor_leafs_ref[]) - t8_free(pelement_indices_ref[]) - end # for - - current_index += 1 - end # for - end # for - - return (interfaces = local_num_conform, - mortars = local_num_mortars, - boundaries = local_num_boundary) -end - -function trixi_t8_fill_mesh_info(forest, elements, interfaces, mortars, boundaries, - boundary_names) - # Check that forest is a committed, that is valid and usable, forest. - @assert t8_forest_is_committed(forest) != 0 - - # Get the number of local elements of forest. - num_local_elements = t8_forest_get_local_num_elements(forest) - # Get the number of ghost elements of forest. - num_ghost_elements = t8_forest_get_num_ghosts(forest) - # Get the number of trees that have elements of this process. - num_local_trees = t8_forest_get_num_local_trees(forest) - - current_index = t8_locidx_t(0) - - local_num_conform = 0 - local_num_mortars = 0 - local_num_boundary = 0 - - for itree in 0:(num_local_trees - 1) - tree_class = t8_forest_get_tree_class(forest, itree) - eclass_scheme = t8_forest_get_eclass_scheme(forest, tree_class) - - # Get the number of elements of this tree. - num_elements_in_tree = t8_forest_get_tree_num_elements(forest, itree) - - for ielement in 0:(num_elements_in_tree - 1) - element = t8_forest_get_element_in_tree(forest, itree, ielement) - - level = t8_element_level(eclass_scheme, element) - - num_faces = t8_element_num_faces(eclass_scheme, element) - - for iface in 0:(num_faces - 1) - - # Compute the `orientation` of the touching faces. - if t8_element_is_root_boundary(eclass_scheme, element, iface) == 1 - cmesh = t8_forest_get_cmesh(forest) - itree_in_cmesh = t8_forest_ltreeid_to_cmesh_ltreeid(forest, itree) - iface_in_tree = t8_element_tree_face(eclass_scheme, element, iface) - orientation_ref = Ref{Cint}() - - t8_cmesh_get_face_neighbor(cmesh, itree_in_cmesh, iface_in_tree, C_NULL, - orientation_ref) - orientation = orientation_ref[] - else - orientation = zero(Cint) - end - - pelement_indices_ref = Ref{Ptr{t8_locidx_t}}() - pneighbor_leafs_ref = Ref{Ptr{Ptr{t8_element}}}() - pneigh_scheme_ref = Ref{Ptr{t8_eclass_scheme}}() - - dual_faces_ref = Ref{Ptr{Cint}}() - num_neighbors_ref = Ref{Cint}() - - forest_is_balanced = Cint(1) - - t8_forest_leaf_face_neighbors(forest, itree, element, - pneighbor_leafs_ref, iface, dual_faces_ref, - num_neighbors_ref, - pelement_indices_ref, pneigh_scheme_ref, - forest_is_balanced) - - num_neighbors = num_neighbors_ref[] - dual_faces = unsafe_wrap(Array, dual_faces_ref[], num_neighbors) - neighbor_ielements = unsafe_wrap(Array, pelement_indices_ref[], - num_neighbors) - neighbor_leafs = unsafe_wrap(Array, pneighbor_leafs_ref[], num_neighbors) - neighbor_scheme = pneigh_scheme_ref[] - - if num_neighbors > 0 - neighbor_level = t8_element_level(neighbor_scheme, neighbor_leafs[1]) - - # Conforming interface: The second condition ensures we only visit the interface once. - if level == neighbor_level && current_index <= neighbor_ielements[1] - local_num_conform += 1 - - faces = (iface, dual_faces[1]) - interface_id = local_num_conform - - # Write data to interfaces container. - interfaces.neighbor_ids[1, interface_id] = current_index + 1 - interfaces.neighbor_ids[2, interface_id] = neighbor_ielements[1] + 1 - - # Save interfaces.node_indices dimension specific in containers_3d.jl. - init_interface_node_indices!(interfaces, faces, orientation, - interface_id) - # Non-conforming interface. - elseif level < neighbor_level - local_num_mortars += 1 - - faces = (dual_faces[1], iface) - - mortar_id = local_num_mortars - - # Last entry is the large element. - mortars.neighbor_ids[end, mortar_id] = current_index + 1 - - # Fill in the `mortars.neighbor_ids` array and reorder if necessary. - init_mortar_neighbor_ids!(mortars, faces[2], faces[1], - orientation, neighbor_ielements, - mortar_id) - - # Fill in the `mortars.node_indices` array. - init_mortar_node_indices!(mortars, faces, orientation, mortar_id) - - # else: "level > neighbor_level" is skipped since we visit the mortar interface only once. - end - - # Domain boundary. - else - local_num_boundary += 1 - boundary_id = local_num_boundary - - boundaries.neighbor_ids[boundary_id] = current_index + 1 - - init_boundary_node_indices!(boundaries, iface, boundary_id) - - # One-based indexing. - boundaries.name[boundary_id] = boundary_names[iface + 1, itree + 1] - end - - t8_free(dual_faces_ref[]) - t8_free(pneighbor_leafs_ref[]) - t8_free(pelement_indices_ref[]) - end # for iface = ... - - current_index += 1 - end # for - end # for - - return (interfaces = local_num_conform, - mortars = local_num_mortars, - boundaries = local_num_boundary) -end - function trixi_t8_get_local_element_levels(forest) # Check that forest is a committed, that is valid and usable, forest. @assert t8_forest_is_committed(forest) != 0 @@ -341,23 +117,16 @@ function adapt_callback(forest, end function trixi_t8_adapt_new(old_forest, indicators) - # Check that forest is a committed, that is valid and usable, forest. - @assert t8_forest_is_committed(old_forest) != 0 - - # Init new forest. new_forest_ref = Ref{t8_forest_t}() t8_forest_init(new_forest_ref) new_forest = new_forest_ref[] - let set_from = C_NULL, recursive = 0, set_for_coarsening = 0, no_repartition = 0, - do_ghost = 1 - + let set_from = C_NULL, recursive = 0, no_repartition = 1, do_ghost = 1 t8_forest_set_user_data(new_forest, pointer(indicators)) t8_forest_set_adapt(new_forest, old_forest, @t8_adapt_callback(adapt_callback), recursive) t8_forest_set_balance(new_forest, set_from, no_repartition) - t8_forest_set_partition(new_forest, set_from, set_for_coarsening) - t8_forest_set_ghost(new_forest, do_ghost, T8_GHOST_FACES) # Note: MPI support not available yet so it is a dummy call. + t8_forest_set_ghost(new_forest, do_ghost, T8_GHOST_FACES) t8_forest_commit(new_forest) end diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 5854c8617c..6f57d6647f 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -726,7 +726,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::P4estMesh, return has_changed end -function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::SerialT8codeMesh, +function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::T8codeMesh, equations, dg::DG, cache, semi, t, iter; only_refine = false, only_coarsen = false, @@ -754,29 +754,29 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::SerialT8codeMe @trixi_timeit timer() "adapt" begin difference = @trixi_timeit timer() "mesh" trixi_t8_adapt!(mesh, indicators) - @trixi_timeit timer() "solver" adapt!(u_ode, adaptor, mesh, equations, dg, - cache, difference) - end + # Store whether there were any cells coarsened or refined and perform load balancing. + has_changed = any(difference .!= 0) - # Store whether there were any cells coarsened or refined and perform load balancing. - has_changed = any(difference .!= 0) + # Check if mesh changed on other processes + if mpi_isparallel() + has_changed = MPI.Allreduce!(Ref(has_changed), |, mpi_comm())[] + end - # TODO: T8codeMesh for MPI not implemented yet. - # Check if mesh changed on other processes - # if mpi_isparallel() - # has_changed = MPI.Allreduce!(Ref(has_changed), |, mpi_comm())[] - # end + if has_changed + @trixi_timeit timer() "solver" adapt!(u_ode, adaptor, mesh, equations, dg, + cache, difference) + end + end if has_changed - # TODO: T8codeMesh for MPI not implemented yet. - # if mpi_isparallel() && amr_callback.dynamic_load_balancing - # @trixi_timeit timer() "dynamic load balancing" begin - # global_first_quadrant = unsafe_wrap(Array, mesh.p4est.global_first_quadrant, mpi_nranks() + 1) - # old_global_first_quadrant = copy(global_first_quadrant) - # partition!(mesh) - # rebalance_solver!(u_ode, mesh, equations, dg, cache, old_global_first_quadrant) - # end - # end + if mpi_isparallel() && amr_callback.dynamic_load_balancing + @trixi_timeit timer() "dynamic load balancing" begin + old_global_first_element_ids = get_global_first_element_ids(mesh) + partition!(mesh) + rebalance_solver!(u_ode, mesh, equations, dg, cache, + old_global_first_element_ids) + end + end reinitialize_boundaries!(semi.boundary_conditions, cache) end diff --git a/src/callbacks_step/amr_dg.jl b/src/callbacks_step/amr_dg.jl index 1dcfdccdea..0a7055af40 100644 --- a/src/callbacks_step/amr_dg.jl +++ b/src/callbacks_step/amr_dg.jl @@ -6,11 +6,14 @@ #! format: noindent # Redistribute data for load balancing after partitioning the mesh -function rebalance_solver!(u_ode::AbstractVector, mesh::ParallelP4estMesh, equations, +function rebalance_solver!(u_ode::AbstractVector, + mesh::Union{ParallelP4estMesh, ParallelT8codeMesh}, + equations, dg::DGSEM, cache, old_global_first_quadrant) - # mpi ranks are 0-based, this array uses 1-based indices - global_first_quadrant = unsafe_wrap(Array, mesh.p4est.global_first_quadrant, - mpi_nranks() + 1) + + # MPI ranks are 0-based. This array uses 1-based indices. + global_first_quadrant = get_global_first_element_ids(mesh) + if global_first_quadrant[mpi_rank() + 1] == old_global_first_quadrant[mpi_rank() + 1] && global_first_quadrant[mpi_rank() + 2] == diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index b816bc06e6..94524b23a3 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -385,7 +385,12 @@ function adapt!(u_ode::AbstractVector, adaptor, mesh::T8codeMesh{2}, equations, # Return early if there is nothing to do. if !any(difference .!= 0) - return nothing + if mpi_isparallel() + # MPICache init uses all-to-all communication -> reinitialize even if there is nothing to do + # locally (there still might be other MPI ranks that have refined elements) + reinitialize_containers!(mesh, equations, dg, cache) + end + return end # Number of (local) cells/elements. diff --git a/src/callbacks_step/amr_dg3d.jl b/src/callbacks_step/amr_dg3d.jl index 392cbba9e2..3f67951baf 100644 --- a/src/callbacks_step/amr_dg3d.jl +++ b/src/callbacks_step/amr_dg3d.jl @@ -316,7 +316,12 @@ function adapt!(u_ode::AbstractVector, adaptor, mesh::T8codeMesh{3}, equations, # Return early if there is nothing to do. if !any(difference .!= 0) - return nothing + if mpi_isparallel() + # MPICache init uses all-to-all communication -> reinitialize even if there is nothing to do + # locally (there still might be other MPI ranks that have refined elements) + reinitialize_containers!(mesh, equations, dg, cache) + end + return end # Number of (local) cells/elements. diff --git a/src/callbacks_step/analysis_dg2d_parallel.jl b/src/callbacks_step/analysis_dg2d_parallel.jl index a04bf73260..000daa015d 100644 --- a/src/callbacks_step/analysis_dg2d_parallel.jl +++ b/src/callbacks_step/analysis_dg2d_parallel.jl @@ -91,7 +91,8 @@ function calc_error_norms_per_element(func, u, t, analyzer, end function calc_error_norms(func, u, t, analyzer, - mesh::ParallelP4estMesh{2}, equations, + mesh::Union{ParallelP4estMesh{2}, ParallelT8codeMesh{2}}, + equations, initial_condition, dg::DGSEM, cache, cache_analysis) @unpack vandermonde, weights = analyzer @unpack node_coordinates, inverse_jacobian = cache.elements @@ -171,7 +172,8 @@ function integrate_via_indices(func::Func, u, end function integrate_via_indices(func::Func, u, - mesh::ParallelP4estMesh{2}, equations, + mesh::Union{ParallelP4estMesh{2}, ParallelT8codeMesh{2}}, + equations, dg::DGSEM, cache, args...; normalize = true) where {Func} @unpack weights = dg.basis diff --git a/src/callbacks_step/analysis_dg3d_parallel.jl b/src/callbacks_step/analysis_dg3d_parallel.jl index d8756d91c9..de777be406 100644 --- a/src/callbacks_step/analysis_dg3d_parallel.jl +++ b/src/callbacks_step/analysis_dg3d_parallel.jl @@ -6,7 +6,8 @@ #! format: noindent function calc_error_norms(func, u, t, analyzer, - mesh::ParallelP4estMesh{3}, equations, + mesh::Union{ParallelP4estMesh{3}, ParallelT8codeMesh{3}}, + equations, initial_condition, dg::DGSEM, cache, cache_analysis) @unpack vandermonde, weights = analyzer @unpack node_coordinates, inverse_jacobian = cache.elements @@ -64,7 +65,8 @@ function calc_error_norms(func, u, t, analyzer, end function integrate_via_indices(func::Func, u, - mesh::ParallelP4estMesh{3}, equations, + mesh::Union{ParallelP4estMesh{3}, ParallelT8codeMesh{3}}, + equations, dg::DGSEM, cache, args...; normalize = true) where {Func} @unpack weights = dg.basis diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 92c21d65e1..8779480cc1 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -276,4 +276,36 @@ function max_dt(u, t, mesh::ParallelP4estMesh{2}, return dt end + +function max_dt(u, t, mesh::ParallelT8codeMesh{2}, + constant_speed::False, equations, dg::DG, cache) + # call the method accepting a general `mesh::T8codeMesh{2}` + # TODO: MPI, we should improve this; maybe we should dispatch on `u` + # and create some MPI array type, overloading broadcasting and mapreduce etc. + # Then, this specific array type should also work well with DiffEq etc. + dt = invoke(max_dt, + Tuple{typeof(u), typeof(t), T8codeMesh{2}, + typeof(constant_speed), typeof(equations), typeof(dg), + typeof(cache)}, + u, t, mesh, constant_speed, equations, dg, cache) + dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + + return dt +end + +function max_dt(u, t, mesh::ParallelT8codeMesh{2}, + constant_speed::True, equations, dg::DG, cache) + # call the method accepting a general `mesh::T8codeMesh{2}` + # TODO: MPI, we should improve this; maybe we should dispatch on `u` + # and create some MPI array type, overloading broadcasting and mapreduce etc. + # Then, this specific array type should also work well with DiffEq etc. + dt = invoke(max_dt, + Tuple{typeof(u), typeof(t), T8codeMesh{2}, + typeof(constant_speed), typeof(equations), typeof(dg), + typeof(cache)}, + u, t, mesh, constant_speed, equations, dg, cache) + dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + + return dt +end end # @muladd diff --git a/src/callbacks_step/stepsize_dg3d.jl b/src/callbacks_step/stepsize_dg3d.jl index 822ab2f87e..664596f989 100644 --- a/src/callbacks_step/stepsize_dg3d.jl +++ b/src/callbacks_step/stepsize_dg3d.jl @@ -150,4 +150,36 @@ function max_dt(u, t, mesh::ParallelP4estMesh{3}, return dt end + +function max_dt(u, t, mesh::ParallelT8codeMesh{3}, + constant_speed::False, equations, dg::DG, cache) + # call the method accepting a general `mesh::T8codeMesh{3}` + # TODO: MPI, we should improve this; maybe we should dispatch on `u` + # and create some MPI array type, overloading broadcasting and mapreduce etc. + # Then, this specific array type should also work well with DiffEq etc. + dt = invoke(max_dt, + Tuple{typeof(u), typeof(t), T8codeMesh{3}, + typeof(constant_speed), typeof(equations), typeof(dg), + typeof(cache)}, + u, t, mesh, constant_speed, equations, dg, cache) + dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + + return dt +end + +function max_dt(u, t, mesh::ParallelT8codeMesh{3}, + constant_speed::True, equations, dg::DG, cache) + # call the method accepting a general `mesh::T8codeMesh{3}` + # TODO: MPI, we should improve this; maybe we should dispatch on `u` + # and create some MPI array type, overloading broadcasting and mapreduce etc. + # Then, this specific array type should also work well with DiffEq etc. + dt = invoke(max_dt, + Tuple{typeof(u), typeof(t), T8codeMesh{3}, + typeof(constant_speed), typeof(equations), typeof(dg), + typeof(cache)}, + u, t, mesh, constant_speed, equations, dg, cache) + dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + + return dt +end end # @muladd diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index f7399da222..dc81bd710e 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1786,8 +1786,8 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::CompressibleEulerEquations2D) +@inline function gradient_conservative(::typeof(pressure), + u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1890,10 +1890,10 @@ end return energy_total(cons, equations) - energy_kinetic(cons, equations) end -# State validation for subcell limiting using Newton-bisection method -@inline function is_valid_state(cons, equations::CompressibleEulerEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 +# State validation for Newton-bisection method of subcell IDP limiting +@inline function Base.isvalid(u, equations::CompressibleEulerEquations2D) + p = pressure(u, equations) + if u[1] <= 0.0 || p <= 0.0 return false end return true diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 387bdaacd7..0722fa5429 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -435,9 +435,9 @@ of the correct length `nvariables(equations)`. """ function energy_internal end -# Default implementation of derivation for `variable`. Used for subcell limiting. -# Implementing a derivative function for a specific function improves the performance. -@inline function variable_derivative(variable, u, equations) +# Default implementation of gradient for `variable`. Used for subcell limiting. +# Implementing a gradient function for a specific variable improves the performance. +@inline function gradient_conservative(variable, u, equations) return ForwardDiff.gradient(x -> variable(x, equations), u) end diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index b1371ba38b..622410de85 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -295,8 +295,8 @@ of local and symmetric parts. It is equivalent to the non-conservative flux of B et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different results on non-conforming meshes(!). -The two other flux functions with the same name return either the local -or symmetric portion of the non-conservative flux based on the type of the +The two other flux functions with the same name return either the local +or symmetric portion of the non-conservative flux based on the type of the nonconservative_type argument, employing multiple dispatch. They are used to compute the subcell fluxes in dg_2d_subcell_limiters.jl. @@ -1119,8 +1119,8 @@ end end # Transformation from conservative variables u to d(p)/d(u) -@inline function variable_derivative(::typeof(pressure), - u, equations::IdealGlmMhdEquations2D) +@inline function gradient_conservative(::typeof(pressure), + u, equations::IdealGlmMhdEquations2D) rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3, psi = u v1 = rho_v1 / rho @@ -1398,10 +1398,10 @@ end cons[9]^2 / 2) end -# State validation for subcell limiting using Newton-bisection method -@inline function is_valid_state(cons, equations::IdealGlmMhdEquations2D) - p = pressure(cons, equations) - if cons[1] <= 0.0 || p <= 0.0 +# State validation for Newton-bisection method of subcell IDP limiting +@inline function Base.isvalid(u, equations::IdealGlmMhdEquations2D) + p = pressure(u, equations) + if u[1] <= 0.0 || p <= 0.0 return false end return true diff --git a/src/meshes/p4est_mesh.jl b/src/meshes/p4est_mesh.jl index c5d39ef00c..abe9d9345b 100644 --- a/src/meshes/p4est_mesh.jl +++ b/src/meshes/p4est_mesh.jl @@ -1700,6 +1700,10 @@ function bilinear_interpolation!(coordinate, face_vertices, u, v) end end +function get_global_first_element_ids(mesh::P4estMesh) + return unsafe_wrap(Array, mesh.p4est.global_first_quadrant, mpi_nranks() + 1) +end + function balance!(mesh::P4estMesh{2}, init_fn = C_NULL) p4est_balance(mesh.p4est, P4EST_CONNECT_FACE, init_fn) # Due to a bug in `p4est`, the forest needs to be rebalanced twice sometimes diff --git a/src/meshes/t8code_mesh.jl b/src/meshes/t8code_mesh.jl index c9665a22af..cb2ac787e1 100644 --- a/src/meshes/t8code_mesh.jl +++ b/src/meshes/t8code_mesh.jl @@ -1,14 +1,12 @@ """ T8codeMesh{NDIMS} <: AbstractMesh{NDIMS} -An unstructured curved mesh based on trees that uses the C library +An unstructured curved mesh based on trees that uses the C library ['t8code'](https://github.com/DLR-AMR/t8code) to manage trees and mesh refinement. """ mutable struct T8codeMesh{NDIMS, RealT <: Real, IsParallel, NDIMSP2, NNODES} <: AbstractMesh{NDIMS} - cmesh :: Ptr{t8_cmesh} # cpointer to coarse mesh - scheme :: Ptr{t8_eclass_scheme} # cpointer to element scheme forest :: Ptr{t8_forest} # cpointer to forest is_parallel :: IsParallel @@ -25,14 +23,15 @@ mutable struct T8codeMesh{NDIMS, RealT <: Real, IsParallel, NDIMSP2, NNODES} <: nmortars :: Int nboundaries :: Int - function T8codeMesh{NDIMS}(cmesh, scheme, forest, tree_node_coordinates, nodes, + nmpiinterfaces :: Int + nmpimortars :: Int + + function T8codeMesh{NDIMS}(forest, tree_node_coordinates, nodes, boundary_names, current_filename) where {NDIMS} - is_parallel = False() + is_parallel = mpi_isparallel() ? True() : False() - mesh = new{NDIMS, Float64, typeof(is_parallel), NDIMS + 2, length(nodes)}(cmesh, - scheme, - forest, + mesh = new{NDIMS, Float64, typeof(is_parallel), NDIMS + 2, length(nodes)}(forest, is_parallel) mesh.nodes = nodes @@ -52,7 +51,7 @@ mutable struct T8codeMesh{NDIMS, RealT <: Real, IsParallel, NDIMSP2, NNODES} <: # further down. However, this might cause a pile-up of `mesh` # objects during long-running sessions. if !MPI.Finalized() - trixi_t8_unref_forest(mesh.forest) + t8_forest_unref(Ref(mesh.forest)) end end @@ -63,7 +62,7 @@ mutable struct T8codeMesh{NDIMS, RealT <: Real, IsParallel, NDIMSP2, NNODES} <: # more information. if haskey(ENV, "TRIXI_T8CODE_SC_FINALIZE") MPI.add_finalize_hook!() do - trixi_t8_unref_forest(mesh.forest) + t8_forest_unref(Ref(mesh.forest)) end end @@ -72,16 +71,15 @@ mutable struct T8codeMesh{NDIMS, RealT <: Real, IsParallel, NDIMSP2, NNODES} <: end const SerialT8codeMesh{NDIMS} = T8codeMesh{NDIMS, <:Real, <:False} +const ParallelT8codeMesh{NDIMS} = T8codeMesh{NDIMS, <:Real, <:True} @inline mpi_parallel(mesh::SerialT8codeMesh) = False() +@inline mpi_parallel(mesh::ParallelT8codeMesh) = True() @inline Base.ndims(::T8codeMesh{NDIMS}) where {NDIMS} = NDIMS @inline Base.real(::T8codeMesh{NDIMS, RealT}) where {NDIMS, RealT} = RealT -@inline ntrees(mesh::T8codeMesh) = Int(t8_forest_get_num_local_trees(mesh.forest)) +@inline ntrees(mesh::T8codeMesh) = size(mesh.tree_node_coordinates)[end] @inline ncells(mesh::T8codeMesh) = Int(t8_forest_get_local_num_elements(mesh.forest)) -@inline ninterfaces(mesh::T8codeMesh) = mesh.ninterfaces -@inline nmortars(mesh::T8codeMesh) = mesh.nmortars -@inline nboundaries(mesh::T8codeMesh) = mesh.nboundaries function Base.show(io::IO, mesh::T8codeMesh) print(io, "T8codeMesh{", ndims(mesh), ", ", real(mesh), "}") @@ -184,21 +182,23 @@ function T8codeMesh(trees_per_dimension; polydeg = 1, T8code.Libt8.p8est_connectivity_destroy(conn) end + do_face_ghost = mpi_isparallel() scheme = t8_scheme_new_default_cxx() - forest = t8_forest_new_uniform(cmesh, scheme, initial_refinement_level, 0, mpi_comm()) + forest = t8_forest_new_uniform(cmesh, scheme, initial_refinement_level, do_face_ghost, + mpi_comm()) basis = LobattoLegendreBasis(RealT, polydeg) nodes = basis.nodes + num_trees = t8_cmesh_get_num_trees(cmesh) + tree_node_coordinates = Array{RealT, NDIMS + 2}(undef, NDIMS, ntuple(_ -> length(nodes), NDIMS)..., - prod(trees_per_dimension)) + num_trees) # Get cell length in reference mesh: Omega_ref = [-1,1]^NDIMS. dx = [2 / n for n in trees_per_dimension] - num_local_trees = t8_cmesh_get_num_local_trees(cmesh) - # Non-periodic boundaries. boundary_names = fill(Symbol("---"), 2 * NDIMS, prod(trees_per_dimension)) @@ -208,7 +208,7 @@ function T8codeMesh(trees_per_dimension; polydeg = 1, mapping_ = mapping end - for itree in 1:num_local_trees + for itree in 1:num_trees veptr = t8_cmesh_get_tree_vertices(cmesh, itree - 1) verts = unsafe_wrap(Array, veptr, (3, 1 << NDIMS)) @@ -256,7 +256,7 @@ function T8codeMesh(trees_per_dimension; polydeg = 1, end end - return T8codeMesh{NDIMS}(cmesh, scheme, forest, tree_node_coordinates, nodes, + return T8codeMesh{NDIMS}(forest, tree_node_coordinates, nodes, boundary_names, "") end @@ -290,21 +290,25 @@ function T8codeMesh(cmesh::Ptr{t8_cmesh}; @assert (NDIMS == 2||NDIMS == 3) "NDIMS should be 2 or 3." + do_face_ghost = mpi_isparallel() scheme = t8_scheme_new_default_cxx() - forest = t8_forest_new_uniform(cmesh, scheme, initial_refinement_level, 0, mpi_comm()) + forest = t8_forest_new_uniform(cmesh, scheme, initial_refinement_level, do_face_ghost, + mpi_comm()) basis = LobattoLegendreBasis(RealT, polydeg) nodes = basis.nodes - num_local_trees = t8_cmesh_get_num_local_trees(cmesh) + num_trees = t8_cmesh_get_num_trees(cmesh) tree_node_coordinates = Array{RealT, NDIMS + 2}(undef, NDIMS, ntuple(_ -> length(nodes), NDIMS)..., - num_local_trees) + num_trees) nodes_in = [-1.0, 1.0] matrix = polynomial_interpolation_matrix(nodes_in, nodes) + num_local_trees = t8_cmesh_get_num_local_trees(cmesh) + if NDIMS == 2 data_in = Array{RealT, 3}(undef, 2, 2, 2) tmp1 = zeros(RealT, 2, length(nodes), length(nodes_in)) @@ -353,7 +357,7 @@ function T8codeMesh(cmesh::Ptr{t8_cmesh}; tmp1 = zeros(RealT, 3, length(nodes), length(nodes_in), length(nodes_in)) verts = zeros(3, 8) - for itree in 0:(num_local_trees - 1) + for itree in 0:(num_trees - 1) veptr = t8_cmesh_get_tree_vertices(cmesh, itree) # Note, `verts = unsafe_wrap(Array, veptr, (3, 1 << NDIMS))` @@ -387,9 +391,9 @@ function T8codeMesh(cmesh::Ptr{t8_cmesh}; map_node_coordinates!(tree_node_coordinates, mapping) # There's no simple and generic way to distinguish boundaries. Name all of them :all. - boundary_names = fill(:all, 2 * NDIMS, num_local_trees) + boundary_names = fill(:all, 2 * NDIMS, num_trees) - return T8codeMesh{NDIMS}(cmesh, scheme, forest, tree_node_coordinates, nodes, + return T8codeMesh{NDIMS}(forest, tree_node_coordinates, nodes, boundary_names, "") end @@ -442,7 +446,7 @@ function T8codeMesh(conn::Ptr{p8est_connectivity}; kwargs...) end """ - T8codeMesh{NDIMS}(meshfile::String; kwargs...) + T8codeMesh(meshfile::String, ndims; kwargs...) Main mesh constructor for the `T8codeMesh` that imports an unstructured, conforming mesh from a Gmsh mesh file (`.msh`). @@ -461,7 +465,6 @@ mesh from a Gmsh mesh file (`.msh`). - `initial_refinement_level::Integer`: refine the mesh uniformly to this level before the simulation starts. """ function T8codeMesh(meshfile::String, ndims; kwargs...) - # Prevent `t8code` from crashing Julia if the file doesn't exist. @assert isfile(meshfile) @@ -482,7 +485,7 @@ end # form a family and we decide whether this family should be coarsened # or only the first element should be refined. # Otherwise `is_family` must equal zero and we consider the first entry -# of the element array for refinement. +# of the element array for refinement. # Entries of the element array beyond the first `num_elements` are undefined. # \param [in] forest the forest to which the new elements belong # \param [in] forest_from the forest that is adapted. @@ -539,8 +542,8 @@ Adapt a `T8codeMesh` according to a user-defined `adapt_callback`. 0 : Stay unchanged. 1 : Refine element. -- `kwargs`: - - `recursive = true`: Adapt the forest recursively. If true the caller must ensure that the callback +- `kwargs`: + - `recursive = true`: Adapt the forest recursively. If true the caller must ensure that the callback returns 0 for every analyzed element at some point to stop the recursion. - `balance = true`: Make sure the adapted forest is 2^(NDIMS-1):1 balanced. - `partition = true`: Partition the forest to redistribute elements evenly among MPI ranks. @@ -586,13 +589,525 @@ function adapt!(mesh::T8codeMesh, adapt_callback; recursive = true, balance = tr return nothing end -# TODO: Just a placeholder. Will be implemented later when MPI is supported. -function balance!(mesh::T8codeMesh, init_fn = C_NULL) +""" + Trixi.balance!(mesh::T8codeMesh) + +Balance a `T8codeMesh` to ensure 2^(NDIMS-1):1 face neighbors. +""" +function balance!(mesh::T8codeMesh) + new_forest_ref = Ref{t8_forest_t}() + t8_forest_init(new_forest_ref) + new_forest = new_forest_ref[] + + let set_from = mesh.forest, no_repartition = 1, do_ghost = 1 + t8_forest_set_balance(new_forest, set_from, no_repartition) + t8_forest_set_ghost(new_forest, do_ghost, T8_GHOST_FACES) + t8_forest_commit(new_forest) + end + + mesh.forest = new_forest + + return nothing +end + +""" + Trixi.partition!(mesh::T8codeMesh) + +Partition a `T8codeMesh` in order to redistribute elements evenly among MPI ranks. + +# Arguments +- `mesh::T8codeMesh`: Initialized mesh object. +""" +function partition!(mesh::T8codeMesh) + new_forest_ref = Ref{t8_forest_t}() + t8_forest_init(new_forest_ref) + new_forest = new_forest_ref[] + + let set_from = mesh.forest, do_ghost = 1, allow_for_coarsening = 1 + t8_forest_set_partition(new_forest, set_from, allow_for_coarsening) + t8_forest_set_ghost(new_forest, do_ghost, T8_GHOST_FACES) + t8_forest_commit(new_forest) + end + + mesh.forest = new_forest + return nothing end -# TODO: Just a placeholder. Will be implemented later when MPI is supported. -function partition!(mesh::T8codeMesh; allow_coarsening = true, weight_fn = C_NULL) +# Compute the global ids (zero-indexed) of first element in each MPI rank. +function get_global_first_element_ids(mesh::T8codeMesh) + n_elements_local = Int(t8_forest_get_local_num_elements(mesh.forest)) + n_elements_by_rank = Vector{Int}(undef, mpi_nranks()) + n_elements_by_rank[mpi_rank() + 1] = n_elements_local + MPI.Allgather!(MPI.UBuffer(n_elements_by_rank, 1), mpi_comm()) + return [sum(n_elements_by_rank[1:(rank - 1)]) for rank in 1:(mpi_nranks() + 1)] +end + +function count_interfaces(mesh::T8codeMesh) + @assert t8_forest_is_committed(mesh.forest) != 0 + + num_local_elements = t8_forest_get_local_num_elements(mesh.forest) + num_local_trees = t8_forest_get_num_local_trees(mesh.forest) + + current_index = t8_locidx_t(0) + + local_num_conform = 0 + local_num_mortars = 0 + local_num_boundary = 0 + + local_num_mpi_conform = 0 + local_num_mpi_mortars = 0 + + visited_global_mortar_ids = Set{UInt64}([]) + + max_level = t8_forest_get_maxlevel(mesh.forest) #UInt64 + max_tree_num_elements = UInt64(2^ndims(mesh))^max_level + + if mpi_isparallel() + ghost_num_trees = t8_forest_ghost_num_trees(mesh.forest) + + ghost_tree_element_offsets = [num_local_elements + + t8_forest_ghost_get_tree_element_offset(mesh.forest, + itree) + for itree in 0:(ghost_num_trees - 1)] + ghost_global_treeids = [t8_forest_ghost_get_global_treeid(mesh.forest, itree) + for itree in 0:(ghost_num_trees - 1)] + end + + for itree in 0:(num_local_trees - 1) + tree_class = t8_forest_get_tree_class(mesh.forest, itree) + eclass_scheme = t8_forest_get_eclass_scheme(mesh.forest, tree_class) + + num_elements_in_tree = t8_forest_get_tree_num_elements(mesh.forest, itree) + + global_itree = t8_forest_global_tree_id(mesh.forest, itree) + + for ielement in 0:(num_elements_in_tree - 1) + element = t8_forest_get_element_in_tree(mesh.forest, itree, ielement) + + level = t8_element_level(eclass_scheme, element) + + num_faces = t8_element_num_faces(eclass_scheme, element) + + # Note: This works only for forests of one element class. + current_linear_id = global_itree * max_tree_num_elements + + t8_element_get_linear_id(eclass_scheme, element, max_level) + + for iface in 0:(num_faces - 1) + pelement_indices_ref = Ref{Ptr{t8_locidx_t}}() + pneighbor_leaves_ref = Ref{Ptr{Ptr{t8_element}}}() + pneigh_scheme_ref = Ref{Ptr{t8_eclass_scheme}}() + + dual_faces_ref = Ref{Ptr{Cint}}() + num_neighbors_ref = Ref{Cint}() + + forest_is_balanced = Cint(1) + + t8_forest_leaf_face_neighbors(mesh.forest, itree, element, + pneighbor_leaves_ref, iface, dual_faces_ref, + num_neighbors_ref, + pelement_indices_ref, pneigh_scheme_ref, + forest_is_balanced) + + num_neighbors = num_neighbors_ref[] + dual_faces = unsafe_wrap(Array, dual_faces_ref[], num_neighbors) + neighbor_ielements = unsafe_wrap(Array, pelement_indices_ref[], + num_neighbors) + neighbor_leaves = unsafe_wrap(Array, pneighbor_leaves_ref[], num_neighbors) + neighbor_scheme = pneigh_scheme_ref[] + + if num_neighbors == 0 + local_num_boundary += 1 + else + neighbor_level = t8_element_level(neighbor_scheme, neighbor_leaves[1]) + + if all(neighbor_ielements .< num_local_elements) + # Conforming interface: The second condition ensures we + # only visit the interface once. + if level == neighbor_level && current_index <= neighbor_ielements[1] + local_num_conform += 1 + elseif level < neighbor_level + local_num_mortars += 1 + # `else level > neighbor_level` is ignored since we + # only want to count the mortar interface once. + end + else + if level == neighbor_level + local_num_mpi_conform += 1 + elseif level < neighbor_level + local_num_mpi_mortars += 1 + + global_mortar_id = 2 * ndims(mesh) * current_linear_id + iface + + else # level > neighbor_level + neighbor_global_ghost_itree = ghost_global_treeids[findlast(ghost_tree_element_offsets .<= + neighbor_ielements[1])] + neighbor_linear_id = neighbor_global_ghost_itree * + max_tree_num_elements + + t8_element_get_linear_id(neighbor_scheme, + neighbor_leaves[1], + max_level) + global_mortar_id = 2 * ndims(mesh) * neighbor_linear_id + + dual_faces[1] + + if !(global_mortar_id in visited_global_mortar_ids) + push!(visited_global_mortar_ids, global_mortar_id) + local_num_mpi_mortars += 1 + end + end + end + end + + t8_free(dual_faces_ref[]) + t8_free(pneighbor_leaves_ref[]) + t8_free(pelement_indices_ref[]) + end # for + + current_index += 1 + end # for + end # for + + return (interfaces = local_num_conform, + mortars = local_num_mortars, + boundaries = local_num_boundary, + mpi_interfaces = local_num_mpi_conform, + mpi_mortars = local_num_mpi_mortars) +end + +# I know this routine is an unmaintainable behemoth. However, I see no real +# and elegant way to refactor this into, for example, smaller parts. The +# `t8_forest_leaf_face_neighbors` routine is as of now rather costly and it +# makes sense to query it only once per face per element and extract all the +# information needed at once in order to fill the connectivity information. +# Instead, I opted for good documentation. +function fill_mesh_info!(mesh::T8codeMesh, interfaces, mortars, boundaries, + boundary_names; mpi_mesh_info = nothing) + @assert t8_forest_is_committed(mesh.forest) != 0 + + num_local_elements = t8_forest_get_local_num_elements(mesh.forest) + num_local_trees = t8_forest_get_num_local_trees(mesh.forest) + + if !isnothing(mpi_mesh_info) + #! format: off + remotes = t8_forest_ghost_get_remotes(mesh.forest) + ghost_num_trees = t8_forest_ghost_num_trees(mesh.forest) + + ghost_remote_first_elem = [num_local_elements + + t8_forest_ghost_remote_first_elem(mesh.forest, remote) + for remote in remotes] + + ghost_tree_element_offsets = [num_local_elements + + t8_forest_ghost_get_tree_element_offset(mesh.forest, itree) + for itree in 0:(ghost_num_trees - 1)] + + ghost_global_treeids = [t8_forest_ghost_get_global_treeid(mesh.forest, itree) + for itree in 0:(ghost_num_trees - 1)] + #! format: on + end + + # Process-local index of the current element in the space-filling curve. + current_index = t8_locidx_t(0) + + # Increment counters for the different interface/mortar/boundary types. + local_num_conform = 0 + local_num_mortars = 0 + local_num_boundary = 0 + + local_num_mpi_conform = 0 + local_num_mpi_mortars = 0 + + # Works for quads and hexs only. This mapping is needed in the MPI mortar + # sections below. + map_iface_to_ichild_to_position = [ + # 0 1 2 3 4 5 6 7 ichild/iface + [1, 0, 2, 0, 3, 0, 4, 0], # 0 + [0, 1, 0, 2, 0, 3, 0, 4], # 1 + [1, 2, 0, 0, 3, 4, 0, 0], # 2 + [0, 0, 1, 2, 0, 0, 3, 4], # 3 + [1, 2, 3, 4, 0, 0, 0, 0], # 4 + [0, 0, 0, 0, 1, 2, 3, 4], # 5 + ] + + # Helper variables to compute unique global MPI interface/mortar ids. + max_level = t8_forest_get_maxlevel(mesh.forest) #UInt64 + max_tree_num_elements = UInt64(2^ndims(mesh))^max_level + + # These two variables help to ensure that we count MPI mortars from smaller + # elements point of view only once. + visited_global_mortar_ids = Set{UInt64}([]) + global_mortar_id_to_local = Dict{UInt64, Int}([]) + + # Loop over all local trees. + for itree in 0:(num_local_trees - 1) + tree_class = t8_forest_get_tree_class(mesh.forest, itree) + eclass_scheme = t8_forest_get_eclass_scheme(mesh.forest, tree_class) + + num_elements_in_tree = t8_forest_get_tree_num_elements(mesh.forest, itree) + + global_itree = t8_forest_global_tree_id(mesh.forest, itree) + + # Loop over all local elements of the current local tree. + for ielement in 0:(num_elements_in_tree - 1) + element = t8_forest_get_element_in_tree(mesh.forest, itree, ielement) + + level = t8_element_level(eclass_scheme, element) + + num_faces = t8_element_num_faces(eclass_scheme, element) + + # Note: This works only for forests of one element class. + current_linear_id = global_itree * max_tree_num_elements + + t8_element_get_linear_id(eclass_scheme, element, max_level) + + # Loop over all faces of the current local element. + for iface in 0:(num_faces - 1) + # Compute the `orientation` of the touching faces. + if t8_element_is_root_boundary(eclass_scheme, element, iface) == 1 + cmesh = t8_forest_get_cmesh(mesh.forest) + itree_in_cmesh = t8_forest_ltreeid_to_cmesh_ltreeid(mesh.forest, itree) + iface_in_tree = t8_element_tree_face(eclass_scheme, element, iface) + orientation_ref = Ref{Cint}() + + t8_cmesh_get_face_neighbor(cmesh, itree_in_cmesh, iface_in_tree, C_NULL, + orientation_ref) + orientation = orientation_ref[] + else + orientation = zero(Cint) + end + + pelement_indices_ref = Ref{Ptr{t8_locidx_t}}() + pneighbor_leaves_ref = Ref{Ptr{Ptr{t8_element}}}() + pneigh_scheme_ref = Ref{Ptr{t8_eclass_scheme}}() + + dual_faces_ref = Ref{Ptr{Cint}}() + num_neighbors_ref = Ref{Cint}() + + forest_is_balanced = Cint(1) + + # Query neighbor information from t8code. + t8_forest_leaf_face_neighbors(mesh.forest, itree, element, + pneighbor_leaves_ref, iface, dual_faces_ref, + num_neighbors_ref, + pelement_indices_ref, pneigh_scheme_ref, + forest_is_balanced) + + num_neighbors = num_neighbors_ref[] + dual_faces = unsafe_wrap(Array, dual_faces_ref[], num_neighbors) + neighbor_ielements = unsafe_wrap(Array, pelement_indices_ref[], + num_neighbors) + neighbor_leaves = unsafe_wrap(Array, pneighbor_leaves_ref[], num_neighbors) + neighbor_scheme = pneigh_scheme_ref[] + + # Now we check for the different cases. The nested if-structure is as follows: + # + # if `boundary`: + # + # + # else: // It must be an interface or mortar. + # + # if `all neighbors are local elements`: + # + # if `local interface`: + # + # elseif `local mortar from larger element point of view`: + # + # else: // `local mortar from smaller elements point of view` + # // We only count local mortars once. + # + # else: // It must be either a MPI interface or a MPI mortar. + # + # if `MPI interface`: + # + # elseif `MPI mortar from larger element point of view`: + # + # else: // `MPI mortar from smaller elements point of view` + # + # + # // end + + # Domain boundary. + if num_neighbors == 0 + local_num_boundary += 1 + boundary_id = local_num_boundary + + boundaries.neighbor_ids[boundary_id] = current_index + 1 + + init_boundary_node_indices!(boundaries, iface, boundary_id) + + # One-based indexing. + boundaries.name[boundary_id] = boundary_names[iface + 1, itree + 1] + + # Interface or mortar. + else + neighbor_level = t8_element_level(neighbor_scheme, neighbor_leaves[1]) + + # Local interface or mortar. + if all(neighbor_ielements .< num_local_elements) + + # Local interface: The second condition ensures we only visit the interface once. + if level == neighbor_level && current_index <= neighbor_ielements[1] + local_num_conform += 1 + + interfaces.neighbor_ids[1, local_num_conform] = current_index + + 1 + interfaces.neighbor_ids[2, local_num_conform] = neighbor_ielements[1] + + 1 + + init_interface_node_indices!(interfaces, (iface, dual_faces[1]), + orientation, + local_num_conform) + # Local mortar. + elseif level < neighbor_level + local_num_mortars += 1 + + # Last entry is the large element. + mortars.neighbor_ids[end, local_num_mortars] = current_index + 1 + + init_mortar_neighbor_ids!(mortars, iface, dual_faces[1], + orientation, neighbor_ielements, + local_num_mortars) + + init_mortar_node_indices!(mortars, (dual_faces[1], iface), + orientation, local_num_mortars) + + # else: `level > neighbor_level` is skipped since we visit the mortar interface only once. + end + + # MPI interface or MPI mortar. + else + + # MPI interface. + if level == neighbor_level + local_num_mpi_conform += 1 + + neighbor_global_ghost_itree = ghost_global_treeids[findlast(ghost_tree_element_offsets .<= + neighbor_ielements[1])] + + neighbor_linear_id = neighbor_global_ghost_itree * + max_tree_num_elements + + t8_element_get_linear_id(neighbor_scheme, + neighbor_leaves[1], + max_level) + + if current_linear_id < neighbor_linear_id + local_side = 1 + smaller_iface = iface + smaller_linear_id = current_linear_id + faces = (iface, dual_faces[1]) + else + local_side = 2 + smaller_iface = dual_faces[1] + smaller_linear_id = neighbor_linear_id + faces = (dual_faces[1], iface) + end + + global_interface_id = 2 * ndims(mesh) * smaller_linear_id + + smaller_iface + + mpi_mesh_info.mpi_interfaces.local_neighbor_ids[local_num_mpi_conform] = current_index + + 1 + mpi_mesh_info.mpi_interfaces.local_sides[local_num_mpi_conform] = local_side + + init_mpi_interface_node_indices!(mpi_mesh_info.mpi_interfaces, + faces, local_side, orientation, + local_num_mpi_conform) + + neighbor_rank = remotes[findlast(ghost_remote_first_elem .<= + neighbor_ielements[1])] + mpi_mesh_info.neighbor_ranks_interface[local_num_mpi_conform] = neighbor_rank + + mpi_mesh_info.global_interface_ids[local_num_mpi_conform] = global_interface_id + + # MPI Mortar: from larger element point of view + elseif level < neighbor_level + local_num_mpi_mortars += 1 + + global_mortar_id = 2 * ndims(mesh) * current_linear_id + iface + + neighbor_ids = neighbor_ielements .+ 1 + + local_neighbor_positions = findall(neighbor_ids .<= + num_local_elements) + local_neighbor_ids = [neighbor_ids[i] + for i in local_neighbor_positions] + local_neighbor_positions = [map_iface_to_ichild_to_position[dual_faces[1] + 1][t8_element_child_id(neighbor_scheme, neighbor_leaves[i]) + 1] + for i in local_neighbor_positions] + + # Last entry is the large element. + push!(local_neighbor_ids, current_index + 1) + push!(local_neighbor_positions, 2^(ndims(mesh) - 1) + 1) + + mpi_mesh_info.mpi_mortars.local_neighbor_ids[local_num_mpi_mortars] = local_neighbor_ids + mpi_mesh_info.mpi_mortars.local_neighbor_positions[local_num_mpi_mortars] = local_neighbor_positions + + init_mortar_node_indices!(mpi_mesh_info.mpi_mortars, + (dual_faces[1], iface), orientation, + local_num_mpi_mortars) + + neighbor_ranks = [remotes[findlast(ghost_remote_first_elem .<= + ineighbor_ghost)] + for ineighbor_ghost in filter(x -> x >= + num_local_elements, + neighbor_ielements)] + mpi_mesh_info.neighbor_ranks_mortar[local_num_mpi_mortars] = neighbor_ranks + + mpi_mesh_info.global_mortar_ids[local_num_mpi_mortars] = global_mortar_id + + # MPI Mortar: from smaller elements point of view + else + neighbor_global_ghost_itree = ghost_global_treeids[findlast(ghost_tree_element_offsets .<= + neighbor_ielements[1])] + neighbor_linear_id = neighbor_global_ghost_itree * + max_tree_num_elements + + t8_element_get_linear_id(neighbor_scheme, + neighbor_leaves[1], + max_level) + global_mortar_id = 2 * ndims(mesh) * neighbor_linear_id + + dual_faces[1] + + if global_mortar_id in visited_global_mortar_ids + local_mpi_mortar_id = global_mortar_id_to_local[global_mortar_id] + + push!(mpi_mesh_info.mpi_mortars.local_neighbor_ids[local_mpi_mortar_id], + current_index + 1) + push!(mpi_mesh_info.mpi_mortars.local_neighbor_positions[local_mpi_mortar_id], + map_iface_to_ichild_to_position[iface + 1][t8_element_child_id(eclass_scheme, element) + 1]) + else + local_num_mpi_mortars += 1 + local_mpi_mortar_id = local_num_mpi_mortars + push!(visited_global_mortar_ids, global_mortar_id) + global_mortar_id_to_local[global_mortar_id] = local_mpi_mortar_id + + mpi_mesh_info.mpi_mortars.local_neighbor_ids[local_mpi_mortar_id] = [ + current_index + 1, + ] + mpi_mesh_info.mpi_mortars.local_neighbor_positions[local_mpi_mortar_id] = [ + map_iface_to_ichild_to_position[iface + 1][t8_element_child_id(eclass_scheme, element) + 1], + ] + init_mortar_node_indices!(mpi_mesh_info.mpi_mortars, + (iface, dual_faces[1]), + orientation, local_mpi_mortar_id) + + neighbor_ranks = [ + remotes[findlast(ghost_remote_first_elem .<= + neighbor_ielements[1])], + ] + mpi_mesh_info.neighbor_ranks_mortar[local_mpi_mortar_id] = neighbor_ranks + + mpi_mesh_info.global_mortar_ids[local_mpi_mortar_id] = global_mortar_id + end + end + end + end + + t8_free(dual_faces_ref[]) + t8_free(pneighbor_leaves_ref[]) + t8_free(pelement_indices_ref[]) + end # for iface + + current_index += 1 + end # for ielement + end # for itree + return nothing end diff --git a/src/semidiscretization/semidiscretization_coupled.jl b/src/semidiscretization/semidiscretization_coupled.jl index 0941ae6a8c..dc21dbe9a1 100644 --- a/src/semidiscretization/semidiscretization_coupled.jl +++ b/src/semidiscretization/semidiscretization_coupled.jl @@ -1,3 +1,10 @@ +# 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 + """ SemidiscretizationCoupled @@ -65,11 +72,13 @@ function Base.show(io::IO, ::MIME"text/plain", semi::SemidiscretizationCoupled) summary_line(io, "system", i) mesh, equations, solver, _ = mesh_equations_solver_cache(semi.semis[i]) summary_line(increment_indent(io), "mesh", mesh |> typeof |> nameof) - summary_line(increment_indent(io), "equations", equations |> typeof |> nameof) + summary_line(increment_indent(io), "equations", + equations |> typeof |> nameof) summary_line(increment_indent(io), "initial condition", semi.semis[i].initial_condition) # no boundary conditions since that could be too much - summary_line(increment_indent(io), "source terms", semi.semis[i].source_terms) + summary_line(increment_indent(io), "source terms", + semi.semis[i].source_terms) summary_line(increment_indent(io), "solver", solver |> typeof |> nameof) end summary_line(io, "total #DOFs per field", ndofs(semi)) @@ -106,20 +115,14 @@ end @inline Base.real(semi::SemidiscretizationCoupled) = promote_type(real.(semi.semis)...) -@inline Base.eltype(semi::SemidiscretizationCoupled) = promote_type(eltype.(semi.semis)...) +@inline function Base.eltype(semi::SemidiscretizationCoupled) + promote_type(eltype.(semi.semis)...) +end @inline function ndofs(semi::SemidiscretizationCoupled) sum(ndofs, semi.semis) end -@inline function nelements(semi::SemidiscretizationCoupled) - return sum(semi.semis) do semi_ - mesh, equations, solver, cache = mesh_equations_solver_cache(semi_) - - nelements(mesh, solver, cache) - end -end - function compute_coefficients(t, semi::SemidiscretizationCoupled) @unpack u_indices = semi @@ -137,23 +140,40 @@ end @view u_ode[semi.u_indices[index]] end +# Same as `foreach(enumerate(something))`, but without allocations. +# +# Note that compile times may increase if this is used with big tuples. +@inline foreach_enumerate(func, collection) = foreach_enumerate(func, collection, 1) +@inline foreach_enumerate(func, collection::Tuple{}, index) = nothing + +@inline function foreach_enumerate(func, collection, index) + element = first(collection) + remaining_collection = Base.tail(collection) + + func((index, element)) + + # Process remaining collection + foreach_enumerate(func, remaining_collection, index + 1) +end + function rhs!(du_ode, u_ode, semi::SemidiscretizationCoupled, t) @unpack u_indices = semi time_start = time_ns() @trixi_timeit timer() "copy to coupled boundaries" begin - for semi_ in semi.semis - copy_to_coupled_boundary!(semi_.boundary_conditions, u_ode, semi) + foreach(semi.semis) do semi_ + copy_to_coupled_boundary!(semi_.boundary_conditions, u_ode, semi, semi_) end end # Call rhs! for each semidiscretization - for i in eachsystem(semi) - u_loc = get_system_u_ode(u_ode, i, semi) - du_loc = get_system_u_ode(du_ode, i, semi) - - @trixi_timeit timer() "system #$i" rhs!(du_loc, u_loc, semi.semis[i], t) + @trixi_timeit timer() "copy to coupled boundaries" begin + foreach_enumerate(semi.semis) do (i, semi_) + u_loc = get_system_u_ode(u_ode, i, semi) + du_loc = get_system_u_ode(du_ode, i, semi) + rhs!(du_loc, u_loc, semi_, t) + end end runtime = time_ns() - time_start @@ -309,7 +329,8 @@ end for i in eachsystem(semi) u_ode_slice = get_system_u_ode(u_ode, i, semi) - save_solution_file(semis[i], u_ode_slice, solution_callback, integrator, system = i) + save_solution_file(semis[i], u_ode_slice, solution_callback, integrator, + system = i) end end @@ -332,7 +353,7 @@ end ################################################################################ """ - BoundaryConditionCoupled(other_semi_index, indices, uEltype) + BoundaryConditionCoupled(other_semi_index, indices, uEltype, coupling_converter) Boundary condition to glue two meshes together. Solution values at the boundary of another mesh will be used as boundary values. This requires the use @@ -348,32 +369,37 @@ This is currently only implemented for [`StructuredMesh`](@ref). - `indices::Tuple`: node/cell indices at the boundary of the mesh in the other semidiscretization. See examples below. - `uEltype::Type`: element type of solution +- `coupling_converter::CouplingConverter`: function to call for converting the solution + state of one system to the other system # Examples ```julia # Connect the left boundary of mesh 2 to our boundary such that our positive # boundary direction will match the positive y direction of the other boundary -BoundaryConditionCoupled(2, (:begin, :i), Float64) +BoundaryConditionCoupled(2, (:begin, :i), Float64, fun) # Connect the same two boundaries oppositely oriented -BoundaryConditionCoupled(2, (:begin, :i_backwards), Float64) +BoundaryConditionCoupled(2, (:begin, :i_backwards), Float64, fun) # Using this as y_neg boundary will connect `our_cells[i, 1, j]` to `other_cells[j, end-i, end]` -BoundaryConditionCoupled(2, (:j, :i_backwards, :end), Float64) +BoundaryConditionCoupled(2, (:j, :i_backwards, :end), Float64, fun) ``` !!! warning "Experimental code" This is an experimental feature and can change any time. """ -mutable struct BoundaryConditionCoupled{NDIMS, NDIMST2M1, uEltype <: Real, Indices} +mutable struct BoundaryConditionCoupled{NDIMS, NDIMST2M1, uEltype <: Real, Indices, + CouplingConverter} # NDIMST2M1 == NDIMS * 2 - 1 # Buffer for boundary values: [variable, nodes_i, nodes_j, cell_i, cell_j] - u_boundary :: Array{uEltype, NDIMST2M1} # NDIMS * 2 - 1 - other_semi_index :: Int - other_orientation :: Int - indices :: Indices - - function BoundaryConditionCoupled(other_semi_index, indices, uEltype) + u_boundary :: Array{uEltype, NDIMST2M1} # NDIMS * 2 - 1 + other_semi_index :: Int + other_orientation :: Int + indices :: Indices + coupling_converter :: CouplingConverter + + function BoundaryConditionCoupled(other_semi_index, indices, uEltype, + coupling_converter) NDIMS = length(indices) u_boundary = Array{uEltype, NDIMS * 2 - 1}(undef, ntuple(_ -> 0, NDIMS * 2 - 1)) @@ -385,8 +411,10 @@ mutable struct BoundaryConditionCoupled{NDIMS, NDIMST2M1, uEltype <: Real, Indic other_orientation = 3 end - new{NDIMS, NDIMS * 2 - 1, uEltype, typeof(indices)}(u_boundary, other_semi_index, - other_orientation, indices) + new{NDIMS, NDIMS * 2 - 1, uEltype, typeof(indices), + typeof(coupling_converter)}(u_boundary, + other_semi_index, other_orientation, + indices, coupling_converter) end end @@ -395,8 +423,10 @@ function Base.eltype(boundary_condition::BoundaryConditionCoupled) end function (boundary_condition::BoundaryConditionCoupled)(u_inner, orientation, direction, - cell_indices, surface_node_indices, - surface_flux_function, equations) + cell_indices, + surface_node_indices, + surface_flux_function, + equations) # get_node_vars(boundary_condition.u_boundary, equations, solver, surface_node_indices..., cell_indices...), # but we don't have a solver here u_boundary = SVector(ntuple(v -> boundary_condition.u_boundary[v, @@ -421,13 +451,15 @@ function allocate_coupled_boundary_conditions(semi::AbstractSemidiscretization) for direction in 1:n_boundaries boundary_condition = semi.boundary_conditions[direction] - allocate_coupled_boundary_condition(boundary_condition, direction, mesh, equations, + allocate_coupled_boundary_condition(boundary_condition, direction, mesh, + equations, solver) end end # Don't do anything for other BCs than BoundaryConditionCoupled -function allocate_coupled_boundary_condition(boundary_condition, direction, mesh, equations, +function allocate_coupled_boundary_condition(boundary_condition, direction, mesh, + equations, solver) return nothing end @@ -448,43 +480,69 @@ function allocate_coupled_boundary_condition(boundary_condition::BoundaryConditi end # Don't do anything for other BCs than BoundaryConditionCoupled -function copy_to_coupled_boundary!(boundary_condition, u_ode, semi) +function copy_to_coupled_boundary!(boundary_condition, u_ode, semi_coupled, semi) return nothing end +function copy_to_coupled_boundary!(u_ode, semi_coupled, semi, i, n_boundaries, + boundary_condition, boundary_conditions...) + copy_to_coupled_boundary!(boundary_condition, u_ode, semi_coupled, semi) + if i < n_boundaries + copy_to_coupled_boundary!(u_ode, semi_coupled, semi, i + 1, n_boundaries, + boundary_conditions...) + end +end + function copy_to_coupled_boundary!(boundary_conditions::Union{Tuple, NamedTuple}, u_ode, - semi) - for boundary_condition in boundary_conditions - copy_to_coupled_boundary!(boundary_condition, u_ode, semi) + semi_coupled, semi) + copy_to_coupled_boundary!(u_ode, semi_coupled, semi, 1, length(boundary_conditions), + boundary_conditions...) +end + +function mesh_equations_solver_cache(other_semi_index, i, semi_, semi_tuple...) + if i == other_semi_index + return mesh_equations_solver_cache(semi_) + else + # Walk through semidiscretizations until we find `i` + mesh_equations_solver_cache(other_semi_index, i + 1, semi_tuple...) end end # In 2D -function copy_to_coupled_boundary!(boundary_condition::BoundaryConditionCoupled{2}, u_ode, - semi) - @unpack u_indices = semi +function copy_to_coupled_boundary!(boundary_condition::BoundaryConditionCoupled{2}, + u_ode, + semi_coupled, semi) + @unpack u_indices = semi_coupled @unpack other_semi_index, other_orientation, indices = boundary_condition + @unpack coupling_converter, u_boundary = boundary_condition + + mesh_own, equations_own, solver_own, cache_own = mesh_equations_solver_cache(semi) + + mesh_other, equations_other, solver_other, cache_other = mesh_equations_solver_cache(other_semi_index, + 1, + semi_coupled.semis...) - mesh, equations, solver, cache = mesh_equations_solver_cache(semi.semis[other_semi_index]) - u = wrap_array(get_system_u_ode(u_ode, other_semi_index, semi), mesh, equations, solver, - cache) + node_coordinates_other = cache_other.elements.node_coordinates + u_ode_other = get_system_u_ode(u_ode, other_semi_index, semi_coupled) + u_other = wrap_array(u_ode_other, mesh_other, equations_other, solver_other, + cache_other) - linear_indices = LinearIndices(size(mesh)) + linear_indices = LinearIndices(size(mesh_other)) if other_orientation == 1 - cells = axes(mesh, 2) + cells = axes(mesh_other, 2) else # other_orientation == 2 - cells = axes(mesh, 1) + cells = axes(mesh_other, 1) end # Copy solution data to the coupled boundary using "delayed indexing" with # a start value and a step size to get the correct face and orientation. - node_index_range = eachnode(solver) + node_index_range = eachnode(solver_other) i_node_start, i_node_step = index_to_start_step_2d(indices[1], node_index_range) j_node_start, j_node_step = index_to_start_step_2d(indices[2], node_index_range) - i_cell_start, i_cell_step = index_to_start_step_2d(indices[1], axes(mesh, 1)) - j_cell_start, j_cell_step = index_to_start_step_2d(indices[2], axes(mesh, 2)) + i_cell_start, i_cell_step = index_to_start_step_2d(indices[1], axes(mesh_other, 1)) + j_cell_start, j_cell_step = index_to_start_step_2d(indices[2], axes(mesh_other, 2)) i_cell = i_cell_start j_cell = j_cell_start @@ -492,16 +550,26 @@ function copy_to_coupled_boundary!(boundary_condition::BoundaryConditionCoupled{ for cell in cells i_node = i_node_start j_node = j_node_start - - for i in eachnode(solver) - for v in 1:size(u, 1) - boundary_condition.u_boundary[v, i, cell] = u[v, i_node, j_node, - linear_indices[i_cell, - j_cell]] + element_id = linear_indices[i_cell, j_cell] + + for element_id in eachnode(solver_other) + x_other = get_node_coords(node_coordinates_other, equations_other, + solver_other, + i_node, j_node, linear_indices[i_cell, j_cell]) + u_node_other = get_node_vars(u_other, equations_other, solver_other, i_node, + j_node, linear_indices[i_cell, j_cell]) + u_node_converted = coupling_converter(x_other, u_node_other, + equations_other, + equations_own) + + for i in eachindex(u_node_converted) + u_boundary[i, element_id, cell] = u_node_converted[i] end + i_node += i_node_step j_node += j_node_step end + i_cell += i_cell_step j_cell += j_cell_step end @@ -511,7 +579,8 @@ end ### DGSEM/structured ################################################################################ -@inline function calc_boundary_flux_by_direction!(surface_flux_values, u, t, orientation, +@inline function calc_boundary_flux_by_direction!(surface_flux_values, u, t, + orientation, boundary_condition::BoundaryConditionCoupled, mesh::StructuredMesh, equations, surface_integral, dg::DG, cache, @@ -531,7 +600,8 @@ end sign_jacobian = sign(inverse_jacobian[node_indices..., element]) # Contravariant vector Ja^i is the normal vector - normal = sign_jacobian * get_contravariant_vector(orientation, contravariant_vectors, + normal = sign_jacobian * + get_contravariant_vector(orientation, contravariant_vectors, node_indices..., element) # If the mapping is orientation-reversing, the normal vector will be reversed (see above). @@ -608,3 +678,4 @@ function analyze_convergence(errors_coupled, iterations, return eoc_mean_values end +end # @muladd diff --git a/src/solvers/dgsem_p4est/containers_parallel.jl b/src/solvers/dgsem_p4est/containers_parallel.jl index 7c7bd86845..fd2749155b 100644 --- a/src/solvers/dgsem_p4est/containers_parallel.jl +++ b/src/solvers/dgsem_p4est/containers_parallel.jl @@ -43,7 +43,8 @@ function Base.resize!(mpi_interfaces::P4estMPIInterfaceContainer, capacity) end # Create MPI interface container and initialize interface data -function init_mpi_interfaces(mesh::ParallelP4estMesh, equations, basis, elements) +function init_mpi_interfaces(mesh::Union{ParallelP4estMesh, ParallelT8codeMesh}, + equations, basis, elements) NDIMS = ndims(elements) uEltype = eltype(elements) @@ -133,7 +134,8 @@ function Base.resize!(mpi_mortars::P4estMPIMortarContainer, capacity) end # Create MPI mortar container and initialize MPI mortar data -function init_mpi_mortars(mesh::ParallelP4estMesh, equations, basis, elements) +function init_mpi_mortars(mesh::Union{ParallelP4estMesh, ParallelT8codeMesh}, equations, + basis, elements) NDIMS = ndims(mesh) RealT = real(mesh) uEltype = eltype(elements) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 299f2f6140..ed21f37144 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -1,7 +1,15 @@ +# 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 method is called when a SemidiscretizationHyperbolicParabolic is constructed. # It constructs the basic `cache` used throughout the simulation to compute # the RHS etc. -function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::AbstractEquations, +function create_cache_parabolic(mesh::P4estMesh{2}, + equations_hyperbolic::AbstractEquations, equations_parabolic::AbstractEquationsParabolic, dg::DG, parabolic_scheme, RealT, uEltype) balance!(mesh) @@ -167,12 +175,14 @@ function calc_gradient!(gradients, u_transformed, t, element) for ii in eachnode(dg) - multiply_add_to_node_vars!(gradients_x, derivative_dhat[ii, i], u_node, + multiply_add_to_node_vars!(gradients_x, derivative_dhat[ii, i], + u_node, equations_parabolic, dg, ii, j, element) end for jj in eachnode(dg) - multiply_add_to_node_vars!(gradients_y, derivative_dhat[jj, j], u_node, + multiply_add_to_node_vars!(gradients_y, derivative_dhat[jj, j], + u_node, equations_parabolic, dg, i, jj, element) end end @@ -185,9 +195,11 @@ function calc_gradient!(gradients, u_transformed, t, Ja21, Ja22 = get_contravariant_vector(2, contravariant_vectors, i, j, element) - gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, dg, + gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, + dg, i, j, element) - gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, dg, + gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, + dg, i, j, element) # note that the contravariant vectors are transposed compared with computations of flux @@ -199,9 +211,11 @@ function calc_gradient!(gradients, u_transformed, t, gradient_y_node = Ja12 * gradients_reference_1 + Ja22 * gradients_reference_2 - set_node_vars!(gradients_x, gradient_x_node, equations_parabolic, dg, i, j, + set_node_vars!(gradients_x, gradient_x_node, equations_parabolic, dg, i, + j, element) - set_node_vars!(gradients_y, gradient_y_node, equations_parabolic, dg, i, j, + set_node_vars!(gradients_y, gradient_y_node, equations_parabolic, dg, i, + j, element) end end @@ -219,7 +233,8 @@ function calc_gradient!(gradients, u_transformed, t, @trixi_timeit timer() "interface flux" begin calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, False(), # False() = no nonconservative terms - equations_parabolic, dg.surface_integral, dg, cache_parabolic) + equations_parabolic, dg.surface_integral, dg, + cache_parabolic) end # Prolong solution to boundaries @@ -231,7 +246,8 @@ function calc_gradient!(gradients, u_transformed, t, # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin calc_boundary_flux_gradients!(cache_parabolic, t, boundary_conditions_parabolic, - mesh, equations_parabolic, dg.surface_integral, dg) + mesh, equations_parabolic, dg.surface_integral, + dg) end # Prolong solution to mortars. This resues the hyperbolic version of `prolong2mortars` @@ -268,70 +284,94 @@ function calc_gradient!(gradients, u_transformed, t, # Compute x-component of gradients # surface at -x - normal_direction_x, _ = get_normal_direction(1, contravariant_vectors, + normal_direction_x, _ = get_normal_direction(1, + contravariant_vectors, 1, l, element) gradients_x[v, 1, l, element] = (gradients_x[v, 1, l, element] + - surface_flux_values[v, l, 1, element] * + surface_flux_values[v, l, 1, + element] * factor_1 * normal_direction_x) # surface at +x - normal_direction_x, _ = get_normal_direction(2, contravariant_vectors, + normal_direction_x, _ = get_normal_direction(2, + contravariant_vectors, nnodes(dg), l, element) - gradients_x[v, nnodes(dg), l, element] = (gradients_x[v, nnodes(dg), l, + gradients_x[v, nnodes(dg), l, element] = (gradients_x[v, nnodes(dg), + l, element] + - surface_flux_values[v, l, 2, + surface_flux_values[v, l, + 2, element] * - factor_2 * normal_direction_x) + factor_2 * + normal_direction_x) # surface at -y - normal_direction_x, _ = get_normal_direction(3, contravariant_vectors, + normal_direction_x, _ = get_normal_direction(3, + contravariant_vectors, l, 1, element) gradients_x[v, l, 1, element] = (gradients_x[v, l, 1, element] + - surface_flux_values[v, l, 3, element] * + surface_flux_values[v, l, 3, + element] * factor_1 * normal_direction_x) # surface at +y - normal_direction_x, _ = get_normal_direction(4, contravariant_vectors, + normal_direction_x, _ = get_normal_direction(4, + contravariant_vectors, l, nnodes(dg), element) - gradients_x[v, l, nnodes(dg), element] = (gradients_x[v, l, nnodes(dg), + gradients_x[v, l, nnodes(dg), element] = (gradients_x[v, l, + nnodes(dg), element] + - surface_flux_values[v, l, 4, + surface_flux_values[v, l, + 4, element] * - factor_2 * normal_direction_x) + factor_2 * + normal_direction_x) # Compute y-component of gradients # surface at -x - _, normal_direction_y = get_normal_direction(1, contravariant_vectors, + _, normal_direction_y = get_normal_direction(1, + contravariant_vectors, 1, l, element) gradients_y[v, 1, l, element] = (gradients_y[v, 1, l, element] + - surface_flux_values[v, l, 1, element] * + surface_flux_values[v, l, 1, + element] * factor_1 * normal_direction_y) # surface at +x - _, normal_direction_y = get_normal_direction(2, contravariant_vectors, + _, normal_direction_y = get_normal_direction(2, + contravariant_vectors, nnodes(dg), l, element) - gradients_y[v, nnodes(dg), l, element] = (gradients_y[v, nnodes(dg), l, + gradients_y[v, nnodes(dg), l, element] = (gradients_y[v, nnodes(dg), + l, element] + - surface_flux_values[v, l, 2, + surface_flux_values[v, l, + 2, element] * - factor_2 * normal_direction_y) + factor_2 * + normal_direction_y) # surface at -y - _, normal_direction_y = get_normal_direction(3, contravariant_vectors, + _, normal_direction_y = get_normal_direction(3, + contravariant_vectors, l, 1, element) gradients_y[v, l, 1, element] = (gradients_y[v, l, 1, element] + - surface_flux_values[v, l, 3, element] * + surface_flux_values[v, l, 3, + element] * factor_1 * normal_direction_y) # surface at +y - _, normal_direction_y = get_normal_direction(4, contravariant_vectors, + _, normal_direction_y = get_normal_direction(4, + contravariant_vectors, l, nnodes(dg), element) - gradients_y[v, l, nnodes(dg), element] = (gradients_y[v, l, nnodes(dg), + gradients_y[v, l, nnodes(dg), element] = (gradients_y[v, l, + nnodes(dg), element] + - surface_flux_values[v, l, 4, + surface_flux_values[v, l, + 4, element] * - factor_2 * normal_direction_y) + factor_2 * + normal_direction_y) end end end @@ -444,24 +484,30 @@ function calc_volume_integral!(du, flux_viscous, @threaded for element in eachelement(dg, cache) # Calculate volume terms in one element for j in eachnode(dg), i in eachnode(dg) - flux1 = get_node_vars(flux_viscous_x, equations_parabolic, dg, i, j, element) - flux2 = get_node_vars(flux_viscous_y, equations_parabolic, dg, i, j, element) + flux1 = get_node_vars(flux_viscous_x, equations_parabolic, dg, i, j, + element) + flux2 = get_node_vars(flux_viscous_y, equations_parabolic, dg, i, j, + element) # Compute the contravariant flux by taking the scalar product of the # first contravariant vector Ja^1 and the flux vector - Ja11, Ja12 = get_contravariant_vector(1, contravariant_vectors, i, j, element) + Ja11, Ja12 = get_contravariant_vector(1, contravariant_vectors, i, j, + element) contravariant_flux1 = Ja11 * flux1 + Ja12 * flux2 for ii in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[ii, i], contravariant_flux1, + multiply_add_to_node_vars!(du, derivative_dhat[ii, i], + contravariant_flux1, equations_parabolic, dg, ii, j, element) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja21, Ja22 = get_contravariant_vector(2, contravariant_vectors, i, j, element) + Ja21, Ja22 = get_contravariant_vector(2, contravariant_vectors, i, j, + element) contravariant_flux2 = Ja21 * flux1 + Ja22 * flux2 for jj in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[jj, j], contravariant_flux2, + multiply_add_to_node_vars!(du, derivative_dhat[jj, j], + contravariant_flux2, equations_parabolic, dg, i, jj, element) end end @@ -503,7 +549,8 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, # this is the outward normal direction on the primary element normal_direction = get_normal_direction(primary_direction, contravariant_vectors, - i_primary, j_primary, primary_element) + i_primary, j_primary, + primary_element) for v in eachvariable(equations_parabolic) # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! @@ -602,7 +649,8 @@ function calc_interface_flux!(surface_flux_values, # primary element. We assume a BR-1 type of flux. viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars(cache_parabolic.interfaces.u, equations_parabolic, - dg, node, + dg, + node, interface) flux = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) @@ -624,9 +672,11 @@ function calc_interface_flux!(surface_flux_values, end function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, 4}}, - mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations, mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) where {uEltype <: Real} + surface_integral, + dg::DGSEM) where {uEltype <: Real} @unpack neighbor_ids, node_indices = cache.mortars @unpack contravariant_vectors = cache.elements index_range = eachnode(dg) @@ -683,7 +733,8 @@ function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, j_large = j_large_start element = neighbor_ids[3, mortar] for i in eachnode(dg) - normal_direction = get_normal_direction(direction_index, contravariant_vectors, + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, i_large, j_large, element) for v in eachvariable(equations) @@ -732,8 +783,10 @@ function calc_mortar_flux_divergence!(surface_flux_values, for position in 1:2 for node in eachnode(dg) for v in eachvariable(equations) - viscous_flux_normal_ll = cache.mortars.u[1, v, position, node, mortar] - viscous_flux_normal_rr = cache.mortars.u[2, v, position, node, mortar] + viscous_flux_normal_ll = cache.mortars.u[1, v, position, node, + mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, node, + mortar] # TODO: parabolic; only BR1 at the moment fstar[position][v, node] = 0.5 * (viscous_flux_normal_ll + @@ -824,7 +877,8 @@ end function calc_boundary_flux_gradients!(cache, t, boundary_condition::Union{BoundaryConditionPeriodic, BoundaryConditionDoNothing}, - mesh::P4estMesh, equations, surface_integral, dg::DG) + mesh::P4estMesh, equations, surface_integral, + dg::DG) @assert isempty(eachboundary(dg, cache)) end @@ -913,7 +967,8 @@ function calc_boundary_flux!(cache, t, boundary_index) # Outward-pointing normal direction (not normalized) - normal_direction = get_normal_direction(direction_index, contravariant_vectors, + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, i_node, j_node, element) # TODO: revisit if we want more general boundary treatments. @@ -922,11 +977,13 @@ function calc_boundary_flux!(cache, t, flux_inner = u_inner # Coordinates at boundary node - x = get_node_coords(node_coordinates, equations_parabolic, dg, i_node, j_node, + x = get_node_coords(node_coordinates, equations_parabolic, dg, i_node, + j_node, element) flux_ = boundary_condition_parabolic(flux_inner, u_inner, normal_direction, - x, t, operator_type, equations_parabolic) + x, t, operator_type, + equations_parabolic) # Copy flux to element storage in the correct orientation for v in eachvariable(equations_parabolic) @@ -938,3 +995,22 @@ function calc_boundary_flux!(cache, t, end end end + +function apply_jacobian_parabolic!(du, mesh::P4estMesh{2}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + factor = inverse_jacobian[i, j, element] + + for v in eachvariable(equations) + du[v, i, j, element] *= factor + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_p4est/dg_2d_parallel.jl b/src/solvers/dgsem_p4est/dg_2d_parallel.jl index a8887351c4..3bf0cd0cab 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parallel.jl @@ -6,7 +6,8 @@ #! format: noindent function prolong2mpiinterfaces!(cache, u, - mesh::ParallelP4estMesh{2}, + mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, equations, surface_integral, dg::DG) @unpack mpi_interfaces = cache index_range = eachnode(dg) @@ -43,7 +44,8 @@ function prolong2mpiinterfaces!(cache, u, end function calc_mpi_interface_flux!(surface_flux_values, - mesh::ParallelP4estMesh{2}, + mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, nonconservative_terms, equations, surface_integral, dg::DG, cache) @unpack local_neighbor_ids, node_indices, local_sides = cache.mpi_interfaces @@ -106,7 +108,8 @@ end # Inlined version of the interface flux computation for conservation laws @inline function calc_mpi_interface_flux!(surface_flux_values, - mesh::P4estMesh{2}, + mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, nonconservative_terms::False, equations, surface_integral, dg::DG, cache, interface_index, normal_direction, @@ -131,7 +134,8 @@ end end function prolong2mpimortars!(cache, u, - mesh::ParallelP4estMesh{2}, equations, + mesh::Union{ParallelP4estMesh{2}, ParallelT8codeMesh{2}}, + equations, mortar_l2::LobattoLegendreMortarL2, surface_integral, dg::DGSEM) @unpack node_indices = cache.mpi_mortars @@ -199,7 +203,7 @@ function prolong2mpimortars!(cache, u, end function calc_mpi_mortar_flux!(surface_flux_values, - mesh::ParallelP4estMesh{2}, + mesh::Union{ParallelP4estMesh{2}, ParallelT8codeMesh{2}}, nonconservative_terms, equations, mortar_l2::LobattoLegendreMortarL2, surface_integral, dg::DG, cache) @@ -253,7 +257,8 @@ end # Inlined version of the mortar flux computation on small elements for conservation laws @inline function calc_mpi_mortar_flux!(fstar, - mesh::ParallelP4estMesh{2}, + mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, nonconservative_terms::False, equations, surface_integral, dg::DG, cache, mortar_index, position_index, normal_direction, @@ -271,7 +276,9 @@ end end @inline function mpi_mortar_fluxes_to_elements!(surface_flux_values, - mesh::ParallelP4estMesh{2}, equations, + mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, + equations, mortar_l2::LobattoLegendreMortarL2, dg::DGSEM, cache, mortar, fstar, u_buffer) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 83d663809a..63d431d35d 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -1,7 +1,15 @@ +# 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 method is called when a SemidiscretizationHyperbolicParabolic is constructed. # It constructs the basic `cache` used throughout the simulation to compute # the RHS etc. -function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::AbstractEquations, +function create_cache_parabolic(mesh::P4estMesh{3}, + equations_hyperbolic::AbstractEquations, equations_parabolic::AbstractEquationsParabolic, dg::DG, parabolic_scheme, RealT, uEltype) balance!(mesh) @@ -73,11 +81,14 @@ function calc_gradient!(gradients, u_transformed, t, Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, i, j, k, element) - gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, dg, + gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, + dg, i, j, k, element) - gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, dg, + gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, + dg, i, j, k, element) - gradients_reference_3 = get_node_vars(gradients_z, equations_parabolic, dg, + gradients_reference_3 = get_node_vars(gradients_z, equations_parabolic, + dg, i, j, k, element) # note that the contravariant vectors are transposed compared with computations of flux @@ -115,7 +126,8 @@ function calc_gradient!(gradients, u_transformed, t, @trixi_timeit timer() "interface flux" begin calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, False(), # False() = no nonconservative terms - equations_parabolic, dg.surface_integral, dg, cache_parabolic) + equations_parabolic, dg.surface_integral, dg, + cache_parabolic) end # Prolong solution to boundaries @@ -127,7 +139,8 @@ function calc_gradient!(gradients, u_transformed, t, # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin calc_boundary_flux_gradients!(cache_parabolic, t, boundary_conditions_parabolic, - mesh, equations_parabolic, dg.surface_integral, dg) + mesh, equations_parabolic, dg.surface_integral, + dg) end # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` @@ -165,7 +178,8 @@ function calc_gradient!(gradients, u_transformed, t, for dim in 1:3 grad = gradients[dim] # surface at -x - normal_direction = get_normal_direction(1, contravariant_vectors, + normal_direction = get_normal_direction(1, + contravariant_vectors, 1, l, m, element) grad[v, 1, l, m, element] = (grad[v, 1, l, m, element] + surface_flux_values[v, l, m, 1, @@ -173,18 +187,22 @@ function calc_gradient!(gradients, u_transformed, t, factor_1 * normal_direction[dim]) # surface at +x - normal_direction = get_normal_direction(2, contravariant_vectors, - nnodes(dg), l, m, element) + normal_direction = get_normal_direction(2, + contravariant_vectors, + nnodes(dg), l, m, + element) grad[v, nnodes(dg), l, m, element] = (grad[v, nnodes(dg), l, m, element] + - surface_flux_values[v, l, m, + surface_flux_values[v, l, + m, 2, element] * factor_2 * normal_direction[dim]) # surface at -y - normal_direction = get_normal_direction(3, contravariant_vectors, + normal_direction = get_normal_direction(3, + contravariant_vectors, l, m, 1, element) grad[v, l, 1, m, element] = (grad[v, l, 1, m, element] + surface_flux_values[v, l, m, 3, @@ -192,18 +210,22 @@ function calc_gradient!(gradients, u_transformed, t, factor_1 * normal_direction[dim]) # surface at +y - normal_direction = get_normal_direction(4, contravariant_vectors, - l, nnodes(dg), m, element) + normal_direction = get_normal_direction(4, + contravariant_vectors, + l, nnodes(dg), m, + element) grad[v, l, nnodes(dg), m, element] = (grad[v, l, nnodes(dg), m, element] + - surface_flux_values[v, l, m, + surface_flux_values[v, l, + m, 4, element] * factor_2 * normal_direction[dim]) # surface at -z - normal_direction = get_normal_direction(5, contravariant_vectors, + normal_direction = get_normal_direction(5, + contravariant_vectors, l, m, 1, element) grad[v, l, m, 1, element] = (grad[v, l, m, 1, element] + surface_flux_values[v, l, m, 5, @@ -211,11 +233,14 @@ function calc_gradient!(gradients, u_transformed, t, factor_1 * normal_direction[dim]) # surface at +z - normal_direction = get_normal_direction(6, contravariant_vectors, - l, m, nnodes(dg), element) + normal_direction = get_normal_direction(6, + contravariant_vectors, + l, m, nnodes(dg), + element) grad[v, l, m, nnodes(dg), element] = (grad[v, l, m, nnodes(dg), element] + - surface_flux_values[v, l, m, + surface_flux_values[v, l, + m, 6, element] * factor_2 * @@ -366,37 +391,46 @@ function calc_volume_integral!(du, flux_viscous, @threaded for element in eachelement(dg, cache) # Calculate volume terms in one element for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - flux1 = get_node_vars(flux_viscous_x, equations_parabolic, dg, i, j, k, element) - flux2 = get_node_vars(flux_viscous_y, equations_parabolic, dg, i, j, k, element) - flux3 = get_node_vars(flux_viscous_z, equations_parabolic, dg, i, j, k, element) + flux1 = get_node_vars(flux_viscous_x, equations_parabolic, dg, i, j, k, + element) + flux2 = get_node_vars(flux_viscous_y, equations_parabolic, dg, i, j, k, + element) + flux3 = get_node_vars(flux_viscous_z, equations_parabolic, dg, i, j, k, + element) # Compute the contravariant flux by taking the scalar product of the # first contravariant vector Ja^1 and the flux vector - Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, i, j, k, + Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, i, j, + k, element) contravariant_flux1 = Ja11 * flux1 + Ja12 * flux2 + Ja13 * flux3 for ii in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[ii, i], contravariant_flux1, + multiply_add_to_node_vars!(du, derivative_dhat[ii, i], + contravariant_flux1, equations_parabolic, dg, ii, j, k, element) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, i, j, k, + Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, i, j, + k, element) contravariant_flux2 = Ja21 * flux1 + Ja22 * flux2 + Ja23 * flux3 for jj in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[jj, j], contravariant_flux2, + multiply_add_to_node_vars!(du, derivative_dhat[jj, j], + contravariant_flux2, equations_parabolic, dg, i, jj, k, element) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, i, j, k, + Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, i, j, + k, element) contravariant_flux3 = Ja31 * flux1 + Ja32 * flux2 + Ja33 * flux3 for kk in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[kk, k], contravariant_flux3, + multiply_add_to_node_vars!(du, derivative_dhat[kk, k], + contravariant_flux3, equations_parabolic, dg, i, j, kk, element) end end @@ -574,7 +608,8 @@ function calc_interface_flux!(surface_flux_values, viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars(cache_parabolic.interfaces.u, equations_parabolic, dg, - i, j, + i, + j, interface) flux = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) @@ -606,7 +641,8 @@ function calc_interface_flux!(surface_flux_values, end function prolong2mortars_divergence!(cache, flux_viscous, - mesh::Union{P4estMesh{3}, T8codeMesh{3}}, equations, + mesh::Union{P4estMesh{3}, T8codeMesh{3}}, + equations, mortar_l2::LobattoLegendreMortarL2, surface_integral, dg::DGSEM) @unpack neighbor_ids, node_indices = cache.mortars @@ -642,11 +678,14 @@ function prolong2mortars_divergence!(cache, flux_viscous, element) for v in eachvariable(equations) - flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, k_small, + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, + k_small, element], - flux_viscous_y[v, i_small, j_small, k_small, + flux_viscous_y[v, i_small, j_small, + k_small, element], - flux_viscous_z[v, i_small, j_small, k_small, + flux_viscous_z[v, i_small, j_small, + k_small, element]) cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, @@ -688,7 +727,8 @@ function prolong2mortars_divergence!(cache, flux_viscous, for i in eachnode(dg) normal_direction = get_normal_direction(direction_index, contravariant_vectors, - i_large, j_large, k_large, element) + i_large, j_large, k_large, + element) for v in eachvariable(equations) flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, @@ -827,7 +867,8 @@ end # TODO: parabolic; only BR1 at the moment flux_ = 0.5 * (u_ll + u_rr) # Copy flux to buffer - set_node_vars!(fstar, flux_, equations, dg, i_node_index, j_node_index, position_index) + set_node_vars!(fstar, flux_, equations, dg, i_node_index, j_node_index, + position_index) end # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` @@ -862,7 +903,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, for j in eachnode(dg) for i in eachnode(dg) # this is the outward normal direction on the primary element - normal_direction = get_normal_direction(direction, contravariant_vectors, + normal_direction = get_normal_direction(direction, + contravariant_vectors, i_node, j_node, k_node, element) for v in eachvariable(equations_parabolic) @@ -873,7 +915,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, flux_viscous_z[v, i_node, j_node, k_node, element]) - boundaries.u[v, i, j, boundary] = dot(flux_viscous, normal_direction) + boundaries.u[v, i, j, boundary] = dot(flux_viscous, + normal_direction) end i_node += i_node_step_i j_node += j_node_step_i @@ -940,7 +983,8 @@ function calc_boundary_flux!(cache, t, j_node, k_node, element) - flux_ = boundary_condition_parabolic(flux_inner, u_inner, normal_direction, + flux_ = boundary_condition_parabolic(flux_inner, u_inner, + normal_direction, x, t, operator_type, equations_parabolic) @@ -959,3 +1003,22 @@ function calc_boundary_flux!(cache, t, end end end + +function apply_jacobian_parabolic!(du, mesh::P4estMesh{3}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + + @threaded for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + factor = inverse_jacobian[i, j, k, element] + + for v in eachvariable(equations) + du[v, i, j, k, element] *= factor + end + end + end + + return nothing +end +end # @muladd diff --git a/src/solvers/dgsem_p4est/dg_3d_parallel.jl b/src/solvers/dgsem_p4est/dg_3d_parallel.jl index 13bf2a1a2e..e504e06d2c 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parallel.jl @@ -6,7 +6,7 @@ #! format: noindent function rhs!(du, u, t, - mesh::ParallelP4estMesh{3}, equations, + mesh::Union{ParallelP4estMesh{3}, ParallelT8codeMesh{3}}, equations, initial_condition, boundary_conditions, source_terms::Source, dg::DG, cache) where {Source} # Start to receive MPI data @@ -113,7 +113,8 @@ function rhs!(du, u, t, end function prolong2mpiinterfaces!(cache, u, - mesh::ParallelP4estMesh{3}, + mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, equations, surface_integral, dg::DG) @unpack mpi_interfaces = cache index_range = eachnode(dg) @@ -160,7 +161,8 @@ function prolong2mpiinterfaces!(cache, u, end function calc_mpi_interface_flux!(surface_flux_values, - mesh::ParallelP4estMesh{3}, + mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, nonconservative_terms, equations, surface_integral, dg::DG, cache) @unpack local_neighbor_ids, node_indices, local_sides = cache.mpi_interfaces @@ -237,7 +239,8 @@ end # Inlined version of the interface flux computation for conservation laws @inline function calc_mpi_interface_flux!(surface_flux_values, - mesh::P4estMesh{3}, + mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, nonconservative_terms::False, equations, surface_integral, dg::DG, cache, interface_index, normal_direction, @@ -265,7 +268,8 @@ end end function prolong2mpimortars!(cache, u, - mesh::ParallelP4estMesh{3}, equations, + mesh::Union{ParallelP4estMesh{3}, ParallelT8codeMesh{3}}, + equations, mortar_l2::LobattoLegendreMortarL2, surface_integral, dg::DGSEM) @unpack node_indices = cache.mpi_mortars @@ -374,7 +378,7 @@ function prolong2mpimortars!(cache, u, end function calc_mpi_mortar_flux!(surface_flux_values, - mesh::ParallelP4estMesh{3}, + mesh::Union{ParallelP4estMesh{3}, ParallelT8codeMesh{3}}, nonconservative_terms, equations, mortar_l2::LobattoLegendreMortarL2, surface_integral, dg::DG, cache) @@ -437,7 +441,8 @@ end # Inlined version of the mortar flux computation on small elements for conservation laws @inline function calc_mpi_mortar_flux!(fstar, - mesh::ParallelP4estMesh{3}, + mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, nonconservative_terms::False, equations, surface_integral, dg::DG, cache, mortar_index, position_index, normal_direction, @@ -456,7 +461,9 @@ end end @inline function mpi_mortar_fluxes_to_elements!(surface_flux_values, - mesh::ParallelP4estMesh{3}, equations, + mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, + equations, mortar_l2::LobattoLegendreMortarL2, dg::DGSEM, cache, mortar, fstar, u_buffer, fstar_tmp) diff --git a/src/solvers/dgsem_p4est/dg_parallel.jl b/src/solvers/dgsem_p4est/dg_parallel.jl index 712ede2bfc..eaa6ab5cee 100644 --- a/src/solvers/dgsem_p4est/dg_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_parallel.jl @@ -166,7 +166,8 @@ end # at `index_base`+1 in the MPI buffer. `data_size` is the data size associated with each small # position (i.e. position 1 or 2). The data corresponding to the large side (i.e. position 3) has # size `2 * data_size`. -@inline function buffer_mortar_indices(mesh::ParallelP4estMesh{2}, index_base, +@inline function buffer_mortar_indices(mesh::Union{ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, index_base, data_size) return ( # first, last for local element in position 1 (small element) @@ -185,7 +186,8 @@ end # at `index_base`+1 in the MPI buffer. `data_size` is the data size associated with each small # position (i.e. position 1 to 4). The data corresponding to the large side (i.e. position 5) has # size `4 * data_size`. -@inline function buffer_mortar_indices(mesh::ParallelP4estMesh{3}, index_base, +@inline function buffer_mortar_indices(mesh::Union{ParallelP4estMesh{3}, + ParallelT8codeMesh{3}}, index_base, data_size) return ( # first, last for local element in position 1 (small element) @@ -491,7 +493,8 @@ end # Exchange normal directions of small elements of the MPI mortars. They are needed on all involved # MPI ranks to calculate the mortar fluxes. -function exchange_normal_directions!(mpi_mortars, mpi_cache, mesh::ParallelP4estMesh, +function exchange_normal_directions!(mpi_mortars, mpi_cache, + mesh::Union{ParallelP4estMesh, ParallelT8codeMesh}, n_nodes) RealT = real(mesh) n_dims = ndims(mesh) diff --git a/src/solvers/dgsem_t8code/containers.jl b/src/solvers/dgsem_t8code/containers.jl index 093feb2985..d7ff79fbf2 100644 --- a/src/solvers/dgsem_t8code/containers.jl +++ b/src/solvers/dgsem_t8code/containers.jl @@ -18,19 +18,22 @@ function reinitialize_containers!(mesh::T8codeMesh, equations, dg::DGSEM, cache) @unpack boundaries = cache resize!(boundaries, mesh.nboundaries) - trixi_t8_fill_mesh_info(mesh.forest, elements, interfaces, mortars, boundaries, - mesh.boundary_names) + fill_mesh_info!(mesh, interfaces, mortars, boundaries, + mesh.boundary_names) return nothing end function count_required_surfaces!(mesh::T8codeMesh) - counts = trixi_t8_count_interfaces(mesh.forest) + counts = count_interfaces(mesh) mesh.nmortars = counts.mortars mesh.ninterfaces = counts.interfaces mesh.nboundaries = counts.boundaries + mesh.nmpimortars = counts.mpi_mortars + mesh.nmpiinterfaces = counts.mpi_interfaces + return counts end @@ -38,7 +41,9 @@ end function count_required_surfaces(mesh::T8codeMesh) return (interfaces = mesh.ninterfaces, mortars = mesh.nmortars, - boundaries = mesh.nboundaries) + boundaries = mesh.nboundaries, + mpi_interfaces = mesh.nmpiinterfaces, + mpi_mortars = mesh.nmpimortars) end # Compatibility to `dgsem_p4est/containers.jl`. diff --git a/src/solvers/dgsem_t8code/containers_2d.jl b/src/solvers/dgsem_t8code/containers_2d.jl index bf77826a34..ce525bfdf6 100644 --- a/src/solvers/dgsem_t8code/containers_2d.jl +++ b/src/solvers/dgsem_t8code/containers_2d.jl @@ -26,6 +26,7 @@ function calc_node_coordinates!(node_coordinates, tree_class = t8_forest_get_tree_class(mesh.forest, itree) eclass_scheme = t8_forest_get_eclass_scheme(mesh.forest, tree_class) num_elements_in_tree = t8_forest_get_tree_num_elements(mesh.forest, itree) + global_itree = t8_forest_global_tree_id(mesh.forest, itree) for ielement in 0:(num_elements_in_tree - 1) element = t8_forest_get_element_in_tree(mesh.forest, itree, ielement) @@ -55,7 +56,7 @@ function calc_node_coordinates!(node_coordinates, multiply_dimensionwise!(view(node_coordinates, :, :, :, current_index += 1), matrix1, matrix2, view(mesh.tree_node_coordinates, :, :, :, - itree + 1), + global_itree + 1), tmp1) end end diff --git a/src/solvers/dgsem_t8code/containers_3d.jl b/src/solvers/dgsem_t8code/containers_3d.jl index f2d54ff07d..4d56bc734a 100644 --- a/src/solvers/dgsem_t8code/containers_3d.jl +++ b/src/solvers/dgsem_t8code/containers_3d.jl @@ -28,6 +28,7 @@ function calc_node_coordinates!(node_coordinates, tree_class = t8_forest_get_tree_class(mesh.forest, itree) eclass_scheme = t8_forest_get_eclass_scheme(mesh.forest, tree_class) num_elements_in_tree = t8_forest_get_tree_num_elements(mesh.forest, itree) + global_itree = t8_forest_global_tree_id(mesh.forest, itree) for ielement in 0:(num_elements_in_tree - 1) element = t8_forest_get_element_in_tree(mesh.forest, itree, ielement) @@ -63,7 +64,7 @@ function calc_node_coordinates!(node_coordinates, current_index += 1), matrix1, matrix2, matrix3, view(mesh.tree_node_coordinates, :, :, :, :, - itree + 1), + global_itree + 1), tmp1) end end diff --git a/src/solvers/dgsem_t8code/containers_parallel.jl b/src/solvers/dgsem_t8code/containers_parallel.jl new file mode 100644 index 0000000000..0cb3f5887a --- /dev/null +++ b/src/solvers/dgsem_t8code/containers_parallel.jl @@ -0,0 +1,65 @@ +function reinitialize_containers!(mesh::ParallelT8codeMesh, equations, dg::DGSEM, cache) + @unpack elements, interfaces, boundaries, mortars, mpi_interfaces, mpi_mortars, + mpi_cache = cache + resize!(elements, ncells(mesh)) + init_elements!(elements, mesh, dg.basis) + + count_required_surfaces!(mesh) + required = count_required_surfaces(mesh) + + resize!(interfaces, required.interfaces) + + resize!(boundaries, required.boundaries) + + resize!(mortars, required.mortars) + + resize!(mpi_interfaces, required.mpi_interfaces) + + resize!(mpi_mortars, required.mpi_mortars) + + mpi_mesh_info = (mpi_mortars = mpi_mortars, + mpi_interfaces = mpi_interfaces, + + # Temporary arrays for updating `mpi_cache`. + global_mortar_ids = fill(UInt64(0), nmpimortars(mpi_mortars)), + global_interface_ids = fill(UInt64(0), nmpiinterfaces(mpi_interfaces)), + neighbor_ranks_mortar = Vector{Vector{Int}}(undef, + nmpimortars(mpi_mortars)), + neighbor_ranks_interface = fill(-1, nmpiinterfaces(mpi_interfaces))) + + fill_mesh_info!(mesh, interfaces, mortars, boundaries, + mesh.boundary_names; mpi_mesh_info = mpi_mesh_info) + + init_mpi_cache!(mpi_cache, mesh, mpi_mesh_info, nvariables(equations), nnodes(dg), + eltype(elements)) + + empty!(mpi_mesh_info.global_mortar_ids) + empty!(mpi_mesh_info.global_interface_ids) + empty!(mpi_mesh_info.neighbor_ranks_mortar) + empty!(mpi_mesh_info.neighbor_ranks_interface) + + # Re-initialize and distribute normal directions of MPI mortars; requires + # MPI communication, so the MPI cache must be re-initialized beforehand. + init_normal_directions!(mpi_mortars, dg.basis, elements) + exchange_normal_directions!(mpi_mortars, mpi_cache, mesh, nnodes(dg)) + + return nothing +end + +# Compatibility to `dgsem_p4est/containers.jl`. +function init_mpi_interfaces!(interfaces, mesh::ParallelT8codeMesh) + # Do nothing. + return nothing +end + +# Compatibility to `dgsem_p4est/containers.jl`. +function init_mpi_mortars!(mortars, mesh::ParallelT8codeMesh) + # Do nothing. + return nothing +end + +# Compatibility to `dgsem_p4est/containers_parallel.jl`. +function init_mpi_mortars!(mpi_mortars, mesh::ParallelT8codeMesh, basis, elements) + # Do nothing. + return nothing +end diff --git a/src/solvers/dgsem_t8code/dg.jl b/src/solvers/dgsem_t8code/dg.jl index 6e9660c917..e01b12e0f8 100644 --- a/src/solvers/dgsem_t8code/dg.jl +++ b/src/solvers/dgsem_t8code/dg.jl @@ -13,8 +13,8 @@ function create_cache(mesh::T8codeMesh, equations::AbstractEquations, dg::DG, :: boundaries = init_boundaries(mesh, equations, dg.basis, elements) mortars = init_mortars(mesh, equations, dg.basis, elements) - trixi_t8_fill_mesh_info(mesh.forest, elements, interfaces, mortars, boundaries, - mesh.boundary_names) + fill_mesh_info!(mesh, interfaces, mortars, boundaries, + mesh.boundary_names) cache = (; elements, interfaces, boundaries, mortars) @@ -29,4 +29,7 @@ end include("containers.jl") include("containers_2d.jl") include("containers_3d.jl") + +include("containers_parallel.jl") +include("dg_parallel.jl") end # @muladd diff --git a/src/solvers/dgsem_t8code/dg_parallel.jl b/src/solvers/dgsem_t8code/dg_parallel.jl new file mode 100644 index 0000000000..ece614b7d7 --- /dev/null +++ b/src/solvers/dgsem_t8code/dg_parallel.jl @@ -0,0 +1,135 @@ +@muladd begin +#! format: noindent + +# This method is called when a `SemidiscretizationHyperbolic` is constructed. +# It constructs the basic `cache` used throughout the simulation to compute +# the RHS etc. +function create_cache(mesh::ParallelT8codeMesh, equations::AbstractEquations, dg::DG, + ::Any, + ::Type{uEltype}) where {uEltype <: Real} + # Make sure to balance and partition the forest before creating any + # containers in case someone has tampered with forest after creating the + # mesh. + balance!(mesh) + partition!(mesh) + + count_required_surfaces!(mesh) + + elements = init_elements(mesh, equations, dg.basis, uEltype) + mortars = init_mortars(mesh, equations, dg.basis, elements) + interfaces = init_interfaces(mesh, equations, dg.basis, elements) + boundaries = init_boundaries(mesh, equations, dg.basis, elements) + + mpi_mortars = init_mpi_mortars(mesh, equations, dg.basis, elements) + mpi_interfaces = init_mpi_interfaces(mesh, equations, dg.basis, elements) + + mpi_mesh_info = (mpi_mortars = mpi_mortars, + mpi_interfaces = mpi_interfaces, + global_mortar_ids = fill(UInt64(0), nmpimortars(mpi_mortars)), + global_interface_ids = fill(UInt64(0), + nmpiinterfaces(mpi_interfaces)), + neighbor_ranks_mortar = Vector{Vector{Int}}(undef, + nmpimortars(mpi_mortars)), + neighbor_ranks_interface = fill(-1, + nmpiinterfaces(mpi_interfaces))) + + fill_mesh_info!(mesh, interfaces, mortars, boundaries, + mesh.boundary_names; mpi_mesh_info = mpi_mesh_info) + + mpi_cache = init_mpi_cache(mesh, mpi_mesh_info, nvariables(equations), nnodes(dg), + uEltype) + + empty!(mpi_mesh_info.global_mortar_ids) + empty!(mpi_mesh_info.global_interface_ids) + empty!(mpi_mesh_info.neighbor_ranks_mortar) + empty!(mpi_mesh_info.neighbor_ranks_interface) + + init_normal_directions!(mpi_mortars, dg.basis, elements) + exchange_normal_directions!(mpi_mortars, mpi_cache, mesh, nnodes(dg)) + + cache = (; elements, interfaces, mpi_interfaces, boundaries, mortars, mpi_mortars, + mpi_cache) + + # Add specialized parts of the cache required to compute the volume integral etc. + cache = (; cache..., + create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) + cache = (; cache..., create_cache(mesh, equations, dg.mortar, uEltype)...) + + return cache +end + +function init_mpi_cache(mesh::ParallelT8codeMesh, mpi_mesh_info, nvars, nnodes, uEltype) + mpi_cache = P4estMPICache(uEltype) + init_mpi_cache!(mpi_cache, mesh, mpi_mesh_info, nvars, nnodes, uEltype) + return mpi_cache +end + +function init_mpi_cache!(mpi_cache::P4estMPICache, mesh::ParallelT8codeMesh, + mpi_mesh_info, nvars, nnodes, uEltype) + mpi_neighbor_ranks, mpi_neighbor_interfaces, mpi_neighbor_mortars = init_mpi_neighbor_connectivity(mpi_mesh_info, + mesh) + + mpi_send_buffers, mpi_recv_buffers, mpi_send_requests, mpi_recv_requests = init_mpi_data_structures(mpi_neighbor_interfaces, + mpi_neighbor_mortars, + ndims(mesh), + nvars, + nnodes, + uEltype) + + n_elements_global = Int(t8_forest_get_global_num_elements(mesh.forest)) + n_elements_local = Int(t8_forest_get_local_num_elements(mesh.forest)) + + n_elements_by_rank = Vector{Int}(undef, mpi_nranks()) + n_elements_by_rank[mpi_rank() + 1] = n_elements_local + + MPI.Allgather!(MPI.UBuffer(n_elements_by_rank, 1), mpi_comm()) + + n_elements_by_rank = OffsetArray(n_elements_by_rank, 0:(mpi_nranks() - 1)) + + # Account for 1-based indexing in Julia. + first_element_global_id = sum(n_elements_by_rank[0:(mpi_rank() - 1)]) + 1 + + @assert n_elements_global==sum(n_elements_by_rank) "error in total number of elements" + + @pack! mpi_cache = mpi_neighbor_ranks, mpi_neighbor_interfaces, + mpi_neighbor_mortars, + mpi_send_buffers, mpi_recv_buffers, + mpi_send_requests, mpi_recv_requests, + n_elements_by_rank, n_elements_global, + first_element_global_id + + return mpi_cache +end + +function init_mpi_neighbor_connectivity(mpi_mesh_info, mesh::ParallelT8codeMesh) + @unpack mpi_interfaces, mpi_mortars, global_interface_ids, neighbor_ranks_interface, global_mortar_ids, neighbor_ranks_mortar = mpi_mesh_info + + mpi_neighbor_ranks = vcat(neighbor_ranks_interface, neighbor_ranks_mortar...) |> + sort |> unique + + p = sortperm(global_interface_ids) + + neighbor_ranks_interface .= neighbor_ranks_interface[p] + interface_ids = collect(1:nmpiinterfaces(mpi_interfaces))[p] + + p = sortperm(global_mortar_ids) + neighbor_ranks_mortar .= neighbor_ranks_mortar[p] + mortar_ids = collect(1:nmpimortars(mpi_mortars))[p] + + # For each neighbor rank, init connectivity data structures + mpi_neighbor_interfaces = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) + mpi_neighbor_mortars = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) + for (index, d) in enumerate(mpi_neighbor_ranks) + mpi_neighbor_interfaces[index] = interface_ids[findall(==(d), + neighbor_ranks_interface)] + mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (d in x), + neighbor_ranks_mortar)] + end + + # Check that all interfaces were counted exactly once + @assert mapreduce(length, +, mpi_neighbor_interfaces; init = 0) == + nmpiinterfaces(mpi_interfaces) + + return mpi_neighbor_ranks, mpi_neighbor_interfaces, mpi_neighbor_mortars +end +end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index b1c2734399..a6c962e03c 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -951,22 +951,4 @@ function apply_jacobian_parabolic!(du, mesh::TreeMesh{2}, return nothing end - -function apply_jacobian_parabolic!(du, mesh::P4estMesh{2}, - equations::AbstractEquationsParabolic, - dg::DG, cache) - @unpack inverse_jacobian = cache.elements - - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - factor = inverse_jacobian[i, j, element] - - for v in eachvariable(equations) - du[v, i, j, element] *= factor - end - end - end - - return nothing -end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d_parallel.jl b/src/solvers/dgsem_tree/dg_2d_parallel.jl index 8095dae123..157d462aa2 100644 --- a/src/solvers/dgsem_tree/dg_2d_parallel.jl +++ b/src/solvers/dgsem_tree/dg_2d_parallel.jl @@ -446,7 +446,8 @@ function init_mpi_neighbor_connectivity(elements, mpi_interfaces, mpi_mortars, end function rhs!(du, u, t, - mesh::Union{ParallelTreeMesh{2}, ParallelP4estMesh{2}}, equations, + mesh::Union{ParallelTreeMesh{2}, ParallelP4estMesh{2}, + ParallelT8codeMesh{2}}, equations, initial_condition, boundary_conditions, source_terms::Source, dg::DG, cache) where {Source} # Start to receive MPI data diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index ee0e7c6b06..d550474474 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -1033,22 +1033,4 @@ function apply_jacobian_parabolic!(du, mesh::TreeMesh{3}, return nothing end - -function apply_jacobian_parabolic!(du, mesh::P4estMesh{3}, - equations::AbstractEquationsParabolic, - dg::DG, cache) - @unpack inverse_jacobian = cache.elements - - @threaded for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - factor = inverse_jacobian[i, j, k, element] - - for v in eachvariable(equations) - du[v, i, j, k, element] *= factor - end - end - end - - return nothing -end end # @muladd diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index c3a0e7fb4e..d93307d476 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -178,12 +178,21 @@ function Base.show(io::IO, limiter::SubcellLimiterIDP) if !(local_minmax || positivity || spec_entropy || math_entropy) print(io, "No limiter selected => pure DG method") else - print(io, "Limiter=(") - local_minmax && print(io, "Local min/max, ") - positivity && print(io, "Positivity, ") - spec_entropy && print(io, "Specific entropy, ") - math_entropy && print(io, "Mathematical entropy, ") - print(io, "), ") + features = String[] + if local_minmax + push!(features, "local min/max") + end + if positivity + push!(features, "positivity") + end + if spec_entropy + push!(features, "specific entropy") + end + if math_entropy + push!(features, "mathematical entropy") + end + join(io, features, ", ") + print(io, "Limiter=($features), ") end limiter.smoothness_indicator && print(io, ", Smoothness indicator: ", limiter.IndicatorHG, diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 74e982ceaa..19eb3eb3a9 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -435,8 +435,8 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, - entropy_spec, initial_check_entropy_spec, - final_check_standard) + entropy_spec, initial_check_entropy_spec_newton_idp, + final_check_standard_newton_idp) end end @@ -460,8 +460,8 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, - entropy_spec, initial_check_entropy_spec, - final_check_standard) + entropy_spec, initial_check_entropy_spec_newton_idp, + final_check_standard_newton_idp) end end @@ -487,8 +487,8 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, - entropy_math, initial_check_entropy_math, - final_check_standard) + entropy_math, initial_check_entropy_math_newton_idp, + final_check_standard_newton_idp) end end @@ -512,8 +512,8 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, - entropy_math, initial_check_entropy_math, - final_check_standard) + entropy_math, initial_check_entropy_math_newton_idp, + final_check_standard_newton_idp) end end @@ -565,8 +565,9 @@ end @threaded for element in elements inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, cache, - variable, var_min, i, j, element) + idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, dt, + dg, cache, variable, var_min, + i, j, element) end end @@ -585,8 +586,9 @@ end @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, cache, - variable, var_min, i, j, element) + idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, dt, + dg, cache, variable, var_min, + i, j, element) end end @@ -594,15 +596,16 @@ end end # Function barrier to dispatch outer function by mesh type -@inline function idp_positivity_inner!(alpha, inverse_jacobian, limiter, u, dt, dg, - cache, variable, var_min, i, j, element) +@inline function idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, + dt, dg, cache, variable, var_min, + i, j, element) (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes (; inverse_weights) = dg.basis (; positivity_correction_factor) = limiter var = u[variable, i, j, element] if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + error("Safe low-order method produces negative value for conservative variable $variable. Try a smaller time step.") end # Compute bound @@ -698,14 +701,15 @@ end u_local = get_node_vars(u, equations, dg, i, j, element) var = variable(u_local, equations) if var < 0 - error("Safe $variable is not safe. element=$element, node: $i $j, value=$var") + error("Safe low-order method produces negative value for conservative variable $variable. Try a smaller time step.") end var_min[i, j, element] = limiter.positivity_correction_factor * var # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, inverse_jacobian, i, j, element, dt, equations, dg, cache, limiter, variable, - initial_check_nonnegative, final_check_nonnegative) + initial_check_nonnegative_newton_idp, + final_check_nonnegative_newton_idp) return nothing end @@ -766,8 +770,8 @@ end u_curr = u + beta * dt * antidiffusive_flux # If state is valid, perform initial check and return if correction is not needed - if is_valid_state(u_curr, equations) - goal = goal_function(variable, bound, u_curr, equations) + if isvalid(u_curr, equations) + goal = goal_function_newton_idp(variable, bound, u_curr, equations) initial_check(bound, goal, newton_abstol) && return nothing end @@ -777,9 +781,9 @@ end beta_old = beta # If the state is valid, evaluate d(goal)/d(beta) - if is_valid_state(u_curr, equations) - dgoal_dbeta = dgoal_function(variable, u_curr, dt, antidiffusive_flux, - equations) + if isvalid(u_curr, equations) + dgoal_dbeta = dgoal_function_newton_idp(variable, u_curr, dt, + antidiffusive_flux, equations) else # Otherwise, perform a bisection step dgoal_dbeta = 0 end @@ -797,13 +801,13 @@ end u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, finish bisection step without checking tolerance and iterate further - if !is_valid_state(u_curr, equations) + if !isvalid(u_curr, equations) beta_R = beta continue end # Check new beta for condition and update bounds - goal = goal_function(variable, bound, u_curr, equations) + goal = goal_function_newton_idp(variable, bound, u_curr, equations) if initial_check(bound, goal, newton_abstol) # New beta fulfills condition beta_L = beta @@ -816,13 +820,13 @@ end u_curr = u + beta * dt * antidiffusive_flux # If the state is invalid, redefine right bound without checking tolerance and iterate further - if !is_valid_state(u_curr, equations) + if !isvalid(u_curr, equations) beta_R = beta continue end # Evaluate goal function - goal = goal_function(variable, bound, u_curr, equations) + goal = goal_function_newton_idp(variable, bound, u_curr, equations) end # Check relative tolerance @@ -846,29 +850,32 @@ end return nothing end +### Auxiliary routines for Newton's bisection method ### # Initial checks -@inline function initial_check_entropy_spec(bound, goal, newton_abstol) +@inline function initial_check_entropy_spec_newton_idp(bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function initial_check_entropy_math(bound, goal, newton_abstol) +@inline function initial_check_entropy_math_newton_idp(bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline initial_check_nonnegative(bound, goal, newton_abstol) = goal <= 0 +@inline initial_check_nonnegative_newton_idp(bound, goal, newton_abstol) = goal <= 0 # Goal and d(Goal)d(u) function -@inline goal_function(variable, bound, u, equations) = bound - variable(u, equations) -@inline function dgoal_function(variable, u, dt, antidiffusive_flux, equations) - -dot(variable_derivative(variable, u, equations), dt * antidiffusive_flux) +@inline goal_function_newton_idp(variable, bound, u, equations) = bound - + variable(u, equations) +@inline function dgoal_function_newton_idp(variable, u, dt, antidiffusive_flux, + equations) + -dot(gradient_conservative(variable, u, equations), dt * antidiffusive_flux) end -# Final check -@inline function final_check_standard(bound, goal, newton_abstol) +# Final checks +@inline function final_check_standard_newton_idp(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end -@inline function final_check_nonnegative(bound, goal, newton_abstol) +@inline function final_check_nonnegative_newton_idp(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end diff --git a/test/test_mpi.jl b/test/test_mpi.jl index ad1ba4e835..001d9bff86 100644 --- a/test/test_mpi.jl +++ b/test/test_mpi.jl @@ -8,6 +8,7 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive = true) +Trixi.MPI.Barrier(Trixi.mpi_comm()) # CI with MPI and some tests fails often on Windows. Thus, we check whether this # is the case here. We use GitHub Actions, so we can check whether we run CI @@ -19,10 +20,12 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() # TreeMesh tests include("test_mpi_tree.jl") - # P4estMesh tests + # P4estMesh and T8codeMesh tests include("test_mpi_p4est_2d.jl") + include("test_mpi_t8code_2d.jl") if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` above include("test_mpi_p4est_3d.jl") + include("test_mpi_t8code_3d.jl") end end # MPI @@ -43,5 +46,6 @@ end # MPI supporting functionality # Clean up afterwards: delete Trixi.jl output directory Trixi.mpi_isroot() && @test_nowarn rm(outdir, recursive = true) +Trixi.MPI.Barrier(Trixi.mpi_comm()) end # module diff --git a/test/test_mpi_p4est_2d.jl b/test/test_mpi_p4est_2d.jl index da90537fcf..6d66bc68a2 100644 --- a/test/test_mpi_p4est_2d.jl +++ b/test/test_mpi_p4est_2d.jl @@ -33,6 +33,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") @test errors.linf≈[0.00011787417954578494] rtol=1.0e-4 end end + + # 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_advection_nonconforming_flag.jl" begin @@ -40,6 +49,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") "elixir_advection_nonconforming_flag.jl"), l2=[3.198940059144588e-5], linf=[0.00030636069494005547]) + + # 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_advection_unstructured_flag.jl" begin @@ -47,6 +65,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") "elixir_advection_unstructured_flag.jl"), l2=[0.0005379687442422346], linf=[0.007438525029884735]) + + # 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_advection_amr_solution_independent.jl" begin @@ -56,6 +83,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") l2=[4.949660644033807e-5], linf=[0.0004867846262313763], coverage_override=(maxiters = 6,)) + + # 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_advection_amr_unstructured_flag.jl" begin @@ -64,6 +100,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") l2=[0.0012766060609964525], linf=[0.01750280631586159], coverage_override=(maxiters = 6,)) + + # 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_advection_restart.jl" begin @@ -73,6 +118,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") # With the default `maxiters = 1` in coverage tests, # there would be no time steps after the restart. coverage_override=(maxiters = 100_000,)) + + # 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_euler_source_terms_nonconforming_unstructured_flag.jl" begin @@ -90,6 +144,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") 0.03759938693042297, 0.08039824959535657, ]) + + # 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 # P4estMesh MPI diff --git a/test/test_mpi_p4est_3d.jl b/test/test_mpi_p4est_3d.jl index 75f4365008..cca9093ec5 100644 --- a/test/test_mpi_p4est_3d.jl +++ b/test/test_mpi_p4est_3d.jl @@ -33,6 +33,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") @test errors.linf≈[0.0014548839020096516] rtol=1.0e-4 end end + + # 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_advection_amr.jl" begin @@ -46,6 +55,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") initial_refinement_level = 2, base_level = 2, med_level = 3, max_level = 4)) + + # 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_advection_amr_unstructured_curved.jl" begin @@ -58,6 +76,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") initial_refinement_level = 0, base_level = 0, med_level = 1, max_level = 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_advection_restart.jl" begin @@ -67,12 +94,30 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") # With the default `maxiters = 1` in coverage tests, # there would be no time steps after the restart. coverage_override=(maxiters = 100_000,)) + + # 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_advection_cubed_sphere.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_cubed_sphere.jl"), l2=[0.002006918015656413], linf=[0.027655117058380085]) + + # 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 # Compressible Euler @@ -94,6 +139,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.008526972236273522, ], tspan=(0.0, 0.01)) + + # 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_euler_source_terms_nonperiodic.jl" begin @@ -114,6 +168,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.01562861968368434, ], tspan=(0.0, 1.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_euler_ec.jl" begin @@ -134,6 +197,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") ], tspan=(0.0, 0.2), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + + # 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_euler_source_terms_nonperiodic_hohqmesh.jl" begin @@ -153,6 +225,15 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.048396544302230504, 0.1154589758186293, ]) + + # 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 # P4estMesh MPI diff --git a/test/test_mpi_t8code_2d.jl b/test/test_mpi_t8code_2d.jl new file mode 100644 index 0000000000..7c7fc03898 --- /dev/null +++ b/test/test_mpi_t8code_2d.jl @@ -0,0 +1,142 @@ +module TestExamplesMPIT8codeMesh2D + +using Test +using Trixi + +include("test_trixi.jl") + +const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_2d_dgsem") + +@testset "T8codeMesh MPI 2D" begin +#! format: noindent + +# Run basic tests +@testset "Examples 2D" begin + # Linear scalar advection + @trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + + @testset "error-based step size control" begin + Trixi.mpi_isroot() && println("-"^100) + Trixi.mpi_isroot() && + println("elixir_advection_basic.jl with error-based step size control") + + sol = solve(ode, RDPK3SpFSAL35(); abstol = 1.0e-4, reltol = 1.0e-4, + ode_default_options()..., callback = callbacks) + summary_callback() + errors = analysis_callback(sol) + if Trixi.mpi_isroot() + @test errors.l2≈[3.3022040342579066e-5] rtol=1.0e-4 + @test errors.linf≈[0.00011787417954578494] rtol=1.0e-4 + end + end + + # 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_advection_nonconforming_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_nonconforming_flag.jl"), + l2=[3.198940059144588e-5], + linf=[0.00030636069494005547]) + + # 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_advection_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_unstructured_flag.jl"), + l2=[0.0005379687442422346], + linf=[0.007438525029884735]) + + # 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_advection_amr_solution_independent.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_solution_independent.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[4.933027431215839e-5], + linf=[0.00048678461161243136], + coverage_override=(maxiters = 6,)) + + # 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_advection_amr_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_flag.jl"), + l2=[0.001980652042312077], + linf=[0.0328882442132265], + coverage_override=(maxiters = 6,)) + + # 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_euler_source_terms_nonconforming_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) + + # 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 # T8codeMesh MPI + +end # module diff --git a/test/test_mpi_t8code_3d.jl b/test/test_mpi_t8code_3d.jl new file mode 100644 index 0000000000..a15690a762 --- /dev/null +++ b/test/test_mpi_t8code_3d.jl @@ -0,0 +1,180 @@ +module TestExamplesMPIT8codeMesh3D + +using Test +using Trixi + +include("test_trixi.jl") + +const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_3d_dgsem") + +@testset "T8codeMesh MPI 3D" begin +#! format: noindent + +# Run basic tests +@testset "Examples 3D" begin + # Linear scalar advection + @trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[0.00016263963870641478], + linf=[0.0014537194925779984]) + + @testset "error-based step size control" begin + Trixi.mpi_isroot() && println("-"^100) + Trixi.mpi_isroot() && + println("elixir_advection_basic.jl with error-based step size control") + + sol = solve(ode, RDPK3SpFSAL35(); abstol = 1.0e-4, reltol = 1.0e-4, + ode_default_options()..., callback = callbacks) + summary_callback() + errors = analysis_callback(sol) + if Trixi.mpi_isroot() + @test errors.l2≈[0.00016800412839949264] rtol=1.0e-4 + @test errors.linf≈[0.0014548839020096516] rtol=1.0e-4 + end + end + + # 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_advection_amr.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[1.1302812803902801e-5], + linf=[0.0007889950196294793], + # override values are different from the serial tests to ensure each process holds at least + # one element, otherwise OrdinaryDiffEq fails during initialization + coverage_override=(maxiters = 6, + initial_refinement_level = 2, + base_level = 2, med_level = 3, + max_level = 4)) + + # 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_advection_amr_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_curved.jl"), + l2=[2.0556575425846923e-5], + linf=[0.00105682693484822], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 6, + initial_refinement_level = 0, + base_level = 0, med_level = 1, + max_level = 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 + + # Compressible Euler + @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_curved.jl"), + l2=[ + 4.070355207909268e-5, + 4.4993257426833716e-5, + 5.10588457841744e-5, + 5.102840924036687e-5, + 0.00019986264001630542, + ], + linf=[ + 0.0016987332417202072, + 0.003622956808262634, + 0.002029576258317789, + 0.0024206977281964193, + 0.008526972236273522, + ], + tspan=(0.0, 0.01)) + + # 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_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 0.0015106060984283647, + 0.0014733349038567685, + 0.00147333490385685, + 0.001473334903856929, + 0.0028149479453087093, + ], + linf=[ + 0.008070806335238156, + 0.009007245083113125, + 0.009007245083121784, + 0.009007245083102688, + 0.01562861968368434, + ], + tspan=(0.0, 1.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_euler_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), + l2=[ + 0.010380390326164493, + 0.006192950051354618, + 0.005970674274073704, + 0.005965831290564327, + 0.02628875593094754, + ], + linf=[ + 0.3326911600075694, + 0.2824952141320467, + 0.41401037398065543, + 0.45574161423218573, + 0.8099577682187109, + ], + tspan=(0.0, 0.2), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + + # 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 # T8codeMesh MPI + +end # module diff --git a/test/test_mpi_tree.jl b/test/test_mpi_tree.jl index 0831f6a131..6351a405b5 100644 --- a/test/test_mpi_tree.jl +++ b/test/test_mpi_tree.jl @@ -76,7 +76,8 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() # Here, we also test that SaveSolutionCallback prints multiple mesh files with AMR # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" - isdir(outdir) && rm(outdir, recursive = true) + Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive = true) + Trixi.MPI.Barrier(Trixi.mpi_comm()) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_refine_twice.jl"), l2=[0.00020547512522578292], diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 6632cd0bb2..9f1382caa6 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -218,9 +218,9 @@ end "elixir_advection_diffusion.jl"), tspan=(0.0, 0.0)) LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 8 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 8)]) + num_leaves = length(LLID) + @assert num_leaves % 8 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leaves / 8)]) tspan = (0.0, 1.5) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), @@ -414,9 +414,9 @@ end "elixir_navierstokes_convergence.jl"), tspan=(0.0, 0.0), initial_refinement_level=3) LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 4 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 4)]) + num_leaves = length(LLID) + @assert num_leaves % 4 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leaves / 4)]) tspan = (0.0, 0.5) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; @@ -561,8 +561,8 @@ end @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_nonperiodic_amr.jl"), tspan=(0.0, 0.01), - l2=[0.00793438523666649], - linf=[0.11030633127144573]) + l2=[0.007933791324450538], + linf=[0.11029480573492567]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 6fbfb8259d..1eaa9f51a5 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -252,9 +252,9 @@ end "elixir_navierstokes_convergence.jl"), tspan=(0.0, 0.0)) LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 16 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 16)]) + num_leaves = length(LLID) + @assert num_leaves % 16 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leaves / 16)]) tspan = (0.0, 0.25) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; @@ -325,9 +325,9 @@ end "elixir_navierstokes_taylor_green_vortex.jl"), tspan=(0.0, 0.0)) LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 32 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 32)]) + num_leaves = length(LLID) + @assert num_leaves % 32 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leaves / 32)]) tspan = (0.0, 0.1) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -429,8 +429,8 @@ end "elixir_advection_diffusion_amr.jl"), l2=[0.000355780485397024], linf=[0.0010810770271614256]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) let t = sol.t[end] u_ode = sol.u[end] @@ -444,8 +444,8 @@ end "elixir_advection_diffusion_nonperiodic.jl"), l2=[0.0009808996243280868], linf=[0.01732621559135459]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) let t = sol.t[end] u_ode = sol.u[end] @@ -472,8 +472,8 @@ end 0.12129218723807476, 0.8433893297612087, ]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) let t = sol.t[end] u_ode = sol.u[end] @@ -495,8 +495,8 @@ end 0.6782397526873181, 0.17663702154066238, 0.17663702154066266, 0.17663702154066238, 1.7327849844825238, ]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) let t = sol.t[end] u_ode = sol.u[end] diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 0a60f0e440..2c364e65b3 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -33,14 +33,34 @@ end @trixi_testset "elixir_advection_coupled.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_coupled.jl"), - l2=[7.816742843181738e-6, 7.816742843196112e-6], - linf=[6.314906965543265e-5, 6.314906965410039e-5], + l2=[ + 7.816742843336293e-6, + 7.816742843340186e-6, + 7.816742843025513e-6, + 7.816742843061526e-6, + ], + linf=[ + 6.314906965276812e-5, + 6.314906965187994e-5, + 6.31490696496595e-5, + 6.314906965032563e-5, + ], coverage_override=(maxiters = 10^5,)) @testset "analysis_callback(sol) for AnalysisCallbackCoupled" begin errors = analysis_callback(sol) - @test errors.l2≈[7.816742843181738e-6, 7.816742843196112e-6] rtol=1.0e-4 - @test errors.linf≈[6.314906965543265e-5, 6.314906965410039e-5] rtol=1.0e-4 + @test errors.l2≈[ + 7.816742843336293e-6, + 7.816742843340186e-6, + 7.816742843025513e-6, + 7.816742843061526e-6, + ] rtol=1.0e-4 + @test errors.linf≈[ + 6.314906965276812e-5, + 6.314906965187994e-5, + 6.31490696496595e-5, + 6.314906965032563e-5, + ] rtol=1.0e-4 # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_t8code_2d.jl b/test/test_t8code_2d.jl index ab95e068d0..d536a6dd73 100644 --- a/test/test_t8code_2d.jl +++ b/test/test_t8code_2d.jl @@ -33,10 +33,9 @@ end @trixi_testset "test check_for_negative_volumes" begin @test_warn "Discovered negative volumes" begin # Unstructured mesh with six cells which have left-handed node ordering. - mesh_file = joinpath(EXAMPLES_DIR, "rectangle_with_negative_volumes.msh") - isfile(mesh_file) || - download("https://gist.githubusercontent.com/jmark/bfe0d45f8e369298d6cc637733819013/raw/cecf86edecc736e8b3e06e354c494b2052d41f7a/rectangle_with_negative_volumes.msh", - mesh_file) + mesh_file = Trixi.download("https://gist.githubusercontent.com/jmark/bfe0d45f8e369298d6cc637733819013/raw/cecf86edecc736e8b3e06e354c494b2052d41f7a/rectangle_with_negative_volumes.msh", + joinpath(EXAMPLES_DIR, + "rectangle_with_negative_volumes.msh")) # This call should throw a warning about negative volumes detected. mesh = T8codeMesh(mesh_file, 2) diff --git a/test/test_threaded.jl b/test/test_threaded.jl index dbbcbf4c7c..a8a1b1b425 100644 --- a/test/test_threaded.jl +++ b/test/test_threaded.jl @@ -8,6 +8,7 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive = true) +Trixi.MPI.Barrier(Trixi.mpi_comm()) @testset "Threaded tests" begin #! format: noindent @@ -471,5 +472,6 @@ end # Clean up afterwards: delete Trixi.jl output directory Trixi.mpi_isroot() && isdir(outdir) && @test_nowarn rm(outdir, recursive = true) +Trixi.MPI.Barrier(Trixi.mpi_comm()) end # module diff --git a/test/test_unit.jl b/test/test_unit.jl index ed6cf2a2ae..ee6f97a210 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1226,7 +1226,7 @@ end end end -@testset "Consistency check for variable_derivative routine" begin +@testset "Consistency check for `gradient_conservative` routine" begin # Set up conservative variables, equations u = [ 0.5011914484393387, @@ -1242,8 +1242,8 @@ end return pressure(u, equations) end - @test Trixi.variable_derivative(pressure_test, u, equations) ≈ - Trixi.variable_derivative(pressure, u, equations) + @test Trixi.gradient_conservative(pressure_test, u, equations) ≈ + Trixi.gradient_conservative(pressure, u, equations) end @testset "Equivalent Fluxes" begin From 6464f4d35e791c5a4239b8c03f865933b881699e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 5 Feb 2024 12:49:51 +0100 Subject: [PATCH 410/423] Clean up testing --- examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl | 5 ++--- test/test_tree_2d_euler.jl | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 51e42bf4a0..71ee8b3bb8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -95,9 +95,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -output_directory = "out" -stage_callbacks = (BoundsCheckCallback(save_errors = true, interval = 100, - output_directory = output_directory),) +stage_callbacks = (BoundsCheckCallback(save_errors = false, interval = 100, + output_directory = "out")) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 42cca8ea59..a32ba98ada 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -515,7 +515,9 @@ end ], tspan=(0.0, 1.0), initial_refinement_level=4, - coverage_override=(maxiters = 6,)) + coverage_override=(maxiters = 6,), + save_errors=true, + output_directory="out") lines = readlines("out/deviations.txt") @test lines[1] == "# iter, simu_time, rho_min, rho_max, rho_v1_min, rho_v1_max, rho_v2_min, rho_v2_max, rho_e_min, rho_e_max, pressure_min" From dc7267804c61b839e1ea1fdaf5257892ec9f59bb Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 5 Feb 2024 13:56:27 +0100 Subject: [PATCH 411/423] Fix bug --- examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 71ee8b3bb8..7751133dcf 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -96,7 +96,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation stage_callbacks = (BoundsCheckCallback(save_errors = false, interval = 100, - output_directory = "out")) + output_directory = "out"),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback From bf47a2bd670aaf77975f49032c0e26401fd47f28 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 20 Mar 2024 13:07:10 +0100 Subject: [PATCH 412/423] Remove doubled foreach_enumerate --- src/auxiliary/auxiliary.jl | 1 + .../semidiscretization_coupled.jl | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/auxiliary/auxiliary.jl b/src/auxiliary/auxiliary.jl index e487699bcd..59af650e2d 100644 --- a/src/auxiliary/auxiliary.jl +++ b/src/auxiliary/auxiliary.jl @@ -373,6 +373,7 @@ end # # Note that compile times may increase if this is used with big tuples. # TODO: Add comment in the respective PR (here and where it is used: `dg_p4est/dg_2d_subcell_limiters.jl`) +# Deleted version in `semidiscretization_coupled.jl` @inline foreach_enumerate(func, collection) = foreach_enumerate(func, collection, 1) @inline foreach_enumerate(func, collection::Tuple{}, index) = nothing diff --git a/src/semidiscretization/semidiscretization_coupled.jl b/src/semidiscretization/semidiscretization_coupled.jl index dc21dbe9a1..ded9373cc8 100644 --- a/src/semidiscretization/semidiscretization_coupled.jl +++ b/src/semidiscretization/semidiscretization_coupled.jl @@ -143,18 +143,18 @@ end # Same as `foreach(enumerate(something))`, but without allocations. # # Note that compile times may increase if this is used with big tuples. -@inline foreach_enumerate(func, collection) = foreach_enumerate(func, collection, 1) -@inline foreach_enumerate(func, collection::Tuple{}, index) = nothing +# @inline foreach_enumerate(func, collection) = foreach_enumerate(func, collection, 1) +# @inline foreach_enumerate(func, collection::Tuple{}, index) = nothing -@inline function foreach_enumerate(func, collection, index) - element = first(collection) - remaining_collection = Base.tail(collection) +# @inline function foreach_enumerate(func, collection, index) +# element = first(collection) +# remaining_collection = Base.tail(collection) - func((index, element)) +# func((index, element)) - # Process remaining collection - foreach_enumerate(func, remaining_collection, index + 1) -end +# # Process remaining collection +# foreach_enumerate(func, remaining_collection, index + 1) +# end function rhs!(du_ode, u_ode, semi::SemidiscretizationCoupled, t) @unpack u_indices = semi From 2507794429be46ecc08d22851677105facb3f4b7 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:00:29 +0100 Subject: [PATCH 413/423] Use @batch reduction for bounds check (#126) * Use @batch reduction for bounds check * Remove section in documentation --- docs/src/performance.md | 11 --- .../subcell_bounds_check_2d.jl | 77 +++++++------------ src/solvers/dgsem_tree/subcell_limiters_2d.jl | 10 +-- 3 files changed, 28 insertions(+), 70 deletions(-) diff --git a/docs/src/performance.md b/docs/src/performance.md index 40970e58c5..9f81d3c3d8 100644 --- a/docs/src/performance.md +++ b/docs/src/performance.md @@ -282,14 +282,3 @@ requires. It can thus be seen as a proxy for "energy used" and, as an extension, timing result, you need to set the analysis interval such that the `AnalysisCallback` is invoked at least once during the course of the simulation and discard the first PID value. - -## Performance issues with multi-threaded reductions -[False sharing](https://en.wikipedia.org/wiki/False_sharing) is a known performance issue -for systems with distributed caches. It also occurred for the implementation of a thread -parallel bounds checking routine for the subcell IDP limiting -in [PR #1736](https://github.com/trixi-framework/Trixi.jl/pull/1736). -After some [testing and discussion](https://github.com/trixi-framework/Trixi.jl/pull/1736#discussion_r1423881895), -it turned out that initializing a vector of length `n * Threads.nthreads()` and only using every -n-th entry instead of a vector of length `Threads.nthreads()` fixes the problem. -Since there are no processors with caches over 128B, we use `n = 128B / size(uEltype)`. -Now, the bounds checking routine of the IDP limiting scales as hoped. diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index a2441e0bcd..9f2cd379aa 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -11,25 +11,15 @@ (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta_local, idp_bounds_delta_global) = limiter.cache - # Note: Accessing the threaded memory vector `idp_bounds_delta_local` with - # `deviation = idp_bounds_delta_local[key][Threads.threadid()]` causes critical performance - # issues due to False Sharing. - # Initializing a vector with n times the length and using every n-th entry fixes this - # problem and allows proper scaling: - # `deviation = idp_bounds_delta_local[key][n * Threads.threadid()]` - # Since there are no processors with caches over 128B, we use `n = 128B / size(uEltype)` - stride_size = div(128, sizeof(eltype(u))) # = n - if local_minmax for v in limiter.local_minmax_variables_cons v_string = string(v) key_min = Symbol(v_string, "_min") key_max = Symbol(v_string, "_max") - deviation_min_threaded = idp_bounds_delta_local[key_min] - deviation_max_threaded = idp_bounds_delta_local[key_max] - @threaded for element in eachelement(solver, cache) - deviation_min = deviation_min_threaded[stride_size * Threads.threadid()] - deviation_max = deviation_max_threaded[stride_size * Threads.threadid()] + deviation_min = idp_bounds_delta_local[key_min] + deviation_max = idp_bounds_delta_local[key_max] + @batch reduction=((max, deviation_min), (max, deviation_max)) for element in eachelement(solver, + cache) for j in eachnode(solver), i in eachnode(solver) var = u[v, i, j, element] deviation_min = max(deviation_min, @@ -37,36 +27,34 @@ deviation_max = max(deviation_max, var - variable_bounds[key_max][i, j, element]) end - deviation_min_threaded[stride_size * Threads.threadid()] = deviation_min - deviation_max_threaded[stride_size * Threads.threadid()] = deviation_max end + idp_bounds_delta_local[key_min] = deviation_min + idp_bounds_delta_local[key_max] = deviation_max end end if spec_entropy key = :spec_entropy_min - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] + deviation = idp_bounds_delta_local[key] + @batch reduction=(max, deviation) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), equations) deviation = max(deviation, variable_bounds[key][i, j, element] - s) end - deviation_threaded[stride_size * Threads.threadid()] = deviation end + idp_bounds_delta_local[key] = deviation end if math_entropy key = :math_entropy_max - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] + deviation = idp_bounds_delta_local[key] + @batch reduction=(max, deviation) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) s = entropy_math(get_node_vars(u, equations, solver, i, j, element), equations) deviation = max(deviation, s - variable_bounds[key][i, j, element]) end - deviation_threaded[stride_size * Threads.threadid()] = deviation end + idp_bounds_delta_local[key] = deviation end if positivity for v in limiter.positivity_variables_cons @@ -74,40 +62,35 @@ continue end key = Symbol(string(v), "_min") - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] + deviation = idp_bounds_delta_local[key] + @batch reduction=(max, deviation) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) var = u[v, i, j, element] deviation = max(deviation, variable_bounds[key][i, j, element] - var) end - deviation_threaded[stride_size * Threads.threadid()] = deviation end + idp_bounds_delta_local[key] = deviation end for variable in limiter.positivity_variables_nonlinear key = Symbol(string(variable), "_min") - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] + deviation = idp_bounds_delta_local[key] + @batch reduction=(max, deviation) for element in eachelement(solver, cache) for j in eachnode(solver), i in eachnode(solver) var = variable(get_node_vars(u, equations, solver, i, j, element), equations) deviation = max(deviation, variable_bounds[key][i, j, element] - var) end - deviation_threaded[stride_size * Threads.threadid()] = deviation end + idp_bounds_delta_local[key] = deviation end end for (key, _) in idp_bounds_delta_local - # Calculate maximum deviations of all threads - idp_bounds_delta_local[key][stride_size] = maximum(idp_bounds_delta_local[key][stride_size * i] - for i in 1:Threads.nthreads()) # Update global maximum deviations idp_bounds_delta_global[key] = max(idp_bounds_delta_global[key], - idp_bounds_delta_local[key][stride_size]) + idp_bounds_delta_local[key]) end return nothing @@ -118,46 +101,38 @@ end (; local_minmax, positivity, spec_entropy, math_entropy) = limiter (; idp_bounds_delta_local) = limiter.cache - stride_size = div(128, sizeof(eltype(u))) # = n - # Print errors to output file open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) if local_minmax for v in limiter.local_minmax_variables_cons v_string = string(v) - print(f, ", ", - idp_bounds_delta_local[Symbol(v_string, "_min")][stride_size], - ", ", - idp_bounds_delta_local[Symbol(v_string, "_max")][stride_size]) + print(f, ", ", idp_bounds_delta_local[Symbol(v_string, "_min")], + ", ", idp_bounds_delta_local[Symbol(v_string, "_max")]) end end if spec_entropy - print(f, ", ", idp_bounds_delta_local[:spec_entropy_min][stride_size]) + print(f, ", ", idp_bounds_delta_local[:spec_entropy_min]) end if math_entropy - print(f, ", ", idp_bounds_delta_local[:math_entropy_max][stride_size]) + print(f, ", ", idp_bounds_delta_local[:math_entropy_max]) end if positivity for v in limiter.positivity_variables_cons if v in limiter.local_minmax_variables_cons continue end - print(f, ", ", - idp_bounds_delta_local[Symbol(string(v), "_min")][stride_size]) + print(f, ", ", idp_bounds_delta_local[Symbol(string(v), "_min")]) end for variable in limiter.positivity_variables_nonlinear - print(f, ", ", - idp_bounds_delta_local[Symbol(string(variable), "_min")][stride_size]) + print(f, ", ", idp_bounds_delta_local[Symbol(string(variable), "_min")]) end end println(f) end # Reset local maximum deviations for (key, _) in idp_bounds_delta_local - for i in 1:Threads.nthreads() - idp_bounds_delta_local[key][stride_size * i] = zero(eltype(idp_bounds_delta_local[key][stride_size])) - end + idp_bounds_delta_local[key] = zero(eltype(idp_bounds_delta_local[key])) end return nothing diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 19eb3eb3a9..4be26f28f2 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -26,18 +26,12 @@ function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquat # Memory for bounds checking routine with `BoundsCheckCallback`. # Local variable contains the maximum deviation since the last export. - # Using a threaded vector to parallelize bounds check. - idp_bounds_delta_local = Dict{Symbol, Vector{real(basis)}}() + idp_bounds_delta_local = Dict{Symbol, real(basis)}() # Global variable contains the total maximum deviation. idp_bounds_delta_global = Dict{Symbol, real(basis)}() - # Note: False sharing causes critical performance issues on multiple threads when using a vector - # of length `Threads.nthreads()`. Initializing a vector of length `n * Threads.nthreads()` - # and then only using every n-th entry, fixes the problem and allows proper scaling. - # Since there are no processors with caches over 128B, we use `n = 128B / size(uEltype)` stride_size = div(128, sizeof(eltype(basis.nodes))) # = n for key in bound_keys - idp_bounds_delta_local[key] = [zero(real(basis)) - for _ in 1:(stride_size * Threads.nthreads())] + idp_bounds_delta_local[key] = zero(real(basis)) idp_bounds_delta_global[key] = zero(real(basis)) end From c2b197ad1a6e5a3bac3f3c3f31f411246953a380 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Sun, 12 May 2024 10:23:04 +0200 Subject: [PATCH 414/423] Merge main (#127) * Merge main (first version) * Fix bug * Fix setup in tutorial * Adapt tests * Add bar_states variable to unit test * fmt --- .github/review-checklist.md | 4 +- .github/workflows/Documenter.yml | 4 +- .github/workflows/Downgrade.yml | 2 +- .github/workflows/Invalidations.yml | 2 +- .github/workflows/SpellCheck.yml | 2 +- .github/workflows/benchmark.yml | 4 +- .github/workflows/ci.yml | 26 +- .github/workflows/downstream.yml | 2 +- NEWS.md | 20 +- Project.toml | 2 +- docs/.gitignore | 1 + docs/Project.toml | 2 + docs/literate/make.jl | 12 +- .../src/files/first_steps/changing_trixi.jl | 40 +- .../files/first_steps/create_first_setup.jl | 110 +++-- .../src/files/first_steps/getting_started.jl | 109 +++-- docs/literate/src/files/hohqmesh_tutorial.jl | 1 + docs/literate/src/files/index.jl | 72 +++- .../src/files/non_periodic_boundaries.jl | 2 +- .../src/files/scalar_linear_advection_1d.jl | 6 +- .../src/files/subcell_shock_capturing.jl | 288 +++++++++++++ docs/make.jl | 13 +- docs/src/meshes/structured_mesh.md | 2 + docs/src/meshes/tree_mesh.md | 2 +- docs/src/multi-physics_coupling.md | 11 + docs/src/overview.md | 8 + .../elixir_burgers_gauss_shock_capturing.jl | 68 +++ ...ixir_advection_amr_solution_independent.jl | 2 +- .../elixir_euler_NACA0012airfoil_mach085.jl | 132 ++++++ .../elixir_euler_double_mach.jl | 5 +- .../elixir_euler_free_stream_sc_subcell.jl | 1 - .../elixir_euler_subsonic_cylinder.jl | 125 ++++++ ...ir_euler_supersonic_cylinder_sc_subcell.jl | 3 +- ...xir_navierstokes_NACA0012airfoil_mach08.jl | 169 ++++++++ .../elixir_linearizedeuler_convergence.jl | 64 +++ ...r_linearizedeuler_characteristic_system.jl | 112 +++++ .../elixir_advection_meshview.jl | 122 ++++++ ...elixir_euler_convergence_wavingflag_IDP.jl | 1 - .../elixir_euler_double_mach.jl | 5 +- .../elixir_euler_free_stream_sc_subcell.jl | 1 - .../elixir_euler_shock_upstream_sc_subcell.jl | 5 +- .../elixir_euler_source_terms_sc_subcell.jl | 5 +- .../structured_2d_dgsem/elixir_mhd_coupled.jl | 136 ++++++ .../elixir_shallowwater_source_terms.jl | 2 +- .../elixir_shallowwater_well_balanced.jl | 2 +- ...ixir_advection_amr_solution_independent.jl | 2 +- .../elixir_linearizedeuler_convergence.jl | 59 +++ .../elixir_linearizedeuler_gauss_wall.jl | 65 +++ .../tree_1d_dgsem/elixir_shallowwater_ec.jl | 2 +- ...xir_shallowwater_quasi_1d_well_balanced.jl | 2 +- .../elixir_shallowwater_well_balanced.jl | 2 +- ...ixir_advection_amr_solution_independent.jl | 2 +- .../elixir_euler_astro_jet_subcell.jl | 5 +- .../elixir_euler_blast_wave_sc_subcell.jl | 5 +- ...euler_blast_wave_sc_subcell_nonperiodic.jl | 5 +- .../elixir_euler_convergence_IDP.jl | 1 - ...kelvin_helmholtz_instability_sc_subcell.jl | 1 - ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 5 +- .../elixir_euler_source_terms_sc_subcell.jl | 2 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 5 +- ...ubble_shockcapturing_subcell_positivity.jl | 1 - .../tree_2d_dgsem/elixir_shallowwater_ec.jl | 2 +- .../elixir_shallowwater_well_balanced.jl | 2 +- .../elixir_shallowwater_well_balanced_wall.jl | 2 +- .../elixir_linearizedeuler_gauss_wall.jl | 65 +++ .../elixir_shallowwater_ec.jl | 2 +- .../elixir_shallowwater_ec_shockcapturing.jl | 2 +- .../elixir_shallowwater_well_balanced.jl | 2 +- src/Trixi.jl | 9 +- src/callbacks_stage/subcell_bounds_check.jl | 41 +- .../subcell_bounds_check_2d.jl | 66 ++- src/callbacks_step/amr.jl | 8 +- src/callbacks_step/analysis.jl | 31 +- src/callbacks_step/analysis_dg2d.jl | 22 +- .../analysis_surface_integral_2d.jl | 400 ++++++++++++++++++ .../euler_acoustics_coupling_dg2d.jl | 2 +- src/callbacks_step/glm_speed.jl | 39 +- src/callbacks_step/save_solution_dg.jl | 1 + src/callbacks_step/stepsize_dg2d.jl | 4 +- src/callbacks_step/time_series_dg.jl | 4 +- src/callbacks_step/time_series_dg_tree.jl | 16 +- .../time_series_dg_unstructured.jl | 10 +- src/equations/compressible_euler_2d.jl | 66 ++- src/equations/compressible_euler_3d.jl | 40 +- src/equations/equations.jl | 2 + src/equations/inviscid_burgers_1d.jl | 1 + src/equations/laplace_diffusion_1d.jl | 11 +- src/equations/laplace_diffusion_2d.jl | 33 +- src/equations/laplace_diffusion_3d.jl | 33 +- src/equations/linearized_euler_1d.jl | 144 +++++++ src/equations/linearized_euler_2d.jl | 4 +- src/equations/linearized_euler_3d.jl | 254 +++++++++++ src/equations/shallow_water_1d.jl | 2 +- src/equations/shallow_water_2d.jl | 2 +- src/equations/shallow_water_quasi_1d.jl | 2 +- src/meshes/mesh_io.jl | 12 +- src/meshes/meshes.jl | 1 + src/meshes/structured_mesh_view.jl | 132 ++++++ .../semidiscretization_coupled.jl | 66 ++- .../semidiscretization_euler_acoustics.jl | 4 +- .../semidiscretization_hyperbolic.jl | 3 +- src/solvers/dg.jl | 5 +- .../dgmulti/flux_differencing_gauss_sbp.jl | 40 +- src/solvers/dgmulti/types.jl | 3 + src/solvers/dgsem_p4est/dg.jl | 3 +- src/solvers/dgsem_structured/containers.jl | 3 +- src/solvers/dgsem_structured/containers_2d.jl | 7 +- src/solvers/dgsem_structured/dg.jl | 11 +- src/solvers/dgsem_structured/dg_2d.jl | 23 +- src/solvers/dgsem_tree/dg_2d.jl | 8 +- .../dgsem_tree/dg_2d_subcell_limiters.jl | 120 +++--- src/solvers/dgsem_tree/subcell_limiters.jl | 143 ++++--- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 248 +++++------ .../sort_boundary_conditions.jl | 18 +- src/time_integration/methods_SSP.jl | 16 +- src/visualization/utilities.jl | 4 +- test/test_dgmulti_1d.jl | 16 + test/test_p4est_2d.jl | 114 ++++- test/test_p4est_3d.jl | 51 +++ test/test_parabolic_1d.jl | 32 +- test/test_parabolic_2d.jl | 53 ++- test/test_structured_1d.jl | 15 + test/test_structured_2d.jl | 107 ++++- test/test_tree_1d.jl | 3 + test/test_tree_1d_linearizedeuler.jl | 51 +++ test/test_tree_1d_shallowwater.jl | 18 +- test/test_tree_2d_euler.jl | 64 ++- test/test_tree_2d_eulermulti.jl | 10 +- test/test_tree_2d_shallowwater.jl | 24 +- test/test_tree_3d_linearizedeuler.jl | 35 ++ test/test_tree_3d_part2.jl | 3 + test/test_trixi.jl | 4 +- test/test_unit.jl | 68 ++- test/test_unstructured_2d.jl | 108 ++--- utils/trixi2txt.jl | 8 +- 135 files changed, 3986 insertions(+), 863 deletions(-) create mode 100644 docs/literate/src/files/subcell_shock_capturing.jl create mode 100644 examples/dgmulti_1d/elixir_burgers_gauss_shock_capturing.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl create mode 100644 examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl create mode 100644 examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl create mode 100644 examples/p4est_3d_dgsem/elixir_linearizedeuler_convergence.jl create mode 100644 examples/structured_1d_dgsem/elixir_linearizedeuler_characteristic_system.jl create mode 100644 examples/structured_2d_dgsem/elixir_advection_meshview.jl create mode 100644 examples/structured_2d_dgsem/elixir_mhd_coupled.jl create mode 100644 examples/tree_1d_dgsem/elixir_linearizedeuler_convergence.jl create mode 100644 examples/tree_1d_dgsem/elixir_linearizedeuler_gauss_wall.jl create mode 100644 examples/tree_3d_dgsem/elixir_linearizedeuler_gauss_wall.jl create mode 100644 src/callbacks_step/analysis_surface_integral_2d.jl create mode 100644 src/equations/linearized_euler_1d.jl create mode 100644 src/equations/linearized_euler_3d.jl create mode 100644 src/meshes/structured_mesh_view.jl create mode 100644 test/test_tree_1d_linearizedeuler.jl create mode 100644 test/test_tree_3d_linearizedeuler.jl diff --git a/.github/review-checklist.md b/.github/review-checklist.md index 2d8a24f197..69410a0701 100644 --- a/.github/review-checklist.md +++ b/.github/review-checklist.md @@ -19,7 +19,7 @@ This checklist is meant to assist creators of PRs (to let them know what reviewe - [ ] Relevant publications are referenced in docstrings (see [example](https://github.com/trixi-framework/Trixi.jl/blob/7f83a1a938eecd9b841efe215a6e482e67cfdcc1/src/equations/compressible_euler_2d.jl#L601-L615) for formatting). - [ ] Inline comments are used to document longer or unusual code sections. - [ ] Comments describe intent ("why?") and not just functionality ("what?"). -- [ ] If the PR introduces a significant change or new feature, it is documented in `NEWS.md`. +- [ ] If the PR introduces a significant change or new feature, it is documented in `NEWS.md` with its PR number. #### Testing - [ ] The PR passes all tests. @@ -35,4 +35,4 @@ This checklist is meant to assist creators of PRs (to let them know what reviewe - [ ] If new equations/methods are added, a convergence test has been run and the results are posted in the PR. -*Created with :heart: by the Trixi.jl community.* \ No newline at end of file +*Created with :heart: by the Trixi.jl community.* diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 8f8d674ffa..df6623839d 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -34,9 +34,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: - version: '1.9' + version: '1.10' show-versioninfo: true - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml index dd5d8ee7e3..234939a801 100644 --- a/.github/workflows/Downgrade.yml +++ b/.github/workflows/Downgrade.yml @@ -64,7 +64,7 @@ jobs: - threaded steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} diff --git a/.github/workflows/Invalidations.yml b/.github/workflows/Invalidations.yml index 18048d26be..b2d34cbc85 100644 --- a/.github/workflows/Invalidations.yml +++ b/.github/workflows/Invalidations.yml @@ -16,7 +16,7 @@ jobs: if: github.base_ref == github.event.repository.default_branch runs-on: ubuntu-latest steps: - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: '1' - uses: actions/checkout@v4 diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml index 87e34cb50f..10bcc22786 100644 --- a/.github/workflows/SpellCheck.yml +++ b/.github/workflows/SpellCheck.yml @@ -10,4 +10,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v4 - name: Check spelling - uses: crate-ci/typos@v1.18.2 + uses: crate-ci/typos@v1.21.0 diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 4531c3aee0..5eba2e70f4 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -11,7 +11,7 @@ jobs: os: - ubuntu-latest version: - - '1.9' + - '1.10' arch: - x64 steps: @@ -21,7 +21,7 @@ jobs: - run: | git fetch --tags git branch --create-reflog main origin/main - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7dfe033a9..b4b3cfa148 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,8 +52,8 @@ jobs: fail-fast: false matrix: version: - - '1.9' - # - '~1.9.0-0' # including development versions + - '1.10' + # - '~1.10.0-0' # including development versions # - 'nightly' os: - ubuntu-latest @@ -86,28 +86,28 @@ jobs: arch: x64 trixi_test: threaded_legacy - version: '1.9' - os: macOS-latest + os: ubuntu-latest arch: x64 - trixi_test: mpi - - version: '1.9' - os: macOS-latest + trixi_test: threaded_legacy + - version: '1.10' + os: macos-13 arch: x64 + trixi_test: mpi + - version: '1.10' + os: macos-latest + arch: aarch64 trixi_test: threaded - - version: '1.9' + - version: '1.10' os: windows-latest arch: x64 trixi_test: mpi - - version: '1.9' + - version: '1.10' os: windows-latest arch: x64 trixi_test: threaded - - version: '1.9' - os: macos-14 - arch: arm64 - trixi_test: threaded steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index b40d5d365c..83ed6cc79c 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -64,7 +64,7 @@ jobs: - TrixiShallowWater.jl steps: - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v1 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} diff --git a/NEWS.md b/NEWS.md index 022252e61a..e2902229f7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,8 +8,11 @@ for human readability. #### Added - Implementation of `TimeSeriesCallback` for curvilinear meshes on `UnstructuredMesh2D` and extension - to 1D and 3D on `TreeMesh`. - + to 1D and 3D on `TreeMesh` ([#1855], [#1873]). +- Implementation of 1D Linearized Euler Equations ([#1867]). +- New analysis callback for 2D `P4estMesh` to compute integrated quantities along a boundary surface, e.g., pressure lift and drag coefficients ([#1812]). +- Optional tuple parameter for `GlmSpeedCallback` called `semi_indices` to specify for which semidiscretization of a `SemidiscretizationCoupled` we need to update the GLM speed ([#1835]). +- Subcell local one-sided limiting support for nonlinear variables in 2D for `TreeMesh` ([#1792]). ## Changes when updating to v0.7 from v0.6.x @@ -187,9 +190,8 @@ for human readability. #### Added - Experimental support for artificial neural network-based indicators for shock capturing and - adaptive mesh refinement ([#632](https://github.com/trixi-framework/Trixi.jl/pull/632)) -- Experimental support for direct-hybrid aeroacoustics simulations - ([#712](https://github.com/trixi-framework/Trixi.jl/pull/712)) + adaptive mesh refinement ([#632]) +- Experimental support for direct-hybrid aeroacoustics simulations ([#712]) - Implementation of shallow water equations in 2D - Experimental support for interactive visualization with [Makie.jl](https://makie.juliaplots.org/) @@ -225,7 +227,7 @@ for human readability. - acoustic perturbation equations - Lattice-Boltzmann equations - Composable `FluxPlusDissipation` and `FluxLaxFriedrichs()`, `FluxHLL()` with adaptable - wave speed estimates were added in [#493](https://github.com/trixi-framework/Trixi.jl/pull/493) + wave speed estimates were added in [#493] - New structured, curvilinear, conforming mesh type `StructuredMesh` - New unstructured, curvilinear, conforming mesh type `UnstructuredMesh2D` in 2D - New unstructured, curvilinear, adaptive (non-conforming) mesh type `P4estMesh` in 2D and 3D @@ -238,13 +240,13 @@ for human readability. - `flux_lax_friedrichs(u_ll, u_rr, orientation, equations::LatticeBoltzmannEquations2D)` and `flux_lax_friedrichs(u_ll, u_rr, orientation, equations::LatticeBoltzmannEquations3D)` were actually using the logic of `flux_godunov`. Thus, they were renamed accordingly - in [#493](https://github.com/trixi-framework/Trixi.jl/pull/493). This is considered a bugfix + in [#493]. This is considered a bugfix (released in Trixi.jl v0.3.22). - The required Julia version is updated to v1.6. #### Deprecated -- `calcflux` → `flux` ([#463](https://github.com/trixi-framework/Trixi.jl/pull/463)) +- `calcflux` → `flux` ([#463]) - `flux_upwind` → `flux_godunov` - `flux_hindenlang` → `flux_hindenlang_gassner` - Providing the keyword argument `solution_variables` of `SaveSolutionCallback` @@ -256,6 +258,6 @@ for human readability. only a single two-point numerical flux for nonconservative is deprecated. The new interface is described in a tutorial. Now, a tuple of two numerical fluxes of the form `(conservative_flux, nonconservative_flux)` needs to be passed for - nonconservative equations, see [#657](https://github.com/trixi-framework/Trixi.jl/pull/657). + nonconservative equations, see [#657]. #### Removed diff --git a/Project.toml b/Project.toml index 6ff7f29686..68f9060b9d 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.7.6-pre" +version = "0.7.12-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" diff --git a/docs/.gitignore b/docs/.gitignore index c8a9e84224..cc6f90fae0 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,3 +1,4 @@ +src/changelog.md src/code_of_conduct.md src/contributing.md diff --git a/docs/Project.toml b/docs/Project.toml index 3b8d169fdb..9f9bb95627 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,6 @@ [deps] CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +Changelog = "5217a498-cd5d-4ec6-b8c2-9b85a09b6e3e" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" HOHQMesh = "e4f4c7b8-17cb-445a-93c5-f69190ed6c8c" @@ -14,6 +15,7 @@ TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" [compat] CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10, 0.11" +Changelog = "1.1" Documenter = "1" ForwardDiff = "0.10" HOHQMesh = "0.1, 0.2" diff --git a/docs/literate/make.jl b/docs/literate/make.jl index 84e4fbdced..262a236971 100644 --- a/docs/literate/make.jl +++ b/docs/literate/make.jl @@ -75,7 +75,17 @@ function create_tutorials(files) end # Generate markdown file for introduction page - Literate.markdown(joinpath(repo_src, "index.jl"), pages_dir; name="introduction") + # Preprocessing introduction file: Generate consecutive tutorial numbers by replacing + # each occurrence of `{index}` with an integer incremented by 1, starting at 1. + function preprocess_introduction(content) + counter = 1 + while occursin("{index}", content) + content = replace(content, "{index}" => "$counter", count = 1) + counter += 1 + end + return content + end + Literate.markdown(joinpath(repo_src, "index.jl"), pages_dir; name="introduction", preprocess=preprocess_introduction) # Navigation system for makedocs pages = Any["Introduction" => "tutorials/introduction.md",] diff --git a/docs/literate/src/files/first_steps/changing_trixi.jl b/docs/literate/src/files/first_steps/changing_trixi.jl index 551377a6a7..b8f1fff6de 100644 --- a/docs/literate/src/files/first_steps/changing_trixi.jl +++ b/docs/literate/src/files/first_steps/changing_trixi.jl @@ -4,6 +4,14 @@ # the cloned directory. +# ## Forking Trixi.jl + +# To create your own fork of Trixi.jl, log in to your GitHub account, visit the +# [Trixi.jl GitHub repository](https://github.com/trixi-framework/Trixi.jl) and click the `Fork` +# button located in the upper-right corner of the page. Then, click on `Create fork` in the opened +# window to complete the forking process. + + # ## Cloning Trixi.jl @@ -15,8 +23,10 @@ # - Download and install [GitHub Desktop](https://desktop.github.com/) and then log in to # your account. # - Open GitHub Desktop, press `Ctrl+Shift+O`. -# - In the opened window, paste `trixi-framework/Trixi.jl` and choose the path to the folder where -# you want to save Trixi.jl. Then click `Clone` and Trixi.jl will be cloned to your computer. +# - In the opened window, navigate to the `URL` tab and paste `trixi-framework/Trixi.jl` or +# `YourGitHubUserName/Trixi.jl` to clone your own fork of Trixi.jl, and choose the +# path to the folder where you want to save Trixi.jl. Then click `Clone` and Trixi.jl will be +# cloned to your computer. # Now you cloned Trixi.jl and only need to tell Julia to use the local clone as the package sources: # - Open a terminal using `Win+r` and `cmd`. Navigate to the folder with the cloned Trixi.jl using `cd`. @@ -54,6 +64,9 @@ # julia --project=. -e 'using Pkg; Pkg.develop(PackageSpec(path=".."))' # Tell Julia to use the local Trixi.jl clone # julia --project=. -e 'using Pkg; Pkg.add(["OrdinaryDiffEq", "Plots"])' # Install additional packages # ``` +# Alternatively, you can clone your own fork of Trixi.jl by replacing the link +# `git@github.com:trixi-framework/Trixi.jl.git` with `git@github.com:YourGitHubUserName/Trixi.jl.git`. + # Note that if you installed Trixi.jl this way, # you always have to start Julia with the `--project` flag set to your `run` directory, e.g., # ```shell @@ -62,9 +75,32 @@ # if already inside the `run` directory. +# ## Developing Trixi.jl + +# If you've created and cloned your own fork of Trixi.jl, you can make local changes to Trixi.jl +# and propose them as a Pull Request (PR) to be merged into `trixi-framework/Trixi.jl`. + +# Linux and MacOS utilize the `git` version control system to manage changes between your local and +# remote repositories. The most commonly used commands include `add`, `commit`, `push` and `pull`. +# You can find detailed information about these functions in the +# [Git documentation](https://git-scm.com/docs). + +# For Windows and GitHub Desktop users, refer to the +# [documentation of GitHub Desktop](https://docs.github.com/en/desktop/overview/getting-started-with-github-desktop#making-changes-in-a-branch). + +# After making local changes to Trixi.jl and pushing them to the remote repository, you can open a +# Pull Request (PR) from your branch to the main branch of `trixi-framework/Trixi.jl`. Then, follow +# the Review checklist provided in the Pull Request to streamline the review process. + + # ## Additional reading # To further delve into Trixi.jl, you may have a look at the following introductory tutorials. +# - [Behind the scenes of a simulation setup](@ref behind_the_scenes_simulation_setup) will guide +# you through a simple Trixi.jl setup ("elixir"), giving an overview of what happens in the +# background during the initialization of a simulation. It clarifies some of the more +# fundamental, technical concepts that are applicable to a variety of (also more complex) +# configurations. # - [Introduction to DG methods](@ref scalar_linear_advection_1d) will teach you how to set up a # simple way to approximate the solution of a hyperbolic partial differential equation. It will # be especially useful to learn about the diff --git a/docs/literate/src/files/first_steps/create_first_setup.jl b/docs/literate/src/files/first_steps/create_first_setup.jl index 906a6f9346..ae78a6a154 100644 --- a/docs/literate/src/files/first_steps/create_first_setup.jl +++ b/docs/literate/src/files/first_steps/create_first_setup.jl @@ -1,4 +1,4 @@ -#src # Create first setup +#src # Create your first setup # In this part of the introductory guide, we will create a first Trixi.jl setup as an extension of # [`elixir_advection_basic.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_advection_basic.jl). @@ -19,7 +19,10 @@ # The first step is to create and open a file with the .jl extension. You can do this with your # favorite text editor (if you do not have one, we recommend [VS Code](https://code.visualstudio.com/)). -# In this file you will create your setup. +# In this file, you will create your setup. The file can then be executed in Julia using, for example, `trixi_include()`. +# Alternatively, you can execute each line of the following code one by one in the +# Julia REPL. This will generate useful output for nearly every +# command and improve your comprehension of the process. # To be able to use functionalities of Trixi.jl, you always need to load Trixi.jl itself # and the [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) package. @@ -65,7 +68,9 @@ mesh = TreeMesh(coordinates_min, coordinates_max, # To approximate the solution of the defined model, we create a [`DGSEM`](@ref) solver. # The solution in each of the recently defined mesh elements will be approximated by a polynomial # of degree `polydeg`. For more information about discontinuous Galerkin methods, -# check out the [Introduction to DG methods](@ref scalar_linear_advection_1d) tutorial. +# check out the [Introduction to DG methods](@ref scalar_linear_advection_1d) tutorial. By default, +# in the weak formulation `DGSEM` initializes the surface flux as `flux_central` and uses the physical flux for +# the volume integral. solver = DGSEM(polydeg=3) @@ -90,8 +95,8 @@ solver = DGSEM(polydeg=3) # [section about analyzing the solution](https://trixi-framework.github.io/Trixi.jl/stable/callbacks/#Analyzing-the-numerical-solution). function initial_condition_sinpi(x, t, equations::LinearScalarAdvectionEquation2D) - scalar = sinpi(x[1]) * sinpi(x[2]) - return SVector(scalar) + u = sinpi(x[1]) * sinpi(x[2]) + return SVector(u) end initial_condition = initial_condition_sinpi @@ -103,18 +108,20 @@ initial_condition = initial_condition_sinpi # equation itself as arguments and returns the source term as a static vector `SVector`. function source_term_exp_sinpi(u, x, t, equations::LinearScalarAdvectionEquation2D) - scalar = - 2 * exp(-t) * sinpi(2*(x[1] - t)) * sinpi(2*(x[2] - t)) - return SVector(scalar) + u = - 2 * exp(-t) * sinpi(2*(x[1] - t)) * sinpi(2*(x[2] - t)) + return SVector(u) end # Now we collect all the information that is necessary to define a spatial discretization, -# which leaves us with an ODE problem in time with a span from 0.0 to 1.0. -# This approach is commonly referred to as the method of lines. semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; source_terms = source_term_exp_sinpi) + +# which leaves us with an ODE problem in time with a span from `0.0` to `1.0`. +# This approach is commonly referred to as the method of lines. + tspan = (0.0, 1.0) -ode = semidiscretize(semi, tspan); +ode = semidiscretize(semi, tspan) # At this point, our problem is defined. We will use the `solve` function defined in # [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) to get the solution. @@ -126,22 +133,27 @@ ode = semidiscretize(semi, tspan); # We will show you how to use some of the common callbacks. # To print a summary of the simulation setup at the beginning -# and to reset timers we use the [`SummaryCallback`](@ref). -# When the returned callback is executed directly, the current timer values are shown. +# and to reset timers to zero, we use the [`SummaryCallback`](@ref). summary_callback = SummaryCallback() # We also want to analyze the current state of the solution in regular intervals. -# The [`AnalysisCallback`](@ref) outputs some useful statistical information during the solving process +# The [`AnalysisCallback`](@ref) outputs some useful statistical information during the simulation # every `interval` time steps. -analysis_callback = AnalysisCallback(semi, interval = 5) +analysis_callback = AnalysisCallback(semi, interval = 20) + +# To indicate that a simulation is still running, we utilize the inexpensive [`AliveCallback`](@ref) +# to periodically print information to the screen, such as the +# current time, every `alive_interval` time steps. + +alive_callback = AliveCallback(alive_interval = 10) # It is also possible to control the time step size using the [`StepsizeCallback`](@ref) if the time # integration method isn't adaptive itself. To get more details, look at # [CFL based step size control](@ref CFL-based-step-size-control). -stepsize_callback = StepsizeCallback(cfl = 1.6) +stepsize_callback = StepsizeCallback(cfl = 0.9) # To save the current solution in regular intervals we use the [`SaveSolutionCallback`](@ref). # We would like to save the initial and final solutions as well. The data @@ -149,7 +161,7 @@ stepsize_callback = StepsizeCallback(cfl = 1.6) # a solution from saved files using Trixi2Vtk.jl and ParaView, which is described below in the # section [Visualize the solution](@ref Visualize-the-solution). -save_solution = SaveSolutionCallback(interval = 5, +save_solution = SaveSolutionCallback(interval = 20, save_initial_solution = true, save_final_solution = true) @@ -170,19 +182,19 @@ save_restart = SaveRestartCallback(interval = 100, save_final_restart = true) # Create a `CallbackSet` to collect all callbacks so that they can be passed to the `solve` # function. -callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback, save_solution, - save_restart) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, + save_solution, save_restart); # The last step is to choose the time integration method. OrdinaryDiffEq.jl defines a wide range of -# [ODE solvers](https://docs.sciml.ai/DiffEqDocs/latest/solvers/ode_solve/), e.g. -# `CarpenterKennedy2N54(williamson_condition = false)`. We will pass the ODE -# problem, the ODE solver and the callbacks to the `solve` function. Also, to use +# [ODE solvers](https://docs.sciml.ai/DiffEqDocs/latest/solvers/ode_solve/), including the +# three-stage, third-order strong stability preserving Runge-Kutta method `SSPRK33`. We will pass +# the ODE problem, the ODE solver and the callbacks to the `solve` function. Also, to use # `StepsizeCallback`, we must explicitly specify the initial trial time step `dt`, the selected # value is not important, because it will be overwritten by the `StepsizeCallback`. And there is no -# need to save every step of the solution, we are only interested in the final result. +# need to save every step of the solution, as we are only interested the output provided by +# our callback [`SaveSolutionCallback`](@ref). -sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), dt = 1.0, - save_everystep = false, callback = callbacks); +sol = solve(ode, SSPRK33(); dt = 1.0, save_everystep = false, callback = callbacks); # Finally, we print the timer summary. @@ -202,17 +214,33 @@ summary_callback() # ### Using Plots.jl # The first option is to use the [Plots.jl](https://github.com/JuliaPlots/Plots.jl) package -# directly after calculations, when the solution is saved in the `sol` variable. We load the -# package and use the `plot` function. +# directly after calculations, when the solution is saved in the `sol` variable. using Plots -plot(sol) -# To show the mesh on the plot, we need to extract the visualization data from the solution as -# a [`PlotData2D`](@ref) object. Mesh extraction is possible using the [`getmesh`](@ref) function. +# As was shown in the [Getting started](@ref getting_started) section, you can plot all +# variables from the system of equations by executing the following. +# ```julia +# plot(sol) +# ``` +# Alternatively, you can configure the plot more precisely. Trixi.jl provides a special data type, +# [`PlotData2D`](@ref), to extract the visualization data from the solution. + +pd = PlotData2D(sol); + +# You can plot specific variables from the system of equations by referring to their names. +# To obtain the names of all variables, execute the following. + +@show pd.variable_names; + +# Plot the variable named "scalar" (which is the name of the variable for the +# linear advection equation in Trixi.jl). + +plot(pd["scalar"]) + +# Mesh extraction is possible using the [`getmesh`](@ref) function. # Plots.jl has the `plot!` function that allows you to modify an already built graph. -pd = PlotData2D(sol) plot!(getmesh(pd)) @@ -222,38 +250,38 @@ plot!(getmesh(pd)) # `solve` function with [`SaveSolutionCallback`](@ref) there is a file with the final solution. # It is located in the `out` folder and is named as follows: `solution_index.h5`. The `index` # is the final time step of the solution that is padded to 6 digits with zeros from the beginning. -# With [Trixi2Vtk](@ref) you can convert the HDF5 output file generated by Trixi.jl into a VTK file. -# This can be used in visualization tools such as [ParaView](https://www.paraview.org) or -# [VisIt](https://visit.llnl.gov) to plot the solution. The important thing is that currently -# Trixi2Vtk.jl supports conversion only for solutions in 2D and 3D spatial domains. +# With [Trixi2Vtk](@ref) you can convert the HDF5 output file generated by Trixi.jl into a VTK/VTU +# files. VTK/VTU are specialized formats designed to store structured data required for +# visualization purposes. This can be used in visualization tools such as +# [ParaView](https://www.paraview.org) or [VisIt](https://visit.llnl.gov) to plot the solution. # If you haven't added Trixi2Vtk.jl to your project yet, you can add it as follows. # ```julia # import Pkg # Pkg.add(["Trixi2Vtk"]) # ``` -# Now we load the Trixi2Vtk.jl package and convert the file `out/solution_000018.h5` with +# Now we load the Trixi2Vtk.jl package and convert the file `out/solution_000032.h5` with # the final solution using the [`trixi2vtk`](@ref) function saving the resulting file in the # `out` folder. using Trixi2Vtk -trixi2vtk(joinpath("out", "solution_000018.h5"), output_directory="out") +trixi2vtk(joinpath("out", "solution_000032.h5"), output_directory="out") -# Now two files `solution_000018.vtu` and `solution_000018_celldata.vtu` have been generated in the +# Now two files `solution_000032.vtu` and `solution_000032_celldata.vtu` have been generated in the # `out` folder. The first one contains all the information for visualizing the solution, the # second one contains all the cell-based or discretization-based information. # Now let's visualize the solution from the generated files in ParaView. Follow this short # instruction to get the visualization. # - Download, install and open [ParaView](https://www.paraview.org/download/). -# - Press `Ctrl+O` and select the generated files `solution_000018.vtu` and -# `solution_000018_celldata.vtu` from the `out` folder. +# - Press `Ctrl+O` and select the generated files `solution_000032.vtu` and +# `solution_000032_celldata.vtu` from the `out` folder. # - In the upper-left corner in the Pipeline Browser window, left-click on the eye-icon near -# `solution_000018.vtu`. +# `solution_000032.vtu`. # - In the lower-left corner in the Properties window, change the Coloring from Solid Color to # scalar. This already generates the visualization of the final solution. # - Now let's add the mesh to the visualization. In the upper-left corner in the -# Pipeline Browser window, left-click on the eye-icon near `solution_000018_celldata.vtu`. +# Pipeline Browser window, left-click on the eye-icon near `solution_000032_celldata.vtu`. # - In the lower-left corner in the Properties window, change the Representation from Surface # to Wireframe. Then a white grid should appear on the visualization. # Now, if you followed the instructions exactly, you should get a similar image as shown in the diff --git a/docs/literate/src/files/first_steps/getting_started.jl b/docs/literate/src/files/first_steps/getting_started.jl index 2bfaf33b5f..80ea78b51f 100644 --- a/docs/literate/src/files/first_steps/getting_started.jl +++ b/docs/literate/src/files/first_steps/getting_started.jl @@ -19,10 +19,10 @@ # Trixi.jl is compatible with the latest stable release of Julia. Additional details regarding Julia # support can be found in the [`README.md`](https://github.com/trixi-framework/Trixi.jl#installation) -# file. The current default Julia installation is managed through `juliaup`. You may follow our -# concise installation guidelines for Windows, Linux, and MacOS provided below. In the event of any -# issues during the installation process, please consult the official -# [Julia installation instruction](https://julialang.org/downloads/). +# file. After installation, the current default Julia version can be managed through the command +# line tool `juliaup`. You may follow our concise installation guidelines for Windows, Linux, and +# MacOS provided below. In the event of any issues during the installation process, please consult +# the official [Julia installation instruction](https://julialang.org/downloads/). # ### Windows @@ -32,6 +32,7 @@ # ```shell # winget install julia -s msstore # ``` +# Note: For this installation an MS Store account is necessary to proceed. # - Verify the successful installation of Julia by executing the following command in the terminal: # ```shell # julia @@ -69,14 +70,17 @@ # [Plots.jl](https://github.com/JuliaPlots/Plots.jl). # - Open a terminal and start Julia. -# - Execute following commands: +# - Execute the following commands to install all mentioned packages. Please note that the +# installation process involves downloading and precompiling the source code, which may take +# some time depending on your machine. # ```julia # import Pkg # Pkg.add(["OrdinaryDiffEq", "Plots", "Trixi"]) # ``` +# - On Windows, the firewall may request permission to install packages. -# Now you have installed all these -# packages. [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) provides time +# Besides Trixi.jl you have now installed two additional +# packages: [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) provides time # integration schemes used by Trixi.jl and [Plots.jl](https://github.com/JuliaPlots/Plots.jl) # can be used to directly visualize Trixi.jl results from the Julia REPL. @@ -102,7 +106,39 @@ # Let's execute a short two-dimensional problem setup. It approximates the solution of # the compressible Euler equations in 2D for an ideal gas ([`CompressibleEulerEquations2D`](@ref)) -# with a weak blast wave as the initial condition. +# with a weak blast wave as the initial condition and periodic boundary conditions. + +# The compressible Euler equations in two spatial dimensions are given by +# ```math +# \frac{\partial}{\partial t} +# \begin{pmatrix} +# \rho \\ \rho v_1 \\ \rho v_2 \\ \rho e +# \end{pmatrix} +# + +# \frac{\partial}{\partial x} +# \begin{pmatrix} +# \rho v_1 \\ \rho v_1^2 + p \\ \rho v_1 v_2 \\ (\rho e + p) v_1 +# \end{pmatrix} +# + +# \frac{\partial}{\partial y} +# \begin{pmatrix} +# \rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + p \\ (\rho e + p) v_2 +# \end{pmatrix} +# = +# \begin{pmatrix} +# 0 \\ 0 \\ 0 \\ 0 +# \end{pmatrix}, +# ``` +# for an ideal gas with the specific heat ratio ``\gamma``. +# Here, ``\rho`` is the density, ``v_1`` and ``v_2`` are the velocities, ``e`` is the specific +# total energy, and +# ```math +# p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right) +# ``` +# is the pressure. + +# The [`initial_condition_weak_blast_wave`](@ref) is specified in +# [`compressible_euler_2d.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/src/equations/compressible_euler_2d.jl) # Start Julia in a terminal and execute the following code: @@ -113,13 +149,26 @@ using Trixi, OrdinaryDiffEq #hide #md trixi_include(@__MODULE__,joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl")) #hide #md +# The output contains a recap of the setup and various information about the course of the simulation. +# For instance, the solution was approximated over the [`TreeMesh`](@ref) with 1024 effective cells using +# the `CarpenterKennedy2N54` ODE +# solver. Further details about the ODE solver can be found in the +# [documentation of OrdinaryDiffEq.jl](https://docs.sciml.ai/DiffEqDocs/stable/solvers/ode_solve/#Low-Storage-Methods) + # To analyze the result of the computation, we can use the Plots.jl package and the function # `plot(...)`, which creates a graphical representation of the solution. `sol` is a variable -# defined in the executed example and it contains the solution at the final moment of the simulation. +# defined in the executed example and it contains the solution after the simulation +# finishes. `sol.u` holds the vector of values at each saved timestep, while `sol.t` holds the +# corresponding times for each saved timestep. In this instance, only two timesteps were saved: the +# initial and final ones. The plot depicts the distribution of the weak blast wave at the final moment +# of time, showing the density, velocities, and pressure of the ideal gas across a 2D domain. using Plots plot(sol) + +# ### Getting an existing setup file + # To obtain a list of all Trixi.jl elixirs execute # [`get_examples`](@ref). It returns the paths to all example setups. @@ -127,9 +176,6 @@ get_examples() # Editing an existing elixir is the best way to start your first own investigation using Trixi.jl. - -# ### Getting an existing setup file - # To edit an existing elixir, you first have to find a suitable one and then copy it to a local # folder. Let's have a look at how to download the `elixir_euler_ec.jl` elixir used in the previous # section from the [Trixi.jl GitHub repository](https://github.com/trixi-framework/Trixi.jl). @@ -146,39 +192,9 @@ get_examples() # ### Modifying an existing setup # As an example, we will change the initial condition for calculations that occur in -# `elixir_euler_ec.jl`. In this example we consider the compressible Euler equations in two spatial -# dimensions, -# ```math -# \frac{\partial}{\partial t} -# \begin{pmatrix} -# \rho \\ \rho v_1 \\ \rho v_2 \\ \rho e -# \end{pmatrix} -# + -# \frac{\partial}{\partial x} -# \begin{pmatrix} -# \rho v_1 \\ \rho v_1^2 + p \\ \rho v_1 v_2 \\ (\rho e + p) v_1 -# \end{pmatrix} -# + -# \frac{\partial}{\partial y} -# \begin{pmatrix} -# \rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + p \\ (\rho e + p) v_2 -# \end{pmatrix} -# = -# \begin{pmatrix} -# 0 \\ 0 \\ 0 \\ 0 -# \end{pmatrix}, -# ``` -# for an ideal gas with the specific heat ratio ``\gamma``. -# Here, ``\rho`` is the density, ``v_1`` and ``v_2`` are the velocities, ``e`` is the specific -# total energy, and -# ```math -# p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right) -# ``` -# is the pressure. -# Initial conditions consist of initial values for ``\rho``, ``\rho v_1``, -# ``\rho v_2`` and ``\rho e``. -# One of the common initial conditions for the compressible Euler equations is a simple density -# wave. Let's implement it. +# `elixir_euler_ec.jl`. Initial conditions for [`CompressibleEulerEquations2D`](@ref) consist of +# initial values for ``\rho``, ``\rho v_1``, ``\rho v_2`` and ``\rho e``. One of the common initial +# conditions for the compressible Euler equations is a simple density wave. Let's implement it. # - Open the downloaded file `elixir_euler_ec.jl` with a text editor. # - Go to the line with the following code: @@ -202,6 +218,7 @@ function initial_condition_density_waves(x, t, equations::CompressibleEulerEquat return SVector(rho, rho*v1, rho*v2, rho_e) end initial_condition = initial_condition_density_waves +nothing; #hide #md # - Execute the following code one more time, but instead of `path/to/file` paste the path to the # `elixir_euler_ec.jl` file that you just edited. @@ -237,6 +254,6 @@ plot(p1, p2, p3, p4) #hide #md # Now you are able to download, modify and execute simulation setups for Trixi.jl. To explore # further details on setting up a new simulation with Trixi.jl, refer to the second part of -# the introduction titled [Create first setup](@ref create_first_setup). +# the introduction titled [Create your first setup](@ref create_first_setup). Sys.rm("out"; recursive=true, force=true) #hide #md \ No newline at end of file diff --git a/docs/literate/src/files/hohqmesh_tutorial.jl b/docs/literate/src/files/hohqmesh_tutorial.jl index b19d363c4b..dd81f47951 100644 --- a/docs/literate/src/files/hohqmesh_tutorial.jl +++ b/docs/literate/src/files/hohqmesh_tutorial.jl @@ -35,6 +35,7 @@ # There is a default example for this mesh type that can be executed by using Trixi +rm("out", force = true, recursive = true) #hide #md redirect_stdio(stdout=devnull, stderr=devnull) do # code that prints annoying stuff we don't want to see here #hide #md trixi_include(default_example_unstructured()) end #hide #md diff --git a/docs/literate/src/files/index.jl b/docs/literate/src/files/index.jl index 6d5800c3b6..fd1d884d47 100644 --- a/docs/literate/src/files/index.jl +++ b/docs/literate/src/files/index.jl @@ -14,14 +14,16 @@ # There are tutorials for the following topics: -# ### [1 First steps in Trixi.jl](@ref getting_started) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} First steps in Trixi.jl](@ref getting_started) #- # This tutorial provides guidance for getting started with Trixi.jl, and Julia as well. It outlines # the installation procedures for both Julia and Trixi.jl, the execution of Trixi.jl elixirs, the # fundamental structure of a Trixi.jl setup, the visualization of results, and the development # process for Trixi.jl. -# ### [2 Behind the scenes of a simulation setup](@ref behind_the_scenes_simulation_setup) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Behind the scenes of a simulation setup](@ref behind_the_scenes_simulation_setup) #- # This tutorial will guide you through a simple Trixi.jl setup ("elixir"), giving an overview of # what happens in the background during the initialization of a simulation. While the setup @@ -30,20 +32,23 @@ # the more fundamental, *technical* concepts that are applicable to a variety of # (also more complex) configurations.s -# ### [3 Introduction to DG methods](@ref scalar_linear_advection_1d) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Introduction to DG methods](@ref scalar_linear_advection_1d) #- # This tutorial gives an introduction to discontinuous Galerkin (DG) methods with the example of the # scalar linear advection equation in 1D. Starting with some theoretical explanations, we first implement # a raw version of a discontinuous Galerkin spectral element method (DGSEM). Then, we will show how # to use features of Trixi.jl to achieve the same result. -# ### [4 DGSEM with flux differencing](@ref DGSEM_FluxDiff) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} DGSEM with flux differencing](@ref DGSEM_FluxDiff) #- # To improve stability often the flux differencing formulation of the DGSEM (split form) is used. # We want to present the idea and formulation on a basic 1D level. Then, we show how this formulation # can be implemented in Trixi.jl and analyse entropy conservation for two different flux combinations. -# ### [5 Shock capturing with flux differencing and stage limiter](@ref shock_capturing) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Shock capturing with flux differencing and stage limiter](@ref shock_capturing) #- # Using the flux differencing formulation, a simple procedure to capture shocks is a hybrid blending # of a high-order DG method and a low-order subcell finite volume (FV) method. We present the idea on a @@ -51,20 +56,35 @@ # explained and added to an exemplary simulation of the Sedov blast wave with the 2D compressible Euler # equations. -# ### [6 Non-periodic boundary conditions](@ref non_periodic_boundaries) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Subcell limiting with the IDP Limiter](@ref subcell_shock_capturing) +#- +# Trixi.jl features a subcell-wise limiting strategy utilizing an Invariant Domain-Preserving (IDP) +# approach. This IDP approach computes a blending factor that balances the high-order +# discontinuous Galerkin (DG) method with a low-order subcell finite volume (FV) method for each +# node within an element. This localized approach minimizes the application of dissipation, +# resulting in less limiting compared to the element-wise strategy. Additionally, the framework +# supports both local bounds, which are primarily used for shock capturing, and global bounds. +# The application of global bounds ensures the minimal necessary limiting to meet physical +# admissibility conditions, such as ensuring the non-negativity of variables. + +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Non-periodic boundary conditions](@ref non_periodic_boundaries) #- # Thus far, all examples used periodic boundaries. In Trixi.jl, you can also set up a simulation with # non-periodic boundaries. This tutorial presents the implementation of the classical Dirichlet # boundary condition with a following example. Then, other non-periodic boundaries are mentioned. -# ### [7 DG schemes via `DGMulti` solver](@ref DGMulti_1) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} DG schemes via `DGMulti` solver](@ref DGMulti_1) #- # This tutorial is about the more general DG solver [`DGMulti`](@ref), introduced [here](@ref DGMulti). # We are showing some examples for this solver, for instance with discretization nodes by Gauss or # triangular elements. Moreover, we present a simple way to include pre-defined triangulate meshes for # non-Cartesian domains using the package [StartUpDG.jl](https://github.com/jlchan/StartUpDG.jl). -# ### [8 Other SBP schemes (FD, CGSEM) via `DGMulti` solver](@ref DGMulti_2) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Other SBP schemes (FD, CGSEM) via `DGMulti` solver](@ref DGMulti_2) #- # Supplementary to the previous tutorial about DG schemes via the `DGMulti` solver we now present # the possibility for `DGMulti` to use other SBP schemes via the package @@ -72,7 +92,8 @@ # For instance, we show how to set up a finite differences (FD) scheme and a continuous Galerkin # (CGSEM) method. -# ### [9 Upwind FD SBP schemes](@ref upwind_fdsbp) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Upwind FD SBP schemes](@ref upwind_fdsbp) #- # General SBP schemes can not only be used via the [`DGMulti`](@ref) solver but # also with a general `DG` solver. In particular, upwind finite difference SBP @@ -80,42 +101,49 @@ # schemes in the `DGMulti` framework, the interface is based on the package # [SummationByPartsOperators.jl](https://github.com/ranocha/SummationByPartsOperators.jl). -# ### [10 Adding a new scalar conservation law](@ref adding_new_scalar_equations) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Adding a new scalar conservation law](@ref adding_new_scalar_equations) #- # This tutorial explains how to add a new physics model using the example of the cubic conservation # law. First, we define the equation using a `struct` `CubicEquation` and the physical flux. Then, # the corresponding standard setup in Trixi.jl (`mesh`, `solver`, `semi` and `ode`) is implemented # and the ODE problem is solved by OrdinaryDiffEq's `solve` method. -# ### [11 Adding a non-conservative equation](@ref adding_nonconservative_equation) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Adding a non-conservative equation](@ref adding_nonconservative_equation) #- # In this part, another physics model is implemented, the nonconservative linear advection equation. # We run two different simulations with different levels of refinement and compare the resulting errors. -# ### [12 Parabolic terms](@ref parabolic_terms) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Parabolic terms](@ref parabolic_terms) #- # This tutorial describes how parabolic terms are implemented in Trixi.jl, e.g., # to solve the advection-diffusion equation. -# ### [13 Adding new parabolic terms](@ref adding_new_parabolic_terms) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Adding new parabolic terms](@ref adding_new_parabolic_terms) #- # This tutorial describes how new parabolic terms can be implemented using Trixi.jl. -# ### [14 Adaptive mesh refinement](@ref adaptive_mesh_refinement) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Adaptive mesh refinement](@ref adaptive_mesh_refinement) #- # Adaptive mesh refinement (AMR) helps to increase the accuracy in sensitive or turbolent regions while # not wasting resources for less interesting parts of the domain. This leads to much more efficient # simulations. This tutorial presents the implementation strategy of AMR in Trixi.jl, including the use of # different indicators and controllers. -# ### [15 Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) #- # In this tutorial, the use of Trixi.jl's structured curved mesh type [`StructuredMesh`](@ref) is explained. # We present the two basic option to initialize such a mesh. First, the curved domain boundaries # of a circular cylinder are set by explicit boundary functions. Then, a fully curved mesh is # defined by passing the transformation mapping. -# ### [16 Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) #- # The purpose of this tutorial is to demonstrate how to use the [`UnstructuredMesh2D`](@ref) # functionality of Trixi.jl. This begins by running and visualizing an available unstructured @@ -124,26 +152,30 @@ # software in the Trixi.jl ecosystem, and then run a simulation using Trixi.jl on said mesh. # In the end, the tutorial briefly explains how to simulate an example using AMR via `P4estMesh`. -# ### [17 P4est mesh from gmsh](@ref p4est_from_gmsh) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} P4est mesh from gmsh](@ref p4est_from_gmsh) #- # This tutorial describes how to obtain a [`P4estMesh`](@ref) from an existing mesh generated # by [`gmsh`](https://gmsh.info/) or any other meshing software that can export to the Abaqus # input `.inp` format. The tutorial demonstrates how edges/faces can be associated with boundary conditions based on the physical nodesets. -# ### [18 Explicit time stepping](@ref time_stepping) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Explicit time stepping](@ref time_stepping) #- # This tutorial is about time integration using [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl). # It explains how to use their algorithms and presents two types of time step choices - with error-based # and CFL-based adaptive step size control. -# ### [19 Differentiable programming](@ref differentiable_programming) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Differentiable programming](@ref differentiable_programming) #- # This part deals with some basic differentiable programming topics. For example, a Jacobian, its # eigenvalues and a curve of total energy (through the simulation) are calculated and plotted for # a few semidiscretizations. Moreover, we calculate an example for propagating errors with Measurement.jl # at the end. -# ### [20 Custom semidiscretization](@ref custom_semidiscretization) +#src Note to developers: Use "{ index }" (but without spaces, see next line) to enable automatic indexing +# ### [{index} Custom semidiscretization](@ref custom_semidiscretization) #- # This tutorial describes the [semidiscretiations](@ref overview-semidiscretizations) of Trixi.jl # and explains how to extend them for custom tasks. diff --git a/docs/literate/src/files/non_periodic_boundaries.jl b/docs/literate/src/files/non_periodic_boundaries.jl index 3b238ad453..8f0e320dfd 100644 --- a/docs/literate/src/files/non_periodic_boundaries.jl +++ b/docs/literate/src/files/non_periodic_boundaries.jl @@ -99,7 +99,7 @@ sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), save_everystep=false, saveat=visnodes, callback=callbacks); using Plots -@gif for step in 1:length(sol.u) +@gif for step in eachindex(sol.u) plot(sol.u[step], semi, ylim=(-1.5, 1.5), legend=true, label="approximation", title="time t=$(round(sol.t[step], digits=5))") scatter!([0.0], [sum(boundary_condition(SVector(0.0), sol.t[step], equations))], label="boundary condition") end diff --git a/docs/literate/src/files/scalar_linear_advection_1d.jl b/docs/literate/src/files/scalar_linear_advection_1d.jl index 9b48f29d34..3e2c7e6d0d 100644 --- a/docs/literate/src/files/scalar_linear_advection_1d.jl +++ b/docs/literate/src/files/scalar_linear_advection_1d.jl @@ -120,7 +120,7 @@ integral = sum(nodes.^3 .* weights) x = Matrix{Float64}(undef, length(nodes), n_elements) for element in 1:n_elements x_l = coordinates_min + (element - 1) * dx + dx/2 - for i in 1:length(nodes) + for i in eachindex(nodes) ξ = nodes[i] # nodes in [-1, 1] x[i, element] = x_l + dx/2 * ξ end @@ -184,7 +184,7 @@ M = diagm(weights) # ``` # With an exact integration the mass matrix would be dense. Choosing numerical integrating and quadrature # with the exact same nodes (collocation) leads to the sparse and diagonal mass matrix $M$. This -# is called mass lumping and has the big advantage of an easy invertation of the matrix. +# is called mass lumping and has the big advantage of an easy inversion of the matrix. # #### Term II: # We use spatial partial integration for the second term: @@ -417,7 +417,7 @@ dx = (coordinates_max - coordinates_min) / n_elements # length of one element x = Matrix{Float64}(undef, length(nodes), n_elements) for element in 1:n_elements x_l = -1 + (element - 1) * dx + dx/2 - for i in 1:length(nodes) # basis points in [-1, 1] + for i in eachindex(nodes) # basis points in [-1, 1] ξ = nodes[i] x[i, element] = x_l + dx/2 * ξ end diff --git a/docs/literate/src/files/subcell_shock_capturing.jl b/docs/literate/src/files/subcell_shock_capturing.jl new file mode 100644 index 0000000000..f5bb630350 --- /dev/null +++ b/docs/literate/src/files/subcell_shock_capturing.jl @@ -0,0 +1,288 @@ +#src # Subcell limiting with the IDP Limiter + +# In the previous tutorial, the element-wise limiting with [`IndicatorHennemannGassner`](@ref) +# and [`VolumeIntegralShockCapturingHG`](@ref) was explained. This tutorial contains a short +# introduction to the idea and implementation of subcell shock capturing approaches in Trixi.jl, +# which is also based on the DGSEM scheme in flux differencing formulation. +# Trixi.jl contains the a-posteriori invariant domain-preserving (IDP) limiter which was +# introduced by [Pazner (2020)](https://doi.org/10.1016/j.cma.2021.113876) and +# [Rueda-Ramírez, Pazner, Gassner (2022)](https://doi.org/10.1016/j.compfluid.2022.105627). +# It is a flux-corrected transport-type (FCT) limiter and is implemented using [`SubcellLimiterIDP`](@ref) +# and [`VolumeIntegralSubcellLimiting`](@ref). +# Since it is an a-posteriori limiter you have to apply a correction stage after each Runge-Kutta +# stage. This is done by passing the stage callback [`SubcellLimiterIDPCorrection`](@ref) to the +# time integration method. + +# ## Time integration method +# As mentioned before, the IDP limiting is an a-posteriori limiter. Its limiting process +# guarantees the target bounds for an explicit (forward) Euler time step. To still achieve a +# high-order approximation, the implementation uses strong-stability preserving (SSP) Runge-Kutta +# methods, which can be written as convex combinations of forward Euler steps. +# As such, they preserve the convexity of convex functions and functionals, such as the TVD +# semi-norm and the maximum principle in 1D, for instance. +#- +# Since IDP/FCT limiting procedure operates on independent forward Euler steps, its +# a-posteriori correction stage is implemented as a stage callback that is triggered after each +# forward Euler step in an SSP Runge-Kutta method. Unfortunately, the `solve(...)` routines in +# [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl), typically employed for time +# integration in Trixi.jl, do not support this type of stage callback. +#- +# Therefore, subcell limiting with the IDP limiter requires the use of a Trixi-intern +# time integration SSPRK method called with +# ````julia +# Trixi.solve(ode, method(stage_callbacks = stage_callbacks); ...) +# ```` +#- +# Right now, only the canonical three-stage, third-order SSPRK method (Shu-Osher) +# [`Trixi.SimpleSSPRK33`](@ref) is implemented. + +# # [IDP Limiting](@id IDPLimiter) +# The implementation of the invariant domain preserving (IDP) limiting approach ([`SubcellLimiterIDP`](@ref)) +# is based on [Pazner (2020)](https://doi.org/10.1016/j.cma.2021.113876) and +# [Rueda-Ramírez, Pazner, Gassner (2022)](https://doi.org/10.101/j.compfluid.2022.105627). +# It supports several types of limiting which are enabled by passing parameters individually. + +# ### [Global bounds](@id global_bounds) +# If enabled, the global bounds enforce physical admissibility conditions, such as non-negativity +# of variables. This can be done for conservative variables, where the limiter is of a one-sided +# Zalesak-type ([Zalesak, 1979](https://doi.org/10.1016/0021-9991(79)90051-2)), and general +# non-linear variables, where a Newton-bisection algorithm is used to enforce the bounds. + +# The Newton-bisection algorithm is an iterative method and requires some parameters. +# It uses a fixed maximum number of iteration steps (`max_iterations_newton = 10`) and +# relative/absolute tolerances (`newton_tolerances = (1.0e-12, 1.0e-14)`). The given values are +# sufficient in most cases and therefore used as default. Additionally, there is the parameter +# `gamma_constant_newton`, which can be used to scale the antidiffusive flux for the computation +# of the blending coefficients of nonlinear variables. The default value is `2 * ndims(equations)`, +# as it was shown by [Pazner (2020)](https://doi.org/10.1016/j.cma.2021.113876) [Section 4.2.2.] +# that this value guarantees the fulfillment of bounds for a forward-Euler increment. + +# Very small non-negative values can be an issue as well. That's why we use an additional +# correction factor in the calculation of the global bounds, +# ```math +# u^{new} \geq \beta * u^{FV}. +# ``` +# By default, $\beta$ (named `positivity_correction_factor`) is set to `0.1` which works properly +# in most of the tested setups. + +# #### Conservative variables +# The procedure to enforce global bounds for a conservative variables is as follows: +# If you want to guarantee non-negativity for the density of the compressible Euler equations, +# you pass the specific quantity name of the conservative variable. +using Trixi +equations = CompressibleEulerEquations2D(1.4) + +# The quantity name of the density is `rho` which is how we enable its limiting. +positivity_variables_cons = ["rho"] + +# The quantity names are passed as a vector to allow several quantities. +# This is used, for instance, if you want to limit the density of two different components using +# the multicomponent compressible Euler equations. +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), + gas_constants = (0.287, 1.578)) + +# Then, we just pass both quantity names. +positivity_variables_cons = ["rho1", "rho2"] + +# Alternatively, it is possible to all limit all density variables with a general command using +positivity_variables_cons = ["rho" * string(i) for i in eachcomponent(equations)] + +# #### Non-linear variables +# To allow limitation for all possible non-linear variables, including variables defined +# on-the-fly, you can directly pass the function that computes the quantity for which you want +# to enforce positivity. For instance, if you want to enforce non-negativity for the pressure, +# do as follows. +positivity_variables_nonlinear = [pressure] + +# ### Local bounds +# Second, Trixi.jl supports the limiting with local bounds for conservative variables using a +# two-sided Zalesak-type limiter ([Zalesak, 1979](https://doi.org/10.1016/0021-9991(79)90051-2)). +# They allow to avoid spurious oscillations within the global bounds and to improve the +# shock-capturing capabilities of the method. The corresponding numerical admissibility conditions +# are frequently formulated as local maximum or minimum principles. The local bounds are computed +# using the maximum and minimum values of all local neighboring nodes. Within this calculation we +# use the low-order FV solution values for each node. + +# As for the limiting with global bounds you are passing the quantity names of the conservative +# variables you want to limit. So, to limit the density with lower and upper local bounds pass +# the following. +local_twosided_variables_cons = ["rho"] + +# ## Exemplary simulation +# How to set up a simulation using the IDP limiting becomes clearer when looking at an exemplary +# setup. This will be a simplified version of `tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl`. +# Since the setup is mostly very similar to a pure DGSEM setup as in +# `tree_2d_dgsem/elixir_euler_blast_wave.jl`, the equivalent parts are used without any explanation +# here. +using OrdinaryDiffEq +using Trixi + +equations = CompressibleEulerEquations2D(1.4) + +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + ## Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + ## Set up polar coordinates + inicenter = SVector(0.0, 0.0) + 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) + + ## Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave; + +# Since the surface integral is equal for both the DG and the subcell FV method, the limiting is +# applied only in the volume integral. +#- +# Note, that the DG method is based on the flux differencing formulation. Hence, you have to use a +# two-point flux, such as [`flux_ranocha`](@ref), [`flux_shima_etal`](@ref), [`flux_chandrashekar`](@ref) +# or [`flux_kennedy_gruber`](@ref), for the DG volume flux. +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha + +# The limiter is implemented within [`SubcellLimiterIDP`](@ref). It always requires the +# parameters `equations` and `basis`. With additional parameters (described [above](@ref IDPLimiter) +# or listed in the docstring) you can specify and enable additional limiting options. +# Here, the simulation should contain local limiting for the density using lower and upper bounds. +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_twosided_variables_cons = ["rho"], + bar_states = false) + +# The initialized limiter is passed to `VolumeIntegralSubcellLimiting` in addition to the volume +# fluxes of the low-order and high-order scheme. +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + +# Then, the volume integral is passed to `solver` as it is done for the standard flux-differencing +# DG scheme or the element-wise limiting. +solver = DGSEM(basis, surface_flux, volume_integral) +#- +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) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +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, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.3) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback); + +# As explained above, the IDP limiter works a-posteriori and requires the additional use of a +# correction stage implemented with the stage callback [`SubcellLimiterIDPCorrection`](@ref). +# This callback is passed within a tuple to the time integration method. +stage_callbacks = (SubcellLimiterIDPCorrection(),) + +# Moreover, as mentioned before as well, simulations with subcell limiting require a Trixi-intern +# SSPRK time integration methods with passed stage callbacks and a Trixi-intern `Trixi.solve(...)` +# routine. +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary + + +# ## Visualization +# As for a standard simulation in Trixi.jl, it is possible to visualize the solution using the +# `plot` routine from Plots.jl. +using Plots +plot(sol) + +# To get an additional look at the amount of limiting that is used, you can use the visualization +# approach using the [`SaveSolutionCallback`](@ref), [`Trixi2Vtk`](https://github.com/trixi-framework/Trixi2Vtk.jl) +# and [ParaView](https://www.paraview.org/download/). More details about this procedure +# can be found in the [visualization documentation](@ref visualization). +# Unfortunately, the support for subcell limiting data is not yet merged into the main branch +# of Trixi2Vtk but lies in the branch [`bennibolm/node-variables`](https://github.com/bennibolm/Trixi2Vtk.jl/tree/node-variables). +#- +# With that implementation and the standard procedure used for Trixi2Vtk you get the following +# dropdown menu in ParaView. +#- +# ![ParaView_Dropdownmenu](https://github.com/trixi-framework/Trixi.jl/assets/74359358/70d15f6a-059b-4349-8291-68d9ab3af43e) + +# The resulting visualization of the density and the limiting parameter then looks like this. +# ![blast_wave_paraview](https://github.com/trixi-framework/Trixi.jl/assets/74359358/e5808bed-c8ab-43bf-af7a-050fe43dd630) + +# You can see that the limiting coefficient does not lie in the interval [0,1] because Trixi2Vtk +# interpolates all quantities to regular nodes by default. +# You can disable this functionality with `reinterpolate=false` within the call of `trixi2vtk(...)` +# and get the following visualization. +# ![blast_wave_paraview_reinterpolate=false](https://github.com/trixi-framework/Trixi.jl/assets/74359358/39274f18-0064-469c-b4da-bac4b843e116) + + +# ## Bounds checking +# Subcell limiting is based on the fulfillment of target bounds - either global or local. +# Although the implementation works and has been thoroughly tested, there are some cases where +# these bounds are not met. +# For instance, the deviations could be in machine precision, which is not problematic. +# Larger deviations can be cause by too large time-step sizes (which can be easily fixed by +# reducing the CFL number), specific boundary conditions or source terms. Insufficient parameters +# for the Newton-bisection algorithm can also be a reason when limiting non-linear variables. +# There are described [above](@ref global_bounds). +#- +# In many cases, it is reasonable to monitor the bounds deviations. +# Because of that, Trixi.jl supports a bounds checking routine implemented using the stage +# callback [`BoundsCheckCallback`](@ref). It checks all target bounds for fulfillment +# in every RK stage. If added to the tuple of stage callbacks like +# ````julia +# stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) +# ```` +# and passed to the time integration method, a summary is added to the final console output. +# For the given example, this summary shows that all bounds are met at all times. +# ```` +# ──────────────────────────────────────────────────────────────────────────────────────────────────── +# Maximum deviation from bounds: +# ──────────────────────────────────────────────────────────────────────────────────────────────────── +# rho: +# - lower bound: 0.0 +# - upper bound: 0.0 +# ──────────────────────────────────────────────────────────────────────────────────────────────────── +# ```` + +# Moreover, it is also possible to monitor the bounds deviations incurred during the simulations. +# To do that use the parameter `save_errors = true`, such that the instant deviations are written +# to `deviations.txt` in `output_directory` every `interval` time steps. +# ````julia +# BoundsCheckCallback(save_errors = true, output_directory = "out", interval = 100) +# ```` +# Then, for the given example the deviations file contains all daviations for the current +# timestep and simulation time. +# ```` +# iter, simu_time, rho_min, rho_max +# 1, 0.0, 0.0, 0.0 +# 101, 0.29394033217556337, 0.0, 0.0 +# 201, 0.6012597465597065, 0.0, 0.0 +# 301, 0.9559096690030839, 0.0, 0.0 +# 401, 1.3674274981949077, 0.0, 0.0 +# 501, 1.8395301696603052, 0.0, 0.0 +# 532, 1.9974179806990118, 0.0, 0.0 +# ```` diff --git a/docs/make.jl b/docs/make.jl index f752a7b0ee..73ee86abd8 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,5 +1,6 @@ using Documenter import Pkg +using Changelog: Changelog # Fix for https://github.com/trixi-framework/Trixi.jl/issues/668 if (get(ENV, "CI", nothing) != "true") && (get(ENV, "TRIXI_DOC_DEFAULT_ENVIRONMENT", nothing) != "true") @@ -69,7 +70,7 @@ files = [ # Topic: introduction "First steps in Trixi.jl" => [ "Getting started" => ("first_steps", "getting_started.jl"), - "Create first setup" => ("first_steps", "create_first_setup.jl"), + "Create your first setup" => ("first_steps", "create_first_setup.jl"), "Changing Trixi.jl itself" => ("first_steps", "changing_trixi.jl"), ], "Behind the scenes of a simulation setup" => "behind_the_scenes_simulation_setup.jl", @@ -77,6 +78,7 @@ files = [ "Introduction to DG methods" => "scalar_linear_advection_1d.jl", "DGSEM with flux differencing" => "DGSEM_FluxDiff.jl", "Shock capturing with flux differencing and stage limiter" => "shock_capturing.jl", + "Subcell limiting with the IDP Limiter" => "subcell_shock_capturing.jl", "Non-periodic boundaries" => "non_periodic_boundaries.jl", "DG schemes via `DGMulti` solver" => "DGMulti_1.jl", "Other SBP schemes (FD, CGSEM) via `DGMulti` solver" => "DGMulti_2.jl", @@ -98,6 +100,14 @@ files = [ ] tutorials = create_tutorials(files) +# Create changelog +Changelog.generate( + Changelog.Documenter(), # output type + joinpath(@__DIR__, "..", "NEWS.md"), # input file + joinpath(@__DIR__, "src", "changelog.md"); # output file + repo = "trixi-framework/Trixi.jl", # default repository for links +) + # Make documentation makedocs( # Specify modules for which docstrings should be shown @@ -150,6 +160,7 @@ makedocs( "TrixiBase.jl" => "reference-trixibase.md", "Trixi2Vtk.jl" => "reference-trixi2vtk.md" ], + "Changelog" => "changelog.md", "Authors" => "authors.md", "Contributing" => "contributing.md", "Code of Conduct" => "code_of_conduct.md", diff --git a/docs/src/meshes/structured_mesh.md b/docs/src/meshes/structured_mesh.md index 7c25c96be6..98f7beb3db 100644 --- a/docs/src/meshes/structured_mesh.md +++ b/docs/src/meshes/structured_mesh.md @@ -2,6 +2,8 @@ The [`StructuredMesh`](@ref) is a structured, curvilinear, conforming mesh type available for one-, two-, and three-dimensional simulations. +An application of the [`StructuredMesh`](@ref) using a user-defined mapping +is provided by [one of the tutorials](https://trixi-framework.github.io/Trixi.jl/stable/tutorials/structured_mesh_mapping/). Due to its curvilinear nature, (numerical) fluxes need to implement methods dispatching on the `normal::AbstractVector`. Rotationally invariant equations diff --git a/docs/src/meshes/tree_mesh.md b/docs/src/meshes/tree_mesh.md index a172a9b9a5..9a88919a40 100644 --- a/docs/src/meshes/tree_mesh.md +++ b/docs/src/meshes/tree_mesh.md @@ -5,7 +5,7 @@ used in many parts of Trixi.jl. Often, the support for this mesh type is developed best since it was the first mesh type in Trixi.jl, and it is available in one, two, and three space dimensions. -It is limited to hypercube domains but supports AMR via the [`AMRCallback`](@ref). +It is limited to hypercube domains (that is, lines in 1D, squares in 2D and cubes in 3D) but supports AMR via the [`AMRCallback`](@ref). Due to its Cartesian nature, (numerical) fluxes need to implement methods dispatching on the `orientation::Integer` as described in the [conventions](@ref conventions). diff --git a/docs/src/multi-physics_coupling.md b/docs/src/multi-physics_coupling.md index eec92bc21d..2c82c1b19e 100644 --- a/docs/src/multi-physics_coupling.md +++ b/docs/src/multi-physics_coupling.md @@ -36,6 +36,17 @@ By passing the equations we can make use of their parameters, if they are requir Examples can be seen in `examples/structured_2d_dgsem/elixir_advection_coupled.jl`. +## GlmSpeedCallback for coupled MHD simulations + +When simulating an MHD system and the [`GlmSpeedCallback`](@ref) is required, +we need to specify for which semidiscretization we need the GLM speed updated. +This can be done with an additional parameter called `semi_indices`, which +is a tuple containing the semidiscretization indices for all systems +that require the GLM speed updated. + +An example elixir can be found at [`examples/structured_2d_dgsem/elixir_mhd_coupled.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/structured_2d_dgsem/elixir_mhd_coupled.jl). + + ## Warning about binary compatibility Currently the coordinate values on the nodes can differ by machine precision when simulating the mesh and when splitting the mesh in multiple domains. diff --git a/docs/src/overview.md b/docs/src/overview.md index 9bc523ca29..72a341de7e 100644 --- a/docs/src/overview.md +++ b/docs/src/overview.md @@ -64,6 +64,14 @@ different features on different mesh types. ᵃ: quad = quadrilateral, hex = hexahedron +Note that except for [`TreeMesh`](@ref) all meshes are of *curvilinear* type, +which means that a (unit) vector normal to the interface (`normal_direction`) needs to be supplied to the +numerical flux function. +You can check the [reference](https://trixi-framework.github.io/Trixi.jl/stable/reference-trixi/) if a certain +numerical flux is implemented with a `normal_direction` +or if currently only the *Cartesian* version (for [`TreeMesh`](@ref)) exists. +In this case, you can still use this flux on curvilinear meshes by rotating it, see [`FluxRotated`](@ref). + ## Time integration methods Trixi.jl is compatible with the [SciML ecosystem for ordinary differential equations](https://diffeq.sciml.ai/latest/). diff --git a/examples/dgmulti_1d/elixir_burgers_gauss_shock_capturing.jl b/examples/dgmulti_1d/elixir_burgers_gauss_shock_capturing.jl new file mode 100644 index 0000000000..b0632b1f97 --- /dev/null +++ b/examples/dgmulti_1d/elixir_burgers_gauss_shock_capturing.jl @@ -0,0 +1,68 @@ +using Trixi +using OrdinaryDiffEq + +equations = InviscidBurgersEquation1D() + +############################################################################### +# setup the GSBP DG discretization that uses the Gauss operators from +# Chan, Del Rey Fernandez, Carpenter (2019). +# [https://doi.org/10.1137/18M1209234](https://doi.org/10.1137/18M1209234) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ec + +polydeg = 3 +basis = DGMultiBasis(Line(), polydeg, approximation_type = GaussSBP()) + +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + +dg = DGMulti(basis, + surface_integral = SurfaceIntegralWeakForm(surface_flux), + volume_integral = volume_integral) + +############################################################################### +# setup the 1D mesh + +cells_per_dimension = (32,) +mesh = DGMultiMesh(dg, cells_per_dimension, + coordinates_min = (-1.0,), coordinates_max = (1.0,), + periodicity = true) + +############################################################################### +# setup the semidiscretization and ODE problem + +semi = SemidiscretizationHyperbolic(mesh, + equations, + initial_condition_convergence_test, + dg) + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# setup the callbacks + +# prints a summary of the simulation setup and resets the timers +summary_callback = SummaryCallback() + +# analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = 100, uEltype = real(dg)) + +# handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 0.5) + +# collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) + +# ############################################################################### +# # run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, save_everystep = false, callback = callbacks); diff --git a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl index 5a2537be4e..a1ddc6a314 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -33,7 +33,7 @@ function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, outer_distance = 1.85 #Iterate over all elements - for element in 1:length(alpha) + for element in eachindex(alpha) # Calculate periodic distance between cell and center. # This requires an uncurved mesh! coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + diff --git a/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl b/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl new file mode 100644 index 0000000000..fb5f29bd03 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl @@ -0,0 +1,132 @@ +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +p_inf() = 1.0 +rho_inf() = p_inf() / (1.0 * 287.87) # p_inf = 1.0, T = 1, R = 287.87 +mach_inf() = 0.85 +aoa() = pi / 180.0 # 1 Degree angle of attack +c_inf(equations) = sqrt(equations.gamma * p_inf() / rho_inf()) +u_inf(equations) = mach_inf() * c_inf(equations) + +@inline function initial_condition_mach085_flow(x, t, + equations::CompressibleEulerEquations2D) + v1 = u_inf(equations) * cos(aoa()) + v2 = u_inf(equations) * sin(aoa()) + + prim = SVector(rho_inf(), v1, v2, p_inf()) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_mach085_flow + +volume_flux = flux_ranocha_turbo +surface_flux = flux_lax_friedrichs + +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +shock_indicator = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) + +mesh_file = Trixi.download("https://gist.githubusercontent.com/Arpit-Babbar/339662b4b46164a016e35c81c66383bb/raw/8bf94f5b426ba907ace87405cfcc1dcc2ef7cbda/NACA0012.inp", + joinpath(@__DIR__, "NACA0012.inp")) + +mesh = P4estMesh{2}(mesh_file) + +# The outer boundary is constant but subsonic, so we cannot compute the +# boundary flux for the external information alone. Thus, we use the numerical flux to distinguish +# between inflow and outflow characteristics +@inline function boundary_condition_subsonic_constant(u_inner, + normal_direction::AbstractVector, x, + t, + surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach085_flow(x, t, equations) + + return Trixi.flux_hll(u_inner, u_boundary, normal_direction, equations) +end + +boundary_conditions = Dict(:Left => boundary_condition_subsonic_constant, + :Right => boundary_condition_subsonic_constant, + :Top => boundary_condition_subsonic_constant, + :Bottom => boundary_condition_subsonic_constant, + :AirfoilBottom => boundary_condition_slip_wall, + :AirfoilTop => boundary_condition_slip_wall) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers + +# Run for a long time to reach a steady state +tspan = (0.0, 20.0) +ode = semidiscretize(semi, tspan) + +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 2000 + +l_inf = 1.0 # Length of airfoil + +force_boundary_names = [:AirfoilBottom, :AirfoilTop] +drag_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, + DragCoefficientPressure(aoa(), rho_inf(), + u_inf(equations), l_inf)) + +lift_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, + LiftCoefficientPressure(aoa(), rho_inf(), + u_inf(equations), l_inf)) + +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + output_directory = "out", + save_analysis = true, + analysis_integrals = (drag_coefficient, + lift_coefficient)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 1.0) + +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 1, + med_level = 3, med_threshold = 0.05, + max_level = 4, max_threshold = 0.1) + +amr_interval = 100 +amr_callback = AMRCallback(semi, amr_controller, + interval = amr_interval, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + stepsize_callback, amr_callback) + +############################################################################### +# run the simulation +sol = solve(ode, SSPRK54(thread = OrdinaryDiffEq.True()), + 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/p4est_2d_dgsem/elixir_euler_double_mach.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl index 949bc40e64..d5d7338ba4 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl @@ -108,8 +108,9 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], positivity_correction_factor = 0.1, max_iterations_newton = 100, bar_states = true) diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index 9d67ad76ce..5e5a0847fe 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -17,7 +17,6 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, - spec_entropy = false, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl b/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl new file mode 100644 index 0000000000..dc23e192de --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl @@ -0,0 +1,125 @@ +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +@inline function initial_condition_mach038_flow(x, t, + equations::CompressibleEulerEquations2D) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 0.38 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_mach038_flow + +volume_flux = flux_ranocha_turbo # FluxRotated(flux_chandrashekar) can also be used +surface_flux = flux_lax_friedrichs + +polydeg = 3 +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +function mapping2cylinder(xi, eta) + xi_, eta_ = 0.5 * (xi + 1), 0.5 * (eta + 1.0) # Map from [-1,1] to [0,1] for simplicity + + R2 = 50.0 # Bigger circle + R1 = 0.5 # Smaller circle + + # Ensure an isotropic mesh by using elements with smaller radial length near the inner circle + + r = R1 * exp(xi_ * log(R2 / R1)) + theta = 2.0 * pi * eta_ + + x = r * cos(theta) + y = r * sin(theta) + return (x, y) +end + +cells_per_dimension = (64, 64) +# xi = -1 maps to the inner circle and xi = +1 maps to the outer circle and we can specify boundary +# conditions there. However, the image of eta = -1, +1 coincides at the line y = 0. There is no +# physical boundary there so we specify `periodicity = true` there and the solver treats the +# element across eta = -1, +1 as neighbours which is what we want +mesh = P4estMesh(cells_per_dimension, mapping = mapping2cylinder, polydeg = polydeg, + periodicity = (false, true)) + +# The boundary condition on the outer cylinder is constant but subsonic, so we cannot compute the +# boundary flux from the external information alone. Thus, we use the numerical flux to distinguish +# between inflow and outflow characteristics +@inline function boundary_condition_subsonic_constant(u_inner, + normal_direction::AbstractVector, x, + t, + surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach038_flow(x, t, equations) + + return surface_flux_function(u_inner, u_boundary, normal_direction, equations) +end + +boundary_conditions = Dict(:x_neg => boundary_condition_slip_wall, + :x_pos => boundary_condition_subsonic_constant) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers + +# Run for a long time to reach a steady state +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 2000 + +aoa = 0.0 +rho_inf = 1.4 +u_inf = 0.38 +l_inf = 1.0 # Diameter of circle + +drag_coefficient = AnalysisSurfaceIntegral(semi, :x_neg, + DragCoefficientPressure(aoa, rho_inf, u_inf, + l_inf)) + +lift_coefficient = AnalysisSurfaceIntegral(semi, :x_neg, + LiftCoefficientPressure(aoa, rho_inf, u_inf, + l_inf)) + +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + output_directory = "out", + save_analysis = true, + analysis_integrals = (drag_coefficient, + lift_coefficient)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 500, + 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; + thread = OrdinaryDiffEq.True()), + 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/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl index de0a0116ec..5157480894 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl @@ -98,7 +98,8 @@ basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], - spec_entropy = true, + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], max_iterations_newton = 100, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl new file mode 100644 index 0000000000..1b485913ab --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl @@ -0,0 +1,169 @@ +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +# Laminar transonic flow around a NACA0012 airfoil. + +# This test is taken from the paper of Swanson and Langer. The values for the drag and lift coefficients +# from Case 5 in Table 3 are used to validate the scheme and computation of surface forces. + +# References: +# - Roy Charles Swanson, Stefan Langer (2016) +# Structured and Unstructured Grid Methods (2016) +# [https://ntrs.nasa.gov/citations/20160003623] (https://ntrs.nasa.gov/citations/20160003623) +# - Deep Ray, Praveen Chandrashekar (2017) +# An entropy stable finite volume scheme for the +# two dimensional Navier–Stokes equations on triangular grids +# [DOI:10.1016/j.amc.2017.07.020](https://doi.org/10.1016/j.amc.2017.07.020) + +equations = CompressibleEulerEquations2D(1.4) + +prandtl_number() = 0.72 +mu() = 0.0031959974968701088 +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) + +rho_inf() = 1.0 +p_inf() = 2.85 +aoa() = 10.0 * pi / 180.0 # 10 degree angle of attack +l_inf() = 1.0 +mach_inf() = 0.8 +u_inf(equations) = mach_inf() * sqrt(equations.gamma * p_inf() / rho_inf()) +@inline function initial_condition_mach08_flow(x, t, equations) + # set the freestream flow parameters + gamma = equations.gamma + u_inf = mach_inf() * sqrt(gamma * p_inf() / rho_inf()) + + v1 = u_inf * cos(aoa()) + v2 = u_inf * sin(aoa()) + + prim = SVector(rho_inf(), v1, v2, p_inf()) + return prim2cons(prim, equations) +end + +initial_condition = initial_condition_mach08_flow + +surface_flux = flux_lax_friedrichs + +polydeg = 3 +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux) + +mesh_file = Trixi.download("https://gist.githubusercontent.com/Arpit-Babbar/339662b4b46164a016e35c81c66383bb/raw/8bf94f5b426ba907ace87405cfcc1dcc2ef7cbda/NACA0012.inp", + joinpath(@__DIR__, "NACA0012.inp")) + +mesh = P4estMesh{2}(mesh_file, initial_refinement_level = 1) + +# The boundary values across outer boundary are constant but subsonic, so we cannot compute the +# boundary flux from the external information alone. Thus, we use the numerical flux to distinguish +# between inflow and outflow characteristics +@inline function boundary_condition_subsonic_constant(u_inner, + normal_direction::AbstractVector, x, + t, + surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach08_flow(x, t, equations) + + return Trixi.flux_hll(u_inner, u_boundary, normal_direction, equations) +end + +boundary_conditions = Dict(:Left => boundary_condition_subsonic_constant, + :Right => boundary_condition_subsonic_constant, + :Top => boundary_condition_subsonic_constant, + :Bottom => boundary_condition_subsonic_constant, + :AirfoilBottom => boundary_condition_slip_wall, + :AirfoilTop => boundary_condition_slip_wall) + +velocity_airfoil = NoSlip((x, t, equations) -> SVector(0.0, 0.0)) + +heat_airfoil = Adiabatic((x, t, equations) -> 0.0) + +boundary_conditions_airfoil = BoundaryConditionNavierStokesWall(velocity_airfoil, + heat_airfoil) + +function momenta_initial_condition_mach08_flow(x, t, equations) + u = initial_condition_mach08_flow(x, t, equations) + momenta = SVector(u[2], u[3]) +end +velocity_bc_square = NoSlip((x, t, equations) -> momenta_initial_condition_mach08_flow(x, t, + equations)) + +heat_bc_square = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_square = BoundaryConditionNavierStokesWall(velocity_bc_square, + heat_bc_square) + +boundary_conditions_parabolic = Dict(:Left => boundary_condition_square, + :Right => boundary_condition_square, + :Top => boundary_condition_square, + :Bottom => boundary_condition_square, + :AirfoilBottom => boundary_conditions_airfoil, + :AirfoilTop => boundary_conditions_airfoil) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers + +# Run for a long time to reach a state where forces stabilize up to 3 digits +tspan = (0.0, 10.0) +ode = semidiscretize(semi, tspan) + +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 2000 + +force_boundary_names = [:AirfoilBottom, :AirfoilTop] +drag_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, + DragCoefficientPressure(aoa(), rho_inf(), + u_inf(equations), + l_inf())) + +lift_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, + LiftCoefficientPressure(aoa(), rho_inf(), + u_inf(equations), + l_inf())) + +drag_coefficient_shear_force = AnalysisSurfaceIntegral(semi, force_boundary_names, + DragCoefficientShearStress(aoa(), + rho_inf(), + u_inf(equations), + l_inf())) + +lift_coefficient_shear_force = AnalysisSurfaceIntegral(semi, force_boundary_names, + LiftCoefficientShearStress(aoa(), + rho_inf(), + u_inf(equations), + l_inf())) + +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + output_directory = "out", + save_analysis = true, + analysis_errors = Symbol[], + analysis_integrals = (drag_coefficient, + lift_coefficient, + drag_coefficient_shear_force, + lift_coefficient_shear_force)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) + +############################################################################### +# run the simulation + +sol = solve(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()); abstol = 1e-8, + reltol = 1e-8, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_linearizedeuler_convergence.jl b/examples/p4est_3d_dgsem/elixir_linearizedeuler_convergence.jl new file mode 100644 index 0000000000..fd066ef895 --- /dev/null +++ b/examples/p4est_3d_dgsem/elixir_linearizedeuler_convergence.jl @@ -0,0 +1,64 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linearized Euler equations + +equations = LinearizedEulerEquations3D(v_mean_global = (0.0, 0.0, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) + +initial_condition = initial_condition_convergence_test + +solver = DGSEM(polydeg = 3, surface_flux = flux_hll) + +coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) + +# `initial_refinement_level` is provided here to allow for a +# convenient convergence test, see +# https://trixi-framework.github.io/Trixi.jl/stable/#Performing-a-convergence-analysis +trees_per_dimension = (4, 4, 4) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, + coordinates_max = coordinates_max, + initial_refinement_level = 0) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span from 0.0 to 0.2 +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +analysis_interval = 100 + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 0.8) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +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); + +# print the timer summary +summary_callback() # print the timer summary diff --git a/examples/structured_1d_dgsem/elixir_linearizedeuler_characteristic_system.jl b/examples/structured_1d_dgsem/elixir_linearizedeuler_characteristic_system.jl new file mode 100644 index 0000000000..663b25b18c --- /dev/null +++ b/examples/structured_1d_dgsem/elixir_linearizedeuler_characteristic_system.jl @@ -0,0 +1,112 @@ + +using OrdinaryDiffEq +using LinearAlgebra: dot +using Trixi + +############################################################################### +# semidiscretization of the linearized Euler equations + +rho_0 = 1.0 +v_0 = 1.0 +c_0 = 1.0 +equations = LinearizedEulerEquations1D(rho_0, v_0, c_0) + +solver = DGSEM(polydeg = 3, surface_flux = flux_hll) + +coordinates_min = (0.0,) # minimum coordinate +coordinates_max = (1.0,) # maximum coordinate +cells_per_dimension = (64,) + +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + +# For eigensystem of the linearized Euler equations see e.g. +# https://www.nas.nasa.gov/assets/nas/pdf/ams/2018/introtocfd/Intro2CFD_Lecture1_Pulliam_Euler_WaveEQ.pdf +# Linearized Euler: Eigensystem +lin_euler_eigvals = [v_0 - c_0; v_0; v_0 + c_0] +lin_euler_eigvecs = [-rho_0/c_0 1 rho_0/c_0; + 1 0 1; + -rho_0*c_0 0 rho_0*c_0] +lin_euler_eigvecs_inv = inv(lin_euler_eigvecs) + +# Trace back characteristics. +# See https://metaphor.ethz.ch/x/2019/hs/401-4671-00L/literature/mishra_hyperbolic_pdes.pdf, p.95 +function compute_char_initial_pos(x, t) + return SVector(x[1], x[1], x[1]) .- t * lin_euler_eigvals +end + +function compute_primal_sol(char_vars) + return lin_euler_eigvecs * char_vars +end + +# Initial condition is in principle arbitrary, only periodicity is required +function initial_condition_entropy_wave(x, t, equations::LinearizedEulerEquations1D) + # Parameters + alpha = 1.0 + beta = 150.0 + center = 0.5 + + rho_prime = alpha * exp(-beta * (x[1] - center)^2) + v_prime = 0.0 + p_prime = 0.0 + + return SVector(rho_prime, v_prime, p_prime) +end + +function initial_condition_char_vars(x, t, equations::LinearizedEulerEquations1D) + # Trace back characteristics + x_char = compute_char_initial_pos(x, t) + + # Employ periodicity + for p in 1:3 + while x_char[p] < coordinates_min[1] + x_char[p] += coordinates_max[1] - coordinates_min[1] + end + while x_char[p] > coordinates_max[1] + x_char[p] -= coordinates_max[1] - coordinates_min[1] + end + end + + # Set up characteristic variables + w = zeros(3) + t_0 = 0 # Assumes t_0 = 0 + for p in 1:3 + u_char = initial_condition_entropy_wave(x_char[p], t_0, equations) + w[p] = dot(lin_euler_eigvecs_inv[p, :], u_char) + end + + return compute_primal_sol(w) +end + +initial_condition = initial_condition_char_vars + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.3) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback) + +stepsize_callback = StepsizeCallback(cfl = 1.0) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_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/structured_2d_dgsem/elixir_advection_meshview.jl b/examples/structured_2d_dgsem/elixir_advection_meshview.jl new file mode 100644 index 0000000000..d8d2703109 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_advection_meshview.jl @@ -0,0 +1,122 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Coupled semidiscretization of two linear advection systems using converter functions +# and mesh views for the semidiscretizations. First we define a parent mesh +# for the entire physical domain, then we define the two mesh views on this parent. +# +# In this elixir, we have a square domain that is divided into left and right subdomains. +# On each half of the domain, a completely independent `SemidiscretizationHyperbolic` +# is created for the linear advection equations. The two systems are coupled in the +# x-direction. +# For a high-level overview, see also the figure below: +# +# (-1, 1) ( 1, 1) +# ┌────────────────────┬────────────────────┐ +# │ ↑ periodic ↑ │ ↑ periodic ↑ │ +# │ │ │ +# │ ========= │ ========= │ +# │ system #1 │ system #2 │ +# │ ========= │ ========= │ +# │ │ │ +# │<-- coupled │<-- coupled │ +# │ coupled -->│ coupled -->│ +# │ │ │ +# │ ↓ periodic ↓ │ ↓ periodic ↓ │ +# └────────────────────┴────────────────────┘ +# (-1, -1) ( 1, -1) + +advection_velocity = (0.2, -0.7) +equations = LinearScalarAdvectionEquation2D(advection_velocity) + +# Create DG solver with polynomial degree = 3 +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +# Domain size of the parent mesh. +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) + +# Cell dimensions of the parent mesh. +cells_per_dimension = (16, 16) + +# Create parent mesh with 16 x 16 elements +parent_mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + +# Create the two mesh views, each of which takes half of the parent mesh. +mesh1 = StructuredMeshView(parent_mesh; indices_min = (1, 1), indices_max = (8, 16)) +mesh2 = StructuredMeshView(parent_mesh; indices_min = (9, 1), indices_max = (16, 16)) + +# The coupling function is simply the identity, as we are dealing with two identical systems. +coupling_function = (x, u, equations_other, equations_own) -> u + +# Define the coupled boundary conditions +# The indices (:end, :i_forward) and (:begin, :i_forward) denote the interface indexing. +# For a system with coupling in x and y see examples/structured_2d_dgsem/elixir_advection_coupled.jl. +boundary_conditions1 = ( + # Connect left boundary with right boundary of left mesh + x_neg = BoundaryConditionCoupled(2, (:end, :i_forward), Float64, + coupling_function), + x_pos = BoundaryConditionCoupled(2, (:begin, :i_forward), Float64, + coupling_function), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) +boundary_conditions2 = ( + # Connect left boundary with right boundary of left mesh + x_neg = BoundaryConditionCoupled(1, (:end, :i_forward), Float64, + coupling_function), + x_pos = BoundaryConditionCoupled(1, (:begin, :i_forward), Float64, + coupling_function), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, + solver, + boundary_conditions = boundary_conditions1) +semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, + solver, + boundary_conditions = boundary_conditions2) +semi = SemidiscretizationCoupled(semi1, semi2) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span from 0.0 to 1.0 +ode = semidiscretize(semi, (0.0, 1.0)); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback1 = AnalysisCallback(semi1, interval = 100) +analysis_callback2 = AnalysisCallback(semi2, interval = 100) +analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2) + +analysis_interval = 100 +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +# The SaveSolutionCallback allows to save the solution to a file in regular intervals +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 1.6) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 5.0e-2, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +# Print the timer summary +summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl index e7435e4712..eb675671ac 100644 --- a/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl +++ b/examples/structured_2d_dgsem/elixir_euler_convergence_wavingflag_IDP.jl @@ -17,7 +17,6 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, - spec_entropy = false, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), bar_states = true, diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index c40d79e3cc..e1fff80510 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -114,8 +114,9 @@ polydeg = 4 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], positivity_correction_factor = 0.1, max_iterations_newton = 100, bar_states = true) diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl index e67130f881..64f28d6356 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream_sc_subcell.jl @@ -17,7 +17,6 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, - spec_entropy = false, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl index 3bfa027197..4d206c66ff 100644 --- a/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_shock_upstream_sc_subcell.jl @@ -37,8 +37,9 @@ polydeg = 5 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], max_iterations_newton = 100, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 1f88427d3e..34ce074f72 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -16,8 +16,9 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/examples/structured_2d_dgsem/elixir_mhd_coupled.jl b/examples/structured_2d_dgsem/elixir_mhd_coupled.jl new file mode 100644 index 0000000000..d3aa4ecf58 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_mhd_coupled.jl @@ -0,0 +1,136 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Two semidiscretizations of the ideal GLM-MHD systems using converter functions such that +# they are coupled across the domain boundaries to generate a periodic system. +# +# In this elixir, we have a square domain that is divided into a left and right half. +# On each half of the domain, an independent SemidiscretizationHyperbolic is created for +# each set of ideal GLM-MHD equations. The two systems are coupled in the x-direction +# and are periodic in the y-direction. +# For a high-level overview, see also the figure below: +# +# (-2, 2) ( 2, 2) +# ┌────────────────────┬────────────────────┐ +# │ ↑ periodic ↑ │ ↑ periodic ↑ │ +# │ │ │ +# │ ========= │ ========= │ +# │ system #1 │ system #2 │ +# │ ========= │ ========= │ +# │ │ │ +# │<-- coupled │<-- coupled │ +# │ coupled -->│ coupled -->│ +# │ │ │ +# │ ↓ periodic ↓ │ ↓ periodic ↓ │ +# └────────────────────┴────────────────────┘ +# (-2, -2) ( 2, -2) + +gamma = 5 / 3 +equations = IdealGlmMhdEquations2D(gamma) + +cells_per_dimension = (32, 64) + +# Extend the definition of the non-conservative Powell flux functions. +import Trixi.flux_nonconservative_powell +function flux_nonconservative_powell(u_ll, u_rr, + normal_direction_ll::AbstractVector, + equations::IdealGlmMhdEquations2D) + flux_nonconservative_powell(u_ll, u_rr, normal_direction_ll, normal_direction_ll, + equations) +end +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +########### +# system #1 +########### + +initial_condition1 = initial_condition_convergence_test +coordinates_min1 = (-1 / sin(pi / 4), -1 / sin(pi / 4)) +coordinates_max1 = (0.0, 1 / sin(pi / 4)) +mesh1 = StructuredMesh(cells_per_dimension, + coordinates_min1, + coordinates_max1, + periodicity = (false, true)) + +coupling_function1 = (x, u, equations_other, equations_own) -> u +boundary_conditions1 = (x_neg = BoundaryConditionCoupled(2, (:end, :i_forward), Float64, + coupling_function1), + x_pos = BoundaryConditionCoupled(2, (:begin, :i_forward), Float64, + coupling_function1), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) + +semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition1, solver, + boundary_conditions = boundary_conditions1) + +########### +# system #2 +########### + +initial_condition2 = initial_condition_convergence_test +coordinates_min2 = (0.0, -1 / sin(pi / 4)) +coordinates_max2 = (1 / sin(pi / 4), 1 / sin(pi / 4)) +mesh2 = StructuredMesh(cells_per_dimension, + coordinates_min2, + coordinates_max2, + periodicity = (false, true)) + +coupling_function2 = (x, u, equations_other, equations_own) -> u +boundary_conditions2 = (x_neg = BoundaryConditionCoupled(1, (:end, :i_forward), Float64, + coupling_function2), + x_pos = BoundaryConditionCoupled(1, (:begin, :i_forward), Float64, + coupling_function2), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) + +semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition2, solver, + boundary_conditions = boundary_conditions2) + +# Create a semidiscretization that bundles all the semidiscretizations. +semi = SemidiscretizationCoupled(semi1, semi2) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 + +analysis_callback1 = AnalysisCallback(semi1, interval = 100) +analysis_callback2 = AnalysisCallback(semi2, interval = 100) +analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +cfl = 1.0 + +stepsize_callback = StepsizeCallback(cfl = cfl) + +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl, + semi_indices = [1, 2]) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback, + glm_speed_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.01, # 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_source_terms.jl b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl index 48fe37b999..532fe8dbe7 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -42,7 +42,7 @@ save_solution = SaveSolutionCallback(interval = 100, save_final_solution = true, solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl = 2.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl index a6a56aa807..09abdf3384 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -108,7 +108,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/t8code_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/t8code_2d_dgsem/elixir_advection_amr_solution_independent.jl index 0589e76a6a..1ed08e1961 100644 --- a/examples/t8code_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/t8code_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -32,7 +32,7 @@ function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, outer_distance = 1.85 # Iterate over all elements. - for element in 1:length(alpha) + for element in eachindex(alpha) # Calculate periodic distance between cell and center. # This requires an uncurved mesh! coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + diff --git a/examples/tree_1d_dgsem/elixir_linearizedeuler_convergence.jl b/examples/tree_1d_dgsem/elixir_linearizedeuler_convergence.jl new file mode 100644 index 0000000000..5b17ab4f3d --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_linearizedeuler_convergence.jl @@ -0,0 +1,59 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linearized Euler equations + +equations = LinearizedEulerEquations1D(v_mean_global = 0.0, c_mean_global = 1.0, + rho_mean_global = 1.0) + +initial_condition = initial_condition_convergence_test + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0) +coordinates_max = (1.0) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 30_000) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +analysis_interval = 100 + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 0.8) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +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_linearizedeuler_gauss_wall.jl b/examples/tree_1d_dgsem/elixir_linearizedeuler_gauss_wall.jl new file mode 100644 index 0000000000..0884249559 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_linearizedeuler_gauss_wall.jl @@ -0,0 +1,65 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linearized Euler equations + +equations = LinearizedEulerEquations1D(v_mean_global = 0.5, c_mean_global = 1.0, + rho_mean_global = 1.0) + +solver = DGSEM(polydeg = 5, surface_flux = flux_hll) + +coordinates_min = (0.0,) +coordinates_max = (90.0,) + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 6, + n_cells_max = 100_000, + periodicity = false) + +# Initialize density and pressure perturbation with a Gaussian bump +# that is advected to left with v - c and to the right with v + c. +# Correspondigly, the bump splits in half. +function initial_condition_gauss_wall(x, t, equations::LinearizedEulerEquations1D) + v1_prime = 0.0 + rho_prime = p_prime = 2 * exp(-(x[1] - 45)^2 / 25) + return SVector(rho_prime, v1_prime, p_prime) +end +initial_condition = initial_condition_gauss_wall + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition_wall) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span from 0.0 to 30.0 +tspan = (0.0, 30.0) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = 100) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 0.7) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +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) + +# Print the timer summary +summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl index a3df37fb96..af0da5d176 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl @@ -77,7 +77,7 @@ save_solution = SaveSolutionCallback(interval = 100, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl index d9f1a52b50..a4f4b0189b 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl @@ -70,7 +70,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl index 649e5023f6..5851530e23 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl @@ -73,7 +73,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl index 03a213689e..c7412660b0 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -31,7 +31,7 @@ function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, outer_distance = 1.85 #Iterate over all elements - for element in 1:length(alpha) + for element in eachindex(alpha) #Calculate periodic distance between cell and center. cell_id = cache.elements.cell_ids[element] coordinates = mesh.tree.coordinates[1:2, cell_id] diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl index 47988bfef0..09e4bdeccd 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_subcell.jl @@ -42,8 +42,9 @@ basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], bar_states = true, max_iterations_newton = 25) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl index 2307a6d139..e70e1970f6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell.jl @@ -39,8 +39,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - math_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_math, + max)], bar_states = false, smoothness_indicator = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index 9d44eae485..d40a6d2b3d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -41,8 +41,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - math_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_math, + max)], bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl index 66d6e77629..7fe7c3d53e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_IDP.jl @@ -17,7 +17,6 @@ limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], positivity_correction_factor = 0.1, - spec_entropy = false, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), bar_states = true, diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl index 5630b51c29..acc2f10019 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_sc_subcell.jl @@ -40,7 +40,6 @@ basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], - spec_entropy = false, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 35d4317dde..7aa94e7739 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,8 +42,9 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], - spec_entropy = true, + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], smoothness_indicator = false, bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl index 5d9a90003d..8e2f06bca4 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_sc_subcell.jl @@ -14,7 +14,7 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], + local_twosided_variables_cons = ["rho"], positivity_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], bar_states = true, diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 6a1aae92b3..20a0c4f6f8 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -86,9 +86,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho" * string(i) - for i in eachcomponent(equations)], - spec_entropy = false, + local_twosided_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)], bar_states = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index 584f55644e..04e83d2dff 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -90,7 +90,6 @@ limiter_idp = SubcellLimiterIDP(equations, basis; for i in eachcomponent(equations)], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - spec_entropy = false, bar_states = false) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl index bc528ae775..8221dfebe3 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl @@ -105,7 +105,7 @@ save_solution = SaveSolutionCallback(dt = 0.2, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl index 13023dfaba..22043392b2 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -105,7 +105,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl index f50bd4e4f6..19073b0504 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl @@ -108,7 +108,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/tree_3d_dgsem/elixir_linearizedeuler_gauss_wall.jl b/examples/tree_3d_dgsem/elixir_linearizedeuler_gauss_wall.jl new file mode 100644 index 0000000000..2eb8ef822a --- /dev/null +++ b/examples/tree_3d_dgsem/elixir_linearizedeuler_gauss_wall.jl @@ -0,0 +1,65 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linearized Euler equations + +equations = LinearizedEulerEquations3D(v_mean_global = (0.5, 0.5, 0.5), c_mean_global = 1.0, + rho_mean_global = 1.0) + +solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs) + +coordinates_min = (0.0, 0.0, 0.0) +coordinates_max = (90.0, 90.0, 90.0) + +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 100_000, + periodicity = false) + +# Initialize density and pressure perturbation with a Gaussian bump +# that splits into radial waves which are advected with v - c and v + c. +function initial_condition_gauss_wall(x, t, equations::LinearizedEulerEquations3D) + v1_prime = 0.0 + v2_prime = 0.0 + v3_prime = 0.0 + rho_prime = p_prime = 2 * exp(-((x[1] - 45)^2 + (x[2] - 45)^2) / 25) + return SVector(rho_prime, v1_prime, v2_prime, v3_prime, p_prime) +end +initial_condition = initial_condition_gauss_wall + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition_wall) + +############################################################################### +# ODE solvers, callbacks etc. + +# At t = 30, the wave moving with v + c crashes into the wall +tspan = (0.0, 30.0) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = 100) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 0.9) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +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) + +# Print the timer summary +summary_callback() diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl index 9122fb8287..1f4aa41490 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl @@ -105,7 +105,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl index 98408db5a7..c4736e8b9a 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl @@ -110,7 +110,7 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl index 6bad3a77f0..6cefca853c 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -104,7 +104,7 @@ save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl = 3.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) diff --git a/src/Trixi.jl b/src/Trixi.jl index 1f74814145..4569bec13d 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -160,7 +160,7 @@ export AcousticPerturbationEquations2D, LatticeBoltzmannEquations2D, LatticeBoltzmannEquations3D, ShallowWaterEquations1D, ShallowWaterEquations2D, ShallowWaterEquationsQuasi1D, - LinearizedEulerEquations2D, + LinearizedEulerEquations1D, LinearizedEulerEquations2D, LinearizedEulerEquations3D, PolytropicEulerEquations2D, TrafficFlowLWREquations1D @@ -227,7 +227,8 @@ export entropy, energy_total, energy_kinetic, energy_internal, energy_magnetic, export lake_at_rest_error export ncomponents, eachcomponent -export TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, T8codeMesh +export TreeMesh, StructuredMesh, StructuredMeshView, UnstructuredMesh2D, P4estMesh, + T8codeMesh export DG, DGSEM, LobattoLegendreBasis, @@ -264,7 +265,9 @@ export SummaryCallback, SteadyStateCallback, AnalysisCallback, AliveCallback, AveragingCallback, AMRCallback, StepsizeCallback, LimitingAnalysisCallback, GlmSpeedCallback, LBMCollisionCallback, EulerAcousticsCouplingCallback, - TrivialCallback, AnalysisCallbackCoupled + TrivialCallback, AnalysisCallbackCoupled, + AnalysisSurfaceIntegral, DragCoefficientPressure, LiftCoefficientPressure, + DragCoefficientShearStress, LiftCoefficientShearStress export load_mesh, load_time, load_timestep, load_timestep!, load_dt, load_adaptive_time_integrator! diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 5ac9bc8b34..d41994ba93 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -89,28 +89,27 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_twosided, positivity, local_onesided) = limiter (; output_directory) = callback variables = varnames(cons2cons, semi.equations) mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time") - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons variable_string = string(variables[v]) print(f, ", " * variable_string * "_min, " * variable_string * "_max") end end - if spec_entropy - print(f, ", specEntr_min") - end - if math_entropy - print(f, ", mathEntr_max") + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + print(f, ", " * string(variable) * "_" * string(min_or_max)) + end end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end print(f, ", " * string(variables[v]) * "_min") @@ -158,15 +157,15 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_twosided, positivity, local_onesided) = limiter (; idp_bounds_delta_global) = limiter.cache variables = varnames(cons2cons, semi.equations) println("─"^100) println("Maximum deviation from bounds:") println("─"^100) - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) println("$(variables[v]):") println("- lower bound: ", @@ -175,17 +174,19 @@ end idp_bounds_delta_global[Symbol(v_string, "_max")]) end end - if spec_entropy - println("spec. entropy:\n- lower bound: ", - idp_bounds_delta_global[:spec_entropy_min]) - end - if math_entropy - println("math. entropy:\n- upper bound: ", - idp_bounds_delta_global[:math_entropy_max]) + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + variable_string = string(variable) + minmax_string = string(min_or_max) + println("$variable_string:") + println("- $minmax_string bound: ", + idp_bounds_delta_global[Symbol(variable_string, "_", + minmax_string)]) + end end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end println(string(variables[v]) * ":\n- positivity: ", diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 4a15a32643..99060d9acc 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -7,7 +7,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP) - (; local_minmax, positivity, spec_entropy, math_entropy) = solver.volume_integral.limiter + (; local_twosided, positivity, local_onesided) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta_local, idp_bounds_delta_global) = limiter.cache @@ -19,8 +19,8 @@ # `@batch` here to allow a possible redefinition of `@threaded` without creating errors here. # See also https://github.com/trixi-framework/Trixi.jl/pull/1888#discussion_r1537785293. - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) key_min = Symbol(v_string, "_min") key_max = Symbol(v_string, "_max") @@ -44,35 +44,28 @@ idp_bounds_delta_local[key_max] = deviation_max end end - if spec_entropy - key = :spec_entropy_min - deviation = idp_bounds_delta_local[key] - @batch reduction=(max, deviation) for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), - equations) - deviation = max(deviation, variable_bounds[key][i, j, element] - s) - end - idp_bounds_delta_local[key_min] = deviation_min - idp_bounds_delta_local[key_max] = deviation_max - end - idp_bounds_delta_local[key] = deviation - end - if math_entropy - key = :math_entropy_max - deviation = idp_bounds_delta_local[key] - @batch reduction=(max, deviation) for element in eachelement(solver, cache) - for j in eachnode(solver), i in eachnode(solver) - s = entropy_math(get_node_vars(u, equations, solver, i, j, element), + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + key = Symbol(string(variable), "_", string(min_or_max)) + deviation = idp_bounds_delta_local[key] + sign_ = min_or_max(1.0, -1.0) + @batch reduction=(max, deviation) for element in eachelement(solver, cache) + for j in eachnode(solver), i in eachnode(solver) + v = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation = max(deviation, s - variable_bounds[key][i, j, element]) + # Note: We always save the absolute deviations >= 0 and therefore use the + # `max` operator for lower and upper bounds. The different directions of + # upper and lower bounds are considered with `sign_`. + deviation = max(deviation, + sign_ * (v - variable_bounds[key][i, j, element])) + end end + idp_bounds_delta_local[key] = deviation end - idp_bounds_delta_local[key] = deviation end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end key = Symbol(string(v), "_min") @@ -112,28 +105,29 @@ end @inline function save_bounds_check_errors(output_directory, u, time, iter, equations, limiter::SubcellLimiterIDP) - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_twosided, positivity, local_onesided) = limiter (; idp_bounds_delta_local) = limiter.cache - # Print errors to output file + # Print to output file open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) print(f, ", ", idp_bounds_delta_local[Symbol(v_string, "_min")], ", ", idp_bounds_delta_local[Symbol(v_string, "_max")]) end end - if spec_entropy - print(f, ", ", idp_bounds_delta_local[:spec_entropy_min]) - end - if math_entropy - print(f, ", ", idp_bounds_delta_local[:math_entropy_max]) + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + key = Symbol(string(variable), "_", string(min_or_max)) + print(f, ", ", + idp_bounds_delta_local[key]) + end end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end print(f, ", ", idp_bounds_delta_local[Symbol(string(v), "_min")]) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 1ab65a3553..45f03fba8f 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -243,7 +243,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @unpack to_refine, to_coarsen = amr_callback.amr_cache empty!(to_refine) empty!(to_coarsen) - for element in 1:length(lambda) + for element in eachindex(lambda) controller_value = lambda[element] if controller_value > 0 push!(to_refine, leaf_cell_ids[element]) @@ -307,7 +307,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, end # Extract only those parent cells for which all children should be coarsened - to_coarsen = collect(1:length(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] + to_coarsen = collect(eachindex(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] # Finally, coarsen mesh coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh.tree, @@ -395,7 +395,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @unpack to_refine, to_coarsen = amr_callback.amr_cache empty!(to_refine) empty!(to_coarsen) - for element in 1:length(lambda) + for element in eachindex(lambda) controller_value = lambda[element] if controller_value > 0 push!(to_refine, leaf_cell_ids[element]) @@ -456,7 +456,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, end # Extract only those parent cells for which all children should be coarsened - to_coarsen = collect(1:length(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] + to_coarsen = collect(eachindex(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] # Finally, coarsen mesh coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh.tree, diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index ba23203295..8f89af755a 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -9,11 +9,11 @@ # - analysis_interval part as PeriodicCallback called after a certain amount of simulation time """ AnalysisCallback(semi; interval=0, - save_analysis=false, - output_directory="out", - analysis_filename="analysis.dat", - extra_analysis_errors=Symbol[], - extra_analysis_integrals=()) + save_analysis=false, + output_directory="out", + analysis_filename="analysis.dat", + extra_analysis_errors=Symbol[], + extra_analysis_integrals=()) Analyze a numerical solution every `interval` time steps and print the results to the screen. If `save_analysis`, the results are also saved in @@ -634,9 +634,7 @@ pretty_form_utf(quantity) = get_name(quantity) pretty_form_ascii(quantity) = get_name(quantity) # Special analyze for `SemidiscretizationHyperbolicParabolic` such that -# precomputed gradients are available. For now only implemented for the `enstrophy` -#!!! warning "Experimental code" -# This code is experimental and may be changed or removed in any future release. +# precomputed gradients are available. function analyze(quantity::typeof(enstrophy), du, u, t, semi::SemidiscretizationHyperbolicParabolic) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) @@ -691,6 +689,23 @@ end # @muladd # specialized implementations specific to some solvers include("analysis_dg1d.jl") include("analysis_dg2d.jl") +include("analysis_surface_integral_2d.jl") include("analysis_dg2d_parallel.jl") include("analysis_dg3d.jl") include("analysis_dg3d_parallel.jl") + +# Special analyze for `SemidiscretizationHyperbolicParabolic` such that +# precomputed gradients are available. Required for `enstrophy` (see above) and viscous forces. +# Note that this needs to be included after `analysis_surface_integral_2d.jl` to +# have `VariableViscous` available. +function analyze(quantity::AnalysisSurfaceIntegral{Variable}, + du, u, t, + semi::SemidiscretizationHyperbolicParabolic) where { + Variable <: + VariableViscous} + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + equations_parabolic = semi.equations_parabolic + cache_parabolic = semi.cache_parabolic + analyze(quantity, du, u, t, mesh, equations, equations_parabolic, solver, cache, + cache_parabolic) +end diff --git a/src/callbacks_step/analysis_dg2d.jl b/src/callbacks_step/analysis_dg2d.jl index a9e0cf87b0..de6b9a2a4a 100644 --- a/src/callbacks_step/analysis_dg2d.jl +++ b/src/callbacks_step/analysis_dg2d.jl @@ -30,7 +30,8 @@ function create_cache_analysis(analyzer, mesh::TreeMesh{2}, end function create_cache_analysis(analyzer, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2}}, equations, dg::DG, cache, RealT, uEltype) @@ -107,8 +108,9 @@ function calc_error_norms(func, u, t, analyzer, end function calc_error_norms(func, u, t, analyzer, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, equations, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2}}, + equations, initial_condition, dg::DGSEM, cache, cache_analysis) @unpack vandermonde, weights = analyzer @unpack node_coordinates, inverse_jacobian = cache.elements @@ -175,8 +177,10 @@ function integrate_via_indices(func::Func, u, end function integrate_via_indices(func::Func, u, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, equations, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, + T8codeMesh{2}}, + equations, dg::DGSEM, cache, args...; normalize = true) where {Func} @unpack weights = dg.basis @@ -203,8 +207,8 @@ function integrate_via_indices(func::Func, u, end function integrate(func::Func, u, - mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2}}, equations, dg::DG, cache; normalize = true) where {Func} integrate_via_indices(u, mesh, equations, dg, cache; normalize = normalize) do u, i, j, element, equations, dg @@ -232,8 +236,8 @@ function integrate(func::Func, u, end function analyze(::typeof(entropy_timederivative), du, u, t, - mesh::Union{TreeMesh{2}, StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2}}, equations, dg::DG, cache) # Calculate ∫(∂S/∂u ⋅ ∂u/∂t)dΩ integrate_via_indices(u, mesh, equations, dg, cache, diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl new file mode 100644 index 0000000000..7ae259e528 --- /dev/null +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -0,0 +1,400 @@ +# 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 callbacks that are performed on the surface like computation of +# surface forces + +""" + AnalysisSurfaceIntegral{Semidiscretization, Variable}(semi, + boundary_symbol_or_boundary_symbols, + variable) + +This struct is used to compute the surface integral of a quantity of interest `variable` alongside +the boundary/boundaries associated with particular name(s) given in `boundary_symbol` +or `boundary_symbols`. +For instance, this can be used to compute the lift [`LiftCoefficientPressure`](@ref) or +drag coefficient [`DragCoefficientPressure`](@ref) of e.g. an airfoil with the boundary +name `:Airfoil` in 2D. + +- `semi::Semidiscretization`: Passed in to retrieve boundary condition information +- `boundary_symbol_or_boundary_symbols::Symbol|Vector{Symbol}`: Name(s) of the boundary/boundaries + where the quantity of interest is computed +- `variable::Variable`: Quantity of interest, like lift or drag +""" +struct AnalysisSurfaceIntegral{Variable} + indices::Vector{Int} # Indices in `boundary_condition_indices` where quantity of interest is computed + variable::Variable # Quantity of interest, like lift or drag + + function AnalysisSurfaceIntegral(semi, boundary_symbol, variable) + @unpack boundary_symbol_indices = semi.boundary_conditions + indices = boundary_symbol_indices[boundary_symbol] + + return new{typeof(variable)}(indices, variable) + end + + function AnalysisSurfaceIntegral(semi, boundary_symbols::Vector{Symbol}, variable) + @unpack boundary_symbol_indices = semi.boundary_conditions + indices = Vector{Int}() + for name in boundary_symbols + append!(indices, boundary_symbol_indices[name]) + end + sort!(indices) + + return new{typeof(variable)}(indices, variable) + end +end + +struct ForceState{RealT <: Real} + psi::Tuple{RealT, RealT} # Unit vector normal or parallel to freestream + rhoinf::RealT + uinf::RealT + linf::RealT +end + +struct LiftCoefficientPressure{RealT <: Real} + force_state::ForceState{RealT} +end + +struct DragCoefficientPressure{RealT <: Real} + force_state::ForceState{RealT} +end + +# Abstract base type used for dispatch of `analyze` for quantities +# requiring gradients of the velocity field. +abstract type VariableViscous end + +struct LiftCoefficientShearStress{RealT <: Real} <: VariableViscous + force_state::ForceState{RealT} +end + +struct DragCoefficientShearStress{RealT <: Real} <: VariableViscous + force_state::ForceState{RealT} +end + +""" + LiftCoefficientPressure(aoa, rhoinf, uinf, linf) + +Compute the lift coefficient +```math +C_{L,p} \\coloneqq \\frac{\\oint_{\\partial \\Omega} p \\boldsymbol n \\cdot \\psi_L \\, \\mathrm{d} S} + {0.5 \\rho_{\\infty} U_{\\infty}^2 L_{\\infty}} +``` +based on the pressure distribution along a boundary. +Supposed to be used in conjunction with [`AnalysisSurfaceIntegral`](@ref) +which stores the boundary information and semidiscretization. + +- `aoa::Real`: Angle of attack in radians (for airfoils etc.) +- `rhoinf::Real`: Free-stream density +- `uinf::Real`: Free-stream velocity +- `linf::Real`: Reference length of geometry (e.g. airfoil chord length) +""" +function LiftCoefficientPressure(aoa, rhoinf, uinf, linf) + # psi_lift is the normal unit vector to the freestream direction. + # Note: The choice of the normal vector psi_lift = (-sin(aoa), cos(aoa)) + # leads to positive lift coefficients for positive angles of attack for airfoils. + # One could also use psi_lift = (sin(aoa), -cos(aoa)) which results in the same + # value, but with the opposite sign. + psi_lift = (-sin(aoa), cos(aoa)) + return LiftCoefficientPressure(ForceState(psi_lift, rhoinf, uinf, linf)) +end + +""" + DragCoefficientPressure(aoa, rhoinf, uinf, linf) + +Compute the drag coefficient +```math +C_{D,p} \\coloneqq \\frac{\\oint_{\\partial \\Omega} p \\boldsymbol n \\cdot \\psi_D \\, \\mathrm{d} S} + {0.5 \\rho_{\\infty} U_{\\infty}^2 L_{\\infty}} +``` +based on the pressure distribution along a boundary. +Supposed to be used in conjunction with [`AnalysisSurfaceIntegral`](@ref) +which stores the boundary information and semidiscretization. + +- `aoa::Real`: Angle of attack in radians (for airfoils etc.) +- `rhoinf::Real`: Free-stream density +- `uinf::Real`: Free-stream velocity +- `linf::Real`: Reference length of geometry (e.g. airfoil chord length) +""" +function DragCoefficientPressure(aoa, rhoinf, uinf, linf) + # `psi_drag` is the unit vector tangent to the freestream direction + psi_drag = (cos(aoa), sin(aoa)) + return DragCoefficientPressure(ForceState(psi_drag, rhoinf, uinf, linf)) +end + +""" + LiftCoefficientShearStress(aoa, rhoinf, uinf, linf) + +Compute the lift coefficient +```math +C_{L,f} \\coloneqq \\frac{\\oint_{\\partial \\Omega} \\boldsymbol \\tau_w \\cdot \\psi_L \\, \\mathrm{d} S} + {0.5 \\rho_{\\infty} U_{\\infty}^2 L_{\\infty}} +``` +based on the wall shear stress vector ``\\tau_w`` along a boundary. +Supposed to be used in conjunction with [`AnalysisSurfaceIntegral`](@ref) +which stores the boundary information and semidiscretization. + +- `aoa::Real`: Angle of attack in radians (for airfoils etc.) +- `rhoinf::Real`: Free-stream density +- `uinf::Real`: Free-stream velocity +- `linf::Real`: Reference length of geometry (e.g. airfoil chord length) +""" +function LiftCoefficientShearStress(aoa, rhoinf, uinf, linf) + # psi_lift is the normal unit vector to the freestream direction. + # Note: The choice of the normal vector psi_lift = (-sin(aoa), cos(aoa)) + # leads to negative lift coefficients for airfoils. + # One could also use psi_lift = (sin(aoa), -cos(aoa)) which results in the same + # value, but with the opposite sign. + psi_lift = (-sin(aoa), cos(aoa)) + return LiftCoefficientShearStress(ForceState(psi_lift, rhoinf, uinf, linf)) +end + +""" + DragCoefficientShearStress(aoa, rhoinf, uinf, linf) + +Compute the drag coefficient +```math +C_{D,f} \\coloneqq \\frac{\\oint_{\\partial \\Omega} \\boldsymbol \\tau_w \\cdot \\psi_D \\, \\mathrm{d} S} + {0.5 \\rho_{\\infty} U_{\\infty}^2 L_{\\infty}} +``` +based on the wall shear stress vector ``\\tau_w`` along a boundary. +Supposed to be used in conjunction with [`AnalysisSurfaceIntegral`](@ref) +which stores the boundary information and semidiscretization. + +- `aoa::Real`: Angle of attack in radians (for airfoils etc.) +- `rhoinf::Real`: Free-stream density +- `uinf::Real`: Free-stream velocity +- `linf::Real`: Reference length of geometry (e.g. airfoil chord length) +""" +function DragCoefficientShearStress(aoa, rhoinf, uinf, linf) + # `psi_drag` is the unit vector tangent to the freestream direction + psi_drag = (cos(aoa), sin(aoa)) + return DragCoefficientShearStress(ForceState(psi_drag, rhoinf, uinf, linf)) +end + +function (lift_coefficient::LiftCoefficientPressure)(u, normal_direction, x, t, + equations) + p = pressure(u, equations) + @unpack psi, rhoinf, uinf, linf = lift_coefficient.force_state + # Normalize as `normal_direction` is not necessarily a unit vector + n = dot(normal_direction, psi) / norm(normal_direction) + return p * n / (0.5 * rhoinf * uinf^2 * linf) +end + +function (drag_coefficient::DragCoefficientPressure)(u, normal_direction, x, t, + equations) + p = pressure(u, equations) + @unpack psi, rhoinf, uinf, linf = drag_coefficient.force_state + # Normalize as `normal_direction` is not necessarily a unit vector + n = dot(normal_direction, psi) / norm(normal_direction) + return p * n / (0.5 * rhoinf * uinf^2 * linf) +end + +# Compute the three components of the symmetric viscous stress tensor +# (tau_11, tau_12, tau_22) based on the gradients of the velocity field. +# This is required for drag and lift coefficients based on shear stress, +# as well as for the non-integrated quantities such as +# skin friction coefficient (to be added). +function viscous_stress_tensor(u, normal_direction, equations_parabolic, + gradients_1, gradients_2) + _, dv1dx, dv2dx, _ = convert_derivative_to_primitive(u, gradients_1, + equations_parabolic) + _, dv1dy, dv2dy, _ = convert_derivative_to_primitive(u, gradients_2, + equations_parabolic) + + # Components of viscous stress tensor + # (4/3 * (v1)_x - 2/3 * (v2)_y) + tau_11 = 4.0 / 3.0 * dv1dx - 2.0 / 3.0 * dv2dy + # ((v1)_y + (v2)_x) + # stress tensor is symmetric + tau_12 = dv1dy + dv2dx # = tau_21 + # (4/3 * (v2)_y - 2/3 * (v1)_x) + tau_22 = 4.0 / 3.0 * dv2dy - 2.0 / 3.0 * dv1dx + + mu = dynamic_viscosity(u, equations_parabolic) + + return mu .* (tau_11, tau_12, tau_22) +end + +function viscous_stress_vector(u, normal_direction, equations_parabolic, + gradients_1, gradients_2) + # Normalize normal direction, should point *into* the fluid => *(-1) + n_normal = -normal_direction / norm(normal_direction) + + tau_11, tau_12, tau_22 = viscous_stress_tensor(u, normal_direction, + equations_parabolic, + gradients_1, gradients_2) + + # Viscous stress vector: Stress tensor * normal vector + visc_stress_vector_1 = tau_11 * n_normal[1] + tau_12 * n_normal[2] + visc_stress_vector_2 = tau_12 * n_normal[1] + tau_22 * n_normal[2] + + return (visc_stress_vector_1, visc_stress_vector_2) +end + +function (lift_coefficient::LiftCoefficientShearStress)(u, normal_direction, x, t, + equations_parabolic, + gradients_1, gradients_2) + visc_stress_vector = viscous_stress_vector(u, normal_direction, equations_parabolic, + gradients_1, gradients_2) + @unpack psi, rhoinf, uinf, linf = lift_coefficient.force_state + return (visc_stress_vector[1] * psi[1] + visc_stress_vector[2] * psi[2]) / + (0.5 * rhoinf * uinf^2 * linf) +end + +function (drag_coefficient::DragCoefficientShearStress)(u, normal_direction, x, t, + equations_parabolic, + gradients_1, gradients_2) + visc_stress_vector = viscous_stress_vector(u, normal_direction, equations_parabolic, + gradients_1, gradients_2) + @unpack psi, rhoinf, uinf, linf = drag_coefficient.force_state + return (visc_stress_vector[1] * psi[1] + visc_stress_vector[2] * psi[2]) / + (0.5 * rhoinf * uinf^2 * linf) +end + +function analyze(surface_variable::AnalysisSurfaceIntegral, du, u, t, + mesh::P4estMesh{2}, + equations, dg::DGSEM, cache) + @unpack boundaries = cache + @unpack surface_flux_values, node_coordinates, contravariant_vectors = cache.elements + @unpack weights = dg.basis + + @unpack indices, variable = surface_variable + + surface_integral = zero(eltype(u)) + index_range = eachnode(dg) + for boundary in indices + element = boundaries.neighbor_ids[boundary] + node_indices = boundaries.node_indices[boundary] + direction = indices2direction(node_indices) + + i_node_start, i_node_step = index_to_start_step_2d(node_indices[1], index_range) + j_node_start, j_node_step = index_to_start_step_2d(node_indices[2], index_range) + + i_node = i_node_start + j_node = j_node_start + for node_index in index_range + u_node = Trixi.get_node_vars(cache.boundaries.u, equations, dg, node_index, + boundary) + # Extract normal direction at nodes which points from the elements outwards, + # i.e., *into* the structure. + normal_direction = get_normal_direction(direction, contravariant_vectors, + i_node, j_node, + element) + + # Coordinates at a boundary node + x = get_node_coords(node_coordinates, equations, dg, i_node, j_node, + element) + + # L2 norm of normal direction (contravariant_vector) is the surface element + dS = weights[node_index] * norm(normal_direction) + + # Integral over entire boundary surface. Note, it is assumed that the + # `normal_direction` is normalized to be a normal vector within the + # function `variable` and the division of the normal scaling factor + # `norm(normal_direction)` is then accounted for with the `dS` quantity. + surface_integral += variable(u_node, normal_direction, x, t, equations) * dS + + i_node += i_node_step + j_node += j_node_step + end + end + return surface_integral +end + +function analyze(surface_variable::AnalysisSurfaceIntegral{Variable}, + du, u, t, mesh::P4estMesh{2}, + equations, equations_parabolic, + dg::DGSEM, cache, + cache_parabolic) where {Variable <: VariableViscous} + @unpack boundaries = cache + @unpack surface_flux_values, node_coordinates, contravariant_vectors = cache.elements + @unpack weights = dg.basis + + @unpack indices, variable = surface_variable + + # Additions for parabolic + @unpack viscous_container = cache_parabolic + @unpack gradients = viscous_container + + gradients_x, gradients_y = gradients + + surface_integral = zero(eltype(u)) + index_range = eachnode(dg) + for boundary in indices + element = boundaries.neighbor_ids[boundary] + node_indices = boundaries.node_indices[boundary] + direction = indices2direction(node_indices) + + i_node_start, i_node_step = index_to_start_step_2d(node_indices[1], index_range) + j_node_start, j_node_step = index_to_start_step_2d(node_indices[2], index_range) + + i_node = i_node_start + j_node = j_node_start + for node_index in index_range + u_node = Trixi.get_node_vars(cache.boundaries.u, equations, dg, node_index, + boundary) + # Extract normal direction at nodes which points from the elements outwards, + # i.e., *into* the structure. + normal_direction = get_normal_direction(direction, contravariant_vectors, + i_node, j_node, + element) + + # Coordinates at a boundary node + x = get_node_coords(node_coordinates, equations, dg, i_node, j_node, + element) + + # L2 norm of normal direction (contravariant_vector) is the surface element + dS = weights[node_index] * norm(normal_direction) + + gradients_1 = get_node_vars(gradients_x, equations_parabolic, dg, i_node, + j_node, element) + gradients_2 = get_node_vars(gradients_y, equations_parabolic, dg, i_node, + j_node, element) + + # Integral over whole boundary surface. Note, it is assumed that the + # `normal_direction` is normalized to be a normal vector within the + # function `variable` and the division of the normal scaling factor + # `norm(normal_direction)` is then accounted for with the `dS` quantity. + surface_integral += variable(u_node, normal_direction, x, t, + equations_parabolic, + gradients_1, gradients_2) * dS + + i_node += i_node_step + j_node += j_node_step + end + end + return surface_integral +end + +function pretty_form_ascii(::AnalysisSurfaceIntegral{<:LiftCoefficientPressure{<:Any}}) + "CL_p" +end +function pretty_form_utf(::AnalysisSurfaceIntegral{<:LiftCoefficientPressure{<:Any}}) + "CL_p" +end + +function pretty_form_ascii(::AnalysisSurfaceIntegral{<:DragCoefficientPressure{<:Any}}) + "CD_p" +end +function pretty_form_utf(::AnalysisSurfaceIntegral{<:DragCoefficientPressure{<:Any}}) + "CD_p" +end + +function pretty_form_ascii(::AnalysisSurfaceIntegral{<:LiftCoefficientShearStress{<:Any}}) + "CL_f" +end +function pretty_form_utf(::AnalysisSurfaceIntegral{<:LiftCoefficientShearStress{<:Any}}) + "CL_f" +end + +function pretty_form_ascii(::AnalysisSurfaceIntegral{<:DragCoefficientShearStress{<:Any}}) + "CD_f" +end +function pretty_form_utf(::AnalysisSurfaceIntegral{<:DragCoefficientShearStress{<:Any}}) + "CD_f" +end +end # muladd diff --git a/src/callbacks_step/euler_acoustics_coupling_dg2d.jl b/src/callbacks_step/euler_acoustics_coupling_dg2d.jl index 16fac4f2d8..8a8bb893dc 100644 --- a/src/callbacks_step/euler_acoustics_coupling_dg2d.jl +++ b/src/callbacks_step/euler_acoustics_coupling_dg2d.jl @@ -12,7 +12,7 @@ function calc_acoustic_sources!(acoustic_source_terms, u_euler, u_acoustics, dg::DGSEM, cache) acoustic_source_terms .= zero(eltype(acoustic_source_terms)) - @threaded for k in 1:length(coupled_element_ids) + @threaded for k in eachindex(coupled_element_ids) element = coupled_element_ids[k] for j in eachnode(dg), i in eachnode(dg) diff --git a/src/callbacks_step/glm_speed.jl b/src/callbacks_step/glm_speed.jl index 036f61a522..8ee406af5f 100644 --- a/src/callbacks_step/glm_speed.jl +++ b/src/callbacks_step/glm_speed.jl @@ -6,7 +6,7 @@ #! format: noindent """ - GlmSpeedCallback(; glm_scale=0.5, cfl) + GlmSpeedCallback(; glm_scale=0.5, cfl, semi_indices=()) Update the divergence cleaning wave speed `c_h` according to the time step computed in [`StepsizeCallback`](@ref) for the ideal GLM-MHD equations. @@ -14,18 +14,26 @@ The `cfl` number should be set to the same value as for the time step size calcu `glm_scale` ensures that the GLM wave speed is lower than the fastest physical waves in the MHD solution and should thus be set to a value within the interval [0,1]. Note that `glm_scale = 0` deactivates the divergence cleaning. + +In case of coupled semidiscretizations, specify for which `semi_index`, i.e. index of the +semidiscretization, the divergence cleaning should be applied. See also +[`SemidiscretizationCoupled`](@ref). +Note: `SemidiscretizationCoupled` and all related features are considered experimental and +may change at any time. """ struct GlmSpeedCallback{RealT <: Real} glm_scale::RealT cfl::RealT + semi_indices::Vector{Int} end function Base.show(io::IO, cb::DiscreteCallback{<:Any, <:GlmSpeedCallback}) @nospecialize cb # reduce precompilation time glm_speed_callback = cb.affect! - @unpack glm_scale, cfl = glm_speed_callback - print(io, "GlmSpeedCallback(glm_scale=", glm_scale, ", cfl=", cfl, ")") + @unpack glm_scale, cfl, semi_indices = glm_speed_callback + print(io, "GlmSpeedCallback(glm_scale=", glm_scale, ", cfl=", cfl, "semi_indices=", + semi_indices, ")") end function Base.show(io::IO, ::MIME"text/plain", @@ -40,15 +48,16 @@ function Base.show(io::IO, ::MIME"text/plain", setup = [ "GLM wave speed scaling" => glm_speed_callback.glm_scale, "Expected CFL number" => glm_speed_callback.cfl, + "Selected semidiscretizations" => glm_speed_callback.semi_indices, ] summary_box(io, "GlmSpeedCallback", setup) end end -function GlmSpeedCallback(; glm_scale = 0.5, cfl) +function GlmSpeedCallback(; glm_scale = 0.5, cfl, semi_indices = Int[]) @assert 0<=glm_scale<=1 "glm_scale must be between 0 and 1" - glm_speed_callback = GlmSpeedCallback(glm_scale, cfl) + glm_speed_callback = GlmSpeedCallback(glm_scale, cfl, semi_indices) DiscreteCallback(glm_speed_callback, glm_speed_callback, # the first one is the condition, the second the affect! save_positions = (false, false), @@ -65,19 +74,29 @@ function (glm_speed_callback::GlmSpeedCallback)(u, t, integrator) return true end -# This method is called as callback after the StepsizeCallback during the time integration. -@inline function (glm_speed_callback::GlmSpeedCallback)(integrator) - dt = get_proposed_dt(integrator) - semi = integrator.p - mesh, equations, solver, cache = mesh_equations_solver_cache(semi) +function update_cleaning_speed!(semi, glm_speed_callback, dt) @unpack glm_scale, cfl = glm_speed_callback + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + # compute time step for GLM linear advection equation with c_h=1 (redone due to the possible AMR) c_h_deltat = calc_dt_for_cleaning_speed(cfl, mesh, equations, solver, cache) # c_h is proportional to its own time step divided by the complete MHD time step equations.c_h = glm_scale * c_h_deltat / dt + return semi +end + +# This method is called as callback after the StepsizeCallback during the time integration. +@inline function (glm_speed_callback::GlmSpeedCallback)(integrator) + dt = get_proposed_dt(integrator) + semi = integrator.p + + # Call the appropriate update function (this indirection allows to specialize on, + # e.g., the semidiscretization type) + update_cleaning_speed!(semi, glm_speed_callback, dt) + # avoid re-evaluating possible FSAL stages u_modified!(integrator, false) diff --git a/src/callbacks_step/save_solution_dg.jl b/src/callbacks_step/save_solution_dg.jl index 350aee7336..7367886ca9 100644 --- a/src/callbacks_step/save_solution_dg.jl +++ b/src/callbacks_step/save_solution_dg.jl @@ -7,6 +7,7 @@ function save_solution_file(u, time, dt, timestep, mesh::Union{SerialTreeMesh, StructuredMesh, + StructuredMeshView, UnstructuredMesh2D, SerialP4estMesh, SerialT8codeMesh}, equations, dg::DG, cache, diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 8779480cc1..709f3cee13 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -179,7 +179,7 @@ end function max_dt(u, t, mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}, - T8codeMesh{2}}, + T8codeMesh{2}, StructuredMeshView{2}}, constant_speed::False, equations, dg::DG, cache) # to avoid a division by zero if the speed vanishes everywhere, # e.g. for steady-state linear advection @@ -215,7 +215,7 @@ end function max_dt(u, t, mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, P4estMesh{2}, - T8codeMesh{2}}, + T8codeMesh{2}, StructuredMeshView{2}}, constant_speed::True, equations, dg::DG, cache) @unpack contravariant_vectors, inverse_jacobian = cache.elements diff --git a/src/callbacks_step/time_series_dg.jl b/src/callbacks_step/time_series_dg.jl index 3781a10662..5ba072bf56 100644 --- a/src/callbacks_step/time_series_dg.jl +++ b/src/callbacks_step/time_series_dg.jl @@ -9,9 +9,9 @@ function save_time_series_file(time_series_callback, mesh::Union{TreeMesh, UnstructuredMesh2D}, equations, dg::DG) - @unpack (interval, solution_variables, variable_names, + @unpack (interval, variable_names, output_directory, filename, point_coordinates, - point_data, time, step, time_series_cache) = time_series_callback + point_data, time, step) = time_series_callback n_points = length(point_data) h5open(joinpath(output_directory, filename), "w") do file diff --git a/src/callbacks_step/time_series_dg_tree.jl b/src/callbacks_step/time_series_dg_tree.jl index 37d4e6ea70..0af1688a8e 100644 --- a/src/callbacks_step/time_series_dg_tree.jl +++ b/src/callbacks_step/time_series_dg_tree.jl @@ -25,7 +25,7 @@ function get_elements_by_coordinates!(element_ids, coordinates, mesh::TreeMesh, cell_id = cell_ids[element] # Iterate over coordinates - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Skip coordinates for which an element has already been found if element_ids[index] > 0 continue @@ -63,7 +63,7 @@ function calc_interpolating_polynomials!(interpolating_polynomials, coordinates, wbary = barycentric_weights(nodes) - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Construct point x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh))) @@ -94,7 +94,7 @@ function record_state_at_points!(point_data, u, solution_variables, new_length = old_length + n_solution_variables # Loop over all points/elements that should be recorded - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Extract data array and element id data = point_data[index] element_id = element_ids[index] @@ -108,7 +108,7 @@ function record_state_at_points!(point_data, u, solution_variables, u_node = solution_variables(get_node_vars(u, equations, dg, i, element_id), equations) - for v in 1:length(u_node) + for v in eachindex(u_node) data[old_length + v] += (u_node[v] * interpolating_polynomials[i, 1, index]) end @@ -126,7 +126,7 @@ function record_state_at_points!(point_data, u, solution_variables, new_length = old_length + n_solution_variables # Loop over all points/elements that should be recorded - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Extract data array and element id data = point_data[index] element_id = element_ids[index] @@ -140,7 +140,7 @@ function record_state_at_points!(point_data, u, solution_variables, u_node = solution_variables(get_node_vars(u, equations, dg, i, j, element_id), equations) - for v in 1:length(u_node) + for v in eachindex(u_node) data[old_length + v] += (u_node[v] * interpolating_polynomials[i, 1, index] * interpolating_polynomials[j, 2, index]) @@ -159,7 +159,7 @@ function record_state_at_points!(point_data, u, solution_variables, new_length = old_length + n_solution_variables # Loop over all points/elements that should be recorded - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Extract data array and element id data = point_data[index] element_id = element_ids[index] @@ -173,7 +173,7 @@ function record_state_at_points!(point_data, u, solution_variables, u_node = solution_variables(get_node_vars(u, equations, dg, i, j, k, element_id), equations) - for v in 1:length(u_node) + for v in eachindex(u_node) data[old_length + v] += (u_node[v] * interpolating_polynomials[i, 1, index] * interpolating_polynomials[j, 2, index] diff --git a/src/callbacks_step/time_series_dg_unstructured.jl b/src/callbacks_step/time_series_dg_unstructured.jl index f6d1bb48f2..85427f1273 100644 --- a/src/callbacks_step/time_series_dg_unstructured.jl +++ b/src/callbacks_step/time_series_dg_unstructured.jl @@ -31,7 +31,7 @@ function get_elements_by_coordinates!(element_ids, coordinates, # Iterate over coordinates distances = zeros(eltype(mesh.corners), mesh.n_elements) indices = zeros(Int, mesh.n_elements, 2) - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Grab the current point for which the element needs found point = SVector(coordinates[1, index], coordinates[2, index]) @@ -77,7 +77,7 @@ function get_elements_by_coordinates!(element_ids, coordinates, # Loop through all the element candidates until we find a vector from the barycenter # to the surface that points in the same direction as the current `point` vector. # This then gives us the correct element. - for element in 1:length(candidates) + for element in eachindex(candidates) bary_center = SVector(bary_centers[1, candidates[element]], bary_centers[2, candidates[element]]) # Vector pointing from the barycenter toward the minimal `surface_point` @@ -153,7 +153,7 @@ function calc_interpolating_polynomials!(interpolating_polynomials, coordinates, # Helper array for a straight-sided quadrilateral element corners = zeros(eltype(mesh.corners), 4, 2) - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Construct point x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh))) @@ -280,7 +280,7 @@ function record_state_at_points!(point_data, u, solution_variables, new_length = old_length + n_solution_variables # Loop over all points/elements that should be recorded - for index in 1:length(element_ids) + for index in eachindex(element_ids) # Extract data array and element id data = point_data[index] element_id = element_ids[index] @@ -294,7 +294,7 @@ function record_state_at_points!(point_data, u, solution_variables, u_node = solution_variables(get_node_vars(u, equations, dg, i, j, element_id), equations) - for v in 1:length(u_node) + for v in eachindex(u_node) data[old_length + v] += (u_node[v] * interpolating_polynomials[i, 1, index] * interpolating_polynomials[j, 2, index]) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index e3a93de437..721e5c1c2d 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -678,7 +678,7 @@ end end """ - flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D) + flux_chandrashekar(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations2D) Entropy conserving two-point flux by - Chandrashekar (2013) @@ -724,6 +724,38 @@ Entropy conserving two-point flux by return SVector(f1, f2, f3, f4) end +@inline function flux_chandrashekar(u_ll, u_rr, normal_direction::AbstractVector, + equations::CompressibleEulerEquations2D) + # Unpack left and right state + rho_ll, v1_ll, v2_ll, p_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, p_rr = cons2prim(u_rr, equations) + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + beta_ll = 0.5 * rho_ll / p_ll + beta_rr = 0.5 * rho_rr / p_rr + specific_kin_ll = 0.5 * (v1_ll^2 + v2_ll^2) + specific_kin_rr = 0.5 * (v1_rr^2 + v2_rr^2) + + # Compute the necessary mean values + rho_avg = 0.5 * (rho_ll + rho_rr) + rho_mean = ln_mean(rho_ll, rho_rr) + beta_mean = ln_mean(beta_ll, beta_rr) + beta_avg = 0.5 * (beta_ll + beta_rr) + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + p_mean = 0.5 * rho_avg / beta_avg + velocity_square_avg = specific_kin_ll + specific_kin_rr + + # Multiply with average of normal velocities + f1 = rho_mean * 0.5 * (v_dot_n_ll + v_dot_n_rr) + f2 = f1 * v1_avg + p_mean * normal_direction[1] + f3 = f1 * v2_avg + p_mean * normal_direction[2] + f4 = f1 * 0.5 * (1 / (equations.gamma - 1) / beta_mean - velocity_square_avg) + + f2 * v1_avg + f3 * v2_avg + + return SVector(f1, f2, f3, f4) +end + """ flux_ranocha(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations2D) @@ -1980,9 +2012,10 @@ end return SVector(w1, w2, w3, w4) end -# Transformation from conservative variables u to entropy vector dSdu, -# S = -rho*s/(gamma-1), s=ln(p)-gamma*ln(rho) -@inline function cons2entropy_spec(u, equations::CompressibleEulerEquations2D) +# Transformation from conservative variables u to entropy vector ds_0/du, +# using the modified specific entropy of Guermond et al. (2019): s_0 = p * rho^(-gamma) / (gamma-1). +# Note: This is *not* the "conventional" specific entropy s = ln(p / rho^(gamma)). +@inline function cons2entropy_guermond_etal(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u v1 = rho_v1 / rho @@ -1997,13 +2030,6 @@ end w3 = -rho_v2 * inv_rho_gammap1 w4 = (1 / rho)^equations.gamma - # The derivative vector for other specific entropy - # sp = 1.0/(gammam1 * (rho_e - 0.5 * rho * v_square) - # w1 = gammam1 * 0.5 * v_square * sp - gamma / rho - # w2 = -gammam1 * v1 * sp - # w3 = -gammam1 * v2 * sp - # w4 = gammam1 * sp - return SVector(w1, w2, w3, w4) end @@ -2113,28 +2139,26 @@ end end # Transformation from conservative variables u to d(s)/d(u) -@inline function variable_derivative(::typeof(entropy_math), - u, equations::CompressibleEulerEquations2D) +@inline function gradient_conservative(::typeof(entropy_math), + u, equations::CompressibleEulerEquations2D) return cons2entropy(u, equations) end -# Calculate specific entropy for conservative variable u -@inline function entropy_spec(u, equations::CompressibleEulerEquations2D) +# Calculate the modified specific entropy of Guermond et al. (2019): s_0 = p * rho^(-gamma) / (gamma-1). +# Note: This is *not* the "conventional" specific entropy s = ln(p / rho^(gamma)). +@inline function entropy_guermond_etal(u, equations::CompressibleEulerEquations2D) rho, rho_v1, rho_v2, rho_e = u # Modified specific entropy from Guermond et al. (2019) s = (rho_e - 0.5 * (rho_v1^2 + rho_v2^2) / rho) * (1 / rho)^equations.gamma - # Other specific entropy - # rho_sp = rho/((equations.gamma - 1.0) * (rho_e - 0.5 * rho * v_square)) - # s = log(p) - (equaions.gamma + 1) * log(rho) return s end # Transformation from conservative variables u to d(s)/d(u) -@inline function variable_derivative(::typeof(entropy_spec), - u, equations::CompressibleEulerEquations2D) - return cons2entropy_spec(u, equations) +@inline function gradient_conservative(::typeof(entropy_guermond_etal), + u, equations::CompressibleEulerEquations2D) + return cons2entropy_guermond_etal(u, equations) end # Default entropy is the mathematical entropy diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index 292b912f00..f156aa2968 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -602,7 +602,7 @@ end end """ - flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D) + flux_chandrashekar(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations3D) Entropy conserving two-point flux by - Chandrashekar (2013) @@ -659,6 +659,44 @@ Entropy conserving two-point flux by return SVector(f1, f2, f3, f4, f5) end +@inline function flux_chandrashekar(u_ll, u_rr, normal_direction::AbstractVector, + equations::CompressibleEulerEquations3D) + # Unpack left and right state + rho_ll, v1_ll, v2_ll, v3_ll, p_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, v3_rr, p_rr = cons2prim(u_rr, equations) + + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + + v3_ll * normal_direction[3] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + v3_rr * normal_direction[3] + + beta_ll = 0.5 * rho_ll / p_ll + beta_rr = 0.5 * rho_rr / p_rr + specific_kin_ll = 0.5 * (v1_ll^2 + v2_ll^2 + v3_ll^2) + specific_kin_rr = 0.5 * (v1_rr^2 + v2_rr^2 + v3_rr^2) + + # Compute the necessary mean values + rho_avg = 0.5 * (rho_ll + rho_rr) + rho_mean = ln_mean(rho_ll, rho_rr) + beta_mean = ln_mean(beta_ll, beta_rr) + beta_avg = 0.5 * (beta_ll + beta_rr) + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + v3_avg = 0.5 * (v3_ll + v3_rr) + p_mean = 0.5 * rho_avg / beta_avg + velocity_square_avg = specific_kin_ll + specific_kin_rr + + # Multiply with average of normal velocities + f1 = rho_mean * 0.5 * (v_dot_n_ll + v_dot_n_rr) + f2 = f1 * v1_avg + p_mean * normal_direction[1] + f3 = f1 * v2_avg + p_mean * normal_direction[2] + f4 = f1 * v3_avg + p_mean * normal_direction[3] + f5 = f1 * 0.5 * (1 / (equations.gamma - 1) / beta_mean - velocity_square_avg) + + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg + + return SVector(f1, f2, f3, f4, f5) +end + """ flux_ranocha(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations3D) diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 98ec84a76b..d1567bdbf5 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -560,7 +560,9 @@ include("acoustic_perturbation_2d.jl") # Linearized Euler equations abstract type AbstractLinearizedEulerEquations{NDIMS, NVARS} <: AbstractEquations{NDIMS, NVARS} end +include("linearized_euler_1d.jl") include("linearized_euler_2d.jl") +include("linearized_euler_3d.jl") abstract type AbstractEquationsParabolic{NDIMS, NVARS, GradientVariables} <: AbstractEquations{NDIMS, NVARS} end diff --git a/src/equations/inviscid_burgers_1d.jl b/src/equations/inviscid_burgers_1d.jl index f2387f26ba..130196a492 100644 --- a/src/equations/inviscid_burgers_1d.jl +++ b/src/equations/inviscid_burgers_1d.jl @@ -168,6 +168,7 @@ end # Convert conservative variables to entropy variables @inline cons2entropy(u, equation::InviscidBurgersEquation1D) = u +@inline entropy2cons(u, equation::InviscidBurgersEquation1D) = u # Calculate entropy for a conservative state `cons` @inline entropy(u::Real, ::InviscidBurgersEquation1D) = 0.5 * u^2 diff --git a/src/equations/laplace_diffusion_1d.jl b/src/equations/laplace_diffusion_1d.jl index 815b9908c1..64a72ef3a1 100644 --- a/src/equations/laplace_diffusion_1d.jl +++ b/src/equations/laplace_diffusion_1d.jl @@ -24,12 +24,13 @@ function flux(u, gradients, orientation::Integer, equations_parabolic::LaplaceDi return equations_parabolic.diffusivity * dudx end -# Dirichlet-type boundary condition for use with a parabolic solver in weak form +# Dirichlet and Neumann boundary conditions for use with parabolic solvers in weak form. +# Note that these are general, so they apply to LaplaceDiffusion in any spatial dimension. @inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, normal::AbstractVector, x, t, operator_type::Gradient, - equations_parabolic::LaplaceDiffusion1D) + equations_parabolic::AbstractLaplaceDiffusion) return boundary_condition.boundary_value_function(x, t, equations_parabolic) end @@ -37,7 +38,7 @@ end normal::AbstractVector, x, t, operator_type::Divergence, - equations_parabolic::LaplaceDiffusion1D) + equations_parabolic::AbstractLaplaceDiffusion) return flux_inner end @@ -45,7 +46,7 @@ end normal::AbstractVector, x, t, operator_type::Divergence, - equations_parabolic::LaplaceDiffusion1D) + equations_parabolic::AbstractLaplaceDiffusion) return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) end @@ -53,6 +54,6 @@ end normal::AbstractVector, x, t, operator_type::Gradient, - equations_parabolic::LaplaceDiffusion1D) + equations_parabolic::AbstractLaplaceDiffusion) return flux_inner end diff --git a/src/equations/laplace_diffusion_2d.jl b/src/equations/laplace_diffusion_2d.jl index b848633fbc..5de989849b 100644 --- a/src/equations/laplace_diffusion_2d.jl +++ b/src/equations/laplace_diffusion_2d.jl @@ -35,35 +35,4 @@ function penalty(u_outer, u_inner, inv_h, equations_parabolic::LaplaceDiffusion2 return dg.penalty_parameter * (u_outer - u_inner) * equations_parabolic.diffusivity end -# Dirichlet-type boundary condition for use with a parabolic solver in weak form -@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Gradient, - equations_parabolic::LaplaceDiffusion2D) - return boundary_condition.boundary_value_function(x, t, equations_parabolic) -end - -@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Divergence, - equations_parabolic::LaplaceDiffusion2D) - return flux_inner -end - -@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Divergence, - equations_parabolic::LaplaceDiffusion2D) - return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) -end - -@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Gradient, - equations_parabolic::LaplaceDiffusion2D) - return flux_inner -end +# General Dirichlet and Neumann boundary condition functions are defined in `src/equations/laplace_diffusion_1d.jl`. diff --git a/src/equations/laplace_diffusion_3d.jl b/src/equations/laplace_diffusion_3d.jl index 3988ce7144..fbd3d27725 100644 --- a/src/equations/laplace_diffusion_3d.jl +++ b/src/equations/laplace_diffusion_3d.jl @@ -38,35 +38,4 @@ function penalty(u_outer, u_inner, inv_h, equations_parabolic::LaplaceDiffusion3 return dg.penalty_parameter * (u_outer - u_inner) * equations_parabolic.diffusivity end -# Dirichlet-type boundary condition for use with a parabolic solver in weak form -@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Gradient, - equations_parabolic::LaplaceDiffusion3D) - return boundary_condition.boundary_value_function(x, t, equations_parabolic) -end - -@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Divergence, - equations_parabolic::LaplaceDiffusion3D) - return flux_inner -end - -@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Divergence, - equations_parabolic::LaplaceDiffusion3D) - return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) -end - -@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, - normal::AbstractVector, - x, t, - operator_type::Gradient, - equations_parabolic::LaplaceDiffusion3D) - return flux_inner -end +# General Dirichlet and Neumann boundary condition functions are defined in `src/equations/laplace_diffusion_1d.jl`. diff --git a/src/equations/linearized_euler_1d.jl b/src/equations/linearized_euler_1d.jl new file mode 100644 index 0000000000..19a3bdcb3b --- /dev/null +++ b/src/equations/linearized_euler_1d.jl @@ -0,0 +1,144 @@ +# 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""" + LinearizedEulerEquations1D(v_mean_global, c_mean_global, rho_mean_global) + +Linearized Euler equations in one space dimension. The equations are given by +```math +\partial_t +\begin{pmatrix} + \rho' \\ v_1' \\ p' +\end{pmatrix} ++ +\partial_x +\begin{pmatrix} + \bar{\rho} v_1' + \bar{v_1} \rho ' \\ \bar{v_1} v_1' + \frac{p'}{\bar{\rho}} \\ \bar{v_1} p' + c^2 \bar{\rho} v_1' +\end{pmatrix} += +\begin{pmatrix} + 0 \\ 0 \\ 0 +\end{pmatrix} +``` +The bar ``\bar{(\cdot)}`` indicates uniform mean flow variables and ``c`` is the speed of sound. +The unknowns are the perturbation quantities of the acoustic velocity ``v_1'``, the pressure ``p'`` +and the density ``\rho'``. +""" +struct LinearizedEulerEquations1D{RealT <: Real} <: + AbstractLinearizedEulerEquations{1, 3} + v_mean_global::RealT + c_mean_global::RealT + rho_mean_global::RealT +end + +function LinearizedEulerEquations1D(v_mean_global::Real, + c_mean_global::Real, rho_mean_global::Real) + if rho_mean_global < 0 + throw(ArgumentError("rho_mean_global must be non-negative")) + elseif c_mean_global < 0 + throw(ArgumentError("c_mean_global must be non-negative")) + end + + return LinearizedEulerEquations1D(v_mean_global, c_mean_global, + rho_mean_global) +end + +# Constructor with keywords +function LinearizedEulerEquations1D(; v_mean_global::Real, + c_mean_global::Real, rho_mean_global::Real) + return LinearizedEulerEquations1D(v_mean_global, c_mean_global, + rho_mean_global) +end + +function varnames(::typeof(cons2cons), ::LinearizedEulerEquations1D) + ("rho_prime", "v1_prime", "p_prime") +end +function varnames(::typeof(cons2prim), ::LinearizedEulerEquations1D) + ("rho_prime", "v1_prime", "p_prime") +end + +""" + initial_condition_convergence_test(x, t, equations::LinearizedEulerEquations1D) + +A smooth initial condition used for convergence tests. +""" +function initial_condition_convergence_test(x, t, equations::LinearizedEulerEquations1D) + rho_prime = -cospi(2 * t) * sinpi(2 * x[1]) + v1_prime = sinpi(2 * t) * cospi(2 * x[1]) + p_prime = rho_prime + + return SVector(rho_prime, v1_prime, p_prime) +end + +""" + boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function, + equations::LinearizedEulerEquations1D) + +Boundary conditions for a solid wall. +""" +function boundary_condition_wall(u_inner, orientation, direction, x, t, + surface_flux_function, + equations::LinearizedEulerEquations1D) + # Boundary state is equal to the inner state except for the velocity. For boundaries + # in the -x/+x direction, we multiply the velocity (in the x direction by) -1. + u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3]) + + # 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 +@inline function flux(u, orientation::Integer, equations::LinearizedEulerEquations1D) + @unpack v_mean_global, c_mean_global, rho_mean_global = equations + rho_prime, v1_prime, p_prime = u + f1 = v_mean_global * rho_prime + rho_mean_global * v1_prime + f2 = v_mean_global * v1_prime + p_prime / rho_mean_global + f3 = v_mean_global * p_prime + c_mean_global^2 * rho_mean_global * v1_prime + + return SVector(f1, f2, f3) +end + +@inline have_constant_speed(::LinearizedEulerEquations1D) = True() + +@inline function max_abs_speeds(equations::LinearizedEulerEquations1D) + @unpack v_mean_global, c_mean_global = equations + return abs(v_mean_global) + c_mean_global +end + +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations1D) + @unpack v_mean_global, c_mean_global = equations + return abs(v_mean_global) + c_mean_global +end + +# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations1D) + min_max_speed_davis(u_ll, u_rr, orientation, equations) +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations1D) + @unpack v_mean_global, c_mean_global = equations + + λ_min = v_mean_global - c_mean_global + λ_max = v_mean_global + c_mean_global + + return λ_min, λ_max +end + +# Convert conservative variables to primitive +@inline cons2prim(u, equations::LinearizedEulerEquations1D) = u +@inline cons2entropy(u, ::LinearizedEulerEquations1D) = u +end # muladd diff --git a/src/equations/linearized_euler_2d.jl b/src/equations/linearized_euler_2d.jl index d497762bf6..3df3093069 100644 --- a/src/equations/linearized_euler_2d.jl +++ b/src/equations/linearized_euler_2d.jl @@ -8,7 +8,7 @@ @doc raw""" LinearizedEulerEquations2D(v_mean_global, c_mean_global, rho_mean_global) -Linearized euler equations in two space dimensions. The equations are given by +Linearized Euler equations in two space dimensions. The equations are given by ```math \partial_t \begin{pmatrix} @@ -29,7 +29,7 @@ Linearized euler equations in two space dimensions. The equations are given by 0 \\ 0 \\ 0 \\ 0 \end{pmatrix} ``` -The bar ``\bar{(\cdot)}`` indicates uniform mean flow variables and c is the speed of sound. +The bar ``\bar{(\cdot)}`` indicates uniform mean flow variables and ``c`` is the speed of sound. The unknowns are the acoustic velocities ``v' = (v_1', v_2')``, the pressure ``p'`` and the density ``\rho'``. """ struct LinearizedEulerEquations2D{RealT <: Real} <: diff --git a/src/equations/linearized_euler_3d.jl b/src/equations/linearized_euler_3d.jl new file mode 100644 index 0000000000..ab5f9863db --- /dev/null +++ b/src/equations/linearized_euler_3d.jl @@ -0,0 +1,254 @@ +# 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""" + LinearizedEulerEquations3D(v_mean_global, c_mean_global, rho_mean_global) + +Linearized Euler equations in three space dimensions. The equations are given by +```math +\partial_t +\begin{pmatrix} + \rho' \\ v_1' \\ v_2' \\ v_3' \\ p' +\end{pmatrix} ++ +\partial_x +\begin{pmatrix} + \bar{\rho} v_1' + \bar{v_1} \rho ' \\ + \bar{v_1} v_1' + \frac{p'}{\bar{\rho}} \\ + \bar{v_1} v_2' \\ + \bar{v_1} v_3' \\ + \bar{v_1} p' + c^2 \bar{\rho} v_1' +\end{pmatrix} ++ +\partial_y +\begin{pmatrix} + \bar{\rho} v_2' + \bar{v_2} \rho ' \\ + \bar{v_2} v_1' \\ + \bar{v_2} v_2' + \frac{p'}{\bar{\rho}} \\ + \bar{v_2} v_3' \\ + \bar{v_2} p' + c^2 \bar{\rho} v_2' +\end{pmatrix} ++ +\partial_z +\begin{pmatrix} + \bar{\rho} v_3' + \bar{v_3} \rho ' \\ + \bar{v_3} v_1' \\ + \bar{v_3} v_2' \\ + \bar{v_3} v_3' + \frac{p'}{\bar{\rho}} \\ + \bar{v_3} p' + c^2 \bar{\rho} v_3' +\end{pmatrix} += +\begin{pmatrix} + 0 \\ 0 \\ 0 \\ 0 \\ 0 +\end{pmatrix} +``` +The bar ``\bar{(\cdot)}`` indicates uniform mean flow variables and ``c`` is the speed of sound. +The unknowns are the acoustic velocities ``v' = (v_1', v_2, v_3')``, the pressure ``p'`` and the density ``\rho'``. +""" +struct LinearizedEulerEquations3D{RealT <: Real} <: + AbstractLinearizedEulerEquations{3, 5} + v_mean_global::SVector{3, RealT} + c_mean_global::RealT + rho_mean_global::RealT +end + +function LinearizedEulerEquations3D(v_mean_global::NTuple{3, <:Real}, + c_mean_global::Real, rho_mean_global::Real) + if rho_mean_global < 0 + throw(ArgumentError("rho_mean_global must be non-negative")) + elseif c_mean_global < 0 + throw(ArgumentError("c_mean_global must be non-negative")) + end + + return LinearizedEulerEquations3D(SVector(v_mean_global), c_mean_global, + rho_mean_global) +end + +function LinearizedEulerEquations3D(; v_mean_global::NTuple{3, <:Real}, + c_mean_global::Real, rho_mean_global::Real) + return LinearizedEulerEquations3D(v_mean_global, c_mean_global, + rho_mean_global) +end + +function varnames(::typeof(cons2cons), ::LinearizedEulerEquations3D) + ("rho_prime", "v1_prime", "v2_prime", "v3_prime", "p_prime") +end +function varnames(::typeof(cons2prim), ::LinearizedEulerEquations3D) + ("rho_prime", "v1_prime", "v2_prime", "v3_prime", "p_prime") +end + +""" + initial_condition_convergence_test(x, t, equations::LinearizedEulerEquations3D) + +A smooth initial condition used for convergence tests. +""" +function initial_condition_convergence_test(x, t, equations::LinearizedEulerEquations3D) + rho_prime = -cospi(2 * t) * (sinpi(2 * x[1]) + sinpi(2 * x[2]) + sinpi(2 * x[3])) + v1_prime = sinpi(2 * t) * cospi(2 * x[1]) + v2_prime = sinpi(2 * t) * cospi(2 * x[2]) + v3_prime = sinpi(2 * t) * cospi(2 * x[3]) + p_prime = rho_prime + + return SVector(rho_prime, v1_prime, v2_prime, v3_prime, p_prime) +end + +""" + boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function, + equations::LinearizedEulerEquations3D) + +Boundary conditions for a solid wall. +""" +function boundary_condition_wall(u_inner, orientation, direction, x, t, + surface_flux_function, + equations::LinearizedEulerEquations3D) + # Boundary state is equal to the inner state except for the velocity. For boundaries + # in the -x/+x direction, we multiply the velocity in the x direction by -1. + # Similarly, for boundaries in the -y/+y or -z/+z direction, we multiply the + # velocity in the y or z direction by -1 + if direction in (1, 2) # x direction + u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4], + u_inner[5]) + elseif direction in (3, 4) # y direction + u_boundary = SVector(u_inner[1], u_inner[2], -u_inner[3], u_inner[4], + u_inner[5]) + else # z direction = (5, 6) + u_boundary = SVector(u_inner[1], u_inner[2], u_inner[3], -u_inner[4], + u_inner[5]) + end + + # Calculate boundary flux depending on the orientation of the boundary + # Odd directions are in negative coordinate direction, + # even directions are in positive coordinate direction. + 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 3D flux for a single point +@inline function flux(u, orientation::Integer, equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global, rho_mean_global = equations + rho_prime, v1_prime, v2_prime, v3_prime, p_prime = u + if orientation == 1 + f1 = v_mean_global[1] * rho_prime + rho_mean_global * v1_prime + f2 = v_mean_global[1] * v1_prime + p_prime / rho_mean_global + f3 = v_mean_global[1] * v2_prime + f4 = v_mean_global[1] * v3_prime + f5 = v_mean_global[1] * p_prime + c_mean_global^2 * rho_mean_global * v1_prime + elseif orientation == 2 + f1 = v_mean_global[2] * rho_prime + rho_mean_global * v2_prime + f2 = v_mean_global[2] * v1_prime + f3 = v_mean_global[2] * v2_prime + p_prime / rho_mean_global + f4 = v_mean_global[2] * v3_prime + f5 = v_mean_global[2] * p_prime + c_mean_global^2 * rho_mean_global * v2_prime + else # orientation == 3 + f1 = v_mean_global[3] * rho_prime + rho_mean_global * v3_prime + f2 = v_mean_global[3] * v1_prime + f3 = v_mean_global[3] * v2_prime + f4 = v_mean_global[3] * v3_prime + p_prime / rho_mean_global + f5 = v_mean_global[3] * p_prime + c_mean_global^2 * rho_mean_global * v3_prime + end + + return SVector(f1, f2, f3, f4, f5) +end + +# Calculate 3D flux for a single point +@inline function flux(u, normal_direction::AbstractVector, + equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global, rho_mean_global = equations + rho_prime, v1_prime, v2_prime, v3_prime, p_prime = u + + v_mean_normal = v_mean_global[1] * normal_direction[1] + + v_mean_global[2] * normal_direction[2] + + v_mean_global[3] * normal_direction[3] + v_prime_normal = v1_prime * normal_direction[1] + v2_prime * normal_direction[2] + + v3_prime * normal_direction[3] + + f1 = v_mean_normal * rho_prime + rho_mean_global * v_prime_normal + f2 = v_mean_normal * v1_prime + normal_direction[1] * p_prime / rho_mean_global + f3 = v_mean_normal * v2_prime + normal_direction[2] * p_prime / rho_mean_global + f4 = v_mean_normal * v3_prime + normal_direction[3] * p_prime / rho_mean_global + f5 = v_mean_normal * p_prime + c_mean_global^2 * rho_mean_global * v_prime_normal + + return SVector(f1, f2, f3, f4, f5) +end + +@inline have_constant_speed(::LinearizedEulerEquations3D) = True() + +@inline function max_abs_speeds(equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global = equations + return abs(v_mean_global[1]) + c_mean_global, abs(v_mean_global[2]) + c_mean_global, + abs(v_mean_global[3]) + c_mean_global +end + +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global = equations + if orientation == 1 + return abs(v_mean_global[1]) + c_mean_global + elseif orientation == 2 + return abs(v_mean_global[2]) + c_mean_global + else # orientation == 3 + return abs(v_mean_global[3]) + c_mean_global + end +end + +@inline function max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global = equations + v_mean_normal = normal_direction[1] * v_mean_global[1] + + normal_direction[2] * v_mean_global[2] + + normal_direction[3] * v_mean_global[3] + return abs(v_mean_normal) + c_mean_global * norm(normal_direction) +end + +# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations3D) + min_max_speed_davis(u_ll, u_rr, orientation, equations) +end + +@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::LinearizedEulerEquations3D) + min_max_speed_davis(u_ll, u_rr, normal_direction, equations) +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global = equations + + λ_min = v_mean_global[orientation] - c_mean_global + λ_max = v_mean_global[orientation] + c_mean_global + + return λ_min, λ_max +end + +@inline function min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, + equations::LinearizedEulerEquations3D) + @unpack v_mean_global, c_mean_global = equations + + norm_ = norm(normal_direction) + + v_normal = v_mean_global[1] * normal_direction[1] + + v_mean_global[2] * normal_direction[2] + + v_mean_global[3] * normal_direction[3] + + # The v_normals are already scaled by the norm + λ_min = v_normal - c_mean_global * norm_ + λ_max = v_normal + c_mean_global * norm_ + + return λ_min, λ_max +end + +# Convert conservative variables to primitive +@inline cons2prim(u, equations::LinearizedEulerEquations3D) = u +@inline cons2entropy(u, ::LinearizedEulerEquations3D) = u +end # muladd diff --git a/src/equations/shallow_water_1d.jl b/src/equations/shallow_water_1d.jl index e348ef946b..7007bea887 100644 --- a/src/equations/shallow_water_1d.jl +++ b/src/equations/shallow_water_1d.jl @@ -551,7 +551,7 @@ end h = waterheight(u, equations) v = velocity(u, equations) - c = equations.gravity * sqrt(h) + c = sqrt(equations.gravity * h) return (abs(v) + c,) end diff --git a/src/equations/shallow_water_2d.jl b/src/equations/shallow_water_2d.jl index 74a299a51e..73fae89a0f 100644 --- a/src/equations/shallow_water_2d.jl +++ b/src/equations/shallow_water_2d.jl @@ -927,7 +927,7 @@ end h = waterheight(u, equations) v1, v2 = velocity(u, equations) - c = equations.gravity * sqrt(h) + c = sqrt(equations.gravity * h) return abs(v1) + c, abs(v2) + c end diff --git a/src/equations/shallow_water_quasi_1d.jl b/src/equations/shallow_water_quasi_1d.jl index 51c360104a..0862002125 100644 --- a/src/equations/shallow_water_quasi_1d.jl +++ b/src/equations/shallow_water_quasi_1d.jl @@ -248,7 +248,7 @@ end h = waterheight(u, equations) v = velocity(u, equations) - c = equations.gravity * sqrt(h) + c = sqrt(equations.gravity * h) return (abs(v) + c,) end diff --git a/src/meshes/mesh_io.jl b/src/meshes/mesh_io.jl index 28e6efa8c5..d74a0c0cea 100644 --- a/src/meshes/mesh_io.jl +++ b/src/meshes/mesh_io.jl @@ -97,7 +97,10 @@ end # of the mesh, like its size and the type of boundary mapping function. # Then, within Trixi2Vtk, the StructuredMesh and its node coordinates are reconstructured from # these attributes for plotting purposes -function save_mesh_file(mesh::StructuredMesh, output_directory; system = "") +# Note: the `timestep` argument is needed for compatibility with the method for +# `StructuredMeshView` +function save_mesh_file(mesh::StructuredMesh, output_directory; system = "", + timestep = 0) # Create output directory (if it does not exist) mkpath(output_directory) @@ -256,7 +259,7 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT) end mesh = TreeMesh(SerialTree{ndims}, max(n_cells_max, capacity)) load_mesh!(mesh, mesh_file) - elseif mesh_type == "StructuredMesh" + elseif mesh_type in ("StructuredMesh", "StructuredMeshView") size_, mapping_as_string = h5open(mesh_file, "r") do file return read(attributes(file)["size"]), read(attributes(file)["mapping"]) @@ -299,6 +302,7 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT) mesh = UnstructuredMesh2D(mesh_filename; RealT = RealT, periodicity = periodicity_, unsaved_changes = false) + mesh.current_filename = mesh_file elseif mesh_type == "P4estMesh" p4est_filename, tree_node_coordinates, nodes, boundary_names_ = h5open(mesh_file, "r") do file @@ -317,7 +321,7 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT) p4est = load_p4est(p4est_file, Val(ndims)) mesh = P4estMesh{ndims}(p4est, tree_node_coordinates, - nodes, boundary_names, "", false, true) + nodes, boundary_names, mesh_file, false, true) else error("Unknown mesh type!") end @@ -405,7 +409,7 @@ function load_mesh_parallel(mesh_file::AbstractString; n_cells_max, RealT) p4est = load_p4est(p4est_file, Val(ndims_)) mesh = P4estMesh{ndims_}(p4est, tree_node_coordinates, - nodes, boundary_names, "", false, true) + nodes, boundary_names, mesh_file, false, true) else error("Unknown mesh type!") end diff --git a/src/meshes/meshes.jl b/src/meshes/meshes.jl index ed2158b169..4d6016e556 100644 --- a/src/meshes/meshes.jl +++ b/src/meshes/meshes.jl @@ -7,6 +7,7 @@ include("tree_mesh.jl") include("structured_mesh.jl") +include("structured_mesh_view.jl") include("surface_interpolant.jl") include("unstructured_mesh.jl") include("face_interpolant.jl") diff --git a/src/meshes/structured_mesh_view.jl b/src/meshes/structured_mesh_view.jl new file mode 100644 index 0000000000..bd55115cc9 --- /dev/null +++ b/src/meshes/structured_mesh_view.jl @@ -0,0 +1,132 @@ +# 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 + +""" + StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS} + +A view on a structured curved mesh. +""" +mutable struct StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS} + parent::StructuredMesh{NDIMS, RealT} + cells_per_dimension::NTuple{NDIMS, Int} + mapping::Any # Not relevant for performance + mapping_as_string::String + current_filename::String + indices_min::NTuple{NDIMS, Int} + indices_max::NTuple{NDIMS, Int} + unsaved_changes::Bool +end + +""" + StructuredMeshView(parent; indices_min, indices_max) + +Create a StructuredMeshView on a StructuredMesh parent. + +# Arguments +- `parent`: the parent StructuredMesh. +- `indices_min`: starting indices of the parent mesh. +- `indices_max`: ending indices of the parent mesh. +""" +function StructuredMeshView(parent::StructuredMesh{NDIMS, RealT}; + indices_min = ntuple(_ -> 1, Val(NDIMS)), + indices_max = size(parent)) where {NDIMS, RealT} + @assert indices_min <= indices_max + @assert all(indices_min .> 0) + @assert indices_max <= size(parent) + + cells_per_dimension = indices_max .- indices_min .+ 1 + + # Compute cell sizes `deltas` + deltas = (parent.mapping.coordinates_max .- parent.mapping.coordinates_min) ./ + parent.cells_per_dimension + # Calculate the domain boundaries. + coordinates_min = parent.mapping.coordinates_min .+ deltas .* (indices_min .- 1) + coordinates_max = parent.mapping.coordinates_min .+ deltas .* indices_max + mapping = coordinates2mapping(coordinates_min, coordinates_max) + mapping_as_string = """ + coordinates_min = $coordinates_min + coordinates_max = $coordinates_max + mapping = coordinates2mapping(coordinates_min, coordinates_max) + """ + + return StructuredMeshView{NDIMS, RealT}(parent, cells_per_dimension, mapping, + mapping_as_string, + parent.current_filename, + indices_min, indices_max, + parent.unsaved_changes) +end + +# Check if mesh is periodic +function isperiodic(mesh::StructuredMeshView) + @unpack parent = mesh + return isperiodic(parent) && size(parent) == size(mesh) +end + +function isperiodic(mesh::StructuredMeshView, dimension) + @unpack parent, indices_min, indices_max = mesh + return (isperiodic(parent, dimension) && + indices_min[dimension] == 1 && + indices_max[dimension] == size(parent, dimension)) +end + +@inline Base.ndims(::StructuredMeshView{NDIMS}) where {NDIMS} = NDIMS +@inline Base.real(::StructuredMeshView{NDIMS, RealT}) where {NDIMS, RealT} = RealT +function Base.size(mesh::StructuredMeshView) + @unpack indices_min, indices_max = mesh + return indices_max .- indices_min .+ 1 +end +function Base.size(mesh::StructuredMeshView, i) + @unpack indices_min, indices_max = mesh + return indices_max[i] - indices_min[i] + 1 +end +Base.axes(mesh::StructuredMeshView) = map(Base.OneTo, size(mesh)) +Base.axes(mesh::StructuredMeshView, i) = Base.OneTo(size(mesh, i)) + +function calc_node_coordinates!(node_coordinates, element, + cell_x, cell_y, mapping, + mesh::StructuredMeshView{2}, + basis) + @unpack nodes = basis + + # Get cell length in reference mesh + dx = 2 / size(mesh, 1) + dy = 2 / size(mesh, 2) + + # Calculate node coordinates of reference mesh + cell_x_offset = -1 + (cell_x - 1) * dx + dx / 2 + cell_y_offset = -1 + (cell_y - 1) * dy + dy / 2 + + for j in eachnode(basis), i in eachnode(basis) + # node_coordinates are the mapped reference node_coordinates + node_coordinates[:, i, j, element] .= mapping(cell_x_offset + dx / 2 * nodes[i], + cell_y_offset + dy / 2 * nodes[j]) + end +end + +# Does not save the mesh itself to an HDF5 file. Instead saves important attributes +# of the mesh, like its size and the type of boundary mapping function. +# Then, within Trixi2Vtk, the StructuredMesh and its node coordinates are reconstructured from +# these attributes for plotting purposes. +function save_mesh_file(mesh::StructuredMeshView, output_directory; system = "", + timestep = 0) + # Create output directory (if it does not exist) + mkpath(output_directory) + + filename = joinpath(output_directory, @sprintf("mesh_%s_%06d.h5", system, timestep)) + + # Open file (clobber existing content) + h5open(filename, "w") do file + # Add context information as attributes + attributes(file)["mesh_type"] = get_name(mesh) + attributes(file)["ndims"] = ndims(mesh) + attributes(file)["size"] = collect(size(mesh)) + attributes(file)["mapping"] = mesh.mapping_as_string + end + + return filename +end +end # @muladd diff --git a/src/semidiscretization/semidiscretization_coupled.jl b/src/semidiscretization/semidiscretization_coupled.jl index ded9373cc8..e744126429 100644 --- a/src/semidiscretization/semidiscretization_coupled.jl +++ b/src/semidiscretization/semidiscretization_coupled.jl @@ -316,7 +316,8 @@ function save_mesh(semi::SemidiscretizationCoupled, output_directory, timestep = mesh, _, _, _ = mesh_equations_solver_cache(semi.semis[i]) if mesh.unsaved_changes - mesh.current_filename = save_mesh_file(mesh, output_directory, system = i) + mesh.current_filename = save_mesh_file(mesh, output_directory; system = i, + timestep = timestep) mesh.unsaved_changes = false end end @@ -348,6 +349,36 @@ function calculate_dt(u_ode, t, cfl_number, semi::SemidiscretizationCoupled) return dt end +function update_cleaning_speed!(semi_coupled::SemidiscretizationCoupled, + glm_speed_callback, dt) + @unpack glm_scale, cfl, semi_indices = glm_speed_callback + + if length(semi_indices) == 0 + throw("Since you have more than one semidiscretization you need to specify the 'semi_indices' for which the GLM speed needs to be calculated.") + end + + # Check that all MHD semidiscretizations received a GLM cleaning speed update. + for (semi_index, semi) in enumerate(semi_coupled.semis) + if (typeof(semi.equations) <: AbstractIdealGlmMhdEquations && + !(semi_index in semi_indices)) + error("Equation of semidiscretization $semi_index needs to be included in 'semi_indices' of 'GlmSpeedCallback'.") + end + end + + for semi_index in semi_indices + semi = semi_coupled.semis[semi_index] + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + + # compute time step for GLM linear advection equation with c_h=1 (redone due to the possible AMR) + c_h_deltat = calc_dt_for_cleaning_speed(cfl, mesh, equations, solver, cache) + + # c_h is proportional to its own time step divided by the complete MHD time step + equations.c_h = glm_scale * c_h_deltat / dt + end + + return semi_coupled +end + ################################################################################ ### Equations ################################################################################ @@ -435,10 +466,28 @@ function (boundary_condition::BoundaryConditionCoupled)(u_inner, orientation, di Val(nvariables(equations)))) # 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) + if surface_flux_function isa Tuple + # In case of conservative (index 1) and non-conservative (index 2) fluxes, + # add the non-conservative one with a factor of 1/2. + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = (surface_flux_function[1](u_inner, u_boundary, orientation, + equations) + + 0.5 * + surface_flux_function[2](u_inner, u_boundary, orientation, + equations)) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = (surface_flux_function[1](u_boundary, u_inner, orientation, + equations) + + 0.5 * + surface_flux_function[2](u_boundary, u_inner, orientation, + equations)) + end + else + 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 end return flux @@ -582,7 +631,9 @@ end @inline function calc_boundary_flux_by_direction!(surface_flux_values, u, t, orientation, boundary_condition::BoundaryConditionCoupled, - mesh::StructuredMesh, equations, + mesh::Union{StructuredMesh, + StructuredMeshView}, + equations, surface_integral, dg::DG, cache, direction, node_indices, surface_node_indices, element) @@ -614,7 +665,8 @@ end end end -function get_boundary_indices(element, orientation, mesh::StructuredMesh{2}) +function get_boundary_indices(element, orientation, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}) cartesian_indices = CartesianIndices(size(mesh)) if orientation == 1 # Get index of element in y-direction diff --git a/src/semidiscretization/semidiscretization_euler_acoustics.jl b/src/semidiscretization/semidiscretization_euler_acoustics.jl index 173523ff89..286315fb96 100644 --- a/src/semidiscretization/semidiscretization_euler_acoustics.jl +++ b/src/semidiscretization/semidiscretization_euler_acoustics.jl @@ -103,7 +103,7 @@ function precompute_weights(source_region, weights, coupled_element_ids, equatio (nnodes(dg), nnodes(dg), length(coupled_element_ids))) - @threaded for k in 1:length(coupled_element_ids) + @threaded for k in eachindex(coupled_element_ids) element = coupled_element_ids[k] for j in eachnode(dg), i in eachnode(dg) x = get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, @@ -197,7 +197,7 @@ function add_acoustic_source_terms!(du_acoustics, acoustic_source_terms, source_ coupled_element_ids, mesh::TreeMesh{2}, equations, dg::DGSEM, cache) - @threaded for k in 1:length(coupled_element_ids) + @threaded for k in eachindex(coupled_element_ids) element = coupled_element_ids[k] for j in eachnode(dg), i in eachnode(dg) diff --git a/src/semidiscretization/semidiscretization_hyperbolic.jl b/src/semidiscretization/semidiscretization_hyperbolic.jl index f61378a7dc..dcd211671c 100644 --- a/src/semidiscretization/semidiscretization_hyperbolic.jl +++ b/src/semidiscretization/semidiscretization_hyperbolic.jl @@ -259,7 +259,8 @@ function check_periodicity_mesh_boundary_conditions(mesh::Union{TreeMesh{1}, end function check_periodicity_mesh_boundary_conditions(mesh::Union{TreeMesh{2}, - StructuredMesh{2}}, + StructuredMesh{2}, + StructuredMeshView{2}}, boundary_conditions::Union{NamedTuple, Tuple}) check_periodicity_mesh_boundary_conditions_x(mesh, boundary_conditions[1], diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 11f7d69f8d..2e79c5e6d1 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -448,8 +448,9 @@ function get_node_variables!(node_variables, mesh, equations, dg::DG, cache) get_node_variables!(node_variables, mesh, equations, dg.volume_integral, dg, cache) end -const MeshesDGSEM = Union{TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, - T8codeMesh} +const MeshesDGSEM = Union{TreeMesh, StructuredMesh, StructuredMeshView, + UnstructuredMesh2D, + P4estMesh, T8codeMesh} @inline function ndofs(mesh::MeshesDGSEM, dg::DG, cache) nelements(cache.elements) * nnodes(dg)^ndims(mesh) diff --git a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl index 9059caf87f..63a37f6780 100644 --- a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl +++ b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl @@ -51,6 +51,29 @@ struct TensorProductGaussFaceOperator{NDIMS, OperatorType <: AbstractGaussOperat nfaces::Int end +function TensorProductGaussFaceOperator(operator::AbstractGaussOperator, + dg::DGMulti{1, Line, GaussSBP}) + rd = dg.basis + + rq1D, wq1D = StartUpDG.gauss_quad(0, 0, polydeg(dg)) + interp_matrix_gauss_to_face_1d = polynomial_interpolation_matrix(rq1D, [-1; 1]) + + nnodes_1d = length(rq1D) + face_indices_tensor_product = nothing # not needed in 1D; we fall back to mul! + + num_faces = 2 + + T_op = typeof(operator) + Tm = typeof(interp_matrix_gauss_to_face_1d) + Tw = typeof(inv.(wq1D)) + Tf = typeof(rd.wf) + Ti = typeof(face_indices_tensor_product) + return TensorProductGaussFaceOperator{1, T_op, Tm, Tw, Tf, Ti}(interp_matrix_gauss_to_face_1d, + inv.(wq1D), rd.wf, + face_indices_tensor_product, + nnodes_1d, num_faces) +end + # constructor for a 2D operator function TensorProductGaussFaceOperator(operator::AbstractGaussOperator, dg::DGMulti{2, Quad, GaussSBP}) @@ -126,6 +149,21 @@ end end end +@inline function tensor_product_gauss_face_operator!(out::AbstractVector, + A::TensorProductGaussFaceOperator{1, + Interpolation}, + x::AbstractVector) + mul!(out, A.interp_matrix_gauss_to_face_1d, x) +end + +@inline function tensor_product_gauss_face_operator!(out::AbstractVector, + A::TensorProductGaussFaceOperator{1, + <:Projection}, + x::AbstractVector) + mul!(out, A.interp_matrix_gauss_to_face_1d', x) + @. out *= A.inv_volume_weights_1d +end + # 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. @@ -352,7 +390,7 @@ end # For now, this is mostly the same as `create_cache` for DGMultiFluxDiff{<:Polynomial}. # In the future, we may modify it so that we can specialize additional parts of GaussSBP() solvers. function create_cache(mesh::DGMultiMesh, equations, - dg::DGMultiFluxDiff{<:GaussSBP, <:Union{Quad, Hex}}, RealT, + dg::DGMultiFluxDiff{<:GaussSBP, <:Union{Line, Quad, Hex}}, RealT, uEltype) # call general Polynomial flux differencing constructor diff --git a/src/solvers/dgmulti/types.jl b/src/solvers/dgmulti/types.jl index 813bc67061..ef9d7d2bf0 100644 --- a/src/solvers/dgmulti/types.jl +++ b/src/solvers/dgmulti/types.jl @@ -347,6 +347,9 @@ function SimpleKronecker(NDIMS, A, eltype_A = eltype(A)) return SimpleKronecker{NDIMS, typeof(A), typeof(tmp_storage)}(A, tmp_storage) end +# fall back to mul! for a 1D Kronecker product +LinearAlgebra.mul!(b, A_kronecker::SimpleKronecker{1}, x) = mul!(b, A_kronecker.A, x) + # Computes `b = kron(A, A) * x` in an optimized fashion function LinearAlgebra.mul!(b_in, A_kronecker::SimpleKronecker{2}, x_in) @unpack A = A_kronecker diff --git a/src/solvers/dgsem_p4est/dg.jl b/src/solvers/dgsem_p4est/dg.jl index ad3b071749..4173c974c6 100644 --- a/src/solvers/dgsem_p4est/dg.jl +++ b/src/solvers/dgsem_p4est/dg.jl @@ -36,7 +36,8 @@ end orientation = (direction + 1) >> 1 normal = get_contravariant_vector(orientation, contravariant_vectors, indices...) - # Contravariant vectors at interfaces in negative coordinate direction are pointing inwards + # Contravariant vectors at interfaces in negative coordinate direction are pointing inwards, + # flip sign to make them point outwards if isodd(direction) return -normal else diff --git a/src/solvers/dgsem_structured/containers.jl b/src/solvers/dgsem_structured/containers.jl index 8adf005b78..7b0d275c5b 100644 --- a/src/solvers/dgsem_structured/containers.jl +++ b/src/solvers/dgsem_structured/containers.jl @@ -23,7 +23,8 @@ struct ElementContainer{NDIMS, RealT <: Real, uEltype <: Real, NDIMSP1, NDIMSP2, end # Create element container and initialize element data -function init_elements(mesh::StructuredMesh{NDIMS, RealT}, +function init_elements(mesh::Union{StructuredMesh{NDIMS, RealT}, + StructuredMeshView{NDIMS, RealT}}, equations::AbstractEquations, basis, ::Type{uEltype}) where {NDIMS, RealT <: Real, uEltype <: Real} diff --git a/src/solvers/dgsem_structured/containers_2d.jl b/src/solvers/dgsem_structured/containers_2d.jl index fb6db48e0a..8a0722fc5d 100644 --- a/src/solvers/dgsem_structured/containers_2d.jl +++ b/src/solvers/dgsem_structured/containers_2d.jl @@ -6,7 +6,8 @@ #! format: noindent # Initialize data structures in element container -function init_elements!(elements, mesh::StructuredMesh{2}, basis::LobattoLegendreBasis) +function init_elements!(elements, mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}, + basis::LobattoLegendreBasis) @unpack node_coordinates, left_neighbors, jacobian_matrix, contravariant_vectors, inverse_jacobian = elements @@ -148,7 +149,9 @@ function calc_inverse_jacobian!(inverse_jacobian::AbstractArray{<:Any, 3}, eleme end # Save id of left neighbor of every element -function initialize_left_neighbor_connectivity!(left_neighbors, mesh::StructuredMesh{2}, +function initialize_left_neighbor_connectivity!(left_neighbors, + mesh::Union{StructuredMesh{2}, + StructuredMeshView{2}}, linear_indices) # Neighbors in x-direction for cell_y in 1:size(mesh, 2) diff --git a/src/solvers/dgsem_structured/dg.jl b/src/solvers/dgsem_structured/dg.jl index de4601a220..ecb2485c68 100644 --- a/src/solvers/dgsem_structured/dg.jl +++ b/src/solvers/dgsem_structured/dg.jl @@ -8,7 +8,8 @@ # This method is called when a SemidiscretizationHyperbolic is constructed. # It constructs the basic `cache` used throughout the simulation to compute # the RHS etc. -function create_cache(mesh::StructuredMesh, equations::AbstractEquations, dg::DG, ::Any, +function create_cache(mesh::Union{StructuredMesh, StructuredMeshView}, + equations::AbstractEquations, dg::DG, ::Any, ::Type{uEltype}) where {uEltype <: Real} elements = init_elements(mesh, equations, dg.basis, uEltype) @@ -30,7 +31,9 @@ end @inline function calc_boundary_flux_by_direction!(surface_flux_values, u, t, orientation, boundary_condition::BoundaryConditionPeriodic, - mesh::StructuredMesh, equations, + mesh::Union{StructuredMesh, + StructuredMeshView}, + equations, surface_integral, dg::DG, cache, direction, node_indices, surface_node_indices, element) @@ -40,7 +43,9 @@ end @inline function calc_boundary_flux_by_direction!(surface_flux_values, u, t, orientation, boundary_condition, - mesh::StructuredMesh, equations, + mesh::Union{StructuredMesh, + StructuredMeshView}, + equations, surface_integral, dg::DG, cache, direction, node_indices, surface_node_indices, element) diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 467b92a7fc..0723751ee7 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -6,7 +6,7 @@ #! format: noindent function rhs!(du, u, t, - mesh::StructuredMesh{2}, equations, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}, equations, initial_condition, boundary_conditions, source_terms::Source, dg::DG, cache) where {Source} # Reset du @@ -59,8 +59,9 @@ See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-17 =# @inline function weak_form_kernel!(du, u, element, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, + T8codeMesh{2}}, nonconservative_terms::False, equations, dg::DGSEM, cache, alpha = true) # true * [some floating point value] == [exactly the same floating point value] @@ -388,7 +389,7 @@ end end function calc_interface_flux!(cache, u, - mesh::StructuredMesh{2}, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}, nonconservative_terms, # can be True/False equations, surface_integral, dg::DG) @unpack elements = cache @@ -417,7 +418,8 @@ end @inline function calc_interface_flux!(surface_flux_values, left_element, right_element, orientation, u, - mesh::StructuredMesh{2}, + mesh::Union{StructuredMesh{2}, + StructuredMeshView{2}}, nonconservative_terms::False, equations, surface_integral, dg::DG, cache) # This is slow for LSA, but for some reason faster for Euler (see #519) @@ -552,13 +554,14 @@ end # TODO: Taal dimension agnostic function calc_boundary_flux!(cache, u, t, boundary_condition::BoundaryConditionPeriodic, - mesh::StructuredMesh{2}, equations, surface_integral, - dg::DG) + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}, + equations, surface_integral, dg::DG) @assert isperiodic(mesh) end function calc_boundary_flux!(cache, u, t, boundary_conditions::NamedTuple, - mesh::StructuredMesh{2}, equations, surface_integral, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}}, + equations, surface_integral, dg::DG) @unpack surface_flux_values = cache.elements linear_indices = LinearIndices(size(mesh)) @@ -617,8 +620,8 @@ function calc_boundary_flux!(cache, u, t, boundary_conditions::NamedTuple, end function apply_jacobian!(du, - mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, + mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, + UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2}}, equations, dg::DG, cache) @unpack inverse_jacobian = cache.elements diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index e7c9978b52..ba0f1a2c7e 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -192,8 +192,8 @@ end function calc_volume_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}, - UnstructuredMesh2D, P4estMesh{2}, - T8codeMesh{2}}, + StructuredMeshView{2}, UnstructuredMesh2D, + P4estMesh{2}, T8codeMesh{2}}, nonconservative_terms, equations, volume_integral::VolumeIntegralWeakForm, dg::DGSEM, cache) @@ -1097,7 +1097,9 @@ end return nothing end -function calc_surface_integral!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}}, +function calc_surface_integral!(du, u, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + StructuredMeshView{2}}, equations, surface_integral::SurfaceIntegralWeakForm, dg::DG, cache) @unpack boundary_interpolation = dg.basis diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 52dc6813c3..90a807c80b 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -866,9 +866,9 @@ end (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; bar_states1, bar_states2) = limiter.cache.container_bar_states - # state variables - if limiter.local_minmax - for v in limiter.local_minmax_variables_cons + # Local two-sided limiting for conservative variables + if limiter.local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) var_min = variable_bounds[Symbol(v_string, "_min")] var_max = variable_bounds[Symbol(v_string, "_max")] @@ -907,78 +907,54 @@ end end end end - # Specific Entropy - if limiter.spec_entropy - s_min = variable_bounds[:spec_entropy_min] - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - s_min[i, j, element] = typemax(eltype(s_min)) - end - # FV solution at node (i, j) - for j in eachnode(dg), i in eachnode(dg) - s = entropy_spec(get_node_vars(u, equations, dg, i, j, element), - equations) - s_min[i, j, element] = min(s_min[i, j, element], s) - # TODO: Add source term! - end - # xi direction: subcell face between (i-1, j) and (i, j) - for j in eachnode(dg), i in 1:(nnodes(dg) + 1) - s = entropy_spec(get_node_vars(bar_states1, equations, dg, i, j, - element), equations) - if i <= nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], s) - end - if i > 1 - s_min[i - 1, j, element] = min(s_min[i - 1, j, element], s) - end - end - # eta direction: subcell face between (i, j-1) and (i, j) - for j in 1:(nnodes(dg) + 1), i in eachnode(dg) - s = entropy_spec(get_node_vars(bar_states2, equations, dg, i, j, - element), equations) - if j <= nnodes(dg) - s_min[i, j, element] = min(s_min[i, j, element], s) - end - if j > 1 - s_min[i, j - 1, element] = min(s_min[i, j - 1, element], s) - end - end - end - end - # Mathematical entropy - if limiter.math_entropy - s_max = variable_bounds[:math_entropy_max] - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - s_max[i, j, element] = typemin(eltype(s_max)) - end - # FV solution at node (i, j) - for j in eachnode(dg), i in eachnode(dg) - s = entropy_math(get_node_vars(u, equations, dg, i, j, element), - equations) - s_max[i, j, element] = max(s_max[i, j, element], s) - # TODO: Add source term! - end - # xi direction: subcell face between (i-1, j) and (i, j) - for j in eachnode(dg), i in 1:(nnodes(dg) + 1) - s = entropy_math(get_node_vars(bar_states1, equations, dg, i, j, - element), equations) - if i <= nnodes(dg) - s_max[i, j, element] = max(s_max[i, j, element], s) + # Local two-sided limiting for non-linear variables + if limiter.local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + var_minmax = variable_bounds[Symbol(string(variable), "_", + string(min_or_max))] + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + if min_or_max === max + var_minmax[i, j, element] = typemin(eltype(var_minmax)) + else + var_minmax[i, j, element] = typemax(eltype(var_minmax)) + end end - if i > 1 - s_max[i - 1, j, element] = max(s_max[i - 1, j, element], s) + # FV solution at node (i, j) + for j in eachnode(dg), i in eachnode(dg) + var = variable(get_node_vars(u, equations, dg, i, j, element), + equations) + var_minmax[i, j, element] = min_or_max(var_minmax[i, j, element], + var) + # TODO: Add source term! end - end - # eta direction: subcell face between (i, j-1) and (i, j) - for j in 1:(nnodes(dg) + 1), i in eachnode(dg) - s = entropy_math(get_node_vars(bar_states2, equations, dg, i, j, - element), equations) - if j <= nnodes(dg) - s_max[i, j, element] = max(s_max[i, j, element], s) + # xi direction: subcell face between (i-1, j) and (i, j) + for j in eachnode(dg), i in 1:(nnodes(dg) + 1) + var = variable(get_node_vars(bar_states1, equations, dg, i, j, + element), equations) + if i <= nnodes(dg) + var_minmax[i, j, element] = min_or_max(var_minmax[i, j, + element], var) + end + if i > 1 + var_minmax[i - 1, j, element] = min_or_max(var_minmax[i - 1, j, + element], + var) + end end - if j > 1 - s_max[i, j - 1, element] = max(s_max[i, j - 1, element], s) + # eta direction: subcell face between (i, j-1) and (i, j) + for j in 1:(nnodes(dg) + 1), i in eachnode(dg) + var = variable(get_node_vars(bar_states2, equations, dg, i, j, + element), equations) + if j <= nnodes(dg) + var_minmax[i, j, element] = min_or_max(var_minmax[i, j, + element], var) + end + if j > 1 + var_minmax[i, j - 1, element] = min_or_max(var_minmax[i, j - 1, + element], + var) + end end end end diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index d93307d476..f3908fbb49 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -20,12 +20,11 @@ end """ SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = String[], + local_twosided_variables_cons = String[], positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, + local_onesided_variables_nonlinear = [], bar_states = true, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), @@ -36,18 +35,25 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) +- Local two-sided Zalesak-type limiting for conservative variables (`local_twosided_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) -- One-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) +- Local one-sided limiting for nonlinear variables, e.g. `entropy_guermond_etal` and `entropy_math` +with `local_onesided_variables_nonlinear` -Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are -passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. +To use these three limiting options use the following structure: + +***Conservative variables*** to be limited are passed as a vector of strings, e.g. +`local_twosided_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. +For ***nonlinear variables***, the wanted variable functions are passed within a vector: To ensure +positivity use a plain vector including the desired variables, e.g. `positivity_variables_nonlinear = [pressure]`. +For local one-sided limiting pass the variable function combined with the requested bound +(`min` or `max`) as a tuple. For instance, to impose a lower local bound on the modified specific +entropy by Guermond et al. use `local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, min)]`. The bounds can be calculated using the `bar_states` or the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. -The limiting of nonlinear variables uses a Newton-bisection method with a maximum of +Local and global limiting of nonlinear variables uses a Newton-bisection method with a maximum of `max_iterations_newton` iterations, relative and absolute tolerances of `newton_tolerances` and a provisional update constant `gamma_constant_newton` (`gamma_constant_newton>=2*d`, where `d = #dimensions`). See equation (20) of Pazner (2020) and equation (30) of Rueda-Ramírez et al. (2022). @@ -73,15 +79,16 @@ indicator values <= `threshold_smoothness_indicator`. This is an experimental feature and may change in future releases. """ struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, - Cache, Indicator} <: AbstractSubcellLimiter - local_minmax::Bool - local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables + LimitingOnesidedVariablesNonlinear, Cache, + Indicator} <: AbstractSubcellLimiter + local_twosided::Bool + local_twosided_variables_cons::Vector{Int} # Local two-sided limiting for conservative variables positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables positivity_correction_factor::RealT - spec_entropy::Bool - math_entropy::Bool + local_onesided::Bool + local_onesided_variables_nonlinear::LimitingOnesidedVariablesNonlinear # Local one-sided limiting for nonlinear variables bar_states::Bool cache::Cache max_iterations_newton::Int @@ -94,12 +101,11 @@ end # this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = String[], + local_twosided_variables_cons = String[], positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, + local_onesided_variables_nonlinear = [], bar_states = true, max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), @@ -107,34 +113,48 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; smoothness_indicator = false, threshold_smoothness_indicator = 0.1, variable_smoothness_indicator = density_pressure) - local_minmax = (length(local_minmax_variables_cons) > 0) + local_twosided = (length(local_twosided_variables_cons) > 0) + local_onesided = (length(local_onesided_variables_nonlinear) > 0) positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) - if math_entropy && spec_entropy - error("Only one of the two can be selected: math_entropy/spec_entropy") + + # When passing `min` or `max` in the elixir, the specific function of Base is used. + # To speed up the simulation, we replace it with `Trixi.min` and `Trixi.max` respectively. + local_onesided_variables_nonlinear_ = Tuple{Function, Function}[] + for (variable, min_or_max) in local_onesided_variables_nonlinear + if min_or_max === Base.max + push!(local_onesided_variables_nonlinear_, (variable, max)) + elseif min_or_max === Base.min + push!(local_onesided_variables_nonlinear_, (variable, min)) + elseif min_or_max === Trixi.max || min_or_max === Trixi.min + push!(local_onesided_variables_nonlinear_, (variable, min_or_max)) + else + error("Parameter $min_or_max is not a valid input. Use `max` or `min` instead.") + end end + local_onesided_variables_nonlinear_ = Tuple(local_onesided_variables_nonlinear_) - local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, - equations) + local_twosided_variables_cons_ = get_variable_index.(local_twosided_variables_cons, + equations) positivity_variables_cons_ = get_variable_index.(positivity_variables_cons, equations) bound_keys = () - if local_minmax - for v in local_minmax_variables_cons_ + if local_twosided + for v in local_twosided_variables_cons_ v_string = string(v) bound_keys = (bound_keys..., Symbol(v_string, "_min"), Symbol(v_string, "_max")) end end - if spec_entropy - bound_keys = (bound_keys..., :spec_entropy_min) - end - if math_entropy - bound_keys = (bound_keys..., :math_entropy_max) + if local_onesided + for (variable, min_or_max) in local_onesided_variables_nonlinear_ + bound_keys = (bound_keys..., + Symbol(string(variable), "_", string(min_or_max))) + end end for v in positivity_variables_cons_ - if !(v in local_minmax_variables_cons_) + if !(v in local_twosided_variables_cons_) bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end @@ -153,43 +173,40 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(positivity_variables_nonlinear), - typeof(cache), typeof(IndicatorHG)}(local_minmax, - local_minmax_variables_cons_, - positivity, - positivity_variables_cons_, - positivity_variables_nonlinear, - positivity_correction_factor, - spec_entropy, math_entropy, - bar_states, - cache, - max_iterations_newton, - newton_tolerances, - gamma_constant_newton, - smoothness_indicator, - threshold_smoothness_indicator, - IndicatorHG) + typeof(local_onesided_variables_nonlinear_), + typeof(cache), + typeof(IndicatorHG)}(local_twosided, + local_twosided_variables_cons_, + positivity, positivity_variables_cons_, + positivity_variables_nonlinear, + positivity_correction_factor, + local_onesided, + local_onesided_variables_nonlinear_, + bar_states, cache, + max_iterations_newton, newton_tolerances, + gamma_constant_newton, + smoothness_indicator, + threshold_smoothness_indicator, + IndicatorHG) end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_twosided, positivity, local_onesided) = limiter print(io, "SubcellLimiterIDP(") - if !(local_minmax || positivity || spec_entropy || math_entropy) + if !(local_twosided || positivity || local_onesided) print(io, "No limiter selected => pure DG method") else features = String[] - if local_minmax + if local_twosided push!(features, "local min/max") end if positivity push!(features, "positivity") end - if spec_entropy - push!(features, "specific entropy") - end - if math_entropy - push!(features, "mathematical entropy") + if local_onesided + push!(features, "local onesided") end join(io, features, ", ") print(io, "Limiter=($features), ") @@ -204,19 +221,19 @@ end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_twosided, positivity, local_onesided) = limiter if get(io, :compact, false) show(io, limiter) else - if !(local_minmax || positivity || spec_entropy || math_entropy) + if !(local_twosided || positivity || local_onesided) setup = ["Limiter" => "No limiter selected => pure DG method"] else setup = ["Limiter" => ""] - if local_minmax + if local_twosided setup = [ setup..., - "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_minmax_variables_cons)", + "" => "Local two-sided limiting for conservative variables $(limiter.local_twosided_variables_cons)", ] end if positivity @@ -227,14 +244,10 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", ] end - if spec_entropy - setup = [setup..., "" => "Local minimum limiting for specific entropy"] - end - if math_entropy - setup = [ - setup..., - "" => "Local maximum limiting for mathematical entropy", - ] + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + setup = [setup..., "" => "Local $min_or_max limiting for $variable"] + end end setup = [ setup..., diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9882ab203b..d127e8f1e8 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -53,22 +53,19 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE elements = eachelement(dg, semi.cache) end - if limiter.local_minmax - @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, limiter, - u, t, dt, semi, - elements) + if limiter.local_twosided + @trixi_timeit timer() "local twosided" idp_local_twosided!(alpha, limiter, + u, t, dt, semi, + elements) end if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi, elements) end - if limiter.spec_entropy - @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, - dt, semi, mesh, elements) - end - if limiter.math_entropy - @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, - dt, semi, mesh, elements) + if limiter.local_onesided + @trixi_timeit timer() "local onesided" idp_local_onesided!(alpha, limiter, + u, t, dt, semi, + elements) end # Calculate alpha1 and alpha2 @@ -197,44 +194,48 @@ end return nothing end -@inline function calc_bounds_onesided!(var_minmax, minmax, typeminmax, variable, u, t, - semi) +@inline function calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) + # Reset bounds for j in eachnode(dg), i in eachnode(dg) - var_minmax[i, j, element] = typeminmax(eltype(var_minmax)) + if min_or_max === max + var_minmax[i, j, element] = typemin(eltype(var_minmax)) + else + var_minmax[i, j, element] = typemax(eltype(var_minmax)) + end end # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) var = variable(get_node_vars(u, equations, dg, i, j, element), equations) - var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) + var_minmax[i, j, element] = min_or_max(var_minmax[i, j, element], var) if i > 1 - var_minmax[i - 1, j, element] = minmax(var_minmax[i - 1, j, element], - var) + var_minmax[i - 1, j, element] = min_or_max(var_minmax[i - 1, j, + element], var) end if i < nnodes(dg) - var_minmax[i + 1, j, element] = minmax(var_minmax[i + 1, j, element], - var) + var_minmax[i + 1, j, element] = min_or_max(var_minmax[i + 1, j, + element], var) end if j > 1 - var_minmax[i, j - 1, element] = minmax(var_minmax[i, j - 1, element], - var) + var_minmax[i, j - 1, element] = min_or_max(var_minmax[i, j - 1, + element], var) end if j < nnodes(dg) - var_minmax[i, j + 1, element] = minmax(var_minmax[i, j + 1, element], - var) + var_minmax[i, j + 1, element] = min_or_max(var_minmax[i, j + 1, + element], var) end end end # Values at element boundary - calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) + calc_bounds_onesided_interface!(var_minmax, min_or_max, variable, u, t, semi, mesh) end -@inline function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, +@inline function calc_bounds_onesided_interface!(var_minmax, min_or_max, variable, u, t, semi, mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; boundary_conditions) = semi @@ -257,10 +258,10 @@ end var_right = variable(get_node_vars(u, equations, dg, index_right..., right), equations) - var_minmax[index_right..., right] = minmax(var_minmax[index_right..., - right], var_left) - var_minmax[index_left..., left] = minmax(var_minmax[index_left..., left], - var_right) + var_minmax[index_right..., right] = min_or_max(var_minmax[index_right..., + right], var_left) + var_minmax[index_left..., left] = min_or_max(var_minmax[index_left..., + left], var_right) end end @@ -290,8 +291,8 @@ end index..., element) var_outer = variable(u_outer, equations) - var_minmax[index..., element] = minmax(var_minmax[index..., element], - var_outer) + var_minmax[index..., element] = min_or_max(var_minmax[index..., element], + var_outer) end end @@ -299,20 +300,20 @@ end end ############################################################################### -# Local minimum/maximum limiting +# Local two-sided limiting of conservative variables -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, elements) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, elements) mesh, _, _, _ = mesh_equations_solver_cache(semi) - for variable in limiter.local_minmax_variables_cons - idp_local_minmax!(alpha, limiter, u, t, dt, semi, mesh, elements, variable) + for variable in limiter.local_twosided_variables_cons + idp_local_twosided!(alpha, limiter, u, t, dt, semi, mesh, elements, variable) end return nothing end -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, - elements, variable) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, + elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -326,17 +327,17 @@ end @threaded for element in elements inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, variable, - var_min, var_max, i, j, element) + idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, + variable, var_min, var_max, i, j, element) end end return nothing end -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements, variable) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -350,8 +351,8 @@ end @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, variable, - var_min, var_max, i, j, element) + idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, + variable, var_min, var_max, i, j, element) end end @@ -359,8 +360,8 @@ end end # Function barrier to dispatch outer function by mesh type -@inline function idp_local_minmax_inner!(alpha, inverse_jacobian, u, dt, dg, cache, - variable, var_min, var_max, i, j, element) +@inline function idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, + variable, var_min, var_max, i, j, element) (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes (; inverse_weights) = dg.basis @@ -409,68 +410,27 @@ end return nothing end -############################################################################### -# Local minimum limiting of specific entropy - -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, - elements) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_min = variable_bounds[:spec_entropy_min] - if !limiter.bar_states - calc_bounds_onesided!(s_min, min, typemax, entropy_spec, u, t, semi) - end - - # Perform Newton's bisection method to find new alpha - @threaded for element in elements - inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, - i, j, element, dt, equations, dg, cache, limiter, - entropy_spec, initial_check_entropy_spec_newton_idp, - final_check_standard_newton_idp) - end - end +############################################################################## +# Local one-sided limiting of nonlinear variables - return nothing -end +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, elements) + mesh, _, _, _ = mesh_equations_solver_cache(semi) -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_min = variable_bounds[:spec_entropy_min] - if !limiter.bar_states - calc_bounds_onesided!(s_min, min, typemax, entropy_spec, u, t, semi) - end - - # Perform Newton's bisection method to find new alpha - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_min[i, j, element], u_local, inverse_jacobian, - i, j, element, dt, equations, dg, cache, limiter, - entropy_spec, initial_check_entropy_spec_newton_idp, - final_check_standard_newton_idp) - end + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + idp_local_onesided!(alpha, limiter, u, t, dt, semi, mesh, elements, + variable, min_or_max) end return nothing end -############################################################################### -# Local maximum limiting of mathematical entropy - -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, - elements) +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, + elements, variable, min_or_max) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_max = variable_bounds[:math_entropy_max] + var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] if !limiter.bar_states - calc_bounds_onesided!(s_max, max, typemin, entropy_math, u, t, semi) + calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) end # Perform Newton's bisection method to find new alpha @@ -478,24 +438,26 @@ end inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, - i, j, element, dt, equations, dg, cache, limiter, - entropy_math, initial_check_entropy_math_newton_idp, - final_check_standard_newton_idp) + newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, + i, j, element, variable, min_or_max, + initial_check_local_onesided_newton_idp, + final_check_local_onesided_newton_idp, inverse_jacobian, + dt, equations, dg, cache, limiter) end end return nothing end -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements) +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, + mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + elements, + variable, min_or_max) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_max = variable_bounds[:math_entropy_max] + var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] if !limiter.bar_states - calc_bounds_onesided!(s_max, max, typemin, entropy_math, u, t, semi) + calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) end # Perform Newton's bisection method to find new alpha @@ -503,10 +465,11 @@ end for j in eachnode(dg), i in eachnode(dg) inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_max[i, j, element], u_local, inverse_jacobian, - i, j, element, dt, equations, dg, cache, limiter, - entropy_math, initial_check_entropy_math_newton_idp, - final_check_standard_newton_idp) + newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, + i, j, element, variable, min_or_max, + initial_check_local_onesided_newton_idp, + final_check_local_onesided_newton_idp, inverse_jacobian, + dt, equations, dg, cache, limiter) end end @@ -602,8 +565,8 @@ end end # Compute bound - if limiter.local_minmax && - variable in limiter.local_minmax_variables_cons && + if limiter.local_twosided && + variable in limiter.local_twosided_variables_cons && var_min[i, j, element] >= positivity_correction_factor * var # Local limiting is more restrictive that positivity limiting # => Skip positivity limiting for this node @@ -699,10 +662,10 @@ end var_min[i, j, element] = limiter.positivity_correction_factor * var # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, var_min[i, j, element], u_local, inverse_jacobian, i, j, - element, dt, equations, dg, cache, limiter, variable, - initial_check_nonnegative_newton_idp, - final_check_nonnegative_newton_idp) + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, variable, + min, initial_check_nonnegative_newton_idp, + final_check_nonnegative_newton_idp, inverse_jacobian, + dt, equations, dg, cache, limiter) return nothing end @@ -710,9 +673,10 @@ end ############################################################################### # Newton-bisection method -@inline function newton_loops_alpha!(alpha, bound, u, inverse_jacobian, i, j, element, - dt, equations, dg, cache, limiter, - variable, initial_check, final_check) +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, + min_or_max, initial_check, final_check, + inverse_jacobian, dt, equations, dg, cache, + limiter) (; inverse_weights) = dg.basis (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes @@ -722,37 +686,38 @@ end antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, - final_check, equations, dt, limiter, antidiffusive_flux) +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, + initial_check, final_check, equations, dt, limiter, + antidiffusive_flux) newton_reltol, newton_abstol = limiter.newton_tolerances beta = 1 - alpha[i, j, element] @@ -766,7 +731,7 @@ end if isvalid(u_curr, equations) goal = goal_function_newton_idp(variable, bound, u_curr, equations) - initial_check(bound, goal, newton_abstol) && return nothing + initial_check(min_or_max, bound, goal, newton_abstol) && return nothing end # Newton iterations @@ -801,7 +766,7 @@ end # Check new beta for condition and update bounds goal = goal_function_newton_idp(variable, bound, u_curr, equations) - if initial_check(bound, goal, newton_abstol) + if initial_check(min_or_max, bound, goal, newton_abstol) # New beta fulfills condition beta_L = beta else @@ -834,26 +799,25 @@ end end new_alpha = 1 - beta - if alpha[i, j, element] > new_alpha + newton_abstol - error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") - else - alpha[i, j, element] = new_alpha - end + alpha[i, j, element] = new_alpha return nothing end ### Auxiliary routines for Newton's bisection method ### # Initial checks -@inline function initial_check_entropy_spec_newton_idp(bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(min), bound, + goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function initial_check_entropy_math_newton_idp(bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(max), bound, + goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline initial_check_nonnegative_newton_idp(bound, goal, newton_abstol) = goal <= 0 +@inline initial_check_nonnegative_newton_idp(min_or_max, bound, goal, newton_abstol) = goal <= + 0 # Goal and d(Goal)d(u) function @inline goal_function_newton_idp(variable, bound, u, equations) = bound - @@ -864,10 +828,12 @@ end end # Final checks -@inline function final_check_standard_newton_idp(bound, goal, newton_abstol) +# final check for one-sided local limiting +@inline function final_check_local_onesided_newton_idp(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end +# final check for nonnegativity limiting @inline function final_check_nonnegative_newton_idp(bound, goal, newton_abstol) (goal <= eps()) && (goal > -max(newton_abstol, abs(bound) * newton_abstol)) end diff --git a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl index b5388cadc8..2c2c6876d7 100644 --- a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl +++ b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl @@ -8,8 +8,8 @@ """ UnstructuredSortedBoundaryTypes -General container to sort the boundary conditions by type for some unstructured meshes/solvers. -It stores a set of global indices for each boundary condition type to expedite computation +General container to sort the boundary conditions by type and name for some unstructured meshes/solvers. +It stores a set of global indices for each boundary condition type and name to expedite computation during the call to `calc_boundary_flux!`. The original dictionary form of the boundary conditions set by the user in the elixir file is also stored for printing. """ @@ -17,6 +17,7 @@ mutable struct UnstructuredSortedBoundaryTypes{N, BCs <: NTuple{N, Any}} boundary_condition_types::BCs # specific boundary condition type(s), e.g. BoundaryConditionDirichlet boundary_indices::NTuple{N, Vector{Int}} # integer vectors containing global boundary indices boundary_dictionary::Dict{Symbol, Any} # boundary conditions as set by the user in the elixir file + boundary_symbol_indices::Dict{Symbol, Vector{Int}} # integer vectors containing global boundary indices per boundary identifier end # constructor that "eats" the original boundary condition dictionary and sorts the information @@ -28,10 +29,14 @@ function UnstructuredSortedBoundaryTypes(boundary_conditions::Dict, cache) n_boundary_types = length(boundary_condition_types) boundary_indices = ntuple(_ -> [], n_boundary_types) + # Initialize `boundary_symbol_indices` as an empty dictionary, filled later in `initialize!` + boundary_symbol_indices = Dict{Symbol, Vector{Int}}() + container = UnstructuredSortedBoundaryTypes{n_boundary_types, typeof(boundary_condition_types)}(boundary_condition_types, boundary_indices, - boundary_conditions) + boundary_conditions, + boundary_symbol_indices) initialize!(container, cache) end @@ -97,6 +102,13 @@ function initialize!(boundary_types_container::UnstructuredSortedBoundaryTypes{N # convert the work array with the boundary indices into a tuple boundary_types_container.boundary_indices = Tuple(_boundary_indices) + # Store boundary indices per symbol (required for force computations, for instance) + for (symbol, _) in boundary_dictionary + indices = findall(x -> x === symbol, cache.boundaries.name) + # Store the indices in `boundary_symbol_indices` dictionary + boundary_types_container.boundary_symbol_indices[symbol] = sort!(indices) + end + return boundary_types_container end end # @muladd diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 4f1df9fcf1..8c99da803d 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -88,7 +88,7 @@ mutable struct SimpleIntegratorSSP{RealT <: Real, uType, Params, Sol, F, Alg, t::RealT tdir::RealT dt::RealT # current time step - dtcache::RealT # ignored + dtcache::RealT # manually set time step iter::Int # current number of time steps (iteration) p::Params # will be the semidiscretization from Trixi sol::Sol # faked @@ -102,7 +102,7 @@ end """ add_tstop!(integrator::SimpleIntegratorSSP, t) -Add a time stop during the time integration process. +Add a time stop during the time integration process. This function is called after the periodic SaveSolutionCallback to specify the next stop to save the solution. """ function add_tstop!(integrator::SimpleIntegratorSSP, t) @@ -145,7 +145,7 @@ function solve(ode::ODEProblem, alg = SimpleSSPRK33()::SimpleAlgorithmSSP; t = first(ode.tspan) tdir = sign(ode.tspan[end] - ode.tspan[1]) iter = 0 - integrator = SimpleIntegratorSSP(u, du, r0, t, tdir, dt, zero(dt), iter, ode.p, + integrator = SimpleIntegratorSSP(u, du, r0, t, tdir, dt, dt, iter, ode.p, (prob = ode,), ode.f, alg, SimpleIntegratorSSPOptions(callback, ode.tspan; kwargs...), @@ -185,6 +185,8 @@ function solve!(integrator::SimpleIntegratorSSP) error("time step size `dt` is NaN") end + modify_dt_for_tstops!(integrator) + # if the next iteration would push the simulation beyond the end time, set dt accordingly if integrator.t + integrator.dt > t_end || isapprox(integrator.t + integrator.dt, t_end) @@ -192,8 +194,6 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end - modify_dt_for_tstops!(integrator) - @. integrator.r0 = integrator.u for stage in eachindex(alg.c) t_stage = integrator.t + integrator.dt * alg.c[stage] @@ -232,7 +232,7 @@ function solve!(integrator::SimpleIntegratorSSP) end end - # Empty the tstops array. + # Empty the tstops array. # This cannot be done in terminate!(integrator::SimpleIntegratorSSP) because DiffEqCallbacks.PeriodicCallbackAffect would return at error. extract_all!(integrator.opts.tstops) @@ -253,12 +253,12 @@ u_modified!(integrator::SimpleIntegratorSSP, ::Bool) = false # used by adaptive timestepping algorithms in DiffEq function set_proposed_dt!(integrator::SimpleIntegratorSSP, dt) - integrator.dt = dt + (integrator.dt = dt; integrator.dtcache = dt) end # used by adaptive timestepping algorithms in DiffEq function get_proposed_dt(integrator::SimpleIntegratorSSP) - return integrator.dt + return ifelse(integrator.opts.adaptive, integrator.dt, integrator.dtcache) end # stop the time integration diff --git a/src/visualization/utilities.jl b/src/visualization/utilities.jl index 05457395ac..c1108128c9 100644 --- a/src/visualization/utilities.jl +++ b/src/visualization/utilities.jl @@ -495,7 +495,7 @@ function cell2node(cell_centered_data) resolution_in, _ = size(first(cell_centered_data)) resolution_out = resolution_in + 1 node_centered_data = [Matrix{Float64}(undef, resolution_out, resolution_out) - for _ in 1:length(cell_centered_data)] + for _ in eachindex(cell_centered_data)] for (cell_data, node_data) in zip(cell_centered_data, node_centered_data) # Fill center with original data @@ -1545,7 +1545,7 @@ end # Create an axis. function axis_curve(nodes_x, nodes_y, nodes_z, slice, point, n_points) - if n_points == nothing + if n_points === nothing n_points = 64 end dimensions = length(point) diff --git a/test/test_dgmulti_1d.jl b/test/test_dgmulti_1d.jl index e470de71ef..0d083cf9a7 100644 --- a/test/test_dgmulti_1d.jl +++ b/test/test_dgmulti_1d.jl @@ -29,6 +29,22 @@ isdir(outdir) && rm(outdir, recursive = true) end end +@trixi_testset "elixir_burgers_gauss_shock_capturing.jl " begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_burgers_gauss_shock_capturing.jl"), + cells_per_dimension=(8,), tspan=(0.0, 0.1), + l2=[0.445804588167854], + linf=[0.74780611426038]) + # 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_euler_flux_diff.jl " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), cells_per_dimension=(16,), diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index 5d4db4c48d..2745f3b4c0 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -230,6 +230,32 @@ end end end +@trixi_testset "elixir_euler_shockcapturing_ec.jl (flux_chandrashekar)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), + l2=[ + 0.09527896382082567, + 0.10557894830184737, + 0.10559379376154387, + 0.3503791205165925, + ], + linf=[ + 0.2733486454092644, + 0.3877283966722886, + 0.38650482703821426, + 1.0053712251056308, + ], + tspan=(0.0, 1.0), + volume_flux=flux_chandrashekar) + # 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_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[ @@ -444,16 +470,16 @@ end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ - 0.8887316108902814, - 6.644244699117552, + 0.8887316275665462, + 6.644244953884147, 3.449004719784639, 76.2706476520857, ], linf=[ 11.047531178706233, - 121.96649938887894, + 121.96650277677288, 35.74266968217143, - 1370.2362649787465, + 1370.2362955295687, ], initial_refinement_level=1, tspan=(0.0, 0.05)) @@ -693,6 +719,86 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + +@trixi_testset "elixir_euler_subsonic_cylinder.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_subsonic_cylinder.jl"), + l2=[ + 0.00011914390523852561, + 0.00010776028621724485, + 6.139954358305467e-5, + 0.0003067693731825959, + ], + linf=[ + 0.1653075586200805, + 0.1868437275544909, + 0.09772818519679008, + 0.4311796171737692, + ], tspan=(0.0, 0.001)) + # 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 + + u_ode = copy(sol.u[end]) + du_ode = zero(u_ode) # Just a placeholder in this case + + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + drag = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + lift = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + + @test isapprox(lift, -6.501138753497174e-15, atol = 1e-13) + @test isapprox(drag, 2.588589856781827, atol = 1e-13) +end + +# Forces computation test in an AMR code +@trixi_testset "elixir_euler_NACA0012airfoil_mach085.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_NACA0012airfoil_mach085.jl"), + l2=[ + 5.371568111383228e-7, 6.4158131303956445e-6, + 1.0324346542348325e-5, 0.0006348064933187732, + ], + linf=[ + 0.0016263400091978443, 0.028471072159724428, + 0.02986133204785877, 1.9481060511014872, + ], + base_level=0, med_level=1, max_level=1, + tspan=(0.0, 0.0001), + adapt_initial_condition=false, + adapt_initial_condition_only_refine=false, + # With the default `maxiters = 1` in coverage tests, + # the values for `drag` and `lift` below would differ. + coverage_override=(maxiters = 100_000,)) + + # 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 + + u_ode = copy(sol.u[end]) + du_ode = zero(u_ode) # Just a placeholder in this case + + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + drag = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + lift = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + + @test isapprox(lift, 0.0262382560809345, atol = 1e-13) + @test isapprox(drag, 0.10898248971932244, atol = 1e-13) +end end # Clean up afterwards: delete Trixi.jl output directory diff --git a/test/test_p4est_3d.jl b/test/test_p4est_3d.jl index ea7d9193ad..7483cde275 100644 --- a/test/test_p4est_3d.jl +++ b/test/test_p4est_3d.jl @@ -313,6 +313,35 @@ end end end +@trixi_testset "elixir_euler_ec.jl (flux_chandrashekar)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), + l2=[ + 0.010368548525287055, + 0.006216054794583285, + 0.006020401857347216, + 0.006019175682769779, + 0.026228080232814154, + ], + linf=[ + 0.3169376449662026, + 0.28950510175646726, + 0.4402523227566396, + 0.4869168122387365, + 0.7999141641954051, + ], + tspan=(0.0, 0.2), + volume_flux=flux_chandrashekar, + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # 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_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[ @@ -535,6 +564,28 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + +@trixi_testset "elixir_linearizedeuler_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_linearizedeuler_convergence.jl"), + l2=[ + 0.04452389418193219, 0.03688186699434862, + 0.03688186699434861, 0.03688186699434858, + 0.044523894181932186, + ], + linf=[ + 0.2295447498696467, 0.058369658071546704, + 0.05836965807154648, 0.05836965807154648, 0.2295447498696468, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 41d375e2e3..38bebdcce1 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -121,8 +121,8 @@ end ], linf=[ 0.002996375101363302, - 0.002863904256059634, - 0.012691132946258676, + 0.0028639041695096433, + 0.012691132694550689, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -148,8 +148,8 @@ end ], linf=[ 0.002754803146635787, - 0.0028567714697580906, - 0.012941794048176192, + 0.0028567713744625124, + 0.012941793784197131, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -168,14 +168,14 @@ end mu = mu(), Prandtl = prandtl_number()), l2=[ - 2.5278824700860636e-5, - 2.5540078777006958e-5, - 0.00012118655083858043, + 2.5278845598681636e-5, + 2.5540145802666872e-5, + 0.0001211867535580826, ], linf=[ - 0.0001466387075579334, - 0.00019422427462629705, - 0.0009556446847707178, + 0.0001466387202588848, + 0.00019422419092429135, + 0.0009556449835592673, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -195,14 +195,14 @@ end Prandtl = prandtl_number(), gradient_variables = GradientVariablesEntropy()), l2=[ - 2.4593501090944024e-5, - 2.3928163240907908e-5, - 0.00011252309905552921, + 2.4593521887223632e-5, + 2.3928212900127102e-5, + 0.00011252332663824173, ], linf=[ - 0.0001185048754512863, - 0.0001898766501935486, - 0.0009597450028770993, + 0.00011850494672183132, + 0.00018987676556476442, + 0.0009597461727750556, ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index d47c34f9e7..7749a0c478 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -579,8 +579,8 @@ end @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_nonperiodic_amr.jl"), tspan=(0.0, 0.01), - l2=[0.007933791324450538], - linf=[0.11029480573492567]) + l2=[0.007934195641974433], + linf=[0.11030265194954081]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -707,6 +707,55 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + +@trixi_testset "elixir_navierstokes_NACA0012airfoil_mach08.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_navierstokes_NACA0012airfoil_mach08.jl"), + l2=[0.000186486564226516, + 0.0005076712323400374, + 0.00038074588984354107, + 0.002128177239782089], + linf=[0.5153387072802718, + 1.199362305026636, + 0.9077214424040279, + 5.666071182328691], tspan=(0.0, 0.001), + initial_refinement_level=0, + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 10_000,)) + # 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 + + u_ode = copy(sol.u[end]) + du_ode = zero(u_ode) # Just a placeholder in this case + + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + + drag_p = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + lift_p = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, + semi.cache) + + drag_f = Trixi.analyze(drag_coefficient_shear_force, du, u, tspan[2], mesh, + equations, equations_parabolic, solver, + semi.cache, semi.cache_parabolic) + lift_f = Trixi.analyze(lift_coefficient_shear_force, du, u, tspan[2], mesh, + equations, equations_parabolic, solver, + semi.cache, semi.cache_parabolic) + + @test isapprox(drag_p, 0.17963843913309516, atol = 1e-13) + @test isapprox(lift_p, 0.26462588007949367, atol = 1e-13) + + @test isapprox(drag_f, 1.5427441885921553, atol = 1e-13) + @test isapprox(lift_f, 0.005621910087395724, atol = 1e-13) +end end # Clean up afterwards: delete Trixi.jl output directory diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index fea06554c5..f97696d089 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -139,6 +139,21 @@ end end end +@trixi_testset "elixir_linearizedeuler_characteristic_system.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_linearizedeuler_characteristic_system.jl"), + l2=[2.9318078842789714e-6, 0.0, 0.0], + linf=[4.291208715723194e-5, 0.0, 0.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_traffic_flow_lwr_greenlight.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_traffic_flow_lwr_greenlight.jl"), diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 42c56017fe..c608b68ed2 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -70,6 +70,30 @@ end end end +@trixi_testset "elixir_advection_meshview.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_meshview.jl"), + l2=[ + 8.311947673083206e-6, + 8.311947673068427e-6, + ], + linf=[ + 6.627000273318195e-5, + 6.62700027264096e-5, + ], + coverage_override=(maxiters = 10^5,)) + + @testset "analysis_callback(sol) for AnalysisCallbackCoupled" begin + # 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 + @trixi_testset "elixir_advection_extended.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), l2=[4.220397559713772e-6], @@ -508,16 +532,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_sc_subcell.jl"), l2=[ - 0.008160127825550706, - 0.008658254974279198, - 0.009351901915798305, - 0.0277570186711509, + 0.00816012943805366, + 0.008658255997419217, + 0.00935190284719103, + 0.027757019482291357, ], linf=[ - 0.027225588710793502, - 0.040734035190958195, - 0.03819406890281263, - 0.08080654623152705, + 0.02722563220635177, + 0.040734034380730755, + 0.03819407626402338, + 0.08080649141597318, ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -1084,15 +1108,15 @@ end @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, + 0.0017286908591070864, + 0.025585037307655684, + 0.028374244567802766, 6.274146767730866e-5, ], linf=[ - 0.012972309788264802, - 0.108283714215621, - 0.15831585777928936, + 0.012973752001194772, + 0.10829375385832263, + 0.15832858475438094, 0.00018196759554722775, ], tspan=(0.0, 0.05)) @@ -1152,6 +1176,61 @@ end @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end + +@trixi_testset "elixir_mhd_coupled.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_coupled.jl"), + l2=[ + 1.0743426980507015e-7, 0.030901698521864966, + 0.030901698662039206, 0.04370160129981656, + 8.259193827852516e-8, 0.03090169908364623, + 0.030901699039770684, 0.04370160128147447, + 8.735923402748945e-9, 1.0743426996067106e-7, + 0.03090169852186498, 0.030901698662039206, + 0.04370160129981657, 8.259193829690747e-8, + 0.03090169908364624, 0.030901699039770726, + 0.04370160128147445, 8.73592340076897e-9, + ], + linf=[ + 9.021023431587949e-7, 0.043701454182710486, + 0.043701458294527366, 0.061803146322536154, + 9.487023335807976e-7, 0.043701561010342616, + 0.04370147392153734, 0.06180318786081025, + 3.430673132525334e-8, 9.02102342825728e-7, + 0.043701454182710764, 0.043701458294525895, + 0.06180314632253597, 9.487023254761695e-7, + 0.04370156101034084, 0.04370147392153745, + 0.06180318786081015, 3.430672973680963e-8, + ], + coverage_override=(maxiters = 10^5,)) + + @testset "analysis_callback(sol) for AnalysisCallbackCoupled" begin + errors = analysis_callback(sol) + @test errors.l2≈[ + 1.0743426980507015e-7, 0.030901698521864966, 0.030901698662039206, + 0.04370160129981656, 8.259193827852516e-8, 0.03090169908364623, + 0.030901699039770684, 0.04370160128147447, 8.735923402748945e-9, + 1.0743426996067106e-7, 0.03090169852186498, 0.030901698662039206, + 0.04370160129981657, 8.259193829690747e-8, 0.03090169908364624, + 0.030901699039770726, 0.04370160128147445, 8.73592340076897e-9, + ] rtol=1.0e-4 + @test errors.linf≈[ + 9.021023431587949e-7, 0.043701454182710486, 0.043701458294527366, + 0.061803146322536154, 9.487023335807976e-7, 0.043701561010342616, + 0.04370147392153734, 0.06180318786081025, 3.430673132525334e-8, + 9.02102342825728e-7, 0.043701454182710764, 0.043701458294525895, + 0.06180314632253597, 9.487023254761695e-7, 0.04370156101034084, + 0.04370147392153745, 0.06180318786081015, 3.430672973680963e-8, + ] rtol=1.0e-4 + # 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 # Clean up afterwards: delete Trixi.jl output directory diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index 4a25a51a45..76129f15e0 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -48,6 +48,9 @@ isdir(outdir) && rm(outdir, recursive = true) # Traffic flow LWR include("test_tree_1d_traffic_flow_lwr.jl") + + # Linearized Euler + include("test_tree_1d_linearizedeuler.jl") end # Coverage test for all initial conditions diff --git a/test/test_tree_1d_linearizedeuler.jl b/test/test_tree_1d_linearizedeuler.jl new file mode 100644 index 0000000000..c7cffee3f6 --- /dev/null +++ b/test/test_tree_1d_linearizedeuler.jl @@ -0,0 +1,51 @@ + +using Test +using Trixi + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") + +@testset "Linearized Euler Equations 1D" begin +#! format: noindent + +@trixi_testset "elixir_linearizedeuler_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_convergence.jl"), + l2=[ + 0.00010894927270421941, + 0.00014295255695912358, + 0.00010894927270421941, + ], + linf=[ + 0.0005154647164193893, + 0.00048457837684242266, + 0.0005154647164193893, + ]) + # 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_linearizedeuler_gauss_wall.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_gauss_wall.jl"), + l2=[0.650082087850354, 0.2913911415488769, 0.650082087850354], + linf=[ + 1.9999505145390108, + 0.9999720404625275, + 1.9999505145390108, + ]) + # 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 diff --git a/test/test_tree_1d_shallowwater.jl b/test/test_tree_1d_shallowwater.jl index 41ad5c32bb..8fe3291a93 100644 --- a/test/test_tree_1d_shallowwater.jl +++ b/test/test_tree_1d_shallowwater.jl @@ -12,10 +12,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @trixi_testset "elixir_shallowwater_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2=[0.244729018751225, 0.8583565222389505, 0.07330427577586297], + l2=[ + 0.24476140682560343, + 0.8587309324660326, + 0.07330427577586297, + ], linf=[ - 2.1635021283528504, - 3.8717508164234453, + 2.1636963952308372, + 3.8737770522883115, 1.7711213427919539, ], tspan=(0.0, 0.25)) @@ -32,13 +36,13 @@ 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, + 0.39472828074570576, + 2.0390687947320076, 4.1623084150546725e-10, ], linf=[ - 0.778905801278281, - 3.2409883402608273, + 0.7793741954662221, + 3.2411927977882096, 7.419800190922032e-10, ], initial_condition=initial_condition_weak_blast_wave, diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index a32ba98ada..2679038d05 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -284,6 +284,38 @@ end end end +@trixi_testset "elixir_euler_shockcapturing_subcell.jl (fixed time step)" begin + # Testing local SSP method without stepsize callback + # Additionally, tests combination with SaveSolutionCallback using time interval + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_shockcapturing_subcell.jl"), + dt=2.0e-3, + tspan=(0.0, 0.25), + save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), + callbacks=CallbackSet(summary_callback, save_solution, + analysis_callback, alive_callback), + l2=[ + 0.05624855363458103, + 0.06931288786158463, + 0.06931283188960778, + 0.6200535829842072, + ], + linf=[ + 0.29029967648805566, + 0.6494728865862608, + 0.6494729363533714, + 3.0949621505674787, + ]) + # 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)) < 15000 + end +end + @trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), l2=[ @@ -365,16 +397,16 @@ end @trixi_testset "elixir_euler_blast_wave_sc_subcell.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell.jl"), l2=[ - 0.30785094769124677, - 0.17599603017990473, - 0.17594201496603085, - 0.614120201076276, + 0.30783113348004093, + 0.17597018114974242, + 0.17594406844552404, + 0.6141151469952726, ], linf=[ - 1.2971828380703805, - 1.1057475500114755, - 1.105770653844522, - 2.4364101844067916, + 1.297252661541156, + 1.105840523330678, + 1.1058680103852032, + 2.434846187265568, ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -393,16 +425,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ - 0.32211935909459755, - 0.17984734129031393, - 0.17983517637561672, - 0.6136858672602447, + 0.3221177942225801, + 0.1798478357478982, + 0.1798364616438908, + 0.6136884131056267, ], linf=[ - 1.3435940880493509, - 1.1748248970276045, - 1.1745481442875036, - 2.421529617190895, + 1.343766644801395, + 1.1749593109683463, + 1.1747613085307178, + 2.4216006041018785, ], tspan=(0.0, 0.5), initial_refinement_level=4, diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 323d88c01e..f515a1c74d 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -98,11 +98,11 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), l2=[ - 76.59096367977872, - 1.9879932386864356, - 59851.34515039375, - 0.18710988181124935, - 0.010631432251136084, + 76.5909636797791, + 1.9879932386864965, + 59851.345150393994, + 0.1871098818112499, + 0.010631432251136151, ], linf=[ 212.71245739310544, diff --git a/test/test_tree_2d_shallowwater.jl b/test/test_tree_2d_shallowwater.jl index 0174264473..9a3ba36c7d 100644 --- a/test/test_tree_2d_shallowwater.jl +++ b/test/test_tree_2d_shallowwater.jl @@ -13,15 +13,15 @@ EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") @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.9911802019934329, + 0.7340106828033273, + 0.7446338002084801, 0.5875351036989047, ], linf=[ - 2.0117744577945413, - 2.9962317608172127, - 2.6554999727293653, + 2.0120253138457564, + 2.991158989293406, + 2.6557412817714035, 3.0, ], tspan=(0.0, 0.25)) @@ -280,15 +280,15 @@ 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, + 0.1351723240085936, + 0.20010881416550014, + 0.2001088141654999, 2.719538414346464e-7, ], linf=[ - 0.5303607982988336, - 0.5080989745682338, - 0.5080989745682352, + 0.5303608302490757, + 0.5080987791967457, + 0.5080987791967506, 1.1301675764130437e-6, ], tspan=(0.0, 0.25)) diff --git a/test/test_tree_3d_linearizedeuler.jl b/test/test_tree_3d_linearizedeuler.jl new file mode 100644 index 0000000000..00f8d62dad --- /dev/null +++ b/test/test_tree_3d_linearizedeuler.jl @@ -0,0 +1,35 @@ + +using Test +using Trixi + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") + +@testset "Linearized Euler Equations 3D" begin +#! format: noindent + +@trixi_testset "elixir_linearizedeuler_gauss_wall.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_gauss_wall.jl"), + l2=[ + 0.020380328336745232, 0.027122442311921492, + 0.02712244231192152, 8.273108096127844e-17, + 0.020380328336745232, + ], + linf=[ + 0.2916021983572774, 0.32763703462270843, + 0.32763703462270855, 1.641012595221666e-15, + 0.2916021983572774, + ], + tspan=(0.0, 1.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 +end diff --git a/test/test_tree_3d_part2.jl b/test/test_tree_3d_part2.jl index 5c7301654a..4b9da039f9 100644 --- a/test/test_tree_3d_part2.jl +++ b/test/test_tree_3d_part2.jl @@ -22,6 +22,9 @@ isdir(outdir) && rm(outdir, recursive = true) # Compressible Euler with self-gravity include("test_tree_3d_eulergravity.jl") + + # Linearized Euler + include("test_tree_3d_linearizedeuler.jl") end @trixi_testset "Additional tests in 3D" begin diff --git a/test/test_trixi.jl b/test/test_trixi.jl index cebe2164ae..7819582588 100644 --- a/test/test_trixi.jl +++ b/test/test_trixi.jl @@ -153,7 +153,9 @@ macro test_nowarn_mod(expr, additional_ignore_content = String[]) 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"] + r"┌ Warning: Layer with Float32 parameters got Float64 input.+\n│.+\n│.+\n│.+\n└ @ Flux.+\n", + # NOTE: These warnings arose from Julia 1.10 onwards + r"WARNING: Method definition .* in module .* at .* overwritten .*.\n"] append!(ignore_content, $additional_ignore_content) for pattern in ignore_content stderr_content = replace(stderr_content, pattern => "") diff --git a/test/test_unit.jl b/test/test_unit.jl index 575df8d493..1f2c7c6721 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -284,7 +284,7 @@ end function MyContainer(data, capacity) c = MyContainer(Vector{Int}(undef, capacity + 1), capacity, length(data), capacity + 1) - c.data[1:length(data)] .= data + c.data[eachindex(data)] .= data return c end MyContainer(data::AbstractArray) = MyContainer(data, length(data)) @@ -416,9 +416,9 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, true, true, - true, "cache", 1, (1.0, 1.0), 1.0, true, 1.0, - nothing) + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, + true, [(Trixi.entropy_guermond_etal, min)], true, + "cache", 1, (1.0, 1.0), 1.0, true, 1.0, nothing) @test_nowarn show(stdout, limiter_idp) limiter_mcl = SubcellLimiterMCL("cache", true, true, true, true, true, true, true, @@ -1436,7 +1436,8 @@ end u_values = [SVector(1.0, 0.5, -0.7, 1.0), SVector(1.5, -0.2, 0.1, 5.0)] fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, - FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, flux_hllc, + FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, + flux_hllc, flux_chandrashekar, ] for f_std in fluxes @@ -1460,7 +1461,8 @@ end u_values = [SVector(1.0, 0.5, -0.7, 0.1, 1.0), SVector(1.5, -0.2, 0.1, 0.2, 5.0)] fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, - FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, flux_hllc, + FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, + flux_hllc, flux_chandrashekar, ] for f_std in fluxes @@ -1541,6 +1543,60 @@ end end end +@testset "Equivalent Wave Speed Estimates" begin + @timed_testset "Linearized Euler 3D" begin + equations = LinearizedEulerEquations3D(v_mean_global = (0.42, 0.37, 0.7), + c_mean_global = 1.0, + rho_mean_global = 1.0) + + normal_x = SVector(1.0, 0.0, 0.0) + normal_y = SVector(0.0, 1.0, 0.0) + normal_z = SVector(0.0, 0.0, 1.0) + + u_ll = SVector(0.3, 0.5, -0.7, 0.1, 1.0) + u_rr = SVector(0.5, -0.2, 0.1, 0.2, 5.0) + + @test all(isapprox(x, y) + for (x, y) in zip(max_abs_speed_naive(u_ll, u_rr, 1, equations), + max_abs_speed_naive(u_ll, u_rr, normal_x, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(max_abs_speed_naive(u_ll, u_rr, 2, equations), + max_abs_speed_naive(u_ll, u_rr, normal_y, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(max_abs_speed_naive(u_ll, u_rr, 3, equations), + max_abs_speed_naive(u_ll, u_rr, normal_z, + equations))) + + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_naive(u_ll, u_rr, 1, equations), + min_max_speed_naive(u_ll, u_rr, normal_x, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_naive(u_ll, u_rr, 2, equations), + min_max_speed_naive(u_ll, u_rr, normal_y, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_naive(u_ll, u_rr, 3, equations), + min_max_speed_naive(u_ll, u_rr, normal_z, + equations))) + + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_davis(u_ll, u_rr, 1, equations), + min_max_speed_davis(u_ll, u_rr, normal_x, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_davis(u_ll, u_rr, 2, equations), + min_max_speed_davis(u_ll, u_rr, normal_y, + equations))) + @test all(isapprox(x, y) + for (x, y) in zip(min_max_speed_davis(u_ll, u_rr, 3, equations), + min_max_speed_davis(u_ll, u_rr, normal_z, + equations))) + end +end + @testset "SimpleKronecker" begin N = 3 diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 6814250dd4..5c228d1e04 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -41,8 +41,8 @@ end 1.4585198700082895e-13, 4.716940764877479e-13, ], linf=[ - 8.804956763697191e-12, 6.261199891888225e-11, - 2.936639820205755e-11, 1.20543575121701e-10, + 7.774003663030271e-12, 9.183176441496244e-11, + 4.5685344396417804e-11, 1.0534506600379245e-10, ], tspan=(0.0, 0.1), atol=3.0e-13) @@ -301,15 +301,15 @@ end @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, + 0.6107326269462766, + 0.48666631722018877, + 0.48309775159067053, + 0.29467422718511704, ], linf=[ - 2.775979948281604, - 3.1721242154451548, - 3.5713448319601393, + 2.776782342826098, + 3.2158378644333707, + 3.652920889487258, 2.052861364219655, ], tspan=(0.0, 0.25)) @@ -328,13 +328,13 @@ end l2=[ 1.2164292510839076, 2.6118925543469468e-12, - 1.1636046671473883e-12, + 2.459878823146057e-12, 1.2164292510839079, ], linf=[ 1.5138512282315846, - 4.998482888288039e-11, - 2.0246214978154587e-11, + 4.706289937431355e-11, + 4.913910192312011e-11, 1.513851228231574, ], tspan=(0.0, 0.25)) @@ -353,13 +353,13 @@ end l2=[ 1.2164292510839085, 1.2643106818778908e-12, - 7.46884905098358e-13, + 1.269230436589819e-12, 1.2164292510839079, ], linf=[ 1.513851228231562, - 1.6287765844373185e-11, - 6.8766999132716964e-12, + 1.6670644673575802e-11, + 1.8426585188623954e-11, 1.513851228231574, ], surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, @@ -381,13 +381,13 @@ end l2=[ 1.2164292510839083, 2.590643638636187e-12, - 1.0945471514840143e-12, + 2.388742604639019e-12, 1.2164292510839079, ], linf=[ 1.5138512282315792, - 5.0276441977281156e-11, - 1.9816934589292803e-11, + 4.761278694199934e-11, + 4.910549479958249e-11, 1.513851228231574, ], surface_flux=(flux_wintermeyer_etal, @@ -408,16 +408,16 @@ 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, + 0.001118134082248467, + 0.044560486817464634, + 0.01430926600634214, + 5.089218476759981e-6, ], linf=[ - 0.007835284004819698, - 0.3486891284278597, - 0.11242778979399048, - 2.6407324614119432e-5, + 0.007798727223654822, + 0.34782952734839157, + 0.11161614702628064, + 2.6407324614341476e-5, ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -433,15 +433,15 @@ end @trixi_testset "elixir_shallowwater_source_terms.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), l2=[ - 0.001119678684752799, - 0.015429108794630785, - 0.01708275441241111, - 5.089218476758271e-6, + 0.0011196838135485918, + 0.01542895635133927, + 0.017082803023121197, + 5.089218476759981e-6, ], linf=[ - 0.014299564388827513, - 0.12785126473870534, - 0.17626788561725526, + 0.014299541415654371, + 0.12783948113206955, + 0.17626489583921323, 2.6407324614341476e-5, ], surface_flux=(FluxHydrostaticReconstruction(flux_hll, @@ -461,15 +461,15 @@ 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, + 0.001118046975499805, + 0.04455969246244461, + 0.014298120235633432, 5.089218476759981e-6, ], linf=[ - 0.007825021762002393, - 0.348550815397918, - 0.1115517935018282, + 0.007776521213640031, + 0.34768318303226353, + 0.11075311228066198, 2.6407324614341476e-5, ], surface_flux=(flux_wintermeyer_etal, @@ -490,15 +490,15 @@ 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.0011196786847528799, - 0.015429108794631075, - 0.017082754412411742, + 0.0011196838135486059, + 0.015428956351339451, + 0.017082803023120943, 5.089218476759981e-6, ], linf=[ - 0.014299564388830177, - 0.12785126473870667, - 0.17626788561728546, + 0.01429954141565526, + 0.12783948113205668, + 0.176264895839215, 2.6407324614341476e-5, ], surface_flux=(flux_hll, @@ -561,15 +561,15 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec_shockcapturing.jl"), l2=[ - 0.6124656312639043, - 0.504371951785709, - 0.49180896200746366, - 0.29467422718511727, + 0.612551520607341, + 0.5039173660221961, + 0.49136517934903523, + 0.29467422718511704, ], linf=[ - 2.7639232436274392, - 3.3985508653311767, - 3.3330308209196224, + 2.7636771472622197, + 3.236168963021072, + 3.3363936775653826, 2.052861364219655, ], tspan=(0.0, 0.25)) @@ -650,7 +650,7 @@ end l2=[4.085391175504837e-5, 7.19179253772227e-5, 7.191792537723135e-5, - 0.00021775241532855398], + 0.0002177522206115571], linf=[0.0004054489124620808, 0.0006164432358217731, 0.0006164432358186644, @@ -701,7 +701,7 @@ end linf=[3.354871935812298e-11, 7.006478730531285e-12, 1.148153794261475e-11, - 9.041265514042607e-10], + 7.461231632532872e-10], tspan=(0.0, 0.05), atol=1.0e-10) # Ensure that we do not have excessive memory allocations diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index 12a3d46760..52ee904d2f 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -86,7 +86,7 @@ function trixi2txt(filename::AbstractString...; "maximum supported level $max_supported_level") end max_available_nodes_per_finest_element = 2^(max_supported_level - max_level) - if nvisnodes == nothing + if nvisnodes === nothing max_nvisnodes = 2 * n_nodes elseif nvisnodes == 0 max_nvisnodes = n_nodes @@ -137,9 +137,9 @@ function trixi2txt(filename::AbstractString...; println(io) # Data - for idx in 1:length(xs) + for idx in eachindex(xs) @printf(io, "%+10.8e", xs[idx]) - for variable_id in 1:length(variables) + for variable_id in eachindex(variables) @printf(io, " %+10.8e ", node_centered_data[idx, variable_id]) end println(io) @@ -199,7 +199,7 @@ function read_meshfile(filename::String) # Extract leaf cells (= cells to be plotted) and contract all other arrays accordingly leaf_cells = similar(levels) n_cells = 0 - for cell_id in 1:length(levels) + for cell_id in eachindex(levels) if sum(child_ids[:, cell_id]) > 0 continue end From aed2c65085aeb5dc517e01d3010cf208a21cb5f4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 May 2024 14:12:25 +0200 Subject: [PATCH 415/423] Fix tests --- test/test_tree_2d_euler.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 4100f0b217..bb90e98da6 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -531,8 +531,8 @@ end # Run with coverage takes 6 time steps. @test startswith(lines[end], "6") else - # Run without coverage takes 89 time steps. - @test startswith(lines[end], "89") + # Run without coverage takes 381 time steps. + @test startswith(lines[end], "381") end # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -780,13 +780,13 @@ end 0.12356154893467916, 0.2695167937393226, ], - tspan=(0.0, 2.0), - coverage_override=(maxiters = 7,), + tspan=(0.0, 0.2), + coverage_override=(maxiters = 3,), save_errors=true) lines = readlines(joinpath("out", "deviations.txt")) @test lines[1] == "# iter, simu_time, rho_min, pressure_min" - # Run without (with) coverage takes 745 (7) time steps - @test startswith(lines[end], "7") + # Run without (with) coverage takes 337 (3) time steps + @test startswith(lines[end], "3") # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From ec1e8b8e613e956e2a6d133e1aff857835c31840 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 14 May 2024 15:47:43 +0200 Subject: [PATCH 416/423] Fix and adapt tests for saving deviations with MCL --- .../elixir_euler_sedov_blast_wave_MCL.jl | 4 ++-- test/test_tree_2d_euler.jl | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl index 7751133dcf..4600d50739 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_MCL.jl @@ -95,8 +95,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors = false, interval = 100, - output_directory = "out"),) +stage_callbacks = (BoundsCheckCallback(save_errors = false, interval = 100),) +# `interval` is used when calling this elixir in the tests with `save_errors=true`. sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index bb90e98da6..40ee67bf27 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -545,7 +545,7 @@ end end @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin - rm("out/deviations.txt", force = true) + rm(joinpath("out", "deviations.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_MCL.jl"), l2=[ 0.4740321851943766, @@ -562,12 +562,20 @@ end tspan=(0.0, 1.0), initial_refinement_level=4, coverage_override=(maxiters = 6,), - save_errors=true, - output_directory="out") - lines = readlines("out/deviations.txt") + save_errors=true) + lines = readlines(joinpath("out", "deviations.txt")) @test lines[1] == "# iter, simu_time, rho_min, rho_max, rho_v1_min, rho_v1_max, rho_v2_min, rho_v2_max, rho_e_min, rho_e_max, pressure_min" - @test startswith(lines[end], "349") || startswith(lines[end], "1") + cmd = string(Base.julia_cmd()) + coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + if coverage + # Run with coverage takes 6 time steps. + @test startswith(lines[end], "6") + else + # Run without coverage takes 349 time steps. + @test startswith(lines[end], "349") + end # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From 8562942492550a0fb97b50dce4522a575d649c4f Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Fri, 24 May 2024 11:15:29 +0200 Subject: [PATCH 417/423] Merge main: Remove dispatching for mesh types (#128) * Add structured mesh support * Fix non-periodic computation of bounds * Use local limiting and nonperiodic domain in source terms elixir * Use local limiting in free stream elixir * Remove not needed lines * Remove P4estMesh * Add non-periodic tests with local bounds * fmt * Fix test * Use `get_inverse_jacobian` instead of dispatching all routines * Simplify `perform_idp_correction!` * Revert stuff * Remove free stream elixir * Use sedov blast instead of source term setup; add news * Update dispatching for mesh types * Remove dispatching for mesh types * Move new sedov tests within the test file * Move new tests within test file * Adapt dispatching * Fix typo * Remove not-needed parameter * Add subcell limiting support for StructuredMesh (#1946) * Add structured mesh support * Fix non-periodic computation of bounds * Use local limiting and nonperiodic domain in source terms elixir * Use local limiting in free stream elixir * Remove not needed lines * Remove P4estMesh * Add non-periodic tests with local bounds * fmt * Fix test * Use `get_inverse_jacobian` instead of dispatching all routines * Simplify `perform_idp_correction!` * Revert stuff * Remove free stream elixir * Use sedov blast instead of source term setup; add news * Update dispatching for mesh types * Move new tests within test file * Adapt dispatching * Fix typo * Remove not-needed parameters * Dispatch `check_bounds` for dimension using u --- NEWS.md | 1 + ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 115 ++++++ src/callbacks_stage/subcell_bounds_check.jl | 12 +- .../subcell_bounds_check_2d.jl | 12 +- .../subcell_limiter_idp_correction_2d.jl | 87 ++-- .../dgsem_tree/dg_2d_subcell_limiters.jl | 8 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 371 ++++++------------ test/test_structured_2d.jl | 56 +++ 8 files changed, 343 insertions(+), 319 deletions(-) create mode 100644 examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl diff --git a/NEWS.md b/NEWS.md index ebc8d9cda3..ecbd70ce47 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ for human readability. - Subcell local one-sided limiting support for nonlinear variables in 2D for `TreeMesh` ([#1792]). - New time integrator `PairedExplicitRK2`, implementing the second-order paired explicit Runge-Kutta method with [Convex.jl](https://github.com/jump-dev/Convex.jl) and [ECOS.jl](https://github.com/jump-dev/ECOS.jl) ([#1908]) +- Add subcell limiting support for `StructuredMesh` ([#1946]). ## Changes when updating to v0.7 from v0.6.x diff --git a/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..2f098037a3 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,115 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave + +boundary_condition = BoundaryConditionDirichlet(initial_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], + max_iterations_newton = 40, # Default value of 10 iterations is too low to fulfill bounds. + positivity_variables_cons = [], + positivity_variables_nonlinear = [], + bar_states = false) +# Variables for global limiting (`positivity_variables_cons` and +# `positivity_variables_nonlinear`) are overwritten and used in the tests. + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +# Get the curved quad mesh from a mapping function +# Mapping as described in https://arxiv.org/abs/2012.12040 +function mapping(xi, eta) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta)) + + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) + + return SVector(x, y) +end + +cells_per_dimension = (16, 16) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# 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) + +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 = 0.7) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + 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/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 1a60564067..49ebb1e9cb 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -38,7 +38,7 @@ function (callback::BoundsCheckCallback)(u_ode, integrator, stage) (; t, iter, alg) = integrator u = wrap_array(u_ode, mesh, equations, solver, cache) - @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, + @trixi_timeit timer() "check_bounds" check_bounds(u, equations, solver, cache, solver.volume_integral) save_errors = callback.save_errors && (callback.interval > 0) && @@ -48,20 +48,20 @@ function (callback::BoundsCheckCallback)(u_ode, integrator, stage) (iter + 1) >= integrator.opts.maxiters) # Maximum iterations reached if save_errors @trixi_timeit timer() "save_errors" save_bounds_check_errors(callback.output_directory, - u, t, iter + 1, + t, iter + 1, equations, solver.volume_integral) end end -@inline function check_bounds(u, mesh, equations, solver, cache, +@inline function check_bounds(u, equations, solver, cache, volume_integral::VolumeIntegralSubcellLimiting) - check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter) + check_bounds(u, equations, solver, cache, volume_integral.limiter) end -@inline function save_bounds_check_errors(output_directory, u, t, iter, equations, +@inline function save_bounds_check_errors(output_directory, t, iter, equations, volume_integral::VolumeIntegralSubcellLimiting) - save_bounds_check_errors(output_directory, u, t, iter, equations, + save_bounds_check_errors(output_directory, t, iter, equations, volume_integral.limiter) end diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 83339e8bda..a89d379383 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -5,7 +5,8 @@ @muladd begin #! format: noindent -@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, +@inline function check_bounds(u::AbstractArray{<:Any, 4}, + equations, solver, cache, limiter::SubcellLimiterIDP) (; local_twosided, positivity, local_onesided) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients @@ -103,7 +104,7 @@ return nothing end -@inline function save_bounds_check_errors(output_directory, u, time, iter, equations, +@inline function save_bounds_check_errors(output_directory, time, iter, equations, limiter::SubcellLimiterIDP) (; local_twosided, positivity, local_onesided) = limiter (; idp_bounds_delta_local) = limiter.cache @@ -145,7 +146,8 @@ end return nothing end -@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, +@inline function check_bounds(u::AbstractArray{<:Any, 4}, + equations, solver, cache, limiter::SubcellLimiterMCL) (; var_min, var_max) = limiter.cache.subcell_limiter_coefficients (; bar_states1, bar_states2, lambda1, lambda2) = limiter.cache.container_bar_states @@ -625,14 +627,14 @@ end return nothing end -@inline function save_bounds_check_errors(output_directory, u, time, iter, equations, +@inline function save_bounds_check_errors(output_directory, time, iter, equations, limiter::SubcellLimiterMCL) (; mcl_bounds_delta_local) = limiter.cache n_vars = nvariables(equations) # Print errors to output file - open("$output_directory/deviations.txt", "a") do f + open(joinpath(output_directory, "deviations.txt"), "a") do f print(f, iter, ", ", time) for v in eachvariable(equations) print(f, ", ", mcl_bounds_delta_local[1, v], ", ", diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index 4ab1357de6..60a87e5762 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -5,29 +5,14 @@ @muladd begin #! format: noindent -function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) - if dg.volume_integral.limiter.smoothness_indicator - elements = cache.element_ids_dgfv - else - elements = eachelement(dg, cache) - end - - # Loop over blended DG-FV elements - @threaded for element in elements - # Sign switch as in apply_jacobian! - inverse_jacobian = -cache.elements.inverse_jacobian[element] - - for j in eachnode(dg), i in eachnode(dg) - perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, cache, - i, j, element) - end - end - - return nothing -end - -function perform_idp_correction!(u, dt, mesh::Union{StructuredMesh{2}, P4estMesh{2}}, +function perform_idp_correction!(u, dt, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, equations, dg, cache) + @unpack inverse_weights = dg.basis + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients + if dg.volume_integral.limiter.smoothness_indicator elements = cache.element_ids_dgfv else @@ -37,43 +22,33 @@ function perform_idp_correction!(u, dt, mesh::Union{StructuredMesh{2}, P4estMesh @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) # Sign switch as in apply_jacobian! - inverse_jacobian = -cache.elements.inverse_jacobian[i, j, element] - - perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, cache, - i, j, element) + inverse_jacobian = -get_inverse_jacobian(cache.elements.inverse_jacobian, + mesh, i, j, element) + + # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} + alpha_flux1 = (1 - alpha1[i, j, element]) * + get_node_vars(antidiffusive_flux1_R, equations, dg, + i, j, element) + alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * + get_node_vars(antidiffusive_flux1_L, equations, dg, + i + 1, j, element) + alpha_flux2 = (1 - alpha2[i, j, element]) * + get_node_vars(antidiffusive_flux2_R, equations, dg, + i, j, element) + alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * + get_node_vars(antidiffusive_flux2_L, equations, dg, + i, j + 1, element) + + for v in eachvariable(equations) + u[v, i, j, element] += dt * inverse_jacobian * + (inverse_weights[i] * + (alpha_flux1_ip1[v] - alpha_flux1[v]) + + inverse_weights[j] * + (alpha_flux2_jp1[v] - alpha_flux2[v])) + end end end return nothing end - -# Function barrier to dispatch outer function by mesh type -@inline function perform_idp_correction_inner!(u, dt, inverse_jacobian, equations, dg, - cache, i, j, element) - (; inverse_weights) = dg.basis - (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - (; alpha1, alpha2) = dg.volume_integral.limiter.cache.subcell_limiter_coefficients - - # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} - alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) - alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, - element) - alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) - alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, - element) - - for v in eachvariable(equations) - u[v, i, j, element] += dt * inverse_jacobian * - (inverse_weights[i] * - (alpha_flux1_ip1[v] - alpha_flux1[v]) + - inverse_weights[j] * - (alpha_flux2_jp1[v] - alpha_flux2[v])) - end - - return nothing -end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 90a807c80b..2e471f2254 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -508,7 +508,9 @@ end # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. @inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, + u, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, nonconservative_terms::False, equations, limiter::SubcellLimiterIDP, dg, element, cache) @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @@ -546,7 +548,9 @@ end # Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. @inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fstar1_L, fstar1_R, fstar2_L, fstar2_R, - u, mesh, + u, + mesh::Union{TreeMesh{2}, StructuredMesh{2}, + P4estMesh{2}}, nonconservative_terms::True, equations, limiter::SubcellLimiterIDP, dg, element, cache) @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index d127e8f1e8..f9449e854a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -303,42 +303,17 @@ end # Local two-sided limiting of conservative variables @inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, elements) - mesh, _, _, _ = mesh_equations_solver_cache(semi) - for variable in limiter.local_twosided_variables_cons - idp_local_twosided!(alpha, limiter, u, t, dt, semi, mesh, elements, variable) + idp_local_twosided!(alpha, limiter, u, t, dt, semi, elements, variable) end return nothing end -@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, - elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) - - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - variable_string = string(variable) - var_min = variable_bounds[Symbol(variable_string, "_min")] - var_max = variable_bounds[Symbol(variable_string, "_max")] - if !limiter.bar_states - calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) - end - - @threaded for element in elements - inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, - variable, var_min, var_max, i, j, element) - end - end - - return nothing -end - -@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, elements, variable) + mesh, _, dg, cache = mesh_equations_solver_cache(semi) + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis (; variable_bounds) = limiter.cache.subcell_limiter_coefficients variable_string = string(variable) @@ -350,110 +325,70 @@ end @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, - variable, var_min, var_max, i, j, element) + inverse_jacobian = get_inverse_jacobian(cache.elements.inverse_jacobian, + mesh, i, j, element) + var = u[variable, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pp and Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1_R[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1_L[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2_R[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2_L[variable, i, j + 1, element] + + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / + (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / + (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) end end return nothing end -# Function barrier to dispatch outer function by mesh type -@inline function idp_local_twosided_inner!(alpha, inverse_jacobian, u, dt, dg, cache, - variable, var_min, var_max, i, j, element) - (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - (; inverse_weights) = dg.basis - - var = u[variable, i, j, element] - # Real Zalesak type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pp and Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1_R[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1_L[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2_R[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2_L[variable, i, j + 1, element] - - Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + - max(0, val_flux2_local) + max(0, val_flux2_local_jp1) - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - - Pp = inverse_jacobian * Pp - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qp = abs(Qp) / - (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) - Qm = abs(Qm) / - (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) - - # Calculate alpha at nodes - alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) - - return nothing -end - ############################################################################## # Local one-sided limiting of nonlinear variables @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, elements) - mesh, _, _, _ = mesh_equations_solver_cache(semi) - for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear - idp_local_onesided!(alpha, limiter, u, t, dt, semi, mesh, elements, + idp_local_onesided!(alpha, limiter, u, t, dt, semi, elements, variable, min_or_max) end return nothing end -@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, mesh::TreeMesh{2}, - elements, variable, min_or_max) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] - if !limiter.bar_states - calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) - end - - # Perform Newton's bisection method to find new alpha - @threaded for element in elements - inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, - i, j, element, variable, min_or_max, - initial_check_local_onesided_newton_idp, - final_check_local_onesided_newton_idp, inverse_jacobian, - dt, equations, dg, cache, limiter) - end - end - - return nothing -end - -@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements, +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, elements, variable, min_or_max) - _, equations, dg, cache = mesh_equations_solver_cache(semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] if !limiter.bar_states @@ -463,7 +398,8 @@ end # Perform Newton's bisection method to find new alpha @threaded for element in elements for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] + inverse_jacobian = get_inverse_jacobian(cache.elements.inverse_jacobian, + mesh, i, j, element) u_local = get_node_vars(u, equations, dg, i, j, element) newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, i, j, element, variable, min_or_max, @@ -480,8 +416,6 @@ end # Global positivity limiting @inline function idp_positivity!(alpha, limiter, u, dt, semi, elements) - mesh, _, _, _ = mesh_equations_solver_cache(semi) - # Conservative variables for variable in limiter.positivity_variables_cons @trixi_timeit timer() "conservative variables" idp_positivity_conservative!(alpha, @@ -489,7 +423,6 @@ end u, dt, semi, - mesh, elements, variable) end @@ -500,7 +433,6 @@ end limiter, u, dt, semi, - mesh, elements, variable) end @@ -511,165 +443,104 @@ end ############################################################################### # Global positivity limiting of conservative variables -@inline function idp_positivity_conservative!(alpha, limiter, u, dt, semi, - mesh::TreeMesh{2}, elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) +@inline function idp_positivity_conservative!(alpha, limiter, u, dt, semi, elements, + variable) + mesh, _, dg, cache = mesh_equations_solver_cache(semi) + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + (; positivity_correction_factor) = limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in elements - inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, dt, - dg, cache, variable, var_min, - i, j, element) - end - end - - return nothing -end - -@inline function idp_positivity_conservative!(alpha, limiter, u, dt, semi, - mesh::Union{StructuredMesh{2}, - P4estMesh{2}}, - elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) - - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol(string(variable), "_min")] + inverse_jacobian = get_inverse_jacobian(cache.elements.inverse_jacobian, + mesh, i, j, element) + var = u[variable, i, j, element] + if var < 0 + error("Safe low-order method produces negative value for conservative variable $variable. Try a smaller time step.") + end - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, dt, - dg, cache, variable, var_min, - i, j, element) + # Compute bound + if limiter.local_twosided && + variable in limiter.local_twosided_variables_cons && + var_min[i, j, element] >= positivity_correction_factor * var + # Local limiting is more restrictive that positivity limiting + # => Skip positivity limiting for this node + return nothing + end + var_min[i, j, element] = positivity_correction_factor * var + + # Real one-sided Zalesak-type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1_R[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1_L[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2_R[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2_L[variable, i, j + 1, element] + + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) + + # Calculate alpha + alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) end end return nothing end -# Function barrier to dispatch outer function by mesh type -@inline function idp_positivity_conservative_inner!(alpha, inverse_jacobian, limiter, u, - dt, dg, cache, variable, var_min, - i, j, element) - (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes - (; inverse_weights) = dg.basis - (; positivity_correction_factor) = limiter - - var = u[variable, i, j, element] - if var < 0 - error("Safe low-order method produces negative value for conservative variable $variable. Try a smaller time step.") - end - - # Compute bound - if limiter.local_twosided && - variable in limiter.local_twosided_variables_cons && - var_min[i, j, element] >= positivity_correction_factor * var - # Local limiting is more restrictive that positivity limiting - # => Skip positivity limiting for this node - return nothing - end - var_min[i, j, element] = positivity_correction_factor * var - - # Real one-sided Zalesak-type limiter - # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" - # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" - # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is - # for each interface, not each node - Qm = min(0, (var_min[i, j, element] - var) / dt) - - # Calculate Pm - # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. - val_flux1_local = inverse_weights[i] * - antidiffusive_flux1_R[variable, i, j, element] - val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1_L[variable, i + 1, j, element] - val_flux2_local = inverse_weights[j] * - antidiffusive_flux2_R[variable, i, j, element] - val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2_L[variable, i, j + 1, element] - - Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + - min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - Pm = inverse_jacobian * Pm - - # Compute blending coefficient avoiding division by zero - # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) - Qm = abs(Qm) / (abs(Pm) + eps(typeof(Qm)) * 100) - - # Calculate alpha - alpha[i, j, element] = max(alpha[i, j, element], 1 - Qm) - - return nothing -end - ############################################################################### # Global positivity limiting of nonlinear variables -@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, - mesh::TreeMesh{2}, elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) +@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, elements, + variable) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + (; positivity_correction_factor) = limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in elements - inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) - idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, dt, - semi, dg, cache, variable, var_min, - i, j, element) - end - end - - return nothing -end + inverse_jacobian = get_inverse_jacobian(cache.elements.inverse_jacobian, + mesh, i, j, element) -@inline function idp_positivity_nonlinear!(alpha, limiter, u, dt, semi, - mesh::Union{StructuredMesh{2}, P4estMesh{2}}, - elements, variable) - _, _, dg, cache = mesh_equations_solver_cache(semi) - - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_min = variable_bounds[Symbol(string(variable), "_min")] + # Compute bound + u_local = get_node_vars(u, equations, dg, i, j, element) + var = variable(u_local, equations) + if var < 0 + error("Safe low-order method produces negative value for variable $variable. Try a smaller time step.") + end + var_min[i, j, element] = positivity_correction_factor * var - @threaded for element in elements - for j in eachnode(dg), i in eachnode(dg) - inverse_jacobian = cache.elements.inverse_jacobian[i, j, element] - idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, dt, - semi, dg, cache, variable, var_min, - i, j, element) + # Perform Newton's bisection method to find new alpha + newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, + variable, min, initial_check_nonnegative_newton_idp, + final_check_nonnegative_newton_idp, inverse_jacobian, + dt, equations, dg, cache, limiter) end end return nothing end -# Function barrier to dispatch outer function by mesh type -@inline function idp_positivity_nonlinear_inner!(alpha, inverse_jacobian, limiter, u, - dt, semi, dg, cache, variable, var_min, - i, j, element) - _, equations, _, _ = mesh_equations_solver_cache(semi) - - u_local = get_node_vars(u, equations, dg, i, j, element) - var = variable(u_local, equations) - if var < 0 - error("Safe low-order method produces negative value for conservative variable $variable. Try a smaller time step.") - end - var_min[i, j, element] = limiter.positivity_correction_factor * var - - # Perform Newton's bisection method to find new alpha - newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, variable, - min, initial_check_nonnegative_newton_idp, - final_check_nonnegative_newton_idp, inverse_jacobian, - dt, equations, dg, cache, limiter) - - return nothing -end - ############################################################################### # Newton-bisection method diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index c608b68ed2..f96dd3c9ab 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -861,6 +861,62 @@ end end end +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl (local bounds)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2=[ + 0.6337774834710513, + 0.30377119245852724, + 0.3111372568571772, + 1.2976221893997268, + ], + linf=[ + 2.2064877103138207, + 1.541067099687334, + 1.5487587769900337, + 6.271271639873466, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl (global bounds)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + positivity_variables_cons=["rho"], + positivity_variables_nonlinear=[pressure], + local_twosided_variables_cons=[], + local_onesided_variables_nonlinear=[], + l2=[ + 0.7869912572385168, + 0.39170886758882073, + 0.39613257454431977, + 1.2951760266455101, + ], + linf=[ + 5.156044534854053, + 3.6261667239538986, + 3.1807681416546085, + 6.3028422220287235, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end +end + @trixi_testset "elixir_euler_rayleigh_taylor_instability.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_rayleigh_taylor_instability.jl"), From 10580fce70497cc97c034ec0c00b14b6c92a9d71 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 24 May 2024 11:19:23 +0200 Subject: [PATCH 418/423] Move `save_bounds_check_errors` to `subcell_bounds_check.jl` --- src/callbacks_stage/subcell_bounds_check.jl | 73 +++++++++++++++++++ .../subcell_bounds_check_2d.jl | 73 ------------------- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 49ebb1e9cb..10e6b76c13 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -216,5 +216,78 @@ end return nothing end +@inline function save_bounds_check_errors(output_directory, time, iter, equations, + limiter::SubcellLimiterIDP) + (; local_twosided, positivity, local_onesided) = limiter + (; idp_bounds_delta_local) = limiter.cache + + # Print to output file + open(joinpath(output_directory, "deviations.txt"), "a") do f + print(f, iter, ", ", time) + if local_twosided + for v in limiter.local_twosided_variables_cons + v_string = string(v) + print(f, ", ", idp_bounds_delta_local[Symbol(v_string, "_min")], + ", ", idp_bounds_delta_local[Symbol(v_string, "_max")]) + end + end + if local_onesided + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + key = Symbol(string(variable), "_", string(min_or_max)) + print(f, ", ", idp_bounds_delta_local[key]) + end + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_twosided_variables_cons + continue + end + print(f, ", ", idp_bounds_delta_local[Symbol(string(v), "_min")]) + end + for variable in limiter.positivity_variables_nonlinear + print(f, ", ", idp_bounds_delta_local[Symbol(string(variable), "_min")]) + end + end + println(f) + end + # Reset local maximum deviations + for (key, _) in idp_bounds_delta_local + idp_bounds_delta_local[key] = zero(eltype(idp_bounds_delta_local[key])) + end + + return nothing +end + +@inline function save_bounds_check_errors(output_directory, time, iter, equations, + limiter::SubcellLimiterMCL) + (; mcl_bounds_delta_local) = limiter.cache + + n_vars = nvariables(equations) + + # Print errors to output file + open(joinpath(output_directory, "deviations.txt"), "a") do f + print(f, iter, ", ", time) + for v in eachvariable(equations) + print(f, ", ", mcl_bounds_delta_local[1, v], ", ", + mcl_bounds_delta_local[2, v]) + end + if limiter.positivity_limiter_pressure + print(f, ", ", mcl_bounds_delta_local[1, n_vars + 1]) + end + println(f) + end + + # Reset mcl_bounds_delta_local + for v in eachvariable(equations) + mcl_bounds_delta_local[1, v] = zero(eltype(mcl_bounds_delta_local)) + mcl_bounds_delta_local[2, v] = zero(eltype(mcl_bounds_delta_local)) + end + if limiter.positivity_limiter_pressure + mcl_bounds_delta_local[1, n_vars + 1] = zero(eltype(mcl_bounds_delta_local)) + end + + return nothing +end + include("subcell_bounds_check_2d.jl") end # @muladd diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index a89d379383..1ea839bf70 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -104,48 +104,6 @@ return nothing end -@inline function save_bounds_check_errors(output_directory, time, iter, equations, - limiter::SubcellLimiterIDP) - (; local_twosided, positivity, local_onesided) = limiter - (; idp_bounds_delta_local) = limiter.cache - - # Print to output file - open(joinpath(output_directory, "deviations.txt"), "a") do f - print(f, iter, ", ", time) - if local_twosided - for v in limiter.local_twosided_variables_cons - v_string = string(v) - print(f, ", ", idp_bounds_delta_local[Symbol(v_string, "_min")], - ", ", idp_bounds_delta_local[Symbol(v_string, "_max")]) - end - end - if local_onesided - for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear - key = Symbol(string(variable), "_", string(min_or_max)) - print(f, ", ", idp_bounds_delta_local[key]) - end - end - if positivity - for v in limiter.positivity_variables_cons - if v in limiter.local_twosided_variables_cons - continue - end - print(f, ", ", idp_bounds_delta_local[Symbol(string(v), "_min")]) - end - for variable in limiter.positivity_variables_nonlinear - print(f, ", ", idp_bounds_delta_local[Symbol(string(variable), "_min")]) - end - end - println(f) - end - # Reset local maximum deviations - for (key, _) in idp_bounds_delta_local - idp_bounds_delta_local[key] = zero(eltype(idp_bounds_delta_local[key])) - end - - return nothing -end - @inline function check_bounds(u::AbstractArray{<:Any, 4}, equations, solver, cache, limiter::SubcellLimiterMCL) @@ -626,35 +584,4 @@ end return nothing end - -@inline function save_bounds_check_errors(output_directory, time, iter, equations, - limiter::SubcellLimiterMCL) - (; mcl_bounds_delta_local) = limiter.cache - - n_vars = nvariables(equations) - - # Print errors to output file - open(joinpath(output_directory, "deviations.txt"), "a") do f - print(f, iter, ", ", time) - for v in eachvariable(equations) - print(f, ", ", mcl_bounds_delta_local[1, v], ", ", - mcl_bounds_delta_local[2, v]) - end - if limiter.positivity_limiter_pressure - print(f, ", ", mcl_bounds_delta_local[1, n_vars + 1]) - end - println(f) - end - - # Reset mcl_bounds_delta_local - for v in eachvariable(equations) - mcl_bounds_delta_local[1, v] = zero(eltype(mcl_bounds_delta_local)) - mcl_bounds_delta_local[2, v] = zero(eltype(mcl_bounds_delta_local)) - end - if limiter.positivity_limiter_pressure - mcl_bounds_delta_local[1, n_vars + 1] = zero(eltype(mcl_bounds_delta_local)) - end - - return nothing -end end # @muladd From c030593a31fe6de41226a6317532af88ff7d4179 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 24 May 2024 12:16:37 +0200 Subject: [PATCH 419/423] Fix newton loop with `continue` --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index f9449e854a..c948d67314 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -468,7 +468,7 @@ end var_min[i, j, element] >= positivity_correction_factor * var # Local limiting is more restrictive that positivity limiting # => Skip positivity limiting for this node - return nothing + continue end var_min[i, j, element] = positivity_correction_factor * var From 53881b7dd00af6ab028768397b974a64a695b534 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Thu, 25 Jul 2024 20:25:33 +0200 Subject: [PATCH 420/423] Fix boundary condition mixed for structured mesh (not used lines of code) --- examples/structured_2d_dgsem/elixir_euler_double_mach.jl | 3 +-- examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index e1fff80510..46b2d6930e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -63,8 +63,7 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond equations) # 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_or_normal, - equations) + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) else flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) end diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index e56392f9b2..2b0acbd0c5 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -63,8 +63,7 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond equations) # 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_or_normal, - equations) + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) else flux = surface_flux_function(u_boundary, u_inner, normal_direction, equations) end From 0ac57af3f7d51f19b2924d9a96d9f15a069ecb29 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:19:16 +0200 Subject: [PATCH 421/423] Merge branch from subcell limiting p4est PR (#129) Make sure I adapted everything correctly. --- .../elixir_euler_double_mach.jl | 9 +- .../elixir_euler_double_mach_MCL.jl | 9 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 102 ++++++++++++++++++ .../elixir_euler_supersonic_cylinder_MCL.jl | 12 +-- ...ir_euler_supersonic_cylinder_sc_subcell.jl | 39 ++++--- .../elixir_euler_double_mach.jl | 7 +- .../elixir_euler_double_mach_MCL.jl | 7 +- src/equations/compressible_euler_2d.jl | 70 ++++++++++++ .../dgsem_p4est/dg_2d_subcell_limiters.jl | 4 +- .../dgsem_p4est/subcell_limiters_2d.jl | 57 +++++----- .../dg_2d_subcell_limiters.jl | 16 +-- .../dgsem_structured/subcell_limiters_2d.jl | 32 +++--- .../dgsem_tree/dg_2d_subcell_limiters.jl | 70 ++++++------ src/solvers/dgsem_tree/subcell_limiters.jl | 10 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 8 +- test/test_p4est_2d.jl | 80 ++++++++------ 16 files changed, 362 insertions(+), 170 deletions(-) create mode 100644 examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl index d5d7338ba4..cf27cfb4d5 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl @@ -71,13 +71,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for P4estMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, + normal_direction::AbstractVector, mesh::P4estMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -160,7 +159,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl index 45f7d12f60..f1266272e8 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -71,13 +71,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for P4estMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, + normal_direction::AbstractVector, mesh::P4estMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -162,7 +161,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors = false),) +stage_callbacks = (BoundsCheckCallback(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..a56dd46eb1 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,102 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end + +initial_condition = initial_condition_sedov_blast_wave + +# Get the DG approximation space +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], + max_iterations_newton = 40, # Default value of 10 iterations is too low to fulfill bounds. + bar_states = false) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +############################################################################### + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg = polydeg, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl index 75b65fe1f2..5185e8625b 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl @@ -48,10 +48,10 @@ initial_condition = initial_condition_mach3_flow return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_supersonic_inflow), - normal_direction::AbstractVector, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) @@ -69,10 +69,10 @@ end return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_outflow), - orientation_or_normal, direction, - mesh::P4estMesh{2}, equations, dg, + orientation_or_normal, + mesh::P4estMesh{2}, equations, dg, cache, indices...) return u_inner end diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl index 5157480894..f136e9038e 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl @@ -13,7 +13,6 @@ # # Keywords: supersonic flow, shock capturing, AMR, unstructured curved mesh, positivity preservation, compressible Euler, 2D -using Downloads: download using OrdinaryDiffEq using Trixi @@ -48,10 +47,10 @@ initial_condition = initial_condition_mach3_flow return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_supersonic_inflow), - normal_direction::AbstractVector, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) @@ -69,10 +68,10 @@ end return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_outflow), - orientation_or_normal, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) return u_inner end @@ -91,28 +90,26 @@ boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, :Right => boundary_condition_outflow, :Left => boundary_condition_supersonic_inflow) +volume_flux = flux_ranocha_turbo surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = ["rho"], + local_twosided_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, min)], - max_iterations_newton = 100, + max_iterations_newton = 50, # Default value of 10 iterations is too low to fulfill bounds. bar_states = false) + volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; 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_mesh_file = joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp")) mesh = P4estMesh{2}(mesh_file, initial_refinement_level = 0) @@ -134,21 +131,21 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval = 100, +save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true, solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl = 0.4) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - stepsize_callback, - save_solution) + save_solution, + stepsize_callback) -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 46b2d6930e..33be05c615 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -76,13 +76,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for StructuredMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -162,7 +161,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 2b0acbd0c5..68290ac31f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -76,13 +76,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for StructuredMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -164,7 +163,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors = false),) +stage_callbacks = (BoundsCheckCallback(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 0b7f7ee49a..c2dae0682c 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -403,6 +403,76 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains requires the boundary +outer state. This function returns the boundary value for [`boundary_condition_slip_wall`](@ref) at +time `t` and for node with spatial indices `indices` and at the boundary with `normal_direction`. + +Should be used together with [`P4estMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], + u_inner[4]) +end + +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + +Should be used together with [`StructuredMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + get_boundary_outer_state(u_inner, t, boundary_condition, normal_direction, + mesh, equations, dg, cache, indices...) +end + +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + orientation::Integer, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + +Should be used together with [`TreeMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + orientation::Integer, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) +end + # TODO: Add docstring when about to merge. # Using with TreeMesh{2} @inline function characteristic_boundary_value_function(outer_boundary_value_function, diff --git a/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl index f8a5ea24ec..1f3eea73d3 100644 --- a/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl @@ -166,9 +166,9 @@ end i_node, j_node, element) u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, normal_direction, - direction, mesh, equations, dg, + mesh, equations, dg, cache, i_node, j_node, element) lambda = max_abs_speed_naive(u_inner, u_outer, normal_direction, diff --git a/src/solvers/dgsem_p4est/subcell_limiters_2d.jl b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl index d014a7b038..7283cb6695 100644 --- a/src/solvers/dgsem_p4est/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl @@ -13,6 +13,7 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, (; neighbor_ids, node_indices) = cache.interfaces index_range = eachnode(dg) + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get element and side index information on the primary element primary_element = neighbor_ids[1, interface] @@ -67,22 +68,25 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, end end - calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) + # Calc bounds at physical boundaries + calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) return nothing end -@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions::BoundaryConditionPeriodic, - mesh, equations, dg, cache) +@inline function calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions::BoundaryConditionPeriodic, + mesh::P4estMesh{2}, + equations, dg, cache) return nothing end -@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) +@inline function calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh::P4estMesh{2}, + equations, dg, cache) (; boundary_condition_types, boundary_indices) = boundary_conditions (; contravariant_vectors) = cache.elements @@ -109,9 +113,9 @@ end u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_condition, normal_direction, - direction, mesh, equations, dg, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, + normal_direction, + mesh, equations, dg, cache, i_node, j_node, element) var_outer = u_outer[variable] @@ -138,6 +142,7 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem index_range = eachnode(dg) index_end = last(index_range) + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get element and side index information on the primary element primary_element = neighbor_ids[1, interface] @@ -186,23 +191,25 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem end end - calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) + # Calc bounds at physical boundaries + calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) return nothing end -@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, - t, - boundary_conditions::BoundaryConditionPeriodic, - mesh, equations, dg, cache) +@inline function calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions::BoundaryConditionPeriodic, + mesh::P4estMesh{2}, + equations, dg, cache) return nothing end -@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, - t, boundary_conditions, - mesh, equations, dg, cache) +@inline function calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions, + mesh::P4estMesh{2}, + equations, dg, cache) (; boundary_condition_types, boundary_indices) = boundary_conditions (; contravariant_vectors) = cache.elements @@ -229,9 +236,9 @@ end u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_condition, normal_direction, - direction, mesh, equations, dg, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, + normal_direction, + mesh, equations, dg, cache, i_node, j_node, element) var_outer = variable(u_outer, equations) diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 3a1a560214..f8428197f4 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -244,9 +244,9 @@ end for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) @@ -270,9 +270,9 @@ end Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, @@ -301,9 +301,9 @@ end for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) @@ -327,9 +327,9 @@ end Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, diff --git a/src/solvers/dgsem_structured/subcell_limiters_2d.jl b/src/solvers/dgsem_structured/subcell_limiters_2d.jl index 83a979a16a..f1f3ee1bed 100644 --- a/src/solvers/dgsem_structured/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_structured/subcell_limiters_2d.jl @@ -59,9 +59,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) var_outer = u_outer[variable] @@ -76,9 +76,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) var_outer = u_outer[variable] @@ -96,9 +96,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) var_outer = u_outer[variable] @@ -113,9 +113,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) var_outer = u_outer[variable] @@ -180,9 +180,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) var_outer = variable(u_outer, equations) @@ -196,9 +196,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) var_outer = variable(u_outer, equations) @@ -215,9 +215,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) var_outer = variable(u_outer, equations) @@ -231,9 +231,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) var_outer = variable(u_outer, equations) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 2e471f2254..f964bcd186 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -766,10 +766,10 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], orientation, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -787,10 +787,10 @@ end else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], orientation, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, @@ -813,10 +813,10 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], orientation, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -834,10 +834,10 @@ end else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], orientation, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, @@ -1814,32 +1814,25 @@ end return nothing end -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_slip_wall), - orientation::Integer, direction, - mesh, equations::CompressibleEulerEquations2D, - dg, indices...) - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) -end - -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_slip_wall), - normal_direction::AbstractVector, direction, - mesh, equations::CompressibleEulerEquations2D, - dg, indices...) - factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) - u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_normal[1], - u_inner[3] - 2.0 * u_normal[2], - u_inner[4]) -end - -@inline function get_boundary_outer_state(u_inner, cache, t, +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::BoundaryConditionDirichlet, + orientation_or_normal, direction, + mesh, equations, dg, cache, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains requires the boundary +outer state. This function returns the boundary value for [`BoundaryConditionDirichlet`](@ref) at +time `t` and for node with spatial indices `indices` at the boundary with `orientation_or_normal` +and `direction`. + +Should be used together with [`TreeMesh`](@ref) or [`StructuredMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionDirichlet, - orientation_or_normal, direction, mesh, - equations, dg, indices...) + orientation_or_normal, direction, + mesh, equations, dg, cache, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1848,12 +1841,12 @@ end return u_outer end -@inline function get_boundary_outer_state(u_inner, cache, t, +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionCharacteristic, orientation_or_normal, direction, mesh::Union{TreeMesh, StructuredMesh}, equations, - dg, indices...) + dg, cache, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1864,10 +1857,11 @@ end return u_outer end -@inline function get_boundary_outer_state(u_inner, cache, t, +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionCharacteristic, - normal_direction::AbstractVector, direction, - mesh::P4estMesh, equations, dg, indices...) + normal_direction::AbstractVector, + mesh::P4estMesh, equations, dg, cache, + indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index f3908fbb49..f7d2b6d3ef 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -237,8 +237,14 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) ] end if positivity - string = "Positivity limiting for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" - setup = [setup..., "" => string] + if !isempty(limiter.positivity_variables_cons) + string = "conservative variables $(limiter.positivity_variables_cons)" + setup = [setup..., "" => "Positivity limiting for " * string] + end + if !isempty(limiter.positivity_variables_nonlinear) + string = "$(limiter.positivity_variables_nonlinear)" + setup = [setup..., "" => "Positivity limiting for " * string] + end setup = [ setup..., "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index c948d67314..4cba931e0f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -179,10 +179,10 @@ end boundary_index += 2 end u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[boundary_index], orientation, boundary_index, - mesh, equations, dg, + mesh, equations, dg, cache, index..., element) var_outer = u_outer[variable] @@ -284,10 +284,10 @@ end boundary_index += 2 end u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[boundary_index], orientation, boundary_index, - mesh, equations, dg, + mesh, equations, dg, cache, index..., element) var_outer = variable(u_outer, equations) diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index 63b53b5566..ede137769f 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -298,6 +298,32 @@ end end end +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2=[ + 0.45737877846538905, + 0.2852097276261684, + 0.28527281809798694, + 1.2881460122856072, + ], + linf=[ + 1.6444110425837906, + 1.6743368122678752, + 1.6760847980983236, + 6.268843623083507, + ], + tspan=(0.0, 0.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)) < 15000 + end +end + @trixi_testset "elixir_euler_sedov.jl with HLLC Flux" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[ @@ -542,28 +568,25 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder_sc_subcell.jl"), l2=[ - 0.015519026585326362, - 0.03624624063147592, - 0.015856390554735263, - 0.11035405581567337, + 0.11085870166618325, + 0.23309905989870722, + 0.13505351590735631, + 0.7932047512585592, ], linf=[ - 1.034507228088565, - 2.7694272511829157, - 1.760899156958975, - 7.7689019494557865, + 2.9808773737943564, + 4.209364526217892, + 6.265341002817672, + 24.077904874883338, ], - tspan=(0.0, 0.001), - skip_coverage=true) - if @isdefined sol # Skipped in coverage run - # 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)) < 15000 - end + tspan=(0.0, 0.02)) + # 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)) < 15000 end end @@ -582,17 +605,14 @@ end 2.271954486109792, 9.900660307619413, ], - tspan=(0.0, 0.001), - skip_coverage=true) - if @isdefined sol # Skipped in coverage run - # 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)) < 15000 - end + tspan=(0.0, 0.001)) + # 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)) < 15000 end end From 0ded2e32b080d488c13acb5c0b1eb926e2c1c743 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Fri, 20 Sep 2024 13:52:43 +0200 Subject: [PATCH 422/423] Merge main (#131) --- .github/workflows/FormatCheck.yml | 2 +- .github/workflows/SpellCheck.yml | 2 +- Project.toml | 14 +- README.md | 22 -- .../src/files/subcell_shock_capturing.jl | 8 +- docs/src/styleguide.md | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 6 +- ...euler_blast_wave_sc_subcell_nonperiodic.jl | 5 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 8 +- .../tree_2d_dgsem/elixir_euler_vortex_amr.jl | 6 +- src/Trixi.jl | 1 + src/auxiliary/math.jl | 5 + src/callbacks_step/alive.jl | 2 +- src/callbacks_step/amr.jl | 2 + src/callbacks_step/analysis.jl | 3 +- src/callbacks_step/analysis_dg2d.jl | 33 ++- src/callbacks_step/analysis_dg2d_parallel.jl | 3 +- src/callbacks_step/analysis_dg3d.jl | 46 +++- src/callbacks_step/analysis_dg3d_parallel.jl | 3 +- src/callbacks_step/averaging.jl | 2 +- src/callbacks_step/glm_speed.jl | 7 +- src/callbacks_step/save_restart.jl | 2 +- src/callbacks_step/save_solution.jl | 4 +- src/callbacks_step/steady_state.jl | 2 +- src/callbacks_step/stepsize.jl | 2 +- src/callbacks_step/stepsize_dg2d.jl | 18 +- src/callbacks_step/stepsize_dg3d.jl | 12 +- src/callbacks_step/time_series.jl | 2 +- src/callbacks_step/visualization.jl | 2 +- src/equations/ideal_glm_mhd_2d.jl | 9 +- src/equations/ideal_glm_mhd_3d.jl | 9 +- .../ideal_glm_mhd_multicomponent_1d.jl | 9 +- .../ideal_glm_mhd_multicomponent_2d.jl | 42 ++- src/meshes/p4est_mesh.jl | 41 ++- src/meshes/parallel_tree.jl | 2 +- src/meshes/parallel_tree_mesh.jl | 30 +- src/meshes/t8code_mesh.jl | 10 +- src/meshes/tree_mesh.jl | 2 +- .../semidiscretization_coupled.jl | 8 +- .../semidiscretization_euler_gravity.jl | 2 +- .../semidiscretization_hyperbolic.jl | 8 +- src/solvers/dg.jl | 12 +- src/solvers/dgsem_p4est/containers.jl | 3 +- src/solvers/dgsem_p4est/containers_2d.jl | 7 +- src/solvers/dgsem_p4est/dg_parallel.jl | 65 ++--- src/solvers/dgsem_t8code/dg_parallel.jl | 6 +- src/solvers/dgsem_tree/containers_2d.jl | 6 + src/solvers/dgsem_tree/dg_2d_parallel.jl | 42 +-- src/solvers/dgsem_tree/indicators.jl | 6 +- src/solvers/dgsem_tree/subcell_limiters.jl | 6 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 3 - test/test_dgmulti_1d.jl | 28 +- test/test_dgmulti_2d.jl | 122 ++++----- test/test_dgmulti_3d.jl | 63 +++-- test/test_mpi_p4est_2d.jl | 4 +- test/test_mpi_p4est_3d.jl | 16 +- test/test_mpi_t8code_2d.jl | 4 +- test/test_mpi_t8code_3d.jl | 12 +- test/test_mpi_tree.jl | 52 ++-- test/test_p4est_2d.jl | 138 ++++++---- test/test_p4est_3d.jl | 68 ++--- ...est_paper_self_gravitating_gas_dynamics.jl | 48 ++-- test/test_parabolic_1d.jl | 24 +- test/test_parabolic_2d.jl | 60 ++-- test/test_parabolic_3d.jl | 60 ++-- test/test_structured_1d.jl | 14 +- test/test_structured_2d.jl | 228 +++++++++------ test/test_structured_3d.jl | 24 +- test/test_t8code_2d.jl | 22 +- test/test_t8code_3d.jl | 32 +-- test/test_threaded.jl | 44 +-- test/test_tree_1d_advection.jl | 8 + test/test_tree_1d_euler.jl | 64 ++--- test/test_tree_1d_eulergravity.jl | 4 +- test/test_tree_1d_eulermulti.jl | 8 +- test/test_tree_1d_fdsbp.jl | 16 +- test/test_tree_1d_hypdiff.jl | 4 + test/test_tree_1d_linearizedeuler.jl | 6 +- test/test_tree_1d_mhd.jl | 44 +-- test/test_tree_1d_shallowwater.jl | 56 ++-- test/test_tree_2d_acoustics.jl | 12 +- test/test_tree_2d_advection.jl | 24 ++ test/test_tree_2d_euler.jl | 259 +++++++++++------- test/test_tree_2d_euleracoustics.jl | 4 +- test/test_tree_2d_eulermulti.jl | 40 +-- test/test_tree_2d_eulerpolytropic.jl | 4 +- test/test_tree_2d_fdsbp.jl | 20 +- test/test_tree_2d_hypdiff.jl | 20 +- test/test_tree_2d_linearizedeuler.jl | 8 +- test/test_tree_2d_mhd.jl | 48 ++-- test/test_tree_2d_shallowwater.jl | 44 +-- test/test_tree_3d_euler.jl | 78 +++--- test/test_tree_3d_eulergravity.jl | 4 +- test/test_tree_3d_fdsbp.jl | 12 +- test/test_tree_3d_hypdiff.jl | 24 +- test/test_tree_3d_linearizedeuler.jl | 4 +- test/test_tree_3d_mhd.jl | 28 +- test/test_unit.jl | 10 +- test/test_unstructured_2d.jl | 80 +++--- utils/trixi-format-file.jl | 2 +- utils/trixi-format.jl | 2 +- 101 files changed, 1461 insertions(+), 1093 deletions(-) diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 7297f1c3ff..26006b9555 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -29,7 +29,7 @@ jobs: # TODO: Change the call below to # format(".") run: | - julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.45"))' + julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.60"))' julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])' - name: Format check run: | diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml index 71eea71769..fedf097ec7 100644 --- a/.github/workflows/SpellCheck.yml +++ b/.github/workflows/SpellCheck.yml @@ -10,4 +10,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v4 - name: Check spelling - uses: crate-ci/typos@v1.23.6 + uses: crate-ci/typos@v1.24.3 diff --git a/Project.toml b/Project.toml index f8be84e0ce..612b65ec6f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.8.9-DEV" +version = "0.8.11-DEV" [deps] +Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" @@ -29,6 +30,7 @@ PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" Requires = "ae029012-a4dd-5104-9daa-d747884805df" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" @@ -50,15 +52,16 @@ TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [weakdeps] -Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" [extensions] -TrixiMakieExt = "Makie" TrixiConvexECOSExt = ["Convex", "ECOS"] +TrixiMakieExt = "Makie" [compat] +Accessors = "0.1.12" CodeTracking = "1.0.5" ConstructionBase = "1.3" Convex = "0.16" @@ -87,12 +90,13 @@ PrecompileTools = "1.1" Preferences = "1.3" Printf = "1" RecipesBase = "1.1" +RecursiveArrayTools = "2.38.10" Reexport = "1.0" Requires = "1.1" SciMLBase = "1.90, 2" SimpleUnPack = "1.1" SparseArrays = "1" -StartUpDG = "0.17.7" +StartUpDG = "0.17.7, 1.1.5" Static = "0.8.7" StaticArrayInterface = "1.4" StaticArrays = "1.5" @@ -109,6 +113,6 @@ UUIDs = "1.6" julia = "1.8" [extras] -Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" diff --git a/README.md b/README.md index a76fa26843..5cda16118e 100644 --- a/README.md +++ b/README.md @@ -19,28 +19,6 @@

-*** -**Trixi.jl at JuliaCon 2024**
-At this year's JuliaCon in Eindhoven, Netherlands, we will be present with several contributions -from the Trixi Framework ecosystem: - -* [**Julia for Particle-Based Multiphysics with TrixiParticles.jl**](https://pretalx.com/juliacon2024/talk/TPFF8L/),
- [*Erik Faulhaber*](https://github.com/efaulhaber/), [*Niklas Neher*](https://github.com/lasnikas/), - 10th July 2024, 11:00–11:30, Function (4.1) -* [**Towards Aerodynamic Simulations in Julia with Trixi.jl**](https://pretalx.com/juliacon2024/talk/XH8KBG/),
- [*Daniel Doehring*](https://github.com/danieldoehring/), - 10th July 2024, 15:30–16:00, While Loop (4.2) -* [**libtrixi: serving legacy codes in earth system modeling with fresh Julia CFD**](https://pretalx.com/juliacon2024/talk/SXC7LA/),
- [*Benedict Geihe*](https://github.com/benegee/), - 12th July 2024, 14:00–17:00, Function (4.1) - -The last talk is part of the -[Julia for High-Performance Computing](https://juliacon.org/2024/minisymposia/hpc/) -minisymposium, which this year is hosted by our own [*Hendrik Ranocha*](https://github.com/ranocha/). - -We are looking forward to seeing you there ♥️ -*** - **Trixi.jl** is a numerical simulation framework for conservation laws written in [Julia](https://julialang.org). A key objective for the framework is to be useful to both scientists and students. Therefore, next to diff --git a/docs/literate/src/files/subcell_shock_capturing.jl b/docs/literate/src/files/subcell_shock_capturing.jl index 1b6b19757d..fbc397f4c8 100644 --- a/docs/literate/src/files/subcell_shock_capturing.jl +++ b/docs/literate/src/files/subcell_shock_capturing.jl @@ -51,7 +51,11 @@ # The Newton-bisection algorithm is an iterative method and requires some parameters. # It uses a fixed maximum number of iteration steps (`max_iterations_newton = 10`) and # relative/absolute tolerances (`newton_tolerances = (1.0e-12, 1.0e-14)`). The given values are -# sufficient in most cases and therefore used as default. Additionally, there is the parameter +# sufficient in most cases and therefore used as default. If the implemented bounds checking +# functionality indicates problems with the limiting (see [below](@ref subcell_bounds_check)) +# the Newton method with the chosen parameters might not manage to converge. If so, adapting +# the mentioned parameters helps fix that. +# Additionally, there is the parameter # `gamma_constant_newton`, which can be used to scale the antidiffusive flux for the computation # of the blending coefficients of nonlinear variables. The default value is `2 * ndims(equations)`, # as it was shown by [Pazner (2020)](https://doi.org/10.1016/j.cma.2021.113876) [Section 4.2.2.] @@ -245,7 +249,7 @@ plot(sol) # ![blast_wave_paraview_reinterpolate=false](https://github.com/trixi-framework/Trixi.jl/assets/74359358/39274f18-0064-469c-b4da-bac4b843e116) -# ## Bounds checking +# ## [Bounds checking](@id subcell_bounds_check) # Subcell limiting is based on the fulfillment of target bounds - either global or local. # Although the implementation works and has been thoroughly tested, there are some cases where # these bounds are not met. diff --git a/docs/src/styleguide.md b/docs/src/styleguide.md index 83d4dfee1b..b192d6288c 100644 --- a/docs/src/styleguide.md +++ b/docs/src/styleguide.md @@ -51,7 +51,7 @@ PRs that verify that running JuliaFormatter.jl again will not change the source To format your contributions before created a PR (or, at least, before requesting a review of your PR), you need to install JuliaFormatter.jl first by running ```shell -julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.45"))' +julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.60"))' ``` You can then recursively format the core Julia files in the Trixi.jl repo by executing ```shell diff --git a/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 2f098037a3..c060fef8eb 100644 --- a/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/structured_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -51,7 +51,9 @@ limiter_idp = SubcellLimiterIDP(equations, basis; local_twosided_variables_cons = ["rho"], local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, min)], - max_iterations_newton = 40, # Default value of 10 iterations is too low to fulfill bounds. + # Default parameters are not sufficient to fulfill bounds properly. + max_iterations_newton = 40, + newton_tolerances = (1.0e-13, 1.0e-15), positivity_variables_cons = [], positivity_variables_nonlinear = [], bar_states = false) @@ -97,7 +99,7 @@ save_solution = SaveSolutionCallback(interval = 100, save_final_solution = true, solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl = 0.7) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index d40a6d2b3d..70ee6eaa96 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -44,7 +44,10 @@ limiter_idp = SubcellLimiterIDP(equations, basis; local_twosided_variables_cons = ["rho"], local_onesided_variables_nonlinear = [(Trixi.entropy_math, max)], - bar_states = false) + bar_states = false, + # Default parameters are not sufficient to fulfill bounds properly. + max_iterations_newton = 70, + newton_tolerances = (1.0e-13, 1.0e-14)) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index d00303fe04..8300c36d7e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -45,7 +45,11 @@ limiter_idp = SubcellLimiterIDP(equations, basis; local_twosided_variables_cons = ["rho"], local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, min)], - bar_states = true) + positivity_variables_nonlinear = [pressure], + bar_states = true, + # Default parameters are not sufficient to fulfill bounds properly. + max_iterations_newton = 60) + volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) @@ -54,7 +58,7 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 3, + initial_refinement_level = 5, n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl index e9831c9552..fd25defd41 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl @@ -27,7 +27,6 @@ function (indicator_vortex::IndicatorVortex)(u::AbstractArray{<:Any, 4}, t, kwargs...) mesh = indicator_vortex.cache.mesh alpha = indicator_vortex.cache.alpha - indicator_threaded = indicator_vortex.cache.indicator_threaded resize!(alpha, nelements(dg, cache)) # get analytical vortex center (based on assumption that center=[0.0,0.0] @@ -57,6 +56,11 @@ function periodic_distance_2d(coordinates, center, domain_length) return sqrt(sum(abs2, dx_periodic)) end +# Optional: Nicer display of the indicator +function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorVortex) + Trixi.summary_box(io, "IndicatorVortex") +end + end # module TrixiExtension import .TrixiExtension diff --git a/src/Trixi.jl b/src/Trixi.jl index b6494d797a..6d2b7b74d9 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -18,6 +18,7 @@ module Trixi # Include other packages that are used in Trixi.jl # (standard library packages first, other packages next, all of them sorted alphabetically) +using Accessors: @reset using LinearAlgebra: LinearAlgebra, Diagonal, diag, dot, mul!, norm, cross, normalize, I, UniformScaling, det using Printf: @printf, @sprintf, println diff --git a/src/auxiliary/math.jl b/src/auxiliary/math.jl index fa816da9a1..6ae0958886 100644 --- a/src/auxiliary/math.jl +++ b/src/auxiliary/math.jl @@ -284,6 +284,11 @@ end # when using `@fastmath`, which we also get from # [Fortran](https://godbolt.org/z/Yrsa1js7P) # or [C++](https://godbolt.org/z/674G7Pccv). +# +# Note however that such a custom reimplementation can cause incompatibilities with other +# packages. Currently we are affected by an issue with MPI.jl on ARM, see +# https://github.com/trixi-framework/Trixi.jl/issues/1922 +# The workaround is to resort to Base.min / Base.max when using MPI reductions. """ Trixi.max(x, y, ...) diff --git a/src/callbacks_step/alive.jl b/src/callbacks_step/alive.jl index 9700f7e4cd..fe2234166c 100644 --- a/src/callbacks_step/alive.jl +++ b/src/callbacks_step/alive.jl @@ -45,7 +45,7 @@ function Base.show(io::IO, ::MIME"text/plain", alive_callback = cb.affect! setup = [ - "interval" => alive_callback.alive_interval, + "interval" => alive_callback.alive_interval ] summary_box(io, "AliveCallback", setup) end diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index b0afd02aff..155e909e29 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -243,6 +243,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @unpack to_refine, to_coarsen = amr_callback.amr_cache empty!(to_refine) empty!(to_coarsen) + # Note: This assumes that the entries of `lambda` are sorted with ascending cell ids for element in eachindex(lambda) controller_value = lambda[element] if controller_value > 0 @@ -395,6 +396,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @unpack to_refine, to_coarsen = amr_callback.amr_cache empty!(to_refine) empty!(to_coarsen) + # Note: This assumes that the entries of `lambda` are sorted with ascending cell ids for element in eachindex(lambda) controller_value = lambda[element] if controller_value > 0 diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index 860e3fa21d..06110d08d2 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -434,7 +434,8 @@ function (analysis_callback::AnalysisCallback)(io, du, u, u_ode, t, semi) res = maximum(abs, view(du, v, ..)) if mpi_isparallel() # TODO: Debugging, here is a type instability - global_res = MPI.Reduce!(Ref(res), max, mpi_root(), mpi_comm()) + # Base.max instead of max needed, see comment in src/auxiliary/math.jl + global_res = MPI.Reduce!(Ref(res), Base.max, mpi_root(), mpi_comm()) if mpi_isroot() res::eltype(du) = global_res[] end diff --git a/src/callbacks_step/analysis_dg2d.jl b/src/callbacks_step/analysis_dg2d.jl index de6b9a2a4a..4cd92ce7c5 100644 --- a/src/callbacks_step/analysis_dg2d.jl +++ b/src/callbacks_step/analysis_dg2d.jl @@ -29,10 +29,39 @@ function create_cache_analysis(analyzer, mesh::TreeMesh{2}, return (; u_local, u_tmp1, x_local, x_tmp1) end +# Specialized cache for P4estMesh to allow for different ambient dimension from mesh dimension +function create_cache_analysis(analyzer, mesh::P4estMesh{2, NDIMS_AMBIENT}, + equations, dg::DG, cache, + RealT, uEltype) where {NDIMS_AMBIENT} + + # pre-allocate buffers + # We use `StrideArray`s here since these buffers are used in performance-critical + # places and the additional information passed to the compiler makes them faster + # than native `Array`s. + u_local = StrideArray(undef, uEltype, + StaticInt(nvariables(equations)), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer))) + u_tmp1 = StrideArray(undef, uEltype, + StaticInt(nvariables(equations)), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(dg))) + x_local = StrideArray(undef, RealT, + StaticInt(NDIMS_AMBIENT), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer))) + x_tmp1 = StrideArray(undef, RealT, + StaticInt(NDIMS_AMBIENT), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(dg))) + jacobian_local = StrideArray(undef, RealT, + StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer))) + jacobian_tmp1 = StrideArray(undef, RealT, + StaticInt(nnodes(analyzer)), StaticInt(nnodes(dg))) + + return (; u_local, u_tmp1, x_local, x_tmp1, jacobian_local, jacobian_tmp1) +end + function create_cache_analysis(analyzer, mesh::Union{StructuredMesh{2}, StructuredMeshView{2}, - UnstructuredMesh2D, - P4estMesh{2}, T8codeMesh{2}}, + UnstructuredMesh2D, T8codeMesh{2}}, equations, dg::DG, cache, RealT, uEltype) diff --git a/src/callbacks_step/analysis_dg2d_parallel.jl b/src/callbacks_step/analysis_dg2d_parallel.jl index 000daa015d..5b3ae858ab 100644 --- a/src/callbacks_step/analysis_dg2d_parallel.jl +++ b/src/callbacks_step/analysis_dg2d_parallel.jl @@ -131,7 +131,8 @@ function calc_error_norms(func, u, t, analyzer, global_l2_error = Vector(l2_error) global_linf_error = Vector(linf_error) MPI.Reduce!(global_l2_error, +, mpi_root(), mpi_comm()) - MPI.Reduce!(global_linf_error, max, mpi_root(), mpi_comm()) + # Base.max instead of max needed, see comment in src/auxiliary/math.jl + MPI.Reduce!(global_linf_error, Base.max, mpi_root(), mpi_comm()) total_volume = MPI.Reduce(volume, +, mpi_root(), mpi_comm()) if mpi_isroot() l2_error = convert(typeof(l2_error), global_l2_error) diff --git a/src/callbacks_step/analysis_dg3d.jl b/src/callbacks_step/analysis_dg3d.jl index 27e8a2b722..fd501a7257 100644 --- a/src/callbacks_step/analysis_dg3d.jl +++ b/src/callbacks_step/analysis_dg3d.jl @@ -35,9 +35,51 @@ function create_cache_analysis(analyzer, mesh::TreeMesh{3}, return (; u_local, u_tmp1, u_tmp2, x_local, x_tmp1, x_tmp2) end +# Specialized cache for P4estMesh to allow for different ambient dimension from mesh dimension function create_cache_analysis(analyzer, - mesh::Union{StructuredMesh{3}, P4estMesh{3}, - T8codeMesh{3}}, + mesh::P4estMesh{3, NDIMS_AMBIENT}, + equations, dg::DG, cache, + RealT, uEltype) where {NDIMS_AMBIENT} + + # pre-allocate buffers + # We use `StrideArray`s here since these buffers are used in performance-critical + # places and the additional information passed to the compiler makes them faster + # than native `Array`s. + u_local = StrideArray(undef, uEltype, + StaticInt(nvariables(equations)), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), StaticInt(nnodes(analyzer))) + u_tmp1 = StrideArray(undef, uEltype, + StaticInt(nvariables(equations)), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(dg)), StaticInt(nnodes(dg))) + u_tmp2 = StrideArray(undef, uEltype, + StaticInt(nvariables(equations)), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), StaticInt(nnodes(dg))) + x_local = StrideArray(undef, RealT, + StaticInt(NDIMS_AMBIENT), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), StaticInt(nnodes(analyzer))) + x_tmp1 = StrideArray(undef, RealT, + StaticInt(NDIMS_AMBIENT), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(dg)), StaticInt(nnodes(dg))) + x_tmp2 = StrideArray(undef, RealT, + StaticInt(NDIMS_AMBIENT), StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), StaticInt(nnodes(dg))) + jacobian_local = StrideArray(undef, RealT, + StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer))) + jacobian_tmp1 = StrideArray(undef, RealT, + StaticInt(nnodes(analyzer)), StaticInt(nnodes(dg)), + StaticInt(nnodes(dg))) + jacobian_tmp2 = StrideArray(undef, RealT, + StaticInt(nnodes(analyzer)), + StaticInt(nnodes(analyzer)), StaticInt(nnodes(dg))) + + return (; u_local, u_tmp1, u_tmp2, x_local, x_tmp1, x_tmp2, jacobian_local, + jacobian_tmp1, jacobian_tmp2) +end + +function create_cache_analysis(analyzer, + mesh::Union{StructuredMesh{3}, T8codeMesh{3}}, equations, dg::DG, cache, RealT, uEltype) diff --git a/src/callbacks_step/analysis_dg3d_parallel.jl b/src/callbacks_step/analysis_dg3d_parallel.jl index de777be406..70a616367c 100644 --- a/src/callbacks_step/analysis_dg3d_parallel.jl +++ b/src/callbacks_step/analysis_dg3d_parallel.jl @@ -49,7 +49,8 @@ function calc_error_norms(func, u, t, analyzer, global_l2_error = Vector(l2_error) global_linf_error = Vector(linf_error) MPI.Reduce!(global_l2_error, +, mpi_root(), mpi_comm()) - MPI.Reduce!(global_linf_error, max, mpi_root(), mpi_comm()) + # Base.max instead of max needed, see comment in src/auxiliary/math.jl + MPI.Reduce!(global_linf_error, Base.max, mpi_root(), mpi_comm()) total_volume = MPI.Reduce(volume, +, mpi_root(), mpi_comm()) if mpi_isroot() l2_error = convert(typeof(l2_error), global_l2_error) diff --git a/src/callbacks_step/averaging.jl b/src/callbacks_step/averaging.jl index efa71af9b9..d23abe2869 100644 --- a/src/callbacks_step/averaging.jl +++ b/src/callbacks_step/averaging.jl @@ -45,7 +45,7 @@ function Base.show(io::IO, ::MIME"text/plain", setup = [ "Start time" => first(averaging_callback.tspan), - "Final time" => last(averaging_callback.tspan), + "Final time" => last(averaging_callback.tspan) ] summary_box(io, "AveragingCallback", setup) end diff --git a/src/callbacks_step/glm_speed.jl b/src/callbacks_step/glm_speed.jl index 8ee406af5f..0bd87c189b 100644 --- a/src/callbacks_step/glm_speed.jl +++ b/src/callbacks_step/glm_speed.jl @@ -48,7 +48,7 @@ function Base.show(io::IO, ::MIME"text/plain", setup = [ "GLM wave speed scaling" => glm_speed_callback.glm_scale, "Expected CFL number" => glm_speed_callback.cfl, - "Selected semidiscretizations" => glm_speed_callback.semi_indices, + "Selected semidiscretizations" => glm_speed_callback.semi_indices ] summary_box(io, "GlmSpeedCallback", setup) end @@ -83,7 +83,10 @@ function update_cleaning_speed!(semi, glm_speed_callback, dt) c_h_deltat = calc_dt_for_cleaning_speed(cfl, mesh, equations, solver, cache) # c_h is proportional to its own time step divided by the complete MHD time step - equations.c_h = glm_scale * c_h_deltat / dt + # We use @reset here since the equations are immutable (to work on GPUs etc.). + # Thus, we need to modify the equations field of the semidiscretization. + @reset equations.c_h = glm_scale * c_h_deltat / dt + semi.equations = equations return semi end diff --git a/src/callbacks_step/save_restart.jl b/src/callbacks_step/save_restart.jl index 0b0d2420c7..181d985a68 100644 --- a/src/callbacks_step/save_restart.jl +++ b/src/callbacks_step/save_restart.jl @@ -38,7 +38,7 @@ function Base.show(io::IO, ::MIME"text/plain", "interval" => save_restart_callback.interval, "save final solution" => save_restart_callback.save_final_restart ? "yes" : "no", - "output directory" => abspath(normpath(save_restart_callback.output_directory)), + "output directory" => abspath(normpath(save_restart_callback.output_directory)) ] summary_box(io, "SaveRestartCallback", setup) end diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 870cea0b9f..3f9abef7f3 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -62,7 +62,7 @@ function Base.show(io::IO, ::MIME"text/plain", "yes" : "no", "save final solution" => save_solution_callback.save_final_solution ? "yes" : "no", - "output directory" => abspath(normpath(save_solution_callback.output_directory)), + "output directory" => abspath(normpath(save_solution_callback.output_directory)) ] summary_box(io, "SaveSolutionCallback", setup) end @@ -85,7 +85,7 @@ function Base.show(io::IO, ::MIME"text/plain", "yes" : "no", "save final solution" => save_solution_callback.save_final_solution ? "yes" : "no", - "output directory" => abspath(normpath(save_solution_callback.output_directory)), + "output directory" => abspath(normpath(save_solution_callback.output_directory)) ] summary_box(io, "SaveSolutionCallback", setup) end diff --git a/src/callbacks_step/steady_state.jl b/src/callbacks_step/steady_state.jl index 15c2e83428..7085d05394 100644 --- a/src/callbacks_step/steady_state.jl +++ b/src/callbacks_step/steady_state.jl @@ -43,7 +43,7 @@ function Base.show(io::IO, ::MIME"text/plain", setup = [ "absolute tolerance" => steady_state_callback.abstol, - "relative tolerance" => steady_state_callback.reltol, + "relative tolerance" => steady_state_callback.reltol ] summary_box(io, "SteadyStateCallback", setup) end diff --git a/src/callbacks_step/stepsize.jl b/src/callbacks_step/stepsize.jl index 5c11494ac9..75faa400de 100644 --- a/src/callbacks_step/stepsize.jl +++ b/src/callbacks_step/stepsize.jl @@ -33,7 +33,7 @@ function Base.show(io::IO, ::MIME"text/plain", stepsize_callback = cb.affect! setup = [ - "CFL number" => stepsize_callback.cfl_number, + "CFL number" => stepsize_callback.cfl_number ] summary_box(io, "StepsizeCallback", setup) end diff --git a/src/callbacks_step/stepsize_dg2d.jl b/src/callbacks_step/stepsize_dg2d.jl index 709f3cee13..9eb6f2e81e 100644 --- a/src/callbacks_step/stepsize_dg2d.jl +++ b/src/callbacks_step/stepsize_dg2d.jl @@ -156,7 +156,8 @@ function max_dt(u, t, mesh::ParallelTreeMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -172,7 +173,8 @@ function max_dt(u, t, mesh::ParallelTreeMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -256,7 +258,8 @@ function max_dt(u, t, mesh::ParallelP4estMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -272,7 +275,8 @@ function max_dt(u, t, mesh::ParallelP4estMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -288,7 +292,8 @@ function max_dt(u, t, mesh::ParallelT8codeMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -304,7 +309,8 @@ function max_dt(u, t, mesh::ParallelT8codeMesh{2}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end diff --git a/src/callbacks_step/stepsize_dg3d.jl b/src/callbacks_step/stepsize_dg3d.jl index 664596f989..49976de650 100644 --- a/src/callbacks_step/stepsize_dg3d.jl +++ b/src/callbacks_step/stepsize_dg3d.jl @@ -130,7 +130,8 @@ function max_dt(u, t, mesh::ParallelP4estMesh{3}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -146,7 +147,8 @@ function max_dt(u, t, mesh::ParallelP4estMesh{3}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -162,7 +164,8 @@ function max_dt(u, t, mesh::ParallelT8codeMesh{3}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end @@ -178,7 +181,8 @@ function max_dt(u, t, mesh::ParallelT8codeMesh{3}, typeof(constant_speed), typeof(equations), typeof(dg), typeof(cache)}, u, t, mesh, constant_speed, equations, dg, cache) - dt = MPI.Allreduce!(Ref(dt), min, mpi_comm())[] + # Base.min instead of min needed, see comment in src/auxiliary/math.jl + dt = MPI.Allreduce!(Ref(dt), Base.min, mpi_comm())[] return dt end diff --git a/src/callbacks_step/time_series.jl b/src/callbacks_step/time_series.jl index ae18c85700..d3c9861d33 100644 --- a/src/callbacks_step/time_series.jl +++ b/src/callbacks_step/time_series.jl @@ -72,7 +72,7 @@ function Base.show(io::IO, ::MIME"text/plain", "interval" => time_series_callback.interval, "solution_variables" => time_series_callback.solution_variables, "output_directory" => time_series_callback.output_directory, - "filename" => time_series_callback.filename, + "filename" => time_series_callback.filename ] summary_box(io, "TimeSeriesCallback", setup) end diff --git a/src/callbacks_step/visualization.jl b/src/callbacks_step/visualization.jl index f91fe27bd3..302e7e4462 100644 --- a/src/callbacks_step/visualization.jl +++ b/src/callbacks_step/visualization.jl @@ -50,7 +50,7 @@ function Base.show(io::IO, ::MIME"text/plain", "variable names" => visualization_callback.variable_names, "show mesh" => visualization_callback.show_mesh, "plot creator" => visualization_callback.plot_creator, - "plot data creator" => visualization_callback.plot_data_creator, + "plot data creator" => visualization_callback.plot_data_creator ] summary_box(io, "VisualizationCallback", setup) end diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index ab2a4b066a..7a6d19facd 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -11,8 +11,8 @@ The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats `gamma` in two space dimensions. """ -mutable struct IdealGlmMhdEquations2D{RealT <: Real} <: - AbstractIdealGlmMhdEquations{2, 9} +struct IdealGlmMhdEquations2D{RealT <: Real} <: + AbstractIdealGlmMhdEquations{2, 9} gamma::RealT # ratio of specific heats inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications c_h::RealT # GLM cleaning speed @@ -28,6 +28,11 @@ function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN) IdealGlmMhdEquations2D(promote(gamma, initial_c_h)...) end +# Outer constructor for `@reset` works correctly +function IdealGlmMhdEquations2D(gamma, inv_gamma_minus_one, c_h) + IdealGlmMhdEquations2D(gamma, c_h) +end + have_nonconservative_terms(::IdealGlmMhdEquations2D) = True() n_nonconservative_terms(::IdealGlmMhdEquations2D) = 2 diff --git a/src/equations/ideal_glm_mhd_3d.jl b/src/equations/ideal_glm_mhd_3d.jl index 2ffaa57524..e922a2e6fd 100644 --- a/src/equations/ideal_glm_mhd_3d.jl +++ b/src/equations/ideal_glm_mhd_3d.jl @@ -11,8 +11,8 @@ The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats `gamma` in three space dimensions. """ -mutable struct IdealGlmMhdEquations3D{RealT <: Real} <: - AbstractIdealGlmMhdEquations{3, 9} +struct IdealGlmMhdEquations3D{RealT <: Real} <: + AbstractIdealGlmMhdEquations{3, 9} gamma::RealT # ratio of specific heats inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications c_h::RealT # GLM cleaning speed @@ -28,6 +28,11 @@ function IdealGlmMhdEquations3D(gamma; initial_c_h = convert(typeof(gamma), NaN) IdealGlmMhdEquations3D(promote(gamma, initial_c_h)...) end +# Outer constructor for `@reset` works correctly +function IdealGlmMhdEquations3D(gamma, inv_gamma_minus_one, c_h) + IdealGlmMhdEquations3D(gamma, c_h) +end + have_nonconservative_terms(::IdealGlmMhdEquations3D) = True() function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations3D) ("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3", "psi") diff --git a/src/equations/ideal_glm_mhd_multicomponent_1d.jl b/src/equations/ideal_glm_mhd_multicomponent_1d.jl index b2ed06e53e..86a69e9fe1 100644 --- a/src/equations/ideal_glm_mhd_multicomponent_1d.jl +++ b/src/equations/ideal_glm_mhd_multicomponent_1d.jl @@ -10,8 +10,8 @@ The ideal compressible multicomponent GLM-MHD equations in one space dimension. """ -mutable struct IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT <: Real} <: - AbstractIdealGlmMhdMulticomponentEquations{1, NVARS, NCOMP} +struct IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT <: Real} <: + AbstractIdealGlmMhdMulticomponentEquations{1, NVARS, NCOMP} gammas::SVector{NCOMP, RealT} gas_constants::SVector{NCOMP, RealT} cv::SVector{NCOMP, RealT} @@ -51,6 +51,11 @@ function IdealGlmMhdMulticomponentEquations1D(; gammas, gas_constants) __gas_constants) end +# Outer constructor for `@reset` works correctly +function IdealGlmMhdMulticomponentEquations1D(gammas, gas_constants, cv, cp, c_h) + IdealGlmMhdMulticomponentEquations1D(gammas = gammas, gas_constants = gas_constants) +end + @inline function Base.real(::IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}) where { NVARS, NCOMP, diff --git a/src/equations/ideal_glm_mhd_multicomponent_2d.jl b/src/equations/ideal_glm_mhd_multicomponent_2d.jl index 3aab048bd9..c56294b664 100644 --- a/src/equations/ideal_glm_mhd_multicomponent_2d.jl +++ b/src/equations/ideal_glm_mhd_multicomponent_2d.jl @@ -10,8 +10,8 @@ The ideal compressible multicomponent GLM-MHD equations in two space dimensions. """ -mutable struct IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT <: Real} <: - AbstractIdealGlmMhdMulticomponentEquations{2, NVARS, NCOMP} +struct IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT <: Real} <: + AbstractIdealGlmMhdMulticomponentEquations{2, NVARS, NCOMP} gammas::SVector{NCOMP, RealT} gas_constants::SVector{NCOMP, RealT} cv::SVector{NCOMP, RealT} @@ -21,18 +21,18 @@ mutable struct IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT <: Real} function IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP, RealT}, gas_constants::SVector{NCOMP, - RealT}) where { - NVARS, - NCOMP, - RealT <: - Real - } + RealT}, + c_h::RealT) where { + NVARS, + NCOMP, + RealT <: + Real + } NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value")) cv = gas_constants ./ (gammas .- 1) cp = gas_constants + gas_constants ./ (gammas .- 1) - c_h = convert(eltype(gammas), NaN) new(gammas, gas_constants, cv, cp, c_h) end @@ -49,8 +49,30 @@ function IdealGlmMhdMulticomponentEquations2D(; gammas, gas_constants) __gammas = SVector(map(RealT, _gammas)) __gas_constants = SVector(map(RealT, _gas_constants)) + c_h = convert(RealT, NaN) + + return IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}(__gammas, + __gas_constants, + c_h) +end + +# Outer constructor for `@reset` works correctly +function IdealGlmMhdMulticomponentEquations2D(gammas, gas_constants, cv, cp, c_h) + _gammas = promote(gammas...) + _gas_constants = promote(gas_constants...) + RealT = promote_type(eltype(_gammas), eltype(_gas_constants)) + + NVARS = length(_gammas) + 8 + NCOMP = length(_gammas) + + __gammas = SVector(map(RealT, _gammas)) + __gas_constants = SVector(map(RealT, _gas_constants)) + + c_h = convert(RealT, c_h) + return IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}(__gammas, - __gas_constants) + __gas_constants, + c_h) end @inline function Base.real(::IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}) where { diff --git a/src/meshes/p4est_mesh.jl b/src/meshes/p4est_mesh.jl index 526f5d9f23..65c0a431b2 100644 --- a/src/meshes/p4est_mesh.jl +++ b/src/meshes/p4est_mesh.jl @@ -6,12 +6,23 @@ #! format: noindent """ - P4estMesh{NDIMS} <: AbstractMesh{NDIMS} + P4estMesh{NDIMS, NDIMS_AMBIENT} <: AbstractMesh{NDIMS} An unstructured curved mesh based on trees that uses the C library `p4est` to manage trees and mesh refinement. + +The parameter `NDIMS` denotes the dimension of the spatial domain or manifold represented +by the mesh itself, while `NDIMS_AMBIENT` denotes the dimension of the ambient space in +which the mesh is embedded. For example, the type `P4estMesh{3, 3}` corresponds to a +standard mesh for a three-dimensional volume, whereas `P4estMesh{2, 3}` corresponds to a +mesh for a two-dimensional surface or shell in three-dimensional space. + +!!! warning "Experimental implementation" + The use of `NDIMS != NDIMS_AMBIENT` is an experimental feature and may change in future + releases. """ -mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NNODES} <: +mutable struct P4estMesh{NDIMS, NDIMS_AMBIENT, RealT <: Real, IsParallel, P, Ghost, + NDIMSP2, NNODES} <: AbstractMesh{NDIMS} p4est :: P # Either PointerWrapper{p4est_t} or PointerWrapper{p8est_t} is_parallel :: IsParallel @@ -48,7 +59,14 @@ mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NN ghost = ghost_new_p4est(p4est) ghost_pw = PointerWrapper(ghost) - mesh = new{NDIMS, eltype(tree_node_coordinates), typeof(is_parallel), + # To enable the treatment of a manifold of dimension NDIMS embedded within an + # ambient space of dimension NDIMS_AMBIENT, we store both as type parameters and + # allow them to differ in the general case. This functionality is used for + # constructing discretizations on spherical shell domains for applications in + # global atmospheric modelling. The ambient dimension NDIMS_AMBIENT is therefore + # set here in the inner constructor to size(tree_node_coordinates, 1). + mesh = new{NDIMS, size(tree_node_coordinates, 1), + eltype(tree_node_coordinates), typeof(is_parallel), typeof(p4est_pw), typeof(ghost_pw), NDIMS + 2, length(nodes)}(p4est_pw, is_parallel, ghost_pw, @@ -66,8 +84,8 @@ mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NN end end -const SerialP4estMesh{NDIMS} = P4estMesh{NDIMS, <:Real, <:False} -const ParallelP4estMesh{NDIMS} = P4estMesh{NDIMS, <:Real, <:True} +const SerialP4estMesh{NDIMS} = P4estMesh{NDIMS, <:Any, <:Real, <:False} +const ParallelP4estMesh{NDIMS} = P4estMesh{NDIMS, <:Any, <:Real, <:True} @inline mpi_parallel(mesh::SerialP4estMesh) = False() @inline mpi_parallel(mesh::ParallelP4estMesh) = True() @@ -87,7 +105,8 @@ function destroy_mesh(mesh::P4estMesh{3}) end @inline Base.ndims(::P4estMesh{NDIMS}) where {NDIMS} = NDIMS -@inline Base.real(::P4estMesh{NDIMS, RealT}) where {NDIMS, RealT} = RealT +@inline Base.real(::P4estMesh{NDIMS, NDIMS_AMBIENT, RealT}) where {NDIMS, NDIMS_AMBIENT, RealT} = RealT +@inline ndims_ambient(::P4estMesh{NDIMS, NDIMS_AMBIENT}) where {NDIMS, NDIMS_AMBIENT} = NDIMS_AMBIENT @inline function ntrees(mesh::P4estMesh) return mesh.p4est.trees.elem_count[] @@ -97,7 +116,8 @@ end @inline ncellsglobal(mesh::P4estMesh) = Int(mesh.p4est.global_num_quadrants[]) function Base.show(io::IO, mesh::P4estMesh) - print(io, "P4estMesh{", ndims(mesh), ", ", real(mesh), "}") + print(io, "P4estMesh{", ndims(mesh), ", ", ndims_ambient(mesh), ", ", real(mesh), + "}") end function Base.show(io::IO, ::MIME"text/plain", mesh::P4estMesh) @@ -107,11 +127,12 @@ function Base.show(io::IO, ::MIME"text/plain", mesh::P4estMesh) setup = [ "#trees" => ntrees(mesh), "current #cells" => ncellsglobal(mesh), - "polydeg" => length(mesh.nodes) - 1, + "polydeg" => length(mesh.nodes) - 1 ] summary_box(io, - "P4estMesh{" * string(ndims(mesh)) * ", " * string(real(mesh)) * - "}", setup) + "P4estMesh{" * string(ndims(mesh)) * ", " * + string(ndims_ambient(mesh)) * + ", " * string(real(mesh)) * "}", setup) end end diff --git a/src/meshes/parallel_tree.jl b/src/meshes/parallel_tree.jl index 83d99c4d11..7175ed4774 100644 --- a/src/meshes/parallel_tree.jl +++ b/src/meshes/parallel_tree.jl @@ -23,7 +23,7 @@ # # An exception to the 2:1 rule exists for the low-level `refine_unbalanced!` # function, which is required for implementing level-wise refinement in a sane -# way. Also, depth-first ordering *might* not by guaranteed during +# way. Also, depth-first ordering *might* not be guaranteed during # refinement/coarsening operations. mutable struct ParallelTree{NDIMS} <: AbstractTree{NDIMS} parent_ids::Vector{Int} diff --git a/src/meshes/parallel_tree_mesh.jl b/src/meshes/parallel_tree_mesh.jl index 050e419680..2b1f137755 100644 --- a/src/meshes/parallel_tree_mesh.jl +++ b/src/meshes/parallel_tree_mesh.jl @@ -20,8 +20,8 @@ function partition!(mesh::ParallelTreeMesh; allow_coarsening = true) n_leaves_per_rank = OffsetArray(fill(div(length(leaves), mpi_nranks()), mpi_nranks()), 0:(mpi_nranks() - 1)) - for d in 0:(rem(length(leaves), mpi_nranks()) - 1) - n_leaves_per_rank[d] += 1 + for rank in 0:(rem(length(leaves), mpi_nranks()) - 1) + n_leaves_per_rank[rank] += 1 end @assert sum(n_leaves_per_rank) == length(leaves) @@ -31,17 +31,20 @@ function partition!(mesh::ParallelTreeMesh; allow_coarsening = true) mesh.n_cells_by_rank = similar(n_leaves_per_rank) leaf_count = 0 + # Assign first cell to rank 0 (employ depth-first indexing of cells) mesh.first_cell_by_rank[0] = 1 # Iterate over all ranks - for d in 0:(mpi_nranks() - 1) - leaf_count += n_leaves_per_rank[d] + for rank in 0:(mpi_nranks() - 1) + leaf_count += n_leaves_per_rank[rank] last_id = leaves[leaf_count] parent_id = mesh.tree.parent_ids[last_id] - # Check if all children of the last parent are leaves + # If coarsening is allowed, we need to make sure that parents of leaves + # are on the same rank as the leaves when coarsened. if allow_coarsening && + # Check if all children of the last parent are leaves all(id -> is_leaf(mesh.tree, id), @view mesh.tree.child_ids[:, parent_id]) && - d < length(n_leaves_per_rank) - 1 + rank < length(n_leaves_per_rank) - 1 # Make sure there is another rank # To keep children of parent together if they are all leaves, # all children are added to this rank @@ -53,20 +56,21 @@ function partition!(mesh::ParallelTreeMesh; allow_coarsening = true) additional_cells) leaf_count += additional_leaves # Add leaves to this rank, remove from next rank - n_leaves_per_rank[d] += additional_leaves - n_leaves_per_rank[d + 1] -= additional_leaves + n_leaves_per_rank[rank] += additional_leaves + n_leaves_per_rank[rank + 1] -= additional_leaves end end @assert all(n -> n > 0, n_leaves_per_rank) "Too many ranks to properly partition the mesh!" - mesh.n_cells_by_rank[d] = last_id - mesh.first_cell_by_rank[d] + 1 - mesh.tree.mpi_ranks[mesh.first_cell_by_rank[d]:last_id] .= d + mesh.n_cells_by_rank[rank] = last_id - mesh.first_cell_by_rank[rank] + 1 + # Use depth-first indexing of cells again to assign also non leaf cells + mesh.tree.mpi_ranks[mesh.first_cell_by_rank[rank]:last_id] .= rank # Set first cell of next rank - if d < length(n_leaves_per_rank) - 1 - mesh.first_cell_by_rank[d + 1] = mesh.first_cell_by_rank[d] + - mesh.n_cells_by_rank[d] + if rank < length(n_leaves_per_rank) - 1 # Make sure there is another rank + mesh.first_cell_by_rank[rank + 1] = mesh.first_cell_by_rank[rank] + + mesh.n_cells_by_rank[rank] end end diff --git a/src/meshes/t8code_mesh.jl b/src/meshes/t8code_mesh.jl index 9b0e0b741a..231e296566 100644 --- a/src/meshes/t8code_mesh.jl +++ b/src/meshes/t8code_mesh.jl @@ -93,7 +93,7 @@ function Base.show(io::IO, ::MIME"text/plain", mesh::T8codeMesh) setup = [ "#trees" => ntrees(mesh), "current #cells" => ncellsglobal(mesh), - "polydeg" => length(mesh.nodes) - 1, + "polydeg" => length(mesh.nodes) - 1 ] summary_box(io, "T8codeMesh{" * string(ndims(mesh)) * ", " * string(real(mesh)) * "}", @@ -982,7 +982,7 @@ function fill_mesh_info!(mesh::T8codeMesh, interfaces, mortars, boundaries, [1, 2, 0, 0, 3, 4, 0, 0], # 2 [0, 0, 1, 2, 0, 0, 3, 4], # 3 [1, 2, 3, 4, 0, 0, 0, 0], # 4 - [0, 0, 0, 0, 1, 2, 3, 4], # 5 + [0, 0, 0, 0, 1, 2, 3, 4] # 5 ] # Helper variables to compute unique global MPI interface/mortar ids. @@ -1235,10 +1235,10 @@ function fill_mesh_info!(mesh::T8codeMesh, interfaces, mortars, boundaries, global_mortar_id_to_local[global_mortar_id] = local_mpi_mortar_id mpi_mesh_info.mpi_mortars.local_neighbor_ids[local_mpi_mortar_id] = [ - current_index + 1, + current_index + 1 ] mpi_mesh_info.mpi_mortars.local_neighbor_positions[local_mpi_mortar_id] = [ - map_iface_to_ichild_to_position[iface + 1][t8_element_child_id(eclass_scheme, element) + 1], + map_iface_to_ichild_to_position[iface + 1][t8_element_child_id(eclass_scheme, element) + 1] ] init_mortar_node_indices!(mpi_mesh_info.mpi_mortars, (iface, dual_faces[1]), @@ -1246,7 +1246,7 @@ function fill_mesh_info!(mesh::T8codeMesh, interfaces, mortars, boundaries, neighbor_ranks = [ remotes[findlast(ghost_remote_first_elem .<= - neighbor_ielements[1])], + neighbor_ielements[1])] ] mpi_mesh_info.neighbor_ranks_mortar[local_mpi_mortar_id] = neighbor_ranks diff --git a/src/meshes/tree_mesh.jl b/src/meshes/tree_mesh.jl index 1092fc54cc..933bfa6272 100644 --- a/src/meshes/tree_mesh.jl +++ b/src/meshes/tree_mesh.jl @@ -200,7 +200,7 @@ function Base.show(io::IO, ::MIME"text/plain", "periodicity" => mesh.tree.periodicity, "current #cells" => mesh.tree.length, "#leaf-cells" => count_leaf_cells(mesh.tree), - "maximum #cells" => mesh.tree.capacity, + "maximum #cells" => mesh.tree.capacity ] summary_box(io, "TreeMesh{" * string(NDIMS) * ", " * string(TreeType) * "}", setup) diff --git a/src/semidiscretization/semidiscretization_coupled.jl b/src/semidiscretization/semidiscretization_coupled.jl index 7c1fbef972..745a8d3f6f 100644 --- a/src/semidiscretization/semidiscretization_coupled.jl +++ b/src/semidiscretization/semidiscretization_coupled.jl @@ -16,7 +16,8 @@ The semidiscretizations can be coupled by gluing meshes together using [`Boundar !!! warning "Experimental code" This is an experimental feature and can change any time. """ -struct SemidiscretizationCoupled{S, Indices, EquationList} <: AbstractSemidiscretization +mutable struct SemidiscretizationCoupled{S, Indices, EquationList} <: + AbstractSemidiscretization semis::S u_indices::Indices # u_ode[u_indices[i]] is the part of u_ode corresponding to semis[i] performance_counter::PerformanceCounter @@ -383,7 +384,10 @@ function update_cleaning_speed!(semi_coupled::SemidiscretizationCoupled, c_h_deltat = calc_dt_for_cleaning_speed(cfl, mesh, equations, solver, cache) # c_h is proportional to its own time step divided by the complete MHD time step - equations.c_h = glm_scale * c_h_deltat / dt + # We use @reset here since the equations are immutable (to work on GPUs etc.). + # Thus, we need to modify the equations field of the semidiscretization. + @reset equations.c_h = glm_scale * c_h_deltat / dt + semi.equations = equations end return semi_coupled diff --git a/src/semidiscretization/semidiscretization_euler_gravity.jl b/src/semidiscretization/semidiscretization_euler_gravity.jl index 4201344df8..97524fb505 100644 --- a/src/semidiscretization/semidiscretization_euler_gravity.jl +++ b/src/semidiscretization/semidiscretization_euler_gravity.jl @@ -59,7 +59,7 @@ function Base.show(io::IO, ::MIME"text/plain", parameters::ParametersEulerGravit "gravitational constant (G)" => parameters.gravitational_constant, "CFL (gravity)" => parameters.cfl, "max. #iterations" => parameters.n_iterations_max, - "time integrator" => parameters.timestep_gravity, + "time integrator" => parameters.timestep_gravity ] summary_box(io, "ParametersEulerGravity", setup) end diff --git a/src/semidiscretization/semidiscretization_hyperbolic.jl b/src/semidiscretization/semidiscretization_hyperbolic.jl index e35c0e2ea9..6c6aa5b457 100644 --- a/src/semidiscretization/semidiscretization_hyperbolic.jl +++ b/src/semidiscretization/semidiscretization_hyperbolic.jl @@ -11,10 +11,10 @@ A struct containing everything needed to describe a spatial semidiscretization of a hyperbolic conservation law. """ -struct SemidiscretizationHyperbolic{Mesh, Equations, InitialCondition, - BoundaryConditions, - SourceTerms, Solver, Cache} <: - AbstractSemidiscretization +mutable struct SemidiscretizationHyperbolic{Mesh, Equations, InitialCondition, + BoundaryConditions, + SourceTerms, Solver, Cache} <: + AbstractSemidiscretization mesh::Mesh equations::Equations diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index b7f4980a75..0d9be65e75 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -86,7 +86,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralFluxDiffe show(io, integral) else setup = [ - "volume flux" => integral.volume_flux, + "volume flux" => integral.volume_flux ] summary_box(io, "VolumeIntegralFluxDifferencing", setup) end @@ -178,7 +178,7 @@ function Base.show(io::IO, ::MIME"text/plain", show(io, integral) else setup = [ - "FV flux" => integral.volume_flux_fv, + "FV flux" => integral.volume_flux_fv ] summary_box(io, "VolumeIntegralPureLGLFiniteVolume", setup) end @@ -287,7 +287,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::VolumeIntegralUpwind) show(io, integral) else setup = [ - "flux splitting" => integral.splitting, + "flux splitting" => integral.splitting ] summary_box(io, "VolumeIntegralUpwind", setup) end @@ -327,7 +327,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::SurfaceIntegralWeakForm show(io, integral) else setup = [ - "surface flux" => integral.surface_flux, + "surface flux" => integral.surface_flux ] summary_box(io, "SurfaceIntegralWeakForm", setup) end @@ -353,7 +353,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::SurfaceIntegralStrongFo show(io, integral) else setup = [ - "surface flux" => integral.surface_flux, + "surface flux" => integral.surface_flux ] summary_box(io, "SurfaceIntegralStrongForm", setup) end @@ -384,7 +384,7 @@ function Base.show(io::IO, ::MIME"text/plain", integral::SurfaceIntegralUpwind) show(io, integral) else setup = [ - "flux splitting" => integral.splitting, + "flux splitting" => integral.splitting ] summary_box(io, "SurfaceIntegralUpwind", setup) end diff --git a/src/solvers/dgsem_p4est/containers.jl b/src/solvers/dgsem_p4est/containers.jl index f9830d0011..3ef9cb2a42 100644 --- a/src/solvers/dgsem_p4est/containers.jl +++ b/src/solvers/dgsem_p4est/containers.jl @@ -81,7 +81,8 @@ function Base.resize!(elements::P4estElementContainer, capacity) end # Create element container and initialize element data -function init_elements(mesh::Union{P4estMesh{NDIMS, RealT}, T8codeMesh{NDIMS, RealT}}, +function init_elements(mesh::Union{P4estMesh{NDIMS, NDIMS, RealT}, + T8codeMesh{NDIMS, RealT}}, equations, basis, ::Type{uEltype}) where {NDIMS, RealT <: Real, uEltype <: Real} diff --git a/src/solvers/dgsem_p4est/containers_2d.jl b/src/solvers/dgsem_p4est/containers_2d.jl index 236d7d24c0..6af6fd6d90 100644 --- a/src/solvers/dgsem_p4est/containers_2d.jl +++ b/src/solvers/dgsem_p4est/containers_2d.jl @@ -37,13 +37,14 @@ end # Interpolate tree_node_coordinates to each quadrant at the specified nodes function calc_node_coordinates!(node_coordinates, - mesh::P4estMesh{2}, - nodes::AbstractVector) + mesh::P4estMesh{2, NDIMS_AMBIENT}, + nodes::AbstractVector) where {NDIMS_AMBIENT} # We use `StrideArray`s here since these buffers are used in performance-critical # places and the additional information passed to the compiler makes them faster # than native `Array`s. tmp1 = StrideArray(undef, real(mesh), - StaticInt(2), static_length(nodes), static_length(mesh.nodes)) + StaticInt(NDIMS_AMBIENT), static_length(nodes), + static_length(mesh.nodes)) matrix1 = StrideArray(undef, real(mesh), static_length(nodes), static_length(mesh.nodes)) matrix2 = similar(matrix1) diff --git a/src/solvers/dgsem_p4est/dg_parallel.jl b/src/solvers/dgsem_p4est/dg_parallel.jl index eaa6ab5cee..0aee0b5652 100644 --- a/src/solvers/dgsem_p4est/dg_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_parallel.jl @@ -49,10 +49,10 @@ function start_mpi_send!(mpi_cache::P4estMPICache, mesh, equations, dg, cache) data_size = nvariables(equations) * nnodes(dg)^(ndims(mesh) - 1) n_small_elements = 2^(ndims(mesh) - 1) - for d in 1:length(mpi_cache.mpi_neighbor_ranks) - send_buffer = mpi_cache.mpi_send_buffers[d] + for rank in 1:length(mpi_cache.mpi_neighbor_ranks) + send_buffer = mpi_cache.mpi_send_buffers[rank] - for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) + for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[rank]) first = (index - 1) * data_size + 1 last = (index - 1) * data_size + data_size local_side = cache.mpi_interfaces.local_sides[interface] @@ -62,14 +62,15 @@ function start_mpi_send!(mpi_cache::P4estMPICache, mesh, equations, dg, cache) # Set send_buffer corresponding to mortar data to NaN and overwrite the parts where local # data exists - interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[d]) * data_size - mortars_data_size = length(mpi_cache.mpi_neighbor_mortars[d]) * + interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[rank]) * + data_size + mortars_data_size = length(mpi_cache.mpi_neighbor_mortars[rank]) * n_small_elements * 2 * data_size # `NaN |> eltype(...)` ensures that the NaN's are of the appropriate floating point type send_buffer[(interfaces_data_size + 1):(interfaces_data_size + mortars_data_size)] .= NaN |> eltype(mpi_cache) - for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[d]) + for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[rank]) index_base = interfaces_data_size + (index - 1) * n_small_elements * 2 * data_size indices = buffer_mortar_indices(mesh, index_base, data_size) @@ -91,18 +92,18 @@ function start_mpi_send!(mpi_cache::P4estMPICache, mesh, equations, dg, cache) end # Start sending - for (index, d) in enumerate(mpi_cache.mpi_neighbor_ranks) + for (index, rank) in enumerate(mpi_cache.mpi_neighbor_ranks) mpi_cache.mpi_send_requests[index] = MPI.Isend(mpi_cache.mpi_send_buffers[index], - d, mpi_rank(), mpi_comm()) + rank, mpi_rank(), mpi_comm()) end return nothing end function start_mpi_receive!(mpi_cache::P4estMPICache) - for (index, d) in enumerate(mpi_cache.mpi_neighbor_ranks) + for (index, rank) in enumerate(mpi_cache.mpi_neighbor_ranks) mpi_cache.mpi_recv_requests[index] = MPI.Irecv!(mpi_cache.mpi_recv_buffers[index], - d, d, mpi_comm()) + rank, rank, mpi_comm()) end return nothing @@ -118,11 +119,11 @@ function finish_mpi_receive!(mpi_cache::P4estMPICache, mesh, equations, dg, cach n_positions = n_small_elements + 1 # Start receiving and unpack received data until all communication is finished - d = MPI.Waitany(mpi_cache.mpi_recv_requests) - while d !== nothing - recv_buffer = mpi_cache.mpi_recv_buffers[d] + data = MPI.Waitany(mpi_cache.mpi_recv_requests) + while data !== nothing + recv_buffer = mpi_cache.mpi_recv_buffers[data] - for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) + for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[data]) first = (index - 1) * data_size + 1 last = (index - 1) * data_size + data_size @@ -133,8 +134,9 @@ function finish_mpi_receive!(mpi_cache::P4estMPICache, mesh, equations, dg, cach end end - interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[d]) * data_size - for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[d]) + interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[data]) * + data_size + for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[data]) index_base = interfaces_data_size + (index - 1) * n_small_elements * 2 * data_size indices = buffer_mortar_indices(mesh, index_base, data_size) @@ -155,7 +157,7 @@ function finish_mpi_receive!(mpi_cache::P4estMPICache, mesh, equations, dg, cach end end - d = MPI.Waitany(mpi_cache.mpi_recv_requests) + data = MPI.Waitany(mpi_cache.mpi_recv_requests) end return nothing @@ -311,10 +313,10 @@ function init_mpi_neighbor_connectivity(mpi_interfaces, mpi_mortars, # For each neighbor rank, init connectivity data structures mpi_neighbor_interfaces = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) mpi_neighbor_mortars = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) - for (index, d) in enumerate(mpi_neighbor_ranks) - mpi_neighbor_interfaces[index] = interface_ids[findall(==(d), + for (index, rank) in enumerate(mpi_neighbor_ranks) + mpi_neighbor_interfaces[index] = interface_ids[findall(==(rank), neighbor_ranks_interface)] - mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (d in x), + mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (rank in x), neighbor_ranks_mortar)] end @@ -519,10 +521,10 @@ function exchange_normal_directions!(mpi_mortars, mpi_cache, recv_requests = Vector{MPI.Request}(undef, length(mpi_neighbor_mortars)) # Fill send buffers - for d in 1:length(mpi_neighbor_ranks) - send_buffer = send_buffers[d] + for rank in 1:length(mpi_neighbor_ranks) + send_buffer = send_buffers[rank] - for (index, mortar) in enumerate(mpi_neighbor_mortars[d]) + for (index, mortar) in enumerate(mpi_neighbor_mortars[rank]) index_base = (index - 1) * n_small_elements * data_size indices = buffer_mortar_indices(mesh, index_base, data_size) for position in mpi_mortars.local_neighbor_positions[mortar] @@ -538,17 +540,18 @@ function exchange_normal_directions!(mpi_mortars, mpi_cache, end # Start data exchange - for (index, d) in enumerate(mpi_neighbor_ranks) - send_requests[index] = MPI.Isend(send_buffers[index], d, mpi_rank(), mpi_comm()) - recv_requests[index] = MPI.Irecv!(recv_buffers[index], d, d, mpi_comm()) + for (index, rank) in enumerate(mpi_neighbor_ranks) + send_requests[index] = MPI.Isend(send_buffers[index], rank, mpi_rank(), + mpi_comm()) + recv_requests[index] = MPI.Irecv!(recv_buffers[index], rank, rank, mpi_comm()) end # Unpack data from receive buffers - d = MPI.Waitany(recv_requests) - while d !== nothing - recv_buffer = recv_buffers[d] + data = MPI.Waitany(recv_requests) + while data !== nothing + recv_buffer = recv_buffers[data] - for (index, mortar) in enumerate(mpi_neighbor_mortars[d]) + for (index, mortar) in enumerate(mpi_neighbor_mortars[data]) index_base = (index - 1) * n_small_elements * data_size indices = buffer_mortar_indices(mesh, index_base, data_size) for position in 1:n_small_elements @@ -563,7 +566,7 @@ function exchange_normal_directions!(mpi_mortars, mpi_cache, end end - d = MPI.Waitany(recv_requests) + data = MPI.Waitany(recv_requests) end # Wait for communication to finish diff --git a/src/solvers/dgsem_t8code/dg_parallel.jl b/src/solvers/dgsem_t8code/dg_parallel.jl index ece614b7d7..2683026135 100644 --- a/src/solvers/dgsem_t8code/dg_parallel.jl +++ b/src/solvers/dgsem_t8code/dg_parallel.jl @@ -119,10 +119,10 @@ function init_mpi_neighbor_connectivity(mpi_mesh_info, mesh::ParallelT8codeMesh) # For each neighbor rank, init connectivity data structures mpi_neighbor_interfaces = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) mpi_neighbor_mortars = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) - for (index, d) in enumerate(mpi_neighbor_ranks) - mpi_neighbor_interfaces[index] = interface_ids[findall(==(d), + for (index, rank) in enumerate(mpi_neighbor_ranks) + mpi_neighbor_interfaces[index] = interface_ids[findall(==(rank), neighbor_ranks_interface)] - mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (d in x), + mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (rank in x), neighbor_ranks_mortar)] end diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 6330839383..e1eddb43c6 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -767,6 +767,7 @@ end # Container data structure (structure-of-arrays style) for DG MPI interfaces mutable struct MPIInterfaceContainer2D{uEltype <: Real} <: AbstractContainer u::Array{uEltype, 4} # [leftright, variables, i, interfaces] + # Note: `local_neighbor_ids` stores the MPI-local neighbors, but with globally valid index! local_neighbor_ids::Vector{Int} # [interfaces] orientations::Vector{Int} # [interfaces] remote_sides::Vector{Int} # [interfaces] @@ -907,6 +908,8 @@ function init_mpi_interfaces!(mpi_interfaces, elements, mesh::TreeMesh2D) # Create interface between elements count += 1 + # Note: `local_neighbor_ids` stores the MPI-local neighbors, + # but with globally valid index! mpi_interfaces.local_neighbor_ids[count] = element if iseven(direction) # element is "left" of interface, remote cell is "right" of interface @@ -941,6 +944,7 @@ end mutable struct MPIL2MortarContainer2D{uEltype <: Real} <: AbstractContainer u_upper::Array{uEltype, 4} # [leftright, variables, i, mortars] u_lower::Array{uEltype, 4} # [leftright, variables, i, mortars] + # Note: `local_neighbor_ids` stores the MPI-local neighbors, but with globally valid index! local_neighbor_ids::Vector{Vector{Int}} # [mortars][ids] local_neighbor_positions::Vector{Vector{Int}} # [mortars][positions] # Large sides: left -> 1, right -> 2 @@ -1214,6 +1218,8 @@ function init_mpi_mortars!(mpi_mortars, elements, mesh::TreeMesh2D) # 3 -> large element count += 1 + # Note: `local_neighbor_ids` stores the MPI-local neighbors, + # but with globally valid index! local_neighbor_ids = Vector{Int}() local_neighbor_positions = Vector{Int}() if is_own_cell(mesh.tree, lower_cell_id) diff --git a/src/solvers/dgsem_tree/dg_2d_parallel.jl b/src/solvers/dgsem_tree/dg_2d_parallel.jl index 157d462aa2..d7b76f5773 100644 --- a/src/solvers/dgsem_tree/dg_2d_parallel.jl +++ b/src/solvers/dgsem_tree/dg_2d_parallel.jl @@ -48,9 +48,9 @@ end # TODO: MPI dimension agnostic function start_mpi_receive!(mpi_cache::MPICache) - for (index, d) in enumerate(mpi_cache.mpi_neighbor_ranks) + for (index, rank) in enumerate(mpi_cache.mpi_neighbor_ranks) mpi_cache.mpi_recv_requests[index] = MPI.Irecv!(mpi_cache.mpi_recv_buffers[index], - d, d, mpi_comm()) + rank, rank, mpi_comm()) end return nothing @@ -60,10 +60,10 @@ end function start_mpi_send!(mpi_cache::MPICache, mesh, equations, dg, cache) data_size = nvariables(equations) * nnodes(dg)^(ndims(mesh) - 1) - for d in 1:length(mpi_cache.mpi_neighbor_ranks) - send_buffer = mpi_cache.mpi_send_buffers[d] + for rank in 1:length(mpi_cache.mpi_neighbor_ranks) + send_buffer = mpi_cache.mpi_send_buffers[rank] - for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) + for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[rank]) first = (index - 1) * data_size + 1 last = (index - 1) * data_size + data_size @@ -78,11 +78,12 @@ function start_mpi_send!(mpi_cache::MPICache, mesh, equations, dg, cache) # Each mortar has a total size of 4 * data_size, set everything to NaN first and overwrite the # parts where local data exists - interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[d]) * data_size - mortars_data_size = length(mpi_cache.mpi_neighbor_mortars[d]) * 4 * data_size + interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[rank]) * + data_size + mortars_data_size = length(mpi_cache.mpi_neighbor_mortars[rank]) * 4 * data_size send_buffer[(interfaces_data_size + 1):(interfaces_data_size + mortars_data_size)] .= NaN - for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[d]) + for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[rank]) # First and last indices in the send buffer for mortar data obtained from local element # in a given position index_base = interfaces_data_size + (index - 1) * 4 * data_size @@ -143,9 +144,9 @@ function start_mpi_send!(mpi_cache::MPICache, mesh, equations, dg, cache) end # Start sending - for (index, d) in enumerate(mpi_cache.mpi_neighbor_ranks) + for (index, rank) in enumerate(mpi_cache.mpi_neighbor_ranks) mpi_cache.mpi_send_requests[index] = MPI.Isend(mpi_cache.mpi_send_buffers[index], - d, mpi_rank(), mpi_comm()) + rank, mpi_rank(), mpi_comm()) end return nothing @@ -161,11 +162,11 @@ function finish_mpi_receive!(mpi_cache::MPICache, mesh, equations, dg, cache) data_size = nvariables(equations) * nnodes(dg)^(ndims(mesh) - 1) # Start receiving and unpack received data until all communication is finished - d = MPI.Waitany(mpi_cache.mpi_recv_requests) - while d !== nothing - recv_buffer = mpi_cache.mpi_recv_buffers[d] + data = MPI.Waitany(mpi_cache.mpi_recv_requests) + while data !== nothing + recv_buffer = mpi_cache.mpi_recv_buffers[data] - for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[d]) + for (index, interface) in enumerate(mpi_cache.mpi_neighbor_interfaces[data]) first = (index - 1) * data_size + 1 last = (index - 1) * data_size + data_size @@ -176,8 +177,9 @@ function finish_mpi_receive!(mpi_cache::MPICache, mesh, equations, dg, cache) end end - interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[d]) * data_size - for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[d]) + interfaces_data_size = length(mpi_cache.mpi_neighbor_interfaces[data]) * + data_size + for (index, mortar) in enumerate(mpi_cache.mpi_neighbor_mortars[data]) # First and last indices in the receive buffer for mortar data obtained from remote element # in a given position index_base = interfaces_data_size + (index - 1) * 4 * data_size @@ -230,7 +232,7 @@ function finish_mpi_receive!(mpi_cache::MPICache, mesh, equations, dg, cache) end end - d = MPI.Waitany(mpi_cache.mpi_recv_requests) + data = MPI.Waitany(mpi_cache.mpi_recv_requests) end return nothing @@ -431,10 +433,10 @@ function init_mpi_neighbor_connectivity(elements, mpi_interfaces, mpi_mortars, # For each neighbor rank, init connectivity data structures mpi_neighbor_interfaces = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) mpi_neighbor_mortars = Vector{Vector{Int}}(undef, length(mpi_neighbor_ranks)) - for (index, d) in enumerate(mpi_neighbor_ranks) - mpi_neighbor_interfaces[index] = interface_ids[findall(x -> (x == d), + for (index, rank) in enumerate(mpi_neighbor_ranks) + mpi_neighbor_interfaces[index] = interface_ids[findall(x -> (x == rank), neighbor_ranks_interface)] - mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (d in x), + mpi_neighbor_mortars[index] = mortar_ids[findall(x -> (rank in x), neighbor_ranks_mortar)] end diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 323c1236c2..04b3bc98ae 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -96,7 +96,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorHennemannGass "indicator variable" => indicator.variable, "max. α" => indicator.alpha_max, "min. α" => indicator.alpha_min, - "smooth α" => (indicator.alpha_smooth ? "yes" : "no"), + "smooth α" => (indicator.alpha_smooth ? "yes" : "no") ] summary_box(io, "IndicatorHennemannGassner", setup) end @@ -196,7 +196,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorLöhner) else setup = [ "indicator variable" => indicator.variable, - "f_wave" => indicator.f_wave, + "f_wave" => indicator.f_wave ] summary_box(io, "IndicatorLöhner", setup) end @@ -254,7 +254,7 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMax) show(io, indicator) else setup = [ - "indicator variable" => indicator.variable, + "indicator variable" => indicator.variable ] summary_box(io, "IndicatorMax", setup) end diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index d08944e7f5..dabd20153d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -414,14 +414,14 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) if limiter.positivity_limiter_pressure setup = [ setup..., - "" => "$(positivity_limiter_pressure_exact ? "(Sharp)" : "(Cautious)") positivity limiter for Pressure à la Kuzmin", + "" => "$(positivity_limiter_pressure_exact ? "(Sharp)" : "(Cautious)") positivity limiter for Pressure à la Kuzmin" ] end if positivity_limiter_density if limiter.positivity_limiter_correction_factor != 0.0 setup = [ setup..., - "" => "Positivity Limiter for Density with correction factor $(limiter.positivity_limiter_correction_factor)", + "" => "Positivity Limiter for Density with correction factor $(limiter.positivity_limiter_correction_factor)" ] else setup = [setup..., "" => "Positivity Limiter for Density"] @@ -432,7 +432,7 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterMCL) if limiter.smoothness_indicator setup = [ setup..., - "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)", + "Smoothness indicator" => "$(limiter.IndicatorHG) using threshold $(limiter.threshold_smoothness_indicator)" ] end summary_box(io, "SubcellLimiterMCL", setup) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index e7bf3a2590..a50191044b 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -353,9 +353,6 @@ end Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) - Qp = max(0, (var_max[i, j, element] - var) / dt) - Qm = min(0, (var_min[i, j, element] - var) / dt) - Pp = inverse_jacobian * Pp Pm = inverse_jacobian * Pm diff --git a/test/test_dgmulti_1d.jl b/test/test_dgmulti_1d.jl index 7ac3c73564..1c3cd604df 100644 --- a/test/test_dgmulti_1d.jl +++ b/test/test_dgmulti_1d.jl @@ -52,12 +52,12 @@ end l2=[ 7.853842541289665e-7, 9.609905503440606e-7, - 2.832322219966481e-6, + 2.832322219966481e-6 ] ./ sqrt(2.0), linf=[ 1.5003758788711963e-6, 1.802998748523521e-6, - 4.83599270806323e-6, + 4.83599270806323e-6 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -76,12 +76,12 @@ end l2=[ 1.673813320412685, 5.980737909458242, - 21.587822949251173, + 21.587822949251173 ], linf=[ 3.1388039126918064, 10.630952212105246, - 37.682826521024865, + 37.682826521024865 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -117,12 +117,12 @@ end l2=[ 6.437827414849647e-6, 2.1840558851820947e-6, - 1.3245669629438228e-5, + 1.3245669629438228e-5 ], linf=[ 2.0715843751295537e-5, 8.519520630301258e-6, - 4.2642194098885255e-5, + 4.2642194098885255e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -146,12 +146,12 @@ end l2=[ 1.8684509287853788e-5, 1.0641411823379635e-5, - 5.178010291876143e-5, + 5.178010291876143e-5 ], linf=[ 6.933493585936645e-5, 3.0277366229292113e-5, - 0.0002220020568932668, + 0.0002220020568932668 ]) show(stdout, semi.solver.basis) show(stdout, MIME"text/plain"(), semi.solver.basis) @@ -169,11 +169,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), l2=[ 9.146929178341782e-7, 1.8997616876521201e-6, - 3.991417701005622e-6, + 3.991417701005622e-6 ], linf=[ 1.7321089882393892e-6, 3.3252888869128583e-6, - 6.525278767988141e-6, + 6.525278767988141e-6 ]) show(stdout, semi.solver.basis) show(stdout, MIME"text/plain"(), semi.solver.basis) @@ -210,13 +210,13 @@ end 3.03001101100507e-6, 1.692177335948727e-5, 3.002634351734614e-16, - 1.1636653574178203e-15, + 1.1636653574178203e-15 ], linf=[ 1.2043401988570679e-5, 5.346847010329059e-5, 9.43689570931383e-16, - 2.220446049250313e-15, + 2.220446049250313e-15 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -236,13 +236,13 @@ end 1.633271343738687e-5, 9.575385661756332e-6, 1.2700331443128421e-5, - 0.0, + 0.0 ], linf=[ 7.304984704381567e-5, 5.2365944135601694e-5, 6.469559594934893e-5, - 0.0, + 0.0 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_dgmulti_2d.jl b/test/test_dgmulti_2d.jl index ab6b505e20..932fb9bc95 100644 --- a/test/test_dgmulti_2d.jl +++ b/test/test_dgmulti_2d.jl @@ -23,13 +23,13 @@ isdir(outdir) && rm(outdir, recursive = true) 0.0013536930300254945, 0.0014315603442106193, 0.001431560344211359, - 0.0047393341007602625, + 0.0047393341007602625 ] ./ 2.0, linf=[ 0.001514260921466004, 0.0020623991944839215, 0.002062399194485476, - 0.004897700392503701, + 0.004897700392503701 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -51,13 +51,13 @@ end 0.0074706882014934735, 0.005306220583603261, 0.005306220583613591, - 0.014724842607716771, + 0.014724842607716771 ] ./ 2.0, linf=[ 0.021563604940952885, 0.01359397832530762, 0.013593978324845324, - 0.03270995869587523, + 0.03270995869587523 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -79,13 +79,13 @@ end 0.00031892254415307093, 0.00033637562986771894, 0.0003363756298680649, - 0.0011100259064243145, + 0.0011100259064243145 ] ./ 2.0, linf=[ 0.001073298211445639, 0.0013568139808282087, 0.0013568139808290969, - 0.0032249020004324613, + 0.0032249020004324613 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -107,13 +107,13 @@ end 0.007801417730672109, 0.00708583561714128, 0.0070858356171393, - 0.015217574294198809, + 0.015217574294198809 ] ./ 2.0, linf=[ 0.011572828457858897, 0.013965298735070686, 0.01396529873508534, - 0.04227683691807904, + 0.04227683691807904 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -136,13 +136,13 @@ end 0.01280067571168776, 0.010607599608273302, 0.010607599608239775, - 0.026408338014056548, + 0.026408338014056548 ] ./ 2.0, linf=[ 0.037983023185674814, 0.05321027922533417, 0.05321027922608157, - 0.13392025411844033, + 0.13392025411844033 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -166,13 +166,13 @@ end 0.0029373718090697975, 0.0030629360605489465, 0.003062936060545615, - 0.0068486089344859755, + 0.0068486089344859755 ] ./ 2.0, linf=[ 0.01360165305316885, 0.01267402847925303, 0.012674028479251254, - 0.02210545278615017, + 0.02210545278615017 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -188,11 +188,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_bilinear.jl"), l2=[ 1.0259432774540821e-5, 9.014087689495575e-6, - 9.01408768888544e-6, 2.738953324859446e-5, + 9.01408768888544e-6, 2.738953324859446e-5 ], linf=[ 7.362605996297233e-5, 6.874189724781488e-5, - 6.874189703509614e-5, 0.00019124355334110277, + 6.874189703509614e-5, 0.00019124355334110277 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -208,11 +208,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), l2=[ 1.7204593127904542e-5, 1.5921547179522804e-5, - 1.5921547180107928e-5, 4.894071422525737e-5, + 1.5921547180107928e-5, 4.894071422525737e-5 ], linf=[ 0.00010525416937667842, 0.00010003778102718464, - 0.00010003778071832059, 0.0003642628211952825, + 0.00010003778071832059, 0.0003642628211952825 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -232,13 +232,13 @@ end 3.4666312079259457e-6, 3.4392774480368986e-6, 3.439277447953705e-6, - 1.0965598424665836e-5, + 1.0965598424665836e-5 ], linf=[ 1.1327280377004811e-5, 1.1343911926253725e-5, 1.1343911906935844e-5, - 3.679582619220412e-5, + 3.679582619220412e-5 ], rtol=2 * sqrt(eps())) # Ensure that we do not have excessive memory allocations @@ -260,13 +260,13 @@ end 7.905498158659466e-6, 8.731690809663625e-6, 8.731690811576996e-6, - 2.9113296018693953e-5, + 2.9113296018693953e-5 ], linf=[ 3.298811230090237e-5, 4.032272476939269e-5, 4.032272526011127e-5, - 0.00012013725458537294, + 0.00012013725458537294 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -284,13 +284,13 @@ end 0.0008153911341517156, 0.0007768159701964676, 0.00047902606811690694, - 0.0015551846076348535, + 0.0015551846076348535 ], linf=[ 0.0029301131365355726, 0.0034427051471457304, 0.0028721569841545502, - 0.011125365074589944, + 0.011125365074589944 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -311,7 +311,7 @@ end 4.243843382379403, 4.128314378833922, 4.128314378397532, - 4.081366752807379, + 4.081366752807379 ], rtol = 0.05) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -328,11 +328,11 @@ end # division by 2.0 corresponds to normalization by the square root of the size of the domain l2=[ 0.0007492755162295128, 0.0007641875305302599, - 0.0007641875305306243, 0.0024232389721009447, + 0.0007641875305306243, 0.0024232389721009447 ], linf=[ 0.0015060064614331736, 0.0019371156800773726, - 0.0019371156800769285, 0.004742431684202408, + 0.0019371156800769285, 0.004742431684202408 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -348,11 +348,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_triangulate_pkg_mesh.jl"), l2=[ 2.344076909832665e-6, 1.8610002398709756e-6, - 2.4095132179484066e-6, 6.37330249340445e-6, + 2.4095132179484066e-6, 6.37330249340445e-6 ], linf=[ 2.509979394305084e-5, 2.2683711321080935e-5, - 2.6180377720841363e-5, 5.575278031910713e-5, + 2.6180377720841363e-5, 5.575278031910713e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -373,13 +373,13 @@ end 0.11140378947116614, 0.06598161188703612, 0.10448953167839563, - 0.16023209181809595, + 0.16023209181809595 ] ./ 2.0, linf=[ 0.24033843177853664, 0.1659992245272325, 0.1235468309508845, - 0.26911424973147735, + 0.26911424973147735 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -401,13 +401,13 @@ end 0.11141270656347146, 0.06598888014584121, 0.1044902203749932, - 0.16023037364774995, + 0.16023037364774995 ] ./ 2.0, linf=[ 0.2414760062126462, 0.1662111846065654, 0.12344140473946856, - 0.26978428189564774, + 0.26978428189564774 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -425,11 +425,11 @@ end cells_per_dimension=(8, 8), tspan=(0.0, 0.2), l2=[ 0.07097806723891838, 0.005168550941966817, - 0.013820912272220933, 0.03243357220022434, + 0.013820912272220933, 0.03243357220022434 ], linf=[ 0.4783395896753895, 0.02244629340135818, - 0.04023357731088538, 0.08515807256615027, + 0.04023357731088538, 0.08515807256615027 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -448,13 +448,13 @@ end 0.006680001611078062, 0.02151676347585447, 0.010696524235364626, - 0.15052841129694647, + 0.15052841129694647 ], linf=[ 0.01544756362800248, 0.09517304772476806, 0.021957154972646383, - 0.33773439650806303, + 0.33773439650806303 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -473,13 +473,13 @@ end 0.05685148333985476, 0.04308122135907089, 0.043081221359070915, - 0.21098131003847664, + 0.21098131003847664 ], linf=[ 0.2360672306096051, 0.16684417686971842, 0.1668441768697189, - 0.8572572782118661, + 0.8572572782118661 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -498,13 +498,13 @@ end 0.05565849298766252, 0.042322816017256494, 0.042322816017256466, - 0.2064212098324083, + 0.2064212098324083 ], linf=[ 0.23633287875008924, 0.16930148707515683, 0.16930148707515688, - 0.8587706761131937, + 0.8587706761131937 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -532,13 +532,13 @@ end 0.0008966318978421226, 0.0011418826379110242, 0.001141882637910878, - 0.0030918374335671393, + 0.0030918374335671393 ] ./ 2.0, linf=[ 0.0015281525343109337, 0.00162430960401716, 0.0016243096040242655, - 0.004447503691245913, + 0.004447503691245913 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -568,13 +568,13 @@ end 0.0014018725496871129, 0.0015887007320868913, 0.001588700732086329, - 0.003870926821031202, + 0.003870926821031202 ] ./ 2.0, linf=[ 0.0029541996523780867, 0.0034520465226108854, 0.003452046522624652, - 0.007677153211004928, + 0.007677153211004928 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -590,11 +590,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), l2=[ 1.333332033888785e-6, 2.044834627786368e-6, - 2.0448346278315884e-6, 5.282189803437435e-6, + 2.0448346278315884e-6, 5.282189803437435e-6 ], linf=[ 2.7000151703315822e-6, 3.988595025372632e-6, - 3.9885950240403645e-6, 8.848583036513702e-6, + 3.9885950240403645e-6, 8.848583036513702e-6 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -614,13 +614,13 @@ end 1.333332034149886e-6, 2.0448346280892024e-6, 2.0448346279766305e-6, - 5.282189803510037e-6, + 5.282189803510037e-6 ], linf=[ 2.700015170553627e-6, 3.988595024262409e-6, 3.988595024928543e-6, - 8.84858303740188e-6, + 8.84858303740188e-6 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -646,13 +646,13 @@ end 0.07318831033918516, 0.10039910610067465, 0.1003991061006748, - 0.2642450566234564, + 0.2642450566234564 ], linf=[ 0.36081081739439735, 0.5244468027020845, 0.5244468027020814, - 1.2210130256735705, + 1.2210130256735705 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -679,13 +679,13 @@ end 1.5440402410017893e-5, 1.4913189903083485e-5, 1.4913189902797073e-5, - 2.6104615985156992e-5, + 2.6104615985156992e-5 ], linf=[ 4.16334345412217e-5, 5.067812788173143e-5, 5.067812786885284e-5, - 9.887976803746312e-5, + 9.887976803746312e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -796,7 +796,7 @@ end 0.0018573693138866614, 0.0020807798141551166, 0.0, - 5.301188920230166e-5, + 5.301188920230166e-5 ], linf=[ 0.01692601228199253, @@ -807,7 +807,7 @@ end 0.00984964453299233, 0.01141708032148614, 0.0, - 0.0002992631411931389, + 0.0002992631411931389 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -827,13 +827,13 @@ end 0.0020316462913319046, 0.023669019044882247, 0.03446194752754684, - 1.9333465252381796e-15, + 1.9333465252381796e-15 ], linf=[ 0.010385010095182778, 0.08750628939565086, 0.12088392994348407, - 9.325873406851315e-15, + 9.325873406851315e-15 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -853,13 +853,13 @@ end 0.004180680322490383, 0.07026192411558974, 0.11815151697006446, - 2.329788936151192e-15, + 2.329788936151192e-15 ], linf=[ 0.02076003852980346, 0.29169601664914424, 0.5674183379872275, - 1.1546319456101628e-14, + 1.1546319456101628e-14 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -881,13 +881,13 @@ end 0.0008309356912456799, 0.01522451288799231, 0.016033969387208476, - 1.2820247308150876e-5, + 1.2820247308150876e-5 ], linf=[ 0.001888045014140971, 0.05466838692127718, 0.06345885709961152, - 3.3989933098554914e-5, + 3.3989933098554914e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -911,13 +911,13 @@ end 7.460461950323111e-5, 0.003685589808444905, 0.0039101604749887785, - 2.0636891126652983e-15, + 2.0636891126652983e-15 ], linf=[ 0.000259995400729629, 0.0072236204211630906, 0.010364675200833062, - 1.021405182655144e-14, + 1.021405182655144e-14 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_dgmulti_3d.jl b/test/test_dgmulti_3d.jl index fa70b11447..5af8c9ee91 100644 --- a/test/test_dgmulti_3d.jl +++ b/test/test_dgmulti_3d.jl @@ -20,12 +20,12 @@ isdir(outdir) && rm(outdir, recursive = true) l2=[ 0.000354593110864001, 0.00041301573702385284, 0.00037934556184883277, 0.0003525767114354012, - 0.0013917457634530887, + 0.0013917457634530887 ], linf=[ 0.0036608123230692513, 0.005625540942772123, 0.0030565781898950206, 0.004158099048202857, - 0.01932716837214299, + 0.01932716837214299 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -47,14 +47,14 @@ end 0.017080219613061526, 0.016589517840793006, 0.015905000907070196, - 0.03903416208587798, + 0.03903416208587798 ] ./ sqrt(8), linf=[ 0.06856547797256729, 0.08225664880340489, 0.06925055630951782, 0.06913016119820181, - 0.19161418499621874, + 0.19161418499621874 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -76,14 +76,14 @@ end 0.00040146357607439464, 0.00040146357607564597, 0.000401463576075708, - 0.0015749412434154315, + 0.0015749412434154315 ] ./ sqrt(8), linf=[ 0.00036910287847780054, 0.00042659774184228283, 0.0004265977427213574, 0.00042659774250686233, - 0.00143803344597071, + 0.00143803344597071 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -98,13 +98,18 @@ end @trixi_testset "elixir_euler_curved.jl (Hex elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), l2=[ - 0.01835488304593566, 0.024412704052042534, - 0.02440852041608929, 0.018163145708800853, - 0.03934280550797125, + 0.0019393929700612259, + 0.003213659298633126, + 0.003203104361527826, + 0.0019407707245105426, + 0.0109274471764788 ], linf=[ - 0.14862225990793032, 0.2895236816183626, 0.291205448481636, - 0.14566031338563246, 0.33153545867790246, + 0.01914151956454324, + 0.0270195960766606, + 0.026891238631389536, + 0.019817504336972602, + 0.09645660501766873 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -122,12 +127,12 @@ end l2=[ 0.0026311315195097097, 0.002914422404496567, 0.0029138891106640368, 0.002615140832315232, - 0.006881528610616624, + 0.006881528610616624 ], linf=[ 0.02099611487415931, 0.021314522450152307, 0.021288322783027613, 0.020273381695449455, - 0.05259874039006007, + 0.05259874039006007 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -144,12 +149,12 @@ end l2=[ 0.00036475807571383924, 0.00043404536371780537, 0.0003985850214093045, 0.0003683451584072326, - 0.00143503620472638, + 0.00143503620472638 ], linf=[ 0.0032278615418719347, 0.005620238272054934, 0.0030514261010661237, 0.0039871165455998, - 0.019282771780667396, + 0.019282771780667396 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -171,14 +176,14 @@ end 0.00044397204714598747, 0.0004439720471461567, 0.0004439720471464591, - 0.0016639410646990126, + 0.0016639410646990126 ] ./ sqrt(8), linf=[ 0.0003674374460325147, 0.0004253921341716982, 0.0004253921340786615, 0.0004253921340831024, - 0.0014333414071048267, + 0.0014333414071048267 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -202,14 +207,14 @@ end 0.002491315550718859, 0.0024913155507195303, 0.002491315550720031, - 0.008585818982343299, + 0.008585818982343299 ] ./ sqrt(8), linf=[ 0.003810078279323559, 0.004998778644230928, 0.004998778643986235, 0.0049987786444081195, - 0.016455044373650196, + 0.016455044373650196 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -229,14 +234,14 @@ end 0.06219350883951729, 0.062193508839503864, 0.08121963221634831, - 0.07082703570808184, + 0.07082703570808184 ], linf=[ 0.0007893509649821162, 0.1481953939988877, 0.14819539399791176, 0.14847291108358926, - 0.21313533492212855, + 0.21313533492212855 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -257,14 +262,14 @@ end 0.062193508839511434, 0.06219350883949677, 0.08121963221635205, - 0.07082703570765223, + 0.07082703570765223 ], linf=[ 0.000789350964946367, 0.14819539399525805, 0.14819539399590542, 0.14847291107658706, - 0.21313533492059378, + 0.21313533492059378 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -291,14 +296,14 @@ end 0.003318758964118284, 0.0033187589641182386, 0.003318758964118252, - 0.012689348410504253, + 0.012689348410504253 ], linf=[ 0.006118565824207778, 0.008486456080185167, 0.008486456080180282, 0.008486456080185611, - 0.035113544599208346, + 0.035113544599208346 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -327,14 +332,14 @@ end 0.004944363692625066, 0.0049443636926250435, 0.004944363692625037, - 0.01788695279620914, + 0.01788695279620914 ], linf=[ 0.013861851418853988, 0.02126572106620328, 0.021265721066209053, 0.021265721066210386, - 0.0771455289446683, + 0.0771455289446683 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -353,14 +358,14 @@ end 6.884047859361093e-5, 6.884047859363204e-5, 6.884047859361148e-5, - 0.000201107274617457, + 0.000201107274617457 ], linf=[ 0.0001337520020225913, 0.00011571467799287305, 0.0001157146779990903, 0.00011571467799376123, - 0.0003446082308800058, + 0.0003446082308800058 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_mpi_p4est_2d.jl b/test/test_mpi_p4est_2d.jl index 29de4efc6d..6ac8133f5d 100644 --- a/test/test_mpi_p4est_2d.jl +++ b/test/test_mpi_p4est_2d.jl @@ -136,13 +136,13 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_mpi_p4est_3d.jl b/test/test_mpi_p4est_3d.jl index 4f9465b85d..d6018e51c8 100644 --- a/test/test_mpi_p4est_3d.jl +++ b/test/test_mpi_p4est_3d.jl @@ -129,14 +129,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, - 0.00019986264001630542, + 0.00019986264001630542 ], linf=[ 0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, - 0.008526972236273522, + 0.008526972236273522 ], tspan=(0.0, 0.01)) @@ -158,14 +158,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, - 0.0028149479453087093, + 0.0028149479453087093 ], linf=[ 0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, - 0.01562861968368434, + 0.01562861968368434 ], tspan=(0.0, 1.0)) @@ -186,14 +186,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, - 0.02628875593094754, + 0.02628875593094754 ], linf=[ 0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, - 0.8099577682187109, + 0.8099577682187109 ], tspan=(0.0, 0.2), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -216,14 +216,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") 0.004122532789279737, 0.0042448149597303616, 0.0036361316700401765, - 0.007389845952982495, + 0.007389845952982495 ], linf=[ 0.04530610539892499, 0.02765695110527666, 0.05670295599308606, 0.048396544302230504, - 0.1154589758186293, + 0.1154589758186293 ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_mpi_t8code_2d.jl b/test/test_mpi_t8code_2d.jl index 75e65c8c38..dcbbf626e2 100644 --- a/test/test_mpi_t8code_2d.jl +++ b/test/test_mpi_t8code_2d.jl @@ -119,13 +119,13 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_2d_dgsem") 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_mpi_t8code_3d.jl b/test/test_mpi_t8code_3d.jl index 2e837f79ad..c4ca592eaf 100644 --- a/test/test_mpi_t8code_3d.jl +++ b/test/test_mpi_t8code_3d.jl @@ -96,14 +96,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_3d_dgsem") 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, - 0.00019986264001630542, + 0.00019986264001630542 ], linf=[ 0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, - 0.008526972236273522, + 0.008526972236273522 ], tspan=(0.0, 0.01)) @@ -125,14 +125,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_3d_dgsem") 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, - 0.0028149479453087093, + 0.0028149479453087093 ], linf=[ 0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, - 0.01562861968368434, + 0.01562861968368434 ], tspan=(0.0, 1.0)) @@ -153,14 +153,14 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "t8code_3d_dgsem") 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, - 0.02628875593094754, + 0.02628875593094754 ], linf=[ 0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, - 0.8099577682187109, + 0.8099577682187109 ], tspan=(0.0, 0.2), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI diff --git a/test/test_mpi_tree.jl b/test/test_mpi_tree.jl index 6114e453e5..1e51da02c6 100644 --- a/test/test_mpi_tree.jl +++ b/test/test_mpi_tree.jl @@ -111,12 +111,12 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() l2=[ 0.00015687751816056159, 0.001025986772217084, - 0.0010259867722169909, + 0.0010259867722169909 ], linf=[ 0.0011986956416591976, 0.006423873516411049, - 0.006423873516411049, + 0.006423873516411049 ]) end end @@ -127,12 +127,12 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() l2=[ 8.61813235543625e-8, 5.619399844542781e-7, - 5.6193998447443e-7, + 5.6193998447443e-7 ], linf=[ 1.124861862180196e-6, 8.622436471039663e-6, - 8.622436470151484e-6, + 8.622436470151484e-6 ]) end @@ -141,12 +141,12 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() l2=[ 8.523077653955306e-6, 2.8779323653065056e-5, - 5.4549427691297846e-5, + 5.4549427691297846e-5 ], linf=[ 5.5227409524905013e-5, 0.0001454489597927185, - 0.00032396328684569653, + 0.00032396328684569653 ]) end @@ -156,12 +156,12 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() l2=[ 5.868147556427088e-6, 3.80517927324465e-5, - 3.805179273249344e-5, + 3.805179273249344e-5 ], linf=[ 3.701965498725812e-5, 0.0002122422943138247, - 0.00021224229431116015, + 0.00021224229431116015 ], atol=2.0e-12) #= required for CI on macOS =# end @@ -177,13 +177,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, - 4.824553091276693e-6, + 4.824553091276693e-6 ], linf=[ 9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, - 4.8869615580926506e-5, + 4.8869615580926506e-5 ], rtol=2000 * sqrt(eps())) end @@ -198,13 +198,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 4.8226610349853444e-5, 4.117706709270575e-5, 4.1177067092959676e-5, - 0.00012205252427437389, + 0.00012205252427437389 ], linf=[ 0.0003543874851490436, 0.0002973166773747593, 0.0002973166773760916, - 0.001154106793870291, + 0.001154106793870291 ], # Let this test run until the end to cover the time-dependent lines # of the indicator and the MPI-specific AMR code. @@ -220,13 +220,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, - 6.3327863238858925e-6, + 6.3327863238858925e-6 ], linf=[ 1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, - 6.0526717141407005e-5, + 6.0526717141407005e-5 ], rtol=0.001) end @@ -239,13 +239,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 0.061751715597716854, 0.05018223615408711, 0.05018989446443463, - 0.225871559730513, + 0.225871559730513 ], linf=[ 0.29347582879608825, 0.31081249232844693, 0.3107380389947736, - 1.0540358049885143, + 1.0540358049885143 ]) @testset "error-based step size control" begin @@ -262,13 +262,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 0.061653630426688116, 0.05006930431098764, 0.05007694316484242, - 0.22550689872331683, + 0.22550689872331683 ] rtol=1.0e-4 @test errors.linf≈[ 0.28516937484583693, 0.2983633696512788, 0.297812036335975, - 1.027368795517512, + 1.027368795517512 ] rtol=1.0e-4 end end @@ -281,13 +281,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 0.00013492249515826863, 0.006615696236378061, 0.006782108219800376, - 0.016393831451740604, + 0.016393831451740604 ], linf=[ 0.0020782600954247776, 0.08150078921935999, 0.08663621974991986, - 0.2829930622010579, + 0.2829930622010579 ], rtol=0.001) end @@ -299,13 +299,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 0.0017208369388227673, 0.09628684992237334, 0.09620157717330868, - 0.1758809552387432, + 0.1758809552387432 ], linf=[ 0.021869936355319086, 0.9956698009442038, 1.0002507727219028, - 2.223249697515648, + 2.223249697515648 ]) end @@ -316,13 +316,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 5.051719943432265e-5, 0.0022574259317084747, 0.0021755998463189713, - 0.004346492398617521, + 0.004346492398617521 ], linf=[ 0.0012880114865917447, 0.03857193149447702, 0.031090457959835893, - 0.12125130332971423, + 0.12125130332971423 ], coverage_override=(maxiters = 6,)) end @@ -335,13 +335,13 @@ CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() 0.0017158367642679273, 0.09619888722871434, 0.09616432767924141, - 0.17553381166255197, + 0.17553381166255197 ], linf=[ 0.021853862449723982, 0.9878047229255944, 0.9880191167111795, - 2.2154030488035588, + 2.2154030488035588 ], rtol=0.001) end diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index 2ee3774567..a8c20ee3bd 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -132,13 +132,13 @@ end 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -156,7 +156,7 @@ end 2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, - 1.4104095258528071e-14, + 1.4104095258528071e-14 ], linf=[1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], atol=2.0e-12,) @@ -177,13 +177,13 @@ end 1.4663777294625118e-15, 2.320054900530864e-14, 3.487555722563465e-14, - 2.008802099296406e-14, + 2.008802099296406e-14 ], linf=[ 2.3092638912203256e-14, 2.0623780461193064e-13, 2.6795232699328153e-13, - 2.362554596402333e-13, + 2.362554596402333e-13 ], atol=2.0e-12,) # Ensure that we do not have excessive memory allocations @@ -192,6 +192,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -202,13 +206,13 @@ end 1.5395023651392628e-16, 5.707276922805213e-15, 6.656058585297407e-15, - 5.171129126439075e-15, + 5.171129126439075e-15 ], linf=[ 2.886579864025407e-15, 5.384581669432009e-14, 9.997558336749535e-14, - 6.217248937900877e-14, + 6.217248937900877e-14 ], trees_per_dimension=(8, 8), atol=2.0e-12,) @@ -218,6 +222,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -228,13 +236,13 @@ end 9.53984675e-02, 1.05633455e-01, 1.05636158e-01, - 3.50747237e-01, + 3.50747237e-01 ], linf=[ 2.94357464e-01, 4.07893014e-01, 3.97334516e-01, - 1.08142520e+00, + 1.08142520e+00 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -253,13 +261,13 @@ end 0.09527896382082567, 0.10557894830184737, 0.10559379376154387, - 0.3503791205165925, + 0.3503791205165925 ], linf=[ 0.2733486454092644, 0.3877283966722886, 0.38650482703821426, - 1.0053712251056308, + 1.0053712251056308 ], tspan=(0.0, 1.0), volume_flux=flux_chandrashekar) @@ -280,13 +288,13 @@ end 0.09539953f0, 0.10563527f0, 0.105637245f0, - 0.3507514f0, + 0.3507514f0 ], linf=[ 0.2942562f0, 0.4079147f0, 0.3972956f0, - 1.0810697f0, + 1.0810697f0 ], tspan=(0.0f0, 1.0f0), rtol=10 * sqrt(eps(Float32)), # to make CI pass @@ -307,13 +315,13 @@ end 3.76149952e-01, 2.46970327e-01, 2.46970327e-01, - 1.28889042e+00, + 1.28889042e+00 ], linf=[ 1.22139001e+00, 1.17742626e+00, 1.17742626e+00, - 6.20638482e+00, + 6.20638482e+00 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -333,13 +341,13 @@ end 0.4573787784168518, 0.28520972760728397, 0.28527281808006966, - 1.2881460122982442, + 1.2881460122982442 ], linf=[ 1.644411040701827, 1.6743368119653912, 1.6760847977977988, - 6.268843623142863, + 6.268843623142863 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -348,6 +356,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -358,13 +370,13 @@ end 0.4229948321239887, 0.2559038337457483, 0.2559038337457484, - 1.2990046683564136, + 1.2990046683564136 ], linf=[ 1.4989357969730492, 1.325456585141623, 1.3254565851416251, - 6.331283015053501, + 6.331283015053501 ], surface_flux=flux_hllc, tspan=(0.0, 0.3)) @@ -384,13 +396,13 @@ end 0.40853279043747015, 0.25356771650524296, 0.2535677165052422, - 1.2984601729572691, + 1.2984601729572691 ], linf=[ 1.3840909333784284, 1.3077772519086124, 1.3077772519086157, - 6.298798630968632, + 6.298798630968632 ], surface_flux=flux_hlle, tspan=(0.0, 0.3)) @@ -410,13 +422,13 @@ end 0.6321850210104147, 0.38691446170269167, 0.3868695626809587, - 1.0657553825683956, + 1.0657553825683956 ], linf=[ 2.7602280007469666, 2.3265993814913672, 2.3258078438689673, - 2.1577683028925416, + 2.1577683028925416 ], tspan=(0.0, 0.3), coverage_override=(maxiters = 6,)) @@ -436,13 +448,13 @@ end 0.02026685991647352, 0.017467584076280237, 0.011378371604813321, - 0.05138942558296091, + 0.05138942558296091 ], linf=[ 0.35924402060711524, 0.32068389566068806, 0.2361141752119986, - 0.9289840057748628, + 0.9289840057748628 ], tspan=(0.0, 0.15)) # Ensure that we do not have excessive memory allocations @@ -461,13 +473,13 @@ end 0.004191480950848891, 0.003781298410569231, 0.0013470418422981045, - 0.03262817609394949, + 0.03262817609394949 ], linf=[ 2.0581500751947113, 2.2051301367971288, 3.8502467979250254, - 17.750333649853616, + 17.750333649853616 ], tspan=(0.0, 0.0001), rtol=1.0e-7, @@ -490,13 +502,13 @@ end 0.051359355290192046, 0.4266034859911273, 0.2438304855475594, - 4.11487176105527, + 4.11487176105527 ], linf=[ 6.902000373057003, 53.95714139820832, 24.241610279839758, - 561.0630401858057, + 561.0630401858057 ], tspan=(0.0, 0.0001), skip_coverage=true) @@ -518,13 +530,13 @@ end 0.8741784143331414, 6.669726935141086, 3.4980245896042237, - 76.33557073504075, + 76.33557073504075 ], linf=[ 11.428353668952052, 142.73486850872337, 38.91639544604301, - 1651.7541390872523, + 1651.7541390872523 ], initial_refinement_level=1, tspan=(0.0, 0.05)) @@ -534,6 +546,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -544,13 +560,13 @@ end 0.8887316275665462, 6.644244953884147, 3.449004719784639, - 76.2706476520857, + 76.2706476520857 ], linf=[ 11.047531178706233, 121.96650277677288, 35.74266968217143, - 1370.2362955295687, + 1370.2362955295687 ], initial_refinement_level=1, tspan=(0.0, 0.05)) @@ -560,6 +576,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -570,13 +590,13 @@ end 0.02676082999794676, 0.05110830068968181, 0.03205164257040607, - 0.1965981012724311, + 0.1965981012724311 ], linf=[ 3.6830683476364476, 4.284442685012427, 6.857777546171545, - 31.749285097390576, + 31.749285097390576 ], tspan=(0.0, 0.001), skip_coverage=true) @@ -599,13 +619,13 @@ end 0.11085870166618325, 0.23309905989870722, 0.13505351590735631, - 0.7932047512585592, + 0.7932047512585592 ], linf=[ 2.9808773737943564, 4.209364526217892, 6.265341002817672, - 24.077904874883338, + 24.077904874883338 ], tspan=(0.0, 0.02)) # Ensure that we do not have excessive memory allocations @@ -614,6 +634,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -625,13 +649,13 @@ end 0.01719185099537115, 0.037755715231922615, 0.018219844214522288, - 0.1211329583241979, + 0.1211329583241979 ], linf=[ 1.36377851955985337, 2.886724226405783, 2.271954486109792, - 9.900660307619413, + 9.900660307619413 ], tspan=(0.0, 0.001)) # Ensure that we do not have excessive memory allocations @@ -640,6 +664,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -648,11 +676,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_NACA6412airfoil_mach2.jl"), l2=[ 0.19107654776276498, 0.3545913719444839, - 0.18492730895077583, 0.817927213517244, + 0.18492730895077583, 0.817927213517244 ], linf=[ 2.5397624311491946, 2.7075156425517917, 2.200980534211764, - 9.031153939238115, + 9.031153939238115 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -671,13 +699,13 @@ end 0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, - 0.0007231525513793697, + 0.0007231525513793697 ], linf=[ 0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, - 0.004793821195083758, + 0.004793821195083758 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -696,13 +724,13 @@ end 9.168126407325352e-5, 0.0009795410115453788, 0.002546408320320785, - 3.941189812642317e-6, + 3.941189812642317e-6 ], linf=[ 0.0009903782521019089, 0.0059752684687262025, 0.010941106525454103, - 1.2129488214718265e-5, + 1.2129488214718265e-5 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -768,13 +796,13 @@ end 0.006047938590548741, 0.0040953286019907035, 0.004222698522497298, - 0.006269492499336128, + 0.006269492499336128 ], linf=[ 0.06386175207349379, 0.0378926444850457, 0.041759728067967065, - 0.06430136016259067, + 0.06430136016259067 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -792,13 +820,13 @@ end 0.00011914390523852561, 0.00010776028621724485, 6.139954358305467e-5, - 0.0003067693731825959, + 0.0003067693731825959 ], linf=[ 0.1653075586200805, 0.1868437275544909, 0.09772818519679008, - 0.4311796171737692, + 0.4311796171737692 ], tspan=(0.0, 0.001)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -829,11 +857,11 @@ end "elixir_euler_NACA0012airfoil_mach085.jl"), l2=[ 5.56114097044427e-7, 6.62284247153255e-6, - 1.0823259724601275e-5, 0.000659804574787503, + 1.0823259724601275e-5, 0.000659804574787503 ], linf=[ 0.002157589754528455, 0.039163189253511164, - 0.038386804399707625, 2.6685831417913914, + 0.038386804399707625, 2.6685831417913914 ], amr_interval=1, base_level=0, med_level=1, max_level=1, @@ -874,13 +902,13 @@ end 0.39957047631960346, 0.21006912294983154, 0.21006903549932, - 0.6280328163981136, + 0.6280328163981136 ], linf=[ 2.20417889887697, 1.5487238480003327, 1.5486788679247812, - 2.4656795949035857, + 2.4656795949035857 ], tspan=(0.0, 0.5), mesh=P4estMesh((64, 64), polydeg = 3, @@ -902,13 +930,13 @@ end 0.11134260363848127, 0.11752357091804219, 0.11829112104640764, - 0.7557891142955036, + 0.7557891142955036 ], linf=[ 0.5728647031475109, 0.8353132977670252, 0.8266797080712205, - 3.9792506230548317, + 3.9792506230548317 ], tspan=(0.0, 0.1), coverage_override=(maxiters = 6,)) diff --git a/test/test_p4est_3d.jl b/test/test_p4est_3d.jl index 3432bd69b2..869b7554bf 100644 --- a/test/test_p4est_3d.jl +++ b/test/test_p4est_3d.jl @@ -132,14 +132,14 @@ end 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, - 0.00019986264001630542, + 0.00019986264001630542 ], linf=[ 0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, - 0.008526972236273522, + 0.008526972236273522 ], tspan=(0.0, 0.01)) # Ensure that we do not have excessive memory allocations @@ -160,14 +160,14 @@ end 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, - 0.0028149479453087093, + 0.0028149479453087093 ], linf=[ 0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, - 0.01562861968368434, + 0.01562861968368434 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -187,14 +187,14 @@ end 1.941857343642486e-14, 2.0232366394187278e-14, 2.3381518645408552e-14, - 7.083114561232324e-14, + 7.083114561232324e-14 ], linf=[ 7.269740365245525e-13, 3.289868377720495e-12, 4.440087186807773e-12, 3.8686831516088205e-12, - 9.412914891981927e-12, + 9.412914891981927e-12 ], tspan=(0.0, 0.03)) # Ensure that we do not have excessive memory allocations @@ -214,14 +214,14 @@ end 4.889826056731442e-15, 2.2921260987087585e-15, 4.268460455702414e-15, - 1.1356712092620279e-14, + 1.1356712092620279e-14 ], linf=[ 7.749356711883593e-14, 2.8792246364872653e-13, 1.1121659149182506e-13, 3.3228975127030935e-13, - 9.592326932761353e-13, + 9.592326932761353e-13 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -240,12 +240,12 @@ end l2=[ 6.530157034651212e-16, 1.6057829680004379e-15, 3.31107455378537e-15, 3.908829498281281e-15, - 5.048390610424672e-15, + 5.048390610424672e-15 ], linf=[ 4.884981308350689e-15, 1.1921019726912618e-14, 1.5432100042289676e-14, 2.298161660974074e-14, - 6.039613253960852e-14, + 6.039613253960852e-14 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -266,14 +266,14 @@ end Float32(1.6057829680004379e-15), Float32(3.31107455378537e-15), Float32(3.908829498281281e-15), - Float32(5.048390610424672e-15), + Float32(5.048390610424672e-15) ], linf=[ Float32(4.884981308350689e-15), Float32(1.1921019726912618e-14), Float32(1.5432100042289676e-14), Float32(2.298161660974074e-14), - Float32(6.039613253960852e-14), + Float32(6.039613253960852e-14) ], RealT=Float32) # Ensure that we do not have excessive memory allocations @@ -293,14 +293,14 @@ end 4.889826056731442e-15, 2.2921260987087585e-15, 4.268460455702414e-15, - 1.1356712092620279e-14, + 1.1356712092620279e-14 ], linf=[ 7.749356711883593e-14, 4.513472928735496e-13, 2.9790059308254513e-13, 1.057154364048074e-12, - 1.6271428648906294e-12, + 1.6271428648906294e-12 ], tspan=(0.0, 0.1), surface_flux=flux_hllc) @@ -321,14 +321,14 @@ end 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, - 0.02628875593094754, + 0.02628875593094754 ], linf=[ 0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, - 0.8099577682187109, + 0.8099577682187109 ], tspan=(0.0, 0.2), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -349,14 +349,14 @@ end 0.006216054794583285, 0.006020401857347216, 0.006019175682769779, - 0.026228080232814154, + 0.026228080232814154 ], linf=[ 0.3169376449662026, 0.28950510175646726, 0.4402523227566396, 0.4869168122387365, - 0.7999141641954051, + 0.7999141641954051 ], tspan=(0.0, 0.2), volume_flux=flux_chandrashekar, @@ -378,14 +378,14 @@ end 4.33260474e-02, 4.33260474e-02, 4.33260474e-02, - 3.75260911e-01, + 3.75260911e-01 ], linf=[ 7.45329845e-01, 3.21754792e-01, 3.21754792e-01, 3.21754792e-01, - 4.76151527e+00, + 4.76151527e+00 ], tspan=(0.0, 0.3), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -406,14 +406,14 @@ end 0.04863386374672001, 0.048633863746720116, 0.04863386374672032, - 0.3751015774232693, + 0.3751015774232693 ], linf=[ 0.789241521871487, 0.42046970270100276, 0.42046970270100276, 0.4204697027010028, - 4.730877375538398, + 4.730877375538398 ], tspan=(0.0, 0.3), surface_flux=flux_hlle) @@ -435,14 +435,14 @@ end 5.4254175153621895e-6, 5.677698851333843e-6, 5.8017136892469794e-6, - 1.3637854615117974e-5, + 1.3637854615117974e-5 ], linf=[ 0.00013996924184311865, 0.00013681539559939893, 0.00013681539539733834, 0.00013681539541021692, - 0.00016833038543762058, + 0.00016833038543762058 ], # Decrease tolerance of adaptive time stepping to get similar results across different systems abstol=1.0e-11, reltol=1.0e-11, @@ -465,14 +465,14 @@ end 3.8630261900166194e-5, 3.8672287531936816e-5, 3.6865116098660796e-5, - 0.05508620970403884, + 0.05508620970403884 ], linf=[ 2.268845333053271e-6, 0.000531462302113539, 0.0005314624461298934, 0.0005129931254772464, - 0.7942778058932163, + 0.7942778058932163 ], tspan=(0.0, 2e2), coverage_override=(trees_per_cube_face = (1, 1), polydeg = 3)) # Prevent long compile time in CI @@ -494,14 +494,14 @@ end 0.00021710076010951073, 0.0004386796338203878, 0.00020836270267103122, - 0.07601887903440395, + 0.07601887903440395 ], linf=[ 1.9107530539574924e-5, 0.02980358831035801, 0.048476331898047564, 0.02200137344113612, - 4.848310144356219, + 4.848310144356219 ], tspan=(0.0, 1e2), # Decrease tolerance of adaptive time stepping to get similar results across different systems @@ -525,14 +525,14 @@ end 0.004122532789279737, 0.0042448149597303616, 0.0036361316700401765, - 0.007389845952982495, + 0.007389845952982495 ], linf=[ 0.04530610539892499, 0.02765695110527666, 0.05670295599308606, 0.048396544302230504, - 0.1154589758186293, + 0.1154589758186293 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -600,11 +600,11 @@ end l2=[ 0.04452389418193219, 0.03688186699434862, 0.03688186699434861, 0.03688186699434858, - 0.044523894181932186, + 0.044523894181932186 ], linf=[ 0.2295447498696467, 0.058369658071546704, - 0.05836965807154648, 0.05836965807154648, 0.2295447498696468, + 0.05836965807154648, 0.05836965807154648, 0.2295447498696468 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -623,14 +623,14 @@ end 0.018525073963833696, 0.019102348105917946, 0.01920515438943838, - 0.15060493968460148, + 0.15060493968460148 ], linf=[ 0.2994949779783401, 0.5530175050084679, 0.5335803757792128, 0.5647252867336123, - 3.6462732329242566, + 3.6462732329242566 ], tspan=(0.0, 0.025), coverage_override=(maxiters = 6,)) diff --git a/test/test_paper_self_gravitating_gas_dynamics.jl b/test/test_paper_self_gravitating_gas_dynamics.jl index 10b4f93ad7..63a7a2b6de 100644 --- a/test/test_paper_self_gravitating_gas_dynamics.jl +++ b/test/test_paper_self_gravitating_gas_dynamics.jl @@ -21,13 +21,13 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "paper_self_gravitating_gas_dynam 0.0001740977055972079, 0.0003369355182519592, 0.0003369355182518708, - 0.0006099171220334989, + 0.0006099171220334989 ], linf=[ 0.001079347149189669, 0.0018836938381321389, 0.001883693838132583, - 0.003971575376718217, + 0.003971575376718217 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -45,13 +45,13 @@ end 1.7187201161597772e-5, 2.678065111772951e-5, 2.678065111783027e-5, - 4.952504160091526e-5, + 4.952504160091526e-5 ], linf=[ 0.0001501749544159381, 0.00016549482504535362, 0.00016549482504601976, - 0.0004372960291432193, + 0.0004372960291432193 ], polydeg=4) # Ensure that we do not have excessive memory allocations @@ -69,12 +69,12 @@ end l2=[ 0.003154024896093942, 0.012394432074951856, - 0.02185973823794725, + 0.02185973823794725 ], linf=[ 0.01731850928579215, 0.07843510773347553, - 0.11242300176349201, + 0.11242300176349201 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -91,12 +91,12 @@ end l2=[ 0.0002511283012128458, 0.0008808243846610255, - 0.0016313343228567005, + 0.0016313343228567005 ], linf=[ 0.0017290715087938668, 0.003129184465704738, - 0.01000728849316701, + 0.01000728849316701 ], polydeg=4) # Ensure that we do not have excessive memory allocations @@ -115,13 +115,13 @@ end 0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, - 0.0007231525513793697, + 0.0007231525513793697 ], linf=[ 0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, - 0.004793821195083758, + 0.004793821195083758 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -140,13 +140,13 @@ end 1.9537712148648045e-5, 2.7564396197947587e-5, 2.7564396197967635e-5, - 5.688838772067586e-5, + 5.688838772067586e-5 ], linf=[ 0.00012335710672761735, 0.00020086268350816283, 0.00020086268350727465, - 0.0004962155455632278, + 0.0004962155455632278 ], tspan=(0.0, 0.1), polydeg=4) # Ensure that we do not have excessive memory allocations @@ -165,13 +165,13 @@ end 0.00024871265138959434, 0.000337007710281087, 0.0003370077102811394, - 0.0007231525515231289, + 0.0007231525515231289 ], linf=[ 0.0015813032941613958, 0.002049428843978518, 0.0020494288439798503, - 0.004793821198143977, + 0.004793821198143977 ], tspan=(0.0, 0.1), timestep_gravity=Trixi.timestep_gravity_erk51_3Sstar!) @@ -191,13 +191,13 @@ end 0.0002487126513894034, 0.00033700771023049785, 0.00033700771023048245, - 0.0007231525514158737, + 0.0007231525514158737 ], linf=[ 0.0015813032943847727, 0.002049428842844314, 0.0020494288428452023, - 0.004793821195971937, + 0.004793821195971937 ], tspan=(0.0, 0.1), timestep_gravity=Trixi.timestep_gravity_erk53_3Sstar!) @@ -218,13 +218,13 @@ end 10733.63378538114, 13356.780607423452, 1.6722844879795038e-6, - 26834.076821148774, + 26834.076821148774 ], linf=[ 15194.296424901113, 18881.481685044182, 6.809726988008751e-6, - 37972.99700513482, + 37972.99700513482 ], tspan=(0.0, 0.1), atol=4.0e-6) @@ -245,13 +245,13 @@ end 10734.598193238024, 13358.217234481384, 1.911011743371934e-6, - 26836.487841241516, + 26836.487841241516 ], linf=[ 15195.661004798487, 18883.512035906537, 7.867948710816926e-6, - 37976.408478975296, + 37976.408478975296 ], tspan=(0.0, 0.1), atol=4.0e-6, # the background field is reatively large, so this corresponds to our usual atol @@ -304,13 +304,13 @@ end 0.046315994852653024, 0.0650818006233669, 0.06508180062336677, - 0.4896707211656037, + 0.4896707211656037 ], linf=[ 2.3874843337593776, 4.07876384374792, 4.07876384374792, - 16.23914384809855, + 16.23914384809855 ], tspan=(0.0, 0.05), coverage_override=(maxiters = 2,)) @@ -331,13 +331,13 @@ end 0.00289222135995042, 0.013724813590853825, 0.013724813590853832, - 0.05822904710548214, + 0.05822904710548214 ], linf=[ 0.26361780693997594, 1.3908873830688688, 1.3908873830688688, - 4.066701303607613, + 4.066701303607613 ], tspan=(0.0, 0.005), initial_refinement_level=8, amr_callback=TrivialCallback()) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 38bebdcce1..062e6363a2 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -67,12 +67,12 @@ end l2=[ 0.0001133835907077494, 6.226282245610444e-5, - 0.0002820171699999139, + 0.0002820171699999139 ], linf=[ 0.0006255102377159538, 0.00036195501456059986, - 0.0016147729485886941, + 0.0016147729485886941 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -94,12 +94,12 @@ end l2=[ 0.00011310615871043463, 6.216495207074201e-5, - 0.00028195843110817814, + 0.00028195843110817814 ], linf=[ 0.0006240837363233886, 0.0003616694320713876, - 0.0016147339542413874, + 0.0016147339542413874 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -117,12 +117,12 @@ end l2=[ 0.00047023310868269237, 0.00032181736027057234, - 0.0014966266486095025, + 0.0014966266486095025 ], linf=[ 0.002996375101363302, 0.0028639041695096433, - 0.012691132694550689, + 0.012691132694550689 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -144,12 +144,12 @@ end l2=[ 0.0004608500483647771, 0.00032431091222851285, - 0.0015159733360626845, + 0.0015159733360626845 ], linf=[ 0.002754803146635787, 0.0028567713744625124, - 0.012941793784197131, + 0.012941793784197131 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -170,12 +170,12 @@ end l2=[ 2.5278845598681636e-5, 2.5540145802666872e-5, - 0.0001211867535580826, + 0.0001211867535580826 ], linf=[ 0.0001466387202588848, 0.00019422419092429135, - 0.0009556449835592673, + 0.0009556449835592673 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -197,12 +197,12 @@ end l2=[ 2.4593521887223632e-5, 2.3928212900127102e-5, - 0.00011252332663824173, + 0.00011252332663824173 ], linf=[ 0.00011850494672183132, 0.00018987676556476442, - 0.0009597461727750556, + 0.0009597461727750556 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index d038354f88..ceefb65e99 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -127,13 +127,13 @@ end 0.0015355076812510957, 0.0033843168272696756, 0.0036531858107443434, - 0.009948436427519214, + 0.009948436427519214 ], linf=[ 0.005522560467190019, 0.013425258500730508, 0.013962115643482154, - 0.027483102120502423, + 0.027483102120502423 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -153,13 +153,13 @@ end 0.004255101916146187, 0.011118488923215765, 0.011281831283462686, - 0.03573656447388509, + 0.03573656447388509 ], linf=[ 0.015071710669706473, 0.04103132025858458, 0.03990424085750277, - 0.1309401718598764, + 0.1309401718598764 ],) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -179,13 +179,13 @@ end 0.00022156125227115747, 0.028318325921401, 0.009509168701070296, - 0.028267900513550506, + 0.028267900513550506 ], linf=[ 0.001562278941298234, 0.14886653390744856, 0.0716323565533752, - 0.19472785105241996, + 0.19472785105241996 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -276,13 +276,13 @@ end 0.002111672530658797, 0.0034322351490857846, 0.0038742528195910416, - 0.012469246082568561, + 0.012469246082568561 ], linf=[ 0.012006418939223495, 0.035520871209746126, 0.024512747492231427, - 0.11191122588756564, + 0.11191122588756564 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -306,13 +306,13 @@ end 0.002103629650383915, 0.003435843933396454, 0.00386735987813341, - 0.012670355349235728, + 0.012670355349235728 ], linf=[ 0.012006261793147788, 0.03550212518982032, 0.025107947319661185, - 0.11647078036571124, + 0.11647078036571124 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -333,13 +333,13 @@ end 0.0021403742517389513, 0.0034258287094908572, 0.0038915122886898517, - 0.012506862343013842, + 0.012506862343013842 ], linf=[ 0.012244412004628336, 0.03507559186162224, 0.024580892345558894, - 0.11425600758350107, + 0.11425600758350107 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -364,13 +364,13 @@ end 0.0021349737347844907, 0.0034301388278203033, 0.0038928324474291572, - 0.012693611436230873, + 0.012693611436230873 ], linf=[ 0.01224423627586213, 0.035054066314102905, 0.025099598504931965, - 0.11795616324751634, + 0.11795616324751634 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -391,13 +391,13 @@ end 0.0021116725306633594, 0.0034322351490827557, 0.0038742528196093542, - 0.012469246082526909, + 0.012469246082526909 ], linf=[ 0.012006418939291663, 0.035520871209594115, 0.024512747491801577, - 0.11191122588591007, + 0.11191122588591007 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -454,13 +454,13 @@ end 0.00015144571529699053, 0.018766076072331623, 0.007065070765652574, - 0.0208399005734258, + 0.0208399005734258 ], linf=[ 0.0014523369373669048, 0.12366779944955864, 0.05532450997115432, - 0.16099927805328207, + 0.16099927805328207 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -479,13 +479,13 @@ end 0.005155557460409018, 0.4048446934219344, 0.43040068852937047, - 1.1255130552079322, + 1.1255130552079322 ], linf=[ 0.03287305649809613, 1.1656793717431393, 1.3917196016246969, - 8.146587380114653, + 8.146587380114653 ], tspan=(0.0, 0.7)) end @@ -497,13 +497,13 @@ end 0.001452856280034929, 0.0007538775539989481, 0.0007538775539988681, - 0.011035506549989587, + 0.011035506549989587 ], linf=[ 0.003291912841311362, 0.002986462478096974, 0.0029864624780958637, - 0.0231954665514138, + 0.0231954665514138 ], tspan=(0.0, 1.0)) end @@ -616,13 +616,13 @@ end 0.0003811978985836709, 0.0005874314969169538, 0.0009142898787923481, - 0.0011613918899727263, + 0.0011613918899727263 ], linf=[ 0.0021633623982135752, 0.009484348274135372, 0.004231572066492217, - 0.011661660275365193, + 0.011661660275365193 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -642,13 +642,13 @@ end 0.00040364962558511795, 0.0005869762481506936, 0.00091488537427274, - 0.0011984191566376762, + 0.0011984191566376762 ], linf=[ 0.0024993634941723464, 0.009487866203944725, 0.004505829506628117, - 0.011634902776245681, + 0.011634902776245681 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -668,13 +668,13 @@ end 0.00028716166408816073, 0.08101204560401647, 0.02099595625377768, - 0.05008149754143295, + 0.05008149754143295 ], linf=[ 0.014804500261322406, 0.9513271652357098, 0.7223919625994717, - 1.4846907331004786, + 1.4846907331004786 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -692,11 +692,11 @@ end tspan=(0.0, 1.0), l2=[ 0.0005323841980601085, 0.07892044543547208, - 0.02909671646389337, 0.11717468256112017, + 0.02909671646389337, 0.11717468256112017 ], linf=[ 0.006045292737899444, 0.9233292581786228, - 0.7982129977236198, 1.6864546235292153, + 0.7982129977236198, 1.6864546235292153 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 863daeeaf3..2690a08cbb 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -21,14 +21,14 @@ isdir(outdir) && rm(outdir, recursive = true) 0.000659263490965341, 0.0007776436127362806, 0.0006592634909662951, - 0.0038073628897809185, + 0.0038073628897809185 ], linf=[ 0.0017039861523615585, 0.002628561703560073, 0.003531057425112172, 0.0026285617036090336, - 0.015587829540351095, + 0.015587829540351095 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -49,14 +49,14 @@ end 0.0021322235533273513, 0.0027873741447455194, 0.0024587473070627423, - 0.00997836818019202, + 0.00997836818019202 ], linf=[ 0.006341750402837576, 0.010306014252246865, 0.01520740250924979, 0.010968264045485565, - 0.047454389831591115, + 0.047454389831591115 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -77,14 +77,14 @@ end 0.015589736382772248, 0.015589736382771884, 0.021943924667273653, - 0.01927370280244222, + 0.01927370280244222 ], linf=[ 0.0006268463584697681, 0.03218881662749007, 0.03218881662697948, 0.053872495395614256, - 0.05183822000984151, + 0.05183822000984151 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -105,14 +105,14 @@ end 0.002653449504302844, 0.002898264205184629, 0.002653449504302853, - 0.009511572365085706, + 0.009511572365085706 ], linf=[ 0.013680656759085918, 0.0356910450154318, 0.023526343547736236, 0.035691045015431855, - 0.11482570604041165, + 0.11482570604041165 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -137,14 +137,14 @@ end 0.0026554367897028506, 0.002892730402724066, 0.002655436789702817, - 0.009596351796609566, + 0.009596351796609566 ], linf=[ 0.013680508110645473, 0.035673446359424356, 0.024024936779729028, 0.03567344635942474, - 0.11839497110809383, + 0.11839497110809383 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -166,14 +166,14 @@ end 0.0026524750946399327, 0.00290860030832445, 0.0026524750946399396, - 0.009509568981439294, + 0.009509568981439294 ], linf=[ 0.01387936112914212, 0.03526260609304053, 0.023554197097368997, 0.035262606093040896, - 0.11719963716509518, + 0.11719963716509518 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -199,14 +199,14 @@ end 0.002654768259143932, 0.002907031063651286, 0.002654768259143901, - 0.009587792882971452, + 0.009587792882971452 ], linf=[ 0.01387919380137137, 0.035244084526358944, 0.02398614622061363, 0.03524408452635828, - 0.12005056512506407, + 0.12005056512506407 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -228,14 +228,14 @@ end 0.002653449504301736, 0.0028982642051960006, 0.0026534495043017384, - 0.009511572364811033, + 0.009511572364811033 ], linf=[ 0.013680656758949583, 0.035691045015224444, 0.02352634354676752, 0.035691045015223424, - 0.11482570603751441, + 0.11482570603751441 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -273,14 +273,14 @@ end 0.0006473493036803503, 0.0007705277238213672, 0.0006280517917198335, - 0.000903927789884075, + 0.000903927789884075 ] @test linf_error ≈ [ 0.0023694155365339142, 0.010634932622402863, 0.006772070862236412, 0.010640551561726901, - 0.019256819038719897, + 0.019256819038719897 ] # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -301,14 +301,14 @@ end 0.015684268393762454, 0.01568426839376248, 0.021991909545192333, - 0.02825413672911425, + 0.02825413672911425 ], linf=[ 0.0008410587892853094, 0.04740176181772552, 0.04740176181772507, 0.07483494924031157, - 0.150181591534448, + 0.150181591534448 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -348,14 +348,14 @@ end 0.006266480163542894, 0.006266489911815533, 0.008829222305770226, - 0.0032859166842329228, + 0.0032859166842329228 ] @test linf_error ≈ [ 0.0002943968186086554, 0.013876261980614757, 0.013883619864959451, 0.025201279960491936, - 0.018679364985388247, + 0.018679364985388247 ] # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -377,14 +377,14 @@ end 0.000461877794472316, 0.0005424899076052261, 0.0004618777944723191, - 0.0015846392581126832, + 0.0015846392581126832 ], linf=[ 0.0025241668929956163, 0.006308461681816373, 0.004334939663169113, 0.006308461681804009, - 0.03176343480493493, + 0.03176343480493493 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -406,14 +406,14 @@ end 0.015637861347119624, 0.015637861347119687, 0.022024699158522523, - 0.009711013505930812, + 0.009711013505930812 ], linf=[ 0.0006696415247340326, 0.03442565722527785, 0.03442565722577423, 0.06295407168705314, - 0.032857472756916195, + 0.032857472756916195 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -464,14 +464,14 @@ end 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, - 0.30978593009044153, + 0.30978593009044153 ], linf=[ 0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, - 0.8433893297612087, + 0.8433893297612087 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -490,11 +490,11 @@ end l2=[ 0.009472104410520866, 0.0017883742549557149, 0.0017883742549557147, 0.0017883742549557196, - 0.024388540048562748, + 0.024388540048562748 ], linf=[ 0.6782397526873181, 0.17663702154066238, - 0.17663702154066266, 0.17663702154066238, 1.7327849844825238, + 0.17663702154066266, 0.17663702154066238, 1.7327849844825238 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 78230e5cf0..f64b8c9c06 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -79,7 +79,7 @@ end linf=[ 3.1661064228547255, 0.16256363944708607, - 2.667676158812806, + 2.667676158812806 ], tspan=(0.0, 12.5), surface_flux=FluxHLL(min_max_speed_davis)) @@ -99,12 +99,12 @@ end l2=[ 2.2527950196212703e-8, 1.8187357193835156e-8, - 7.705669939973104e-8, + 7.705669939973104e-8 ], linf=[ 1.6205433861493646e-7, 1.465427772462391e-7, - 5.372255111879554e-7, + 5.372255111879554e-7 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -122,12 +122,12 @@ end l2=[ 3.8099996914101204e-6, 1.6745575717106341e-6, - 7.732189531480852e-6, + 7.732189531480852e-6 ], linf=[ 1.2971473393186272e-5, 9.270328934274374e-6, - 3.092514399671842e-5, + 3.092514399671842e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -176,12 +176,12 @@ end l2=[ 0.019355699748523896, 0.022326984561234497, - 0.02523665947241734, + 0.02523665947241734 ], linf=[ 0.02895961127645519, 0.03293442484199227, - 0.04246098278632804, + 0.04246098278632804 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index d8fa822060..8254712cf3 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -52,13 +52,13 @@ end 7.816742843336293e-6, 7.816742843340186e-6, 7.816742843025513e-6, - 7.816742843061526e-6, + 7.816742843061526e-6 ], linf=[ 6.314906965276812e-5, 6.314906965187994e-5, 6.31490696496595e-5, - 6.314906965032563e-5, + 6.314906965032563e-5 ], coverage_override=(maxiters = 10^5,)) @@ -68,13 +68,13 @@ end 7.816742843336293e-6, 7.816742843340186e-6, 7.816742843025513e-6, - 7.816742843061526e-6, + 7.816742843061526e-6 ] rtol=1.0e-4 @test errors.linf≈[ 6.314906965276812e-5, 6.314906965187994e-5, 6.31490696496595e-5, - 6.314906965032563e-5, + 6.314906965032563e-5 ] rtol=1.0e-4 # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -91,11 +91,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_meshview.jl"), l2=[ 8.311947673083206e-6, - 8.311947673068427e-6, + 8.311947673068427e-6 ], linf=[ 6.627000273318195e-5, - 6.62700027264096e-5, + 6.62700027264096e-5 ], coverage_override=(maxiters = 10^5,)) @@ -313,14 +313,14 @@ end 1.51236516273878e-5, 2.4544918394022538e-5, 5.904791661362391e-6, - 1.1809583322724782e-5, + 1.1809583322724782e-5 ], linf=[ 8.393471747591974e-5, 8.393471748258108e-5, 0.00015028562494778797, 3.504466610437795e-5, - 7.00893322087559e-5, + 7.00893322087559e-5 ]) # Ensure that we do not have excessive memory allocations @@ -340,13 +340,13 @@ end 0.3398358793878119, 0.03398358793878129, 0.06796717587756244, - 0.008495896984696072, + 0.008495896984696072 ], linf=[ 0.8360446582060936, 0.08360446582060972, 0.16720893164122444, - 0.02090111645397741, + 0.02090111645397741 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -355,6 +355,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -366,13 +370,13 @@ end 0.33983417649330827, 0.033983417649330924, 0.06796683529866161, - 0.008495854412336827, + 0.008495854412336827 ], linf=[ 0.8360446582068146, 0.083604465820679, 0.16720893164136671, - 0.02090111645399162, + 0.02090111645399162 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -381,6 +385,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -392,13 +400,13 @@ end 9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, - 4.824553091276693e-6, + 4.824553091276693e-6 ], linf=[ 9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, - 4.8869615580926506e-5, + 4.8869615580926506e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -419,13 +427,13 @@ end 9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, - 4.824553091276693e-6, + 4.824553091276693e-6 ], linf=[ 9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, - 4.8869615580926506e-5, + 4.8869615580926506e-5 ], alpha=0.0) # Ensure that we do not have excessive memory allocations @@ -446,13 +454,13 @@ end 9.321188057029291e-7, 1.3195106906473365e-6, 1.510307360354032e-6, - 4.82455408101712e-6, + 4.82455408101712e-6 ], linf=[ 9.57723626271445e-6, 1.0480225511866337e-5, 1.2817828088262928e-5, - 4.886962393513272e-5, + 4.886962393513272e-5 ], alpha=0.1) # Ensure that we do not have excessive memory allocations @@ -473,13 +481,13 @@ end 9.32127973957391e-7, 8.477824799744325e-7, 1.8175286311402784e-6, - 4.824562453521076e-6, + 4.824562453521076e-6 ], linf=[ 9.576898420737834e-6, 5.057704352218195e-6, 1.635260719945464e-5, - 4.886978754825577e-5, + 4.886978754825577e-5 ], alpha=0.2 * pi) # Ensure that we do not have excessive memory allocations @@ -500,13 +508,13 @@ end 9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, - 4.824553091276693e-6, + 4.824553091276693e-6 ], linf=[ 9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, - 4.8869615580926506e-5, + 4.8869615580926506e-5 ], alpha=0.5 * pi) # Ensure that we do not have excessive memory allocations @@ -527,13 +535,13 @@ end 1.1167802955144833e-5, 1.0805775514153104e-5, 1.953188337010932e-5, - 5.5033856574857146e-5, + 5.5033856574857146e-5 ], linf=[ 8.297006495561199e-5, 8.663281475951301e-5, 0.00012264160606778596, - 0.00041818802502024965, + 0.00041818802502024965 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -552,13 +560,13 @@ end 0.00816012943805366, 0.008658255997419217, 0.00935190284719103, - 0.027757019482291357, + 0.027757019482291357 ], linf=[ 0.02722563220635177, 0.040734034380730755, 0.03819407626402338, - 0.08080649141597318, + 0.08080649141597318 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -567,6 +575,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -578,13 +590,13 @@ end 2.991891317562739e-5, 3.6063177168283174e-5, 2.7082941743640572e-5, - 0.00011414695350996946, + 0.00011414695350996946 ], linf=[ 0.0002437454930492855, 0.0003438936171968887, 0.00024217622945688078, - 0.001266380414757684, + 0.001266380414757684 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -602,13 +614,13 @@ end 2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, - 1.4104095258528071e-14, + 1.4104095258528071e-14 ], linf=[ 1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, - 2.7000623958883807e-13, + 2.7000623958883807e-13 ], atol=7.0e-13) # Ensure that we do not have excessive memory allocations @@ -628,13 +640,13 @@ end 1.4663777294625118e-15, 2.320054900530864e-14, 3.487555722563465e-14, - 2.008802099296406e-14, + 2.008802099296406e-14 ], linf=[ 2.3092638912203256e-14, 2.0623780461193064e-13, 2.6795232699328153e-13, - 2.362554596402333e-13, + 2.362554596402333e-13 ], atol=7.0e-13) # Ensure that we do not have excessive memory allocations @@ -643,6 +655,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -653,13 +669,13 @@ end 8.457600308458635e-16, 2.185478357408446e-14, 3.14987670823871e-14, - 1.6817763381190492e-14, + 1.6817763381190492e-14 ], linf=[ 2.1316282072803006e-14, 2.0759782781709646e-13, 2.4705237855471296e-13, - 2.255973186038318e-13, + 2.255973186038318e-13 ], atol=7.0e-13) # Ensure that we do not have excessive memory allocations @@ -668,6 +684,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -679,13 +699,13 @@ end 2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, - 1.4104095258528071e-14, + 1.4104095258528071e-14 ], linf=[ 1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, - 2.7000623958883807e-13, + 2.7000623958883807e-13 ], atol=7.0e-13) # Ensure that we do not have excessive memory allocations @@ -704,13 +724,13 @@ end 0.87417841433288, 6.669726935171785, 3.4980245896465387, - 76.33557073534843, + 76.33557073534843 ], linf=[ 11.428353671462515, 142.73486852796972, 38.91639544578682, - 1651.7541392659086, + 1651.7541392659086 ], initial_refinement_level=2, tspan=(0.0, 0.05)) @@ -720,6 +740,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -730,13 +754,13 @@ end 0.8887316108902574, 6.644244699117507, 3.449004719354504, - 76.27064751067829, + 76.27064751067829 ], linf=[ 11.047531144845593, 121.9664993888814, 35.74266955717666, - 1370.2362649787694, + 1370.2362649787694 ], initial_refinement_level=2, tspan=(0.0, 0.05)) @@ -746,6 +770,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -757,13 +785,13 @@ end 1.2251169601680385, 1.1492245175358053, 1.6159494561956207, - 11.595399424356522, + 11.595399424356522 ], linf=[ 5.510615373248864, 6.031732951057033, 7.75523532462757, - 50.34978438323783, + 50.34978438323783 ], cells_per_dimension=(4, 6), tspan=(0.0, 0.5)) @@ -773,6 +801,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -783,13 +815,13 @@ end 1.251060277251583, 1.113113246031922, 1.6514902305846646, - 11.691342485806103, + 11.691342485806103 ], linf=[ 5.893750268397502, 5.620631940554678, 9.523570698421638, - 50.004005679063496, + 50.004005679063496 ], cells_per_dimension=(4, 6), tspan=(0.0, 0.5)) @@ -799,6 +831,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -810,13 +846,13 @@ end 2.259440511901724e-6, 2.3188881559075347e-6, 2.3188881559568146e-6, - 6.332786324137878e-6, + 6.332786324137878e-6 ], linf=[ 1.4987382622067003e-5, 1.918201192063762e-5, 1.918201192019353e-5, - 6.052671713430158e-5, + 6.052671713430158e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -834,13 +870,13 @@ end 0.03774907669925568, 0.02845190575242045, 0.028262802829412605, - 0.13785915638851698, + 0.13785915638851698 ], linf=[ 0.3368296929764073, 0.27644083771519773, 0.27990039685141377, - 1.1971436487402016, + 1.1971436487402016 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -859,13 +895,13 @@ end 3.69856202e-01, 2.35242180e-01, 2.41444928e-01, - 1.28807120e+00, + 1.28807120e+00 ], linf=[ 1.82786223e+00, 1.30452904e+00, 1.40347257e+00, - 6.21791658e+00, + 6.21791658e+00 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -882,16 +918,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ - 0.6337774834710513, - 0.30377119245852724, - 0.3111372568571772, - 1.2976221893997268, + 0.6403528328480915, + 0.3068073114438902, + 0.3140151910019577, + 1.2977732581465693 ], linf=[ - 2.2064877103138207, - 1.541067099687334, - 1.5487587769900337, - 6.271271639873466, + 2.239791987419344, + 1.5580885989144924, + 1.5392923786831547, + 6.2729281824590855 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -900,6 +936,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -912,16 +952,16 @@ end local_twosided_variables_cons=[], local_onesided_variables_nonlinear=[], l2=[ - 0.7869912572385168, - 0.39170886758882073, - 0.39613257454431977, - 1.2951760266455101, + 0.7979084213982606, + 0.3980284851419719, + 0.4021949448633982, + 1.2956482394747346 ], linf=[ - 5.156044534854053, - 3.6261667239538986, - 3.1807681416546085, - 6.3028422220287235, + 5.477809925838038, + 3.7793130706228273, + 3.2838862964081637, + 6.316943647948965 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -930,6 +970,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end @@ -939,11 +983,11 @@ end "elixir_euler_rayleigh_taylor_instability.jl"), l2=[ 0.06365630515019809, 0.007166887172039836, - 0.0028787103533600804, 0.010247678008197966, + 0.0028787103533600804, 0.010247678008197966 ], linf=[ 0.47992143569849377, 0.02459548251933757, - 0.02059810091623976, 0.0319077000843877, + 0.02059810091623976, 0.0319077000843877 ], cells_per_dimension=(8, 8), tspan=(0.0, 0.3)) @@ -964,13 +1008,13 @@ end 0.00019387402388722496, 0.03086514388623955, 0.04541427917165, - 43.892826583444716, + 43.892826583444716 ], linf=[ 0.0015942305974430138, 0.17449778969139373, 0.3729704262394843, - 307.6706958565337, + 307.6706958565337 ], cells_per_dimension=(32, 16), tspan=(0.0, 10.0)) @@ -988,11 +1032,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), l2=[ 0.00166898321776379, 0.00259202637930991, - 0.0032810744946276406, + 0.0032810744946276406 ], linf=[ 0.010994883201888683, 0.013309526619369905, - 0.020080326611175536, + 0.020080326611175536 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1012,11 +1056,11 @@ end volume_integral = VolumeIntegralFluxDifferencing(volume_flux)), l2=[ 0.001668882059653298, 0.002592168188567654, - 0.0032809503514328307, + 0.0032809503514328307 ], linf=[ 0.01099467966437917, 0.013311978456333584, - 0.020080117011337606, + 0.020080117011337606 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1033,12 +1077,12 @@ end l2=[ 0.03647890611450939, 0.025284915444045052, - 0.025340697771609126, + 0.025340697771609126 ], linf=[ 0.32516731565355583, 0.37509762516540046, - 0.29812843284727336, + 0.29812843284727336 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1055,11 +1099,11 @@ end "elixir_eulerpolytropic_isothermal_wave.jl"), l2=[ 0.004998778512795407, 0.004998916021367992, - 8.991558055435833e-17, + 8.991558055435833e-17 ], linf=[ 0.010001103632831354, 0.010051165055185603, - 7.60697457718599e-16, + 7.60697457718599e-16 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1075,11 +1119,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_wave.jl"), l2=[ 0.23642871172548174, 0.2090519382039672, - 8.778842676292274e-17, + 8.778842676292274e-17 ], linf=[ 0.4852276879687425, 0.25327870807625175, - 5.533921691832115e-16, + 5.533921691832115e-16 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1103,6 +1147,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -1113,12 +1161,12 @@ end l2=[ 0.19357947606509474, 0.47041398037626814, - 0.4704139803762686, + 0.4704139803762686 ], linf=[ 0.35026352556630114, 0.8344372248051408, - 0.8344372248051408, + 0.8344372248051408 ], tspan=(0.0, 0.1), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -1184,13 +1232,13 @@ end 0.0017286908591070864, 0.025585037307655684, 0.028374244567802766, - 6.274146767730866e-5, + 6.274146767730866e-5 ], linf=[ 0.012973752001194772, 0.10829375385832263, 0.15832858475438094, - 0.00018196759554722775, + 0.00018196759554722775 ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -1209,13 +1257,13 @@ end 0.7920927046419308, 9.92129670988898e-15, 1.0118635033124588e-14, - 0.7920927046419308, + 0.7920927046419308 ], linf=[ 2.408429868800133, 5.5835419986809516e-14, 5.448874313931364e-14, - 2.4084298688001335, + 2.4084298688001335 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -1261,7 +1309,7 @@ end 0.03090169852186498, 0.030901698662039206, 0.04370160129981657, 8.259193829690747e-8, 0.03090169908364624, 0.030901699039770726, - 0.04370160128147445, 8.73592340076897e-9, + 0.04370160128147445, 8.73592340076897e-9 ], linf=[ 9.021023431587949e-7, 0.043701454182710486, @@ -1272,7 +1320,7 @@ end 0.043701454182710764, 0.043701458294525895, 0.06180314632253597, 9.487023254761695e-7, 0.04370156101034084, 0.04370147392153745, - 0.06180318786081015, 3.430672973680963e-8, + 0.06180318786081015, 3.430672973680963e-8 ], coverage_override=(maxiters = 10^5,)) @@ -1284,7 +1332,7 @@ end 0.030901699039770684, 0.04370160128147447, 8.735923402748945e-9, 1.0743426996067106e-7, 0.03090169852186498, 0.030901698662039206, 0.04370160129981657, 8.259193829690747e-8, 0.03090169908364624, - 0.030901699039770726, 0.04370160128147445, 8.73592340076897e-9, + 0.030901699039770726, 0.04370160128147445, 8.73592340076897e-9 ] rtol=1.0e-4 @test errors.linf≈[ 9.021023431587949e-7, 0.043701454182710486, 0.043701458294527366, @@ -1292,7 +1340,7 @@ end 0.04370147392153734, 0.06180318786081025, 3.430673132525334e-8, 9.02102342825728e-7, 0.043701454182710764, 0.043701458294525895, 0.06180314632253597, 9.487023254761695e-7, 0.04370156101034084, - 0.04370147392153745, 0.06180318786081015, 3.430672973680963e-8, + 0.04370147392153745, 0.06180318786081015, 3.430672973680963e-8 ] rtol=1.0e-4 # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_structured_3d.jl b/test/test_structured_3d.jl index a52c459d6b..ac932b9535 100644 --- a/test/test_structured_3d.jl +++ b/test/test_structured_3d.jl @@ -84,14 +84,14 @@ end 0.009776048833895767, 0.00977604883389591, 0.009776048833895733, - 0.01506687097416608, + 0.01506687097416608 ], linf=[ 0.03285848350791731, 0.0321792316408982, 0.032179231640894645, 0.032179231640895534, - 0.0655408023333299, + 0.0655408023333299 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -110,14 +110,14 @@ end 9.361915278236651e-15, 9.95614203619935e-15, 1.6809941842374106e-14, - 1.4815037041566735e-14, + 1.4815037041566735e-14 ], linf=[ 4.1300296516055823e-14, 2.0444756998472258e-13, 1.0133560657266116e-13, 2.0627943797535409e-13, - 2.8954616482224083e-13, + 2.8954616482224083e-13 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -137,14 +137,14 @@ end 9.361915278236651e-15, 9.95614203619935e-15, 1.6809941842374106e-14, - 1.4815037041566735e-14, + 1.4815037041566735e-14 ], linf=[ 4.1300296516055823e-14, 2.0444756998472258e-13, 1.0133560657266116e-13, 2.0627943797535409e-13, - 2.8954616482224083e-13, + 2.8954616482224083e-13 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -164,14 +164,14 @@ end 0.003275679548217804, 0.0030020672748714084, 0.00324007343451744, - 0.005721986362580164, + 0.005721986362580164 ], linf=[ 0.03156756290660656, 0.033597629023726316, 0.02095783702361409, 0.03353574465232212, - 0.05873635745032857, + 0.05873635745032857 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -190,14 +190,14 @@ end 0.007022020327490176, 0.006759580335962235, 0.006820337637760632, - 0.02912659127566544, + 0.02912659127566544 ], linf=[ 0.2761764220925329, 0.20286331858055706, 0.18763944865434593, 0.19313636558790004, - 0.707563913727584, + 0.707563913727584 ], tspan=(0.0, 0.25), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -218,14 +218,14 @@ end 2.53167260e-02, 2.64276438e-02, 2.52195992e-02, - 3.56830295e-01, + 3.56830295e-01 ], linf=[ 6.16356950e-01, 2.50600049e-01, 2.74796377e-01, 2.46448217e-01, - 4.77888479e+00, + 4.77888479e+00 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations diff --git a/test/test_t8code_2d.jl b/test/test_t8code_2d.jl index c1fcc35521..644995778d 100644 --- a/test/test_t8code_2d.jl +++ b/test/test_t8code_2d.jl @@ -160,13 +160,13 @@ end 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -185,7 +185,7 @@ end 2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, - 1.4104095258528071e-14, + 1.4104095258528071e-14 ], linf=[1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], atol=2.0e-12,) @@ -206,13 +206,13 @@ end 9.53984675e-02, 1.05633455e-01, 1.05636158e-01, - 3.50747237e-01, + 3.50747237e-01 ], linf=[ 2.94357464e-01, 4.07893014e-01, 3.97334516e-01, - 1.08142520e+00, + 1.08142520e+00 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -233,13 +233,13 @@ end 3.76149952e-01, 2.46970327e-01, 2.46970327e-01, - 1.28889042e+00, + 1.28889042e+00 ], linf=[ 1.22139001e+00, 1.17742626e+00, 1.17742626e+00, - 6.20638482e+00, + 6.20638482e+00 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -259,13 +259,13 @@ end 9.168126407325352e-5, 0.0009795410115453788, 0.002546408320320785, - 3.941189812642317e-6, + 3.941189812642317e-6 ], linf=[ 0.0009903782521019089, 0.0059752684687262025, 0.010941106525454103, - 1.2129488214718265e-5, + 1.2129488214718265e-5 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -332,13 +332,13 @@ end 0.10823279736983638, 0.1158152939803735, 0.11633970342992006, - 0.751152651902375, + 0.751152651902375 ], linf=[ 0.5581611332828653, 0.8354026029724041, 0.834485181423738, - 3.923553028014343, + 3.923553028014343 ], tspan=(0.0, 0.1), coverage_override=(maxiters = 6,)) diff --git a/test/test_t8code_3d.jl b/test/test_t8code_3d.jl index 940d2c4337..da7ea60c65 100644 --- a/test/test_t8code_3d.jl +++ b/test/test_t8code_3d.jl @@ -119,14 +119,14 @@ mkdir(outdir) 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, - 0.00019986264001630542, + 0.00019986264001630542 ], linf=[ 0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, - 0.008526972236273522, + 0.008526972236273522 ], tspan=(0.0, 0.01)) # Ensure that we do not have excessive memory allocations @@ -148,14 +148,14 @@ mkdir(outdir) 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, - 0.0028149479453087093, + 0.0028149479453087093 ], linf=[ 0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, - 0.01562861968368434, + 0.01562861968368434 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -176,14 +176,14 @@ mkdir(outdir) 1.941857343642486e-14, 2.0232366394187278e-14, 2.3381518645408552e-14, - 7.083114561232324e-14, + 7.083114561232324e-14 ], linf=[ 7.269740365245525e-13, 3.289868377720495e-12, 4.440087186807773e-12, 3.8686831516088205e-12, - 9.412914891981927e-12, + 9.412914891981927e-12 ], tspan=(0.0, 0.03)) # Ensure that we do not have excessive memory allocations @@ -204,14 +204,14 @@ mkdir(outdir) 4.889826056731442e-15, 2.2921260987087585e-15, 4.268460455702414e-15, - 1.1356712092620279e-14, + 1.1356712092620279e-14 ], linf=[ 7.749356711883593e-14, 2.8792246364872653e-13, 1.1121659149182506e-13, 3.3228975127030935e-13, - 9.592326932761353e-13, + 9.592326932761353e-13 ], tspan=(0.0, 0.1), atol=5.0e-13,) # Ensure that we do not have excessive memory allocations @@ -232,14 +232,14 @@ mkdir(outdir) 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, - 0.02628875593094754, + 0.02628875593094754 ], linf=[ 0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, - 0.8099577682187109, + 0.8099577682187109 ], tspan=(0.0, 0.2), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -262,14 +262,14 @@ mkdir(outdir) 4.33260474e-02, 4.33260474e-02, 4.33260474e-02, - 3.75260911e-01, + 3.75260911e-01 ], linf=[ 7.45329845e-01, 3.21754792e-01, 3.21754792e-01, 3.21754792e-01, - 4.76151527e+00, + 4.76151527e+00 ], tspan=(0.0, 0.3), coverage_override=(polydeg = 3,)) # Prevent long compile time in CI @@ -291,14 +291,14 @@ mkdir(outdir) 0.032062252638283974, 0.032062252638283974, 0.03206225263828395, - 0.12228177813586687, + 0.12228177813586687 ], linf=[ 0.0693648413632646, 0.0622101894740843, 0.06221018947408474, 0.062210189474084965, - 0.24196451799555962, + 0.24196451799555962 ], mesh=T8codeMesh((4, 4, 4), polydeg = 3, coordinates_min = (0.0, 0.0, 0.0), @@ -324,14 +324,14 @@ mkdir(outdir) 0.0176268986746271, 0.01817514447099777, 0.018271085903740675, - 0.15193033077438198, + 0.15193033077438198 ], linf=[ 0.2898958869606375, 0.529717119064458, 0.5567193302705906, 0.570663236219957, - 3.5496520808512027, + 3.5496520808512027 ], tspan=(0.0, 0.025), coverage_override=(maxiters = 6,)) diff --git a/test/test_threaded.jl b/test/test_threaded.jl index 7fb64d61cb..760c5ca0d7 100644 --- a/test/test_threaded.jl +++ b/test/test_threaded.jl @@ -92,13 +92,13 @@ Trixi.MPI.Barrier(Trixi.mpi_comm()) 2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, - 6.3327863238858925e-6, + 6.3327863238858925e-6 ], linf=[ 1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, - 6.0526717141407005e-5, + 6.0526717141407005e-5 ], rtol=0.001) @@ -119,13 +119,13 @@ Trixi.MPI.Barrier(Trixi.mpi_comm()) 0.061751715597716854, 0.05018223615408711, 0.05018989446443463, - 0.225871559730513, + 0.225871559730513 ], linf=[ 0.29347582879608825, 0.31081249232844693, 0.3107380389947736, - 1.0540358049885143, + 1.0540358049885143 ]) # Ensure that we do not have excessive memory allocations @@ -180,13 +180,13 @@ Trixi.MPI.Barrier(Trixi.mpi_comm()) 1.7088389997042244e-6, 1.7437997855125774e-6, 1.7437997855350776e-6, - 5.457223460127621e-6, + 5.457223460127621e-6 ], linf=[ 9.796504903736292e-6, 9.614745892783105e-6, 9.614745892783105e-6, - 4.026107182575345e-5, + 4.026107182575345e-5 ], tspan=(0.0, 0.1)) @@ -283,13 +283,13 @@ end 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) # Ensure that we do not have excessive memory allocations @@ -309,13 +309,13 @@ end 0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, - 0.0007231525513793697, + 0.0007231525513793697 ], linf=[ 0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, - 0.004793821195083758, + 0.004793821195083758 ], tspan=(0.0, 0.1)) end @@ -329,13 +329,13 @@ end 0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, - 0.004731710454271893, + 0.004731710454271893 ], linf=[ 0.04155789011775046, 0.024772109862748914, 0.03759938693042297, - 0.08039824959535657, + 0.08039824959535657 ]) end @@ -346,13 +346,13 @@ end 0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, - 0.0007231525513793697, + 0.0007231525513793697 ], linf=[ 0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, - 0.004793821195083758, + 0.004793821195083758 ], tspan=(0.0, 0.1)) end @@ -370,13 +370,13 @@ end 0.006400337855843578, 0.005303799804137764, 0.005303799804119745, - 0.013204169007030144, + 0.013204169007030144 ], linf=[ 0.03798302318566282, 0.05321027922532284, 0.05321027922605448, - 0.13392025411839015, + 0.13392025411839015 ],) # Ensure that we do not have excessive memory allocations @@ -397,13 +397,13 @@ end 1.7204593127904542e-5, 1.5921547179522804e-5, 1.5921547180107928e-5, - 4.894071422525737e-5, + 4.894071422525737e-5 ], linf=[ 0.00010525416930584619, 0.00010003778091061122, 0.00010003778085621029, - 0.00036426282101720275, + 0.00036426282101720275 ]) # Ensure that we do not have excessive memory allocations @@ -423,13 +423,13 @@ end 2.344076909832665e-6, 1.8610002398709756e-6, 2.4095132179484066e-6, - 6.37330249340445e-6, + 6.37330249340445e-6 ], linf=[ 2.509979394305084e-5, 2.2683711321080935e-5, 2.6180377720841363e-5, - 5.575278031910713e-5, + 5.575278031910713e-5 ]) # Ensure that we do not have excessive memory allocations @@ -449,13 +449,13 @@ end 1.3333320340010056e-6, 2.044834627970641e-6, 2.044834627855601e-6, - 5.282189803559564e-6, + 5.282189803559564e-6 ], linf=[ 2.7000151718858945e-6, 3.988595028259212e-6, 3.9885950273710336e-6, - 8.848583042286862e-6, + 8.848583042286862e-6 ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_1d_advection.jl b/test/test_tree_1d_advection.jl index 20586c4f3b..115c5f3c69 100644 --- a/test/test_tree_1d_advection.jl +++ b/test/test_tree_1d_advection.jl @@ -92,6 +92,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 8000 end end @@ -112,6 +116,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 8000 end end diff --git a/test/test_tree_1d_euler.jl b/test/test_tree_1d_euler.jl index dc523586f8..7490855252 100644 --- a/test/test_tree_1d_euler.jl +++ b/test/test_tree_1d_euler.jl @@ -15,12 +15,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") l2=[ 2.2527950196212703e-8, 1.8187357193835156e-8, - 7.705669939973104e-8, + 7.705669939973104e-8 ], linf=[ 1.6205433861493646e-7, 1.465427772462391e-7, - 5.372255111879554e-7, + 5.372255111879554e-7 ], # With the default `maxiters = 1` in coverage tests, # there would be no time series to check against. @@ -52,12 +52,12 @@ end l2=[ 0.019355699748523896, 0.022326984561234497, - 0.02523665947241734, + 0.02523665947241734 ], linf=[ 0.02895961127645519, 0.03293442484199227, - 0.04246098278632804, + 0.04246098278632804 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -74,12 +74,12 @@ end l2=[ 0.0011482554820217855, 0.00011482554830323462, - 5.741277429325267e-6, + 5.741277429325267e-6 ], linf=[ 0.004090978306812376, 0.0004090978313582294, - 2.045489210189544e-5, + 2.045489210189544e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -96,12 +96,12 @@ end l2=[ 7.71293052584723e-16, 1.9712947511091717e-14, - 7.50672833504266e-15, + 7.50672833504266e-15 ], linf=[ 3.774758283725532e-15, 6.733502644351574e-14, - 2.4868995751603507e-14, + 2.4868995751603507e-14 ], initial_condition=initial_condition_constant) # Ensure that we do not have excessive memory allocations @@ -120,12 +120,12 @@ end l2=[ 3.8099996914101204e-6, 1.6745575717106341e-6, - 7.732189531480852e-6, + 7.732189531480852e-6 ], linf=[ 1.2971473393186272e-5, 9.270328934274374e-6, - 3.092514399671842e-5, + 3.092514399671842e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -142,12 +142,12 @@ end l2=[ 0.11821957357197649, 0.15330089521538678, - 0.4417674632047301, + 0.4417674632047301 ], linf=[ 0.24280567569982958, 0.29130548795961936, - 0.8847009003152442, + 0.8847009003152442 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -164,12 +164,12 @@ end l2=[ 0.07803455838661963, 0.10032577312032283, - 0.29228156303827935, + 0.29228156303827935 ], linf=[ 0.2549869853794955, 0.3376472164661263, - 0.9650477546553962, + 0.9650477546553962 ], maxiters=10, surface_flux=flux_kennedy_gruber, @@ -189,12 +189,12 @@ end l2=[ 0.07800654460172655, 0.10030365573277883, - 0.2921481199111959, + 0.2921481199111959 ], linf=[ 0.25408579350400395, 0.3388657679031271, - 0.9776486386921928, + 0.9776486386921928 ], maxiters=10, surface_flux=flux_shima_etal, @@ -214,12 +214,12 @@ end l2=[ 0.07801923089205756, 0.10039557434912669, - 0.2922210399923278, + 0.2922210399923278 ], linf=[ 0.2576521982607225, 0.3409717926625057, - 0.9772961936567048, + 0.9772961936567048 ], maxiters=10, surface_flux=flux_chandrashekar, @@ -240,7 +240,7 @@ end linf=[ 0.192621556068018, 0.25184744005299536, - 0.7264977555504792, + 0.7264977555504792 ], maxiters=10, surface_flux=flux_hll, @@ -260,12 +260,12 @@ end l2=[ 0.11606096465319675, 0.15028768943458806, - 0.4328230323046703, + 0.4328230323046703 ], linf=[ 0.18031710091067965, 0.2351582421501841, - 0.6776805692092567, + 0.6776805692092567 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -283,7 +283,7 @@ end linf=[ 2.9766770877037168, 0.16838100902295852, - 2.6655773445485798, + 2.6655773445485798 ], coverage_override=(maxiters = 6,)) # Ensure that we do not have excessive memory allocations @@ -319,7 +319,7 @@ end linf=[ 3.4296365168219216, 0.17635583964559245, - 2.6574584326179505, + 2.6574584326179505 ], # Let this test run longer to cover some lines in flux_hllc coverage_override=(maxiters = 10^5, tspan = (0.0, 0.1))) @@ -339,7 +339,7 @@ end linf=[ 3.1773015255764427, 0.21331831536493773, - 2.6650170188241047, + 2.6650170188241047 ], shock_indicator_variable=pressure, cfl=0.2, @@ -360,7 +360,7 @@ end linf=[ 3.1087017048015824, 0.17734706962928956, - 2.666689753470263, + 2.666689753470263 ], shock_indicator_variable=density, cfl=0.2, @@ -396,7 +396,7 @@ end linf=[ 1.5180897390290355, 1.3967085956620369, - 2.0663825294019595, + 2.0663825294019595 ], maxiters=30) # Ensure that we do not have excessive memory allocations @@ -423,13 +423,13 @@ end 3.876288369618363e-7, 2.2247043122302947e-7, 2.964004224572679e-7, - 5.2716983399807875e-8, + 5.2716983399807875e-8 ], linf=[ 2.3925118561862746e-6, 1.3603693522767912e-6, 1.821888865105592e-6, - 1.1166012159335992e-7, + 1.1166012159335992e-7 ]) # Ensure that we do not have excessive memory allocations @@ -449,13 +449,13 @@ end 0.045510421156346015, 0.036750584788912195, 0.2468985959132176, - 0.03684494180829024, + 0.03684494180829024 ], linf=[ 0.3313374853025697, 0.11621933362158643, 1.827403013568638, - 0.28045939999015723, + 0.28045939999015723 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -473,13 +473,13 @@ end 0.08889113985713998, 0.16199235348889673, 0.40316524365054346, - 2.9602775074723667e-16, + 2.9602775074723667e-16 ], linf=[ 0.28891355898284043, 0.3752709888964313, 0.84477102402413, - 8.881784197001252e-16, + 8.881784197001252e-16 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_1d_eulergravity.jl b/test/test_tree_1d_eulergravity.jl index 17bc0c71a7..70cc294812 100644 --- a/test/test_tree_1d_eulergravity.jl +++ b/test/test_tree_1d_eulergravity.jl @@ -14,11 +14,11 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), l2=[ 0.00021708496949694728, 0.0002913795242132917, - 0.0006112500956552259, + 0.0006112500956552259 ], linf=[ 0.0004977733237385706, 0.0013594226727522418, - 0.0020418739554664, + 0.0020418739554664 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_1d_eulermulti.jl b/test/test_tree_1d_eulermulti.jl index b6c79ce03d..7f5b6d50c9 100644 --- a/test/test_tree_1d_eulermulti.jl +++ b/test/test_tree_1d_eulermulti.jl @@ -51,13 +51,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") 0.1522380497572071, 0.43830846465313206, 0.03907262116499431, - 0.07814524232998862, + 0.07814524232998862 ], linf=[ 0.24939193075537294, 0.7139395740052739, 0.06324208768391237, - 0.12648417536782475, + 0.12648417536782475 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -75,13 +75,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") 8.575236038539227e-5, 0.00016387804318585358, 1.9412699303977585e-5, - 3.882539860795517e-5, + 3.882539860795517e-5 ], linf=[ 0.00030593277277124464, 0.0006244803933350696, 7.253121435135679e-5, - 0.00014506242870271358, + 0.00014506242870271358 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_1d_fdsbp.jl b/test/test_tree_1d_fdsbp.jl index 33d67e3366..71e77eeb38 100644 --- a/test/test_tree_1d_fdsbp.jl +++ b/test/test_tree_1d_fdsbp.jl @@ -94,12 +94,12 @@ end l2=[ 4.1370344463620254e-6, 4.297052451817826e-6, - 9.857382045003056e-6, + 9.857382045003056e-6 ], linf=[ 1.675305070092392e-5, 1.3448113863834266e-5, - 3.8185336878271414e-5, + 3.8185336878271414e-5 ], tspan=(0.0, 0.5)) @@ -118,12 +118,12 @@ end l2=[ 3.413790589105506e-6, 4.243957977156001e-6, - 8.667369423676437e-6, + 8.667369423676437e-6 ], linf=[ 1.4228079689537765e-5, 1.3249887941046978e-5, - 3.201552933251861e-5, + 3.201552933251861e-5 ], tspan=(0.0, 0.5), flux_splitting=splitting_vanleer_haenel) @@ -143,12 +143,12 @@ end l2=[ 8.6126767518378e-6, 7.670897071480729e-6, - 1.4972772284191368e-5, + 1.4972772284191368e-5 ], linf=[ 6.707982777909294e-5, 3.487256699541419e-5, - 0.00010170331350556339, + 0.00010170331350556339 ], tspan=(0.0, 0.5), solver=DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), @@ -169,12 +169,12 @@ end l2=[ 1.5894925236031034e-5, 9.428412101106044e-6, - 0.0008986477358789918, + 0.0008986477358789918 ], linf=[ 4.969438024382544e-5, 2.393091812063694e-5, - 0.003271817388146303, + 0.003271817388146303 ], tspan=(0.0, 0.005), abstol=1.0e-9, reltol=1.0e-9) diff --git a/test/test_tree_1d_hypdiff.jl b/test/test_tree_1d_hypdiff.jl index 896a3d4c8d..cd570c1670 100644 --- a/test/test_tree_1d_hypdiff.jl +++ b/test/test_tree_1d_hypdiff.jl @@ -37,6 +37,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 end end diff --git a/test/test_tree_1d_linearizedeuler.jl b/test/test_tree_1d_linearizedeuler.jl index c7cffee3f6..210ad8645d 100644 --- a/test/test_tree_1d_linearizedeuler.jl +++ b/test/test_tree_1d_linearizedeuler.jl @@ -14,12 +14,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") l2=[ 0.00010894927270421941, 0.00014295255695912358, - 0.00010894927270421941, + 0.00010894927270421941 ], linf=[ 0.0005154647164193893, 0.00048457837684242266, - 0.0005154647164193893, + 0.0005154647164193893 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -37,7 +37,7 @@ end linf=[ 1.9999505145390108, 0.9999720404625275, - 1.9999505145390108, + 1.9999505145390108 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_1d_mhd.jl b/test/test_tree_1d_mhd.jl index 2150ddfd07..e27a075b09 100644 --- a/test/test_tree_1d_mhd.jl +++ b/test/test_tree_1d_mhd.jl @@ -20,7 +20,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") 3.9938347410210535e-14, 3.984545392098788e-16, 2.4782402104201577e-15, - 1.551737464879987e-15, + 1.551737464879987e-15 ], linf=[ 1.9984014443252818e-15, @@ -30,7 +30,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") 7.815970093361102e-14, 8.881784197001252e-16, 2.886579864025407e-15, - 2.942091015256665e-15, + 2.942091015256665e-15 ], initial_condition=initial_condition_constant, tspan=(0.0, 1.0)) @@ -54,7 +54,7 @@ end 5.084863194951084e-6, 1.1963224165731992e-16, 3.598916927583752e-5, - 3.598916927594727e-5, + 3.598916927594727e-5 ], linf=[ 2.614095879338585e-5, @@ -64,7 +64,7 @@ end 1.5066209528846741e-5, 2.220446049250313e-16, 0.00012658678753942054, - 0.00012658678753908748, + 0.00012658678753908748 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -86,7 +86,7 @@ end 1.967962220860377e-6, 1.1963224165731992e-16, 3.583562899483433e-5, - 3.583562899486565e-5, + 3.583562899486565e-5 ], linf=[ 5.830577969345718e-5, @@ -96,7 +96,7 @@ end 6.978806516122482e-6, 2.220446049250313e-16, 0.00012564003648959932, - 0.00012564003648994626, + 0.00012564003648994626 ], volume_flux=flux_derigs_etal) # Ensure that we do not have excessive memory allocations @@ -115,13 +115,13 @@ end 1.036850596986597e-5, 1.965192583650368e-6, 3.5882124656715505e-5, 3.5882124656638764e-5, 5.270975504780837e-6, 1.1963224165731992e-16, - 3.595811808912869e-5, 3.5958118089159453e-5, + 3.595811808912869e-5, 3.5958118089159453e-5 ], linf=[ 2.887280521446378e-5, 7.310580790352001e-6, 0.00012390046377899755, 0.00012390046377787345, 1.5102711136583125e-5, 2.220446049250313e-16, - 0.0001261935452181312, 0.0001261935452182006, + 0.0001261935452181312, 0.0001261935452182006 ], surface_flux=flux_hllc) # Ensure that we do not have excessive memory allocations @@ -144,7 +144,7 @@ end 0.15578125987042743, 4.130462730494e-17, 0.05465258887150046, - 0.05465258887150046, + 0.05465258887150046 ], linf=[ 0.12165312668363826, @@ -154,7 +154,7 @@ end 0.44079257431070706, 1.1102230246251565e-16, 0.10528911365809579, - 0.10528911365809579, + 0.10528911365809579 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -176,7 +176,7 @@ end 0.3723215736814466, 1.2060075775846403e-15, 0.36276754492568164, - 0.0, + 0.0 ], linf=[ 0.5797109945880677, @@ -186,7 +186,7 @@ end 1.0526758874956808, 5.995204332975845e-15, 1.5122922036932964, - 0.0, + 0.0 ], coverage_override=(maxiters = 6,)) # Ensure that we do not have excessive memory allocations @@ -209,7 +209,7 @@ end 0.9204708961093411, 1.3216517820475193e-16, 0.28897419402047725, - 0.25521206483145126, + 0.25521206483145126 ], linf=[ 1.2185238171352286, @@ -219,7 +219,7 @@ end 1.660723397705417, 2.220446049250313e-16, 0.6874726847741993, - 0.65536978110274, + 0.65536978110274 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -238,13 +238,13 @@ end 0.4573799618744708, 0.4792633358230866, 0.34064852506872795, 0.4479668434955162, 0.9203891782415092, 1.3216517820475193e-16, 0.28887826520860815, - 0.255281629265771, + 0.255281629265771 ], linf=[ 1.2382842201671505, 0.8929169308132259, 0.871298623806198, 0.9822415614542821, 1.6726170732132717, 2.220446049250313e-16, 0.7016155888023747, - 0.6556091522071984, + 0.6556091522071984 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -266,7 +266,7 @@ end 0.9606363432904367, 6.608258910237605e-17, 0.21542929107153735, - 0.10705457908737925, + 0.10705457908737925 ], linf=[ 0.6447951791685409, @@ -276,7 +276,7 @@ end 2.0770652030507053, 1.1102230246251565e-16, 0.49670855513788204, - 0.24830199967863564, + 0.24830199967863564 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -299,7 +299,7 @@ end 5.21930435e+01, 6.56538824e-16, 1.01022340e+00, - 0.00000000e+00, + 0.00000000e+00 ], linf=[ 2.87172004e+00, @@ -309,7 +309,7 @@ end 1.35152372e+02, 3.44169138e-15, 2.83556069e+00, - 0.00000000e+00, + 0.00000000e+00 ], tspan=(0.0, 0.2), coverage_override=(maxiters = 6,)) @@ -336,7 +336,7 @@ end 5.23565514e+01, 3.18641825e-16, 1.00485291e+00, - 0.00000000e+00, + 0.00000000e+00 ], linf=[ 2.92876280e+00, @@ -346,7 +346,7 @@ end 1.36966213e+02, 1.55431223e-15, 2.80548864e+00, - 0.00000000e+00, + 0.00000000e+00 ], initial_condition=initial_condition_shu_osher_shock_tube_flipped, boundary_conditions=BoundaryConditionDirichlet(initial_condition_shu_osher_shock_tube_flipped), diff --git a/test/test_tree_1d_shallowwater.jl b/test/test_tree_1d_shallowwater.jl index 42a91e578e..79fd313148 100644 --- a/test/test_tree_1d_shallowwater.jl +++ b/test/test_tree_1d_shallowwater.jl @@ -15,12 +15,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") l2=[ 0.24476140682560343, 0.8587309324660326, - 0.07330427577586297, + 0.07330427577586297 ], linf=[ 2.1636963952308372, 3.8737770522883115, - 1.7711213427919539, + 1.7711213427919539 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -38,12 +38,12 @@ end l2=[ 0.39472828074570576, 2.0390687947320076, - 4.1623084150546725e-10, + 4.1623084150546725e-10 ], linf=[ 0.7793741954662221, 3.2411927977882096, - 7.419800190922032e-10, + 7.419800190922032e-10 ], initial_condition=initial_condition_weak_blast_wave, tspan=(0.0, 0.25)) @@ -62,7 +62,7 @@ end l2=[ 0.10416666834254829, 1.4352935256803184e-14, - 0.10416666834254838, + 0.10416666834254838 ], linf=[1.9999999999999996, 3.248036646353028e-14, 2.0], tspan=(0.0, 0.25)) @@ -81,7 +81,7 @@ end l2=[ 0.10416666834254835, 1.1891029971551825e-14, - 0.10416666834254838, + 0.10416666834254838 ], linf=[2.0000000000000018, 2.4019608337954543e-14, 2.0], surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, @@ -103,7 +103,7 @@ end l2=[ 0.10416666834254838, 1.6657566141935285e-14, - 0.10416666834254838, + 0.10416666834254838 ], linf=[2.0000000000000004, 3.0610625110157164e-14, 2.0], surface_flux=(flux_wintermeyer_etal, @@ -124,12 +124,12 @@ end l2=[ 0.0022363707373868713, 0.01576799981934617, - 4.436491725585346e-5, + 4.436491725585346e-5 ], linf=[ 0.00893601803417754, 0.05939797350246456, - 9.098379777405796e-5, + 9.098379777405796e-5 ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -147,12 +147,12 @@ end l2=[ 0.002275023323848826, 0.015861093821754046, - 4.436491725585346e-5, + 4.436491725585346e-5 ], linf=[ 0.008461451098266792, 0.05722331401673486, - 9.098379777405796e-5, + 9.098379777405796e-5 ], tspan=(0.0, 0.025), surface_flux=(flux_hll, @@ -172,12 +172,12 @@ end l2=[ 0.005774284062933275, 0.017408601639513584, - 4.43649172561843e-5, + 4.43649172561843e-5 ], linf=[ 0.01639116193303547, 0.05102877460799604, - 9.098379777450205e-5, + 9.098379777450205e-5 ], surface_flux=(flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal), @@ -198,12 +198,12 @@ end l2=[ 0.0022667320585353927, 0.01571629729279524, - 4.4364917255842716e-5, + 4.4364917255842716e-5 ], linf=[ 0.008945234652224965, 0.059403165802872415, - 9.098379777405796e-5, + 9.098379777405796e-5 ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -222,12 +222,12 @@ end l2=[ 0.0022774071143995952, 0.01566214422689219, - 4.4364917255842716e-5, + 4.4364917255842716e-5 ], linf=[ 0.008451721489057373, 0.05720939055279217, - 9.098379777405796e-5, + 9.098379777405796e-5 ], surface_flux=(FluxHydrostaticReconstruction(FluxHLL(min_max_speed_naive), hydrostatic_reconstruction_audusse_etal), @@ -249,12 +249,12 @@ end l2=[ 1.725964362045055e-8, 5.0427180314307505e-16, - 1.7259643530442137e-8, + 1.7259643530442137e-8 ], linf=[ 3.844551077492042e-8, 3.469453422316143e-15, - 3.844551077492042e-8, + 3.844551077492042e-8 ], tspan=(0.0, 0.25), surface_flux=(FluxHLL(min_max_speed_naive), @@ -275,12 +275,12 @@ end l2=[ 1.7259643614361866e-8, 3.5519018243195145e-16, - 1.7259643530442137e-8, + 1.7259643530442137e-8 ], linf=[ 3.844551010878661e-8, 9.846474508971374e-16, - 3.844551077492042e-8, + 3.844551077492042e-8 ], tspan=(0.0, 0.25), surface_flux=(FluxHLL(min_max_speed_naive), @@ -303,7 +303,7 @@ end linf=[ 1.1209754279344226, 1.3230788645853582, - 0.8646939843534251, + 0.8646939843534251 ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -323,13 +323,13 @@ end 6.37048760275098e-5, 0.0002745658116815704, 4.436491725647962e-6, - 8.872983451152218e-6, + 8.872983451152218e-6 ], linf=[ 0.00026747526881631956, 0.0012106730729152249, 9.098379777500165e-6, - 1.8196759554278685e-5, + 1.8196759554278685e-5 ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -349,13 +349,13 @@ end 1.4250229186905198e-14, 2.495109919406496e-12, 7.408599286788738e-17, - 2.7205812409138776e-16, + 2.7205812409138776e-16 ], linf=[ 5.284661597215745e-14, 2.74056233065078e-12, 2.220446049250313e-16, - 8.881784197001252e-16, + 8.881784197001252e-16 ], tspan=(0.0, 100.0)) # Ensure that we do not have excessive memory allocations @@ -375,13 +375,13 @@ end 0.02843233740533314, 0.14083324483705398, 0.0054554472558998, - 0.005455447255899814, + 0.005455447255899814 ], linf=[ 0.26095842440037487, 0.45919004549253795, 0.09999999999999983, - 0.10000000000000009, + 0.10000000000000009 ],) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_2d_acoustics.jl b/test/test_tree_2d_acoustics.jl index 89bccbf8ca..070eca8772 100644 --- a/test/test_tree_2d_acoustics.jl +++ b/test/test_tree_2d_acoustics.jl @@ -19,7 +19,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.0, 0.0, 0.0, - 0.0, + 0.0 ], linf=[ 0.00769282588065634, @@ -28,7 +28,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.0, 0.0, 0.0, - 0.0, + 0.0 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -49,7 +49,7 @@ end 0.0, 0.0, 0.0, - 0.0, + 0.0 ], linf=[ 0.17261097190220992, @@ -58,7 +58,7 @@ end 0.0, 0.0, 0.0, - 0.0, + 0.0 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -79,7 +79,7 @@ end 0.0, 0.0, 0.0, - 0.0, + 0.0 ], linf=[ 0.03970270697049378, @@ -88,7 +88,7 @@ end 0.0, 0.0, 0.0, - 0.0, + 0.0 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_2d_advection.jl b/test/test_tree_2d_advection.jl index b111651aa6..f62239c7e9 100644 --- a/test/test_tree_2d_advection.jl +++ b/test/test_tree_2d_advection.jl @@ -163,6 +163,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -180,6 +184,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -197,6 +205,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -212,6 +224,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -228,6 +244,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -245,6 +265,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 40ee67bf27..65448da0e3 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -16,13 +16,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, - 4.824553091276693e-6, + 4.824553091276693e-6 ], linf=[ 9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, - 4.8869615580926506e-5, + 4.8869615580926506e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -41,13 +41,13 @@ end 2.0633069593983843e-6, 1.9337331005472223e-6, 1.9337331005227536e-6, - 5.885362117543159e-6, + 5.885362117543159e-6 ], linf=[ 1.636984098429828e-5, 1.5579038690871627e-5, 1.557903868998345e-5, - 5.260532107742577e-5, + 5.260532107742577e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -55,6 +55,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -65,13 +69,13 @@ end 0.026440292358506527, 0.013245905852168414, 0.013245905852168479, - 0.03912520302609374, + 0.03912520302609374 ], linf=[ 0.042130817806361964, 0.022685499230187034, 0.022685499230187922, - 0.06999771202145322, + 0.06999771202145322 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -89,13 +93,13 @@ end 0.1289984161854359, 0.012899841618543363, 0.025799683237087086, - 0.003224960404636081, + 0.003224960404636081 ], linf=[ 0.9436588685021441, 0.0943658868502173, 0.1887317737004306, - 0.02359147170911058, + 0.02359147170911058 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -103,6 +107,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -113,13 +121,13 @@ end 0.0010600778457964775, 0.00010600778457634275, 0.00021201556915872665, - 2.650194614399671e-5, + 2.650194614399671e-5 ], linf=[ 0.006614198043413566, 0.0006614198043973507, 0.001322839608837334, - 0.000165354951256802, + 0.000165354951256802 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -139,13 +147,13 @@ end 2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, - 6.3327863238858925e-6, + 6.3327863238858925e-6 ], linf=[ 1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, - 6.0526717141407005e-5, + 6.0526717141407005e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -163,13 +171,13 @@ end 0.061751715597716854, 0.05018223615408711, 0.05018989446443463, - 0.225871559730513, + 0.225871559730513 ], linf=[ 0.29347582879608825, 0.31081249232844693, 0.3107380389947736, - 1.0540358049885143, + 1.0540358049885143 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -187,13 +195,13 @@ end 0.03481471610306124, 0.027694280613944234, 0.027697905866996532, - 0.12932052501462554, + 0.12932052501462554 ], linf=[ 0.31052098400669004, 0.3481295959664616, 0.34807152194137336, - 1.1044947556170719, + 1.1044947556170719 ], maxiters=10, surface_flux=flux_kennedy_gruber, @@ -214,13 +222,13 @@ end 0.03481122603050542, 0.027662840593087695, 0.027665658732350273, - 0.12927455860656786, + 0.12927455860656786 ], linf=[ 0.3110089578739834, 0.34888111987218107, 0.3488278669826813, - 1.1056349046774305, + 1.1056349046774305 ], maxiters=10, surface_flux=flux_chandrashekar, @@ -241,13 +249,13 @@ end 0.05380629130119074, 0.04696798008325309, 0.04697067787841479, - 0.19687382235494968, + 0.19687382235494968 ], linf=[ 0.18527440131928286, 0.2404798030563736, 0.23269573860381076, - 0.6874012187446894, + 0.6874012187446894 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -266,13 +274,13 @@ end 0.08508152653623638, 0.04510301725066843, 0.04510304668512745, - 0.6930705064715306, + 0.6930705064715306 ], linf=[ 0.31136518019691406, 0.5617651935473419, 0.5621200790240503, - 2.8866869108596056, + 2.8866869108596056 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -280,6 +288,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -298,13 +310,13 @@ end 0.05624855363458103, 0.06931288786158463, 0.06931283188960778, - 0.6200535829842072, + 0.6200535829842072 ], linf=[ 0.29029967648805566, 0.6494728865862608, 0.6494729363533714, - 3.0949621505674787, + 3.0949621505674787 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -312,6 +324,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -322,13 +338,13 @@ end 0.14170569763947993, 0.11647068900798814, 0.11647072556898294, - 0.3391989213659599, + 0.3391989213659599 ], linf=[ 1.6544204510794196, 1.35194638484646, 1.3519463848472744, - 1.831228461662809, + 1.831228461662809 ], maxiters=30) # Ensure that we do not have excessive memory allocations @@ -347,13 +363,13 @@ end 0.39957047631960346, 0.21006912294983154, 0.21006903549932, - 0.6280328163981136, + 0.6280328163981136 ], linf=[ 2.20417889887697, 1.5487238480003327, 1.5486788679247812, - 2.4656795949035857, + 2.4656795949035857 ], tspan=(0.0, 0.5), # Let this test run longer to cover some lines in flux_hllc @@ -374,13 +390,13 @@ end 0.6835576416907511, 0.2839963955262972, 0.28399565983676, - 0.7229447806293277, + 0.7229447806293277 ], linf=[ 3.0969614882801393, 1.7967947300740248, 1.7967508302506658, - 3.040149575567518, + 3.040149575567518 ], tspan=(0.0, 1.0), coverage_override=(maxiters = 6,)) @@ -400,13 +416,13 @@ end 0.30783113348004093, 0.17597018114974242, 0.17594406844552404, - 0.6141151469952726, + 0.6141151469952726 ], linf=[ 1.297252661541156, 1.105840523330678, 1.1058680103852032, - 2.434846187265568, + 2.434846187265568 ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -417,6 +433,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -425,16 +445,16 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), l2=[ - 0.3221177942225801, - 0.1798478357478982, - 0.1798364616438908, - 0.6136884131056267, + 0.3221078812528291, + 0.17985175694043076, + 0.17983453493705628, + 0.6136916718599121 ], linf=[ - 1.343766644801395, - 1.1749593109683463, - 1.1747613085307178, - 2.4216006041018785, + 1.343237509126809, + 1.1747101056222315, + 1.174585608472406, + 2.4216027326405487 ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -445,6 +465,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -455,13 +479,13 @@ end 0.32716628280821736, 0.17711362716405113, 0.17710881738119433, - 0.6192141753914343, + 0.6192141753914343 ], linf=[ 1.3147680231795071, 1.1313232952582144, 1.1308868661560831, - 2.4962119219206, + 2.4962119219206 ], tspan=(0.0, 0.5), initial_refinement_level=4, @@ -472,6 +496,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -482,13 +510,13 @@ end 0.4866953770742574, 0.1673477470091984, 0.16734774700934, - 0.6184367248923149, + 0.6184367248923149 ], linf=[ 2.6724832723962053, 1.2916089288910635, 1.2916089289001427, - 6.474699399394252, + 6.474699399394252 ], tspan=(0.0, 1.0), coverage_override=(maxiters = 6,)) @@ -507,23 +535,24 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ - 0.47651273561515994, - 0.16605194156429376, - 0.16605194156447747, - 0.6184646142923547, + 0.47655346892955674, + 0.16607711235359662, + 0.1660771123538105, + 0.6184647017781574 ], linf=[ - 2.559717182592356, - 1.3594817545576394, - 1.3594817545666105, - 6.451896959781657, + 2.5594865854274684, + 1.357936711037511, + 1.3579367110516134, + 6.451786248376557 ], tspan=(0.0, 1.0), initial_refinement_level=4, coverage_override=(maxiters = 6,), save_errors=true) lines = readlines(joinpath("out", "deviations.txt")) - @test lines[1] == "# iter, simu_time, rho_min, rho_max, entropy_guermond_etal_min" + @test lines[1] == + "# iter, simu_time, rho_min, rho_max, entropy_guermond_etal_min, pressure_min" cmd = string(Base.julia_cmd()) coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", cmd) @@ -540,6 +569,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -551,13 +584,13 @@ end 0.4740321851943766, 0.15889871334104985, 0.15889871334104988, - 0.6190405536267991, + 0.6190405536267991 ], linf=[ 4.011954283668753, 1.8527131099524292, 1.8527131099524277, - 6.465833729130187, + 6.465833729130187 ], tspan=(0.0, 1.0), initial_refinement_level=4, @@ -582,6 +615,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -592,13 +629,13 @@ end 0.352405949321075, 0.17207721487429464, 0.17207721487433883, - 0.6263024434020885, + 0.6263024434020885 ], linf=[ 2.760997358628186, 1.8279186132509326, 1.8279186132502805, - 6.251573757093399, + 6.251573757093399 ], tspan=(0.0, 0.5), callbacks=CallbackSet(summary_callback, @@ -621,13 +658,13 @@ end 0.48862067511841695, 0.16787541578869494, 0.16787541578869422, - 0.6184319933114926, + 0.6184319933114926 ], linf=[ 2.6766520821013002, 1.2910938760258996, 1.2910938760258899, - 6.473385481404865, + 6.473385481404865 ], tspan=(0.0, 1.0), coverage_override=(maxiters = 3,)) @@ -647,13 +684,13 @@ end 0.22271619518391986, 0.6284824759323494, 0.24864213447943648, - 2.9591811489995474, + 2.9591811489995474 ], linf=[ 9.15245400430106, 24.96562810334389, 10.388109127032374, - 101.20581544156934, + 101.20581544156934 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -672,13 +709,13 @@ end 0.2086261501910662, 1.2118352377894666, 0.10255333189606497, - 5.296238138639236, + 5.296238138639236 ], linf=[ 14.829071984498198, 74.12967742435727, 6.863554388300223, - 303.58813147491134, + 303.58813147491134 ], tspan=(0.0, 0.12), # Let this test run longer to cover the ControllerThreeLevelCombined lines @@ -700,13 +737,13 @@ end 0.1057230211245312, 0.10621112311257341, 0.07260957505339989, - 0.11178239111065721, + 0.11178239111065721 ], linf=[ 2.998719417992662, 2.1400285015556166, 1.1569648700415078, - 1.8922492268110913, + 1.8922492268110913 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -726,13 +763,13 @@ end 0.055691508271624536, 0.032986009333751655, 0.05224390923711999, - 0.08009536362771563, + 0.08009536362771563 ], linf=[ 0.24043622527087494, 0.1660878796929941, 0.12355946691711608, - 0.2694290787257758, + 0.2694290787257758 ], tspan=(0.0, 0.2)) # Ensure that we do not have excessive memory allocations @@ -752,13 +789,13 @@ end 0.05569452733654995, 0.033107109983417926, 0.05223609622852158, - 0.08007777597488817, + 0.08007777597488817 ], linf=[ 0.2535807803900303, 0.17397028249895308, 0.12321616095649354, - 0.269046666668995, + 0.269046666668995 ], tspan=(0.0, 0.2), coverage_override=(maxiters = 2,)) @@ -780,13 +817,13 @@ end 0.055703165296633834, 0.032987233605927, 0.05224472051711956, - 0.08011565264331237, + 0.08011565264331237 ], linf=[ 0.24091018397460595, 0.1660190071332282, 0.12356154893467916, - 0.2695167937393226, + 0.2695167937393226 ], tspan=(0.0, 0.2), coverage_override=(maxiters = 3,), @@ -801,6 +838,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -812,13 +853,13 @@ end 0.055703165296633834, 0.032987233605927, 0.05224472051711956, - 0.08011565264331237, + 0.08011565264331237 ], linf=[ 0.24091018397460595, 0.1660190071332282, 0.12356154893467916, - 0.2695167937393226, + 0.2695167937393226 ], tspan=(0.0, 0.2), initial_refinement_level=5, @@ -829,6 +870,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -839,13 +884,13 @@ end 0.007237139090503349, 0.044887582765386916, 1.0453570959003603e-6, - 0.6627307840935432, + 0.6627307840935432 ], linf=[ 0.19437260992446315, 0.5554343646648533, 5.943891455255412e-5, - 15.188919846360125, + 15.188919846360125 ], tspan=(0.0, 0.1)) # Ensure that we do not have excessive memory allocations @@ -864,13 +909,13 @@ end 0.006768801432802192, 0.032184992228603666, 6.923887797276484e-7, - 0.6784222932398366, + 0.6784222932398366 ], linf=[ 0.2508663007713608, 0.4097017076529792, 0.0003528986458217968, - 22.435474993016918, + 22.435474993016918 ], tspan=(0.0, 0.1), coverage_override=(maxiters = 2,)) @@ -890,13 +935,13 @@ end 0.011338365293662804, 10.09743543555765, 0.00392429463200361, - 4031.7811487690506, + 4031.7811487690506 ], linf=[ 3.3178633141984193, 2993.6445033486402, 8.031723414357423, - 1.1918867260293828e6, + 1.1918867260293828e6 ], tspan=(0.0, 1.0e-7), coverage_override=(maxiters = 6,)) @@ -916,13 +961,13 @@ end 0.4186473232186195, 341.42386623555944, 12.913743102619245, - 135260.31735534978, + 135260.31735534978 ], linf=[ 6.594617349637199, 5225.251243383396, 417.4788228266706, - 2.0263599311276933e6, + 2.0263599311276933e6 ], initial_refinement_level=5, tspan=(0.0, 1.0e-4), @@ -933,6 +978,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -943,13 +992,13 @@ end 0.4142490642847159, 339.10045752248817, 12.41716316125269, - 134277.32794840127, + 134277.32794840127 ], linf=[ 5.649893737038036, 4628.887032664001, 373.39317079274724, - 1.8133961097673306e6, + 1.8133961097673306e6 ], initial_refinement_level=5, tspan=(0.0, 1.0e-4), @@ -960,6 +1009,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -970,13 +1023,13 @@ end 0.00013492249515826863, 0.006615696236378061, 0.006782108219800376, - 0.016393831451740604, + 0.016393831451740604 ], linf=[ 0.0020782600954247776, 0.08150078921935999, 0.08663621974991986, - 0.2829930622010579, + 0.2829930622010579 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -995,13 +1048,13 @@ end 0.0017208369388227673, 0.09628684992237334, 0.09620157717330868, - 0.1758809552387432, + 0.1758809552387432 ], linf=[ 0.021869936355319086, 0.9956698009442038, 1.0002507727219028, - 2.223249697515648, + 2.223249697515648 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1019,13 +1072,13 @@ end 0.0017203323613648241, 0.09628962878682261, 0.09621241164155782, - 0.17585995600340926, + 0.17585995600340926 ], linf=[ 0.021740570456931674, 0.9938841665880938, 1.004140123355135, - 2.224108857746245, + 2.224108857746245 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1043,13 +1096,13 @@ end 0.0017158367642679273, 0.09619888722871434, 0.09616432767924141, - 0.17553381166255197, + 0.17553381166255197 ], linf=[ 0.021853862449723982, 0.9878047229255944, 0.9880191167111795, - 2.2154030488035588, + 2.2154030488035588 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1068,13 +1121,13 @@ end 0.0017203324051381415, 0.09628962899999398, 0.0962124115572114, - 0.1758599596626405, + 0.1758599596626405 ], linf=[ 0.021740568112562086, 0.9938841624655501, 1.0041401179009877, - 2.2241087041100798, + 2.2241087041100798 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -1093,13 +1146,13 @@ end 5.051719943432265e-5, 0.0022574259317084747, 0.0021755998463189713, - 0.004346492398617521, + 0.004346492398617521 ], linf=[ 0.0012880114865917447, 0.03857193149447702, 0.031090457959835893, - 0.12125130332971423, + 0.12125130332971423 ], # Let this test run longer to cover some lines in the AMR indicator coverage_override=(maxiters = 10^5, tspan = (0.0, 10.5))) @@ -1119,13 +1172,13 @@ end 0.03341239373099515, 0.026673245711492915, 0.026678871434568822, - 0.12397486476145089, + 0.12397486476145089 ], linf=[ 0.3290981764688339, 0.3812055782309788, 0.3812041851225023, - 1.168251216556933, + 1.168251216556933 ], periodicity=false, boundary_conditions=boundary_condition_slip_wall, @@ -1146,13 +1199,13 @@ end 0.0001379946769624388, 0.02078779689715382, 0.033237241571263176, - 31.36068872331705, + 31.36068872331705 ], linf=[ 0.0016286690573188434, 0.15623770697198225, 0.3341371832270615, - 334.5373488726036, + 334.5373488726036 ], tspan=(0.0, 10.0), initial_refinement_level=4) @@ -1174,13 +1227,13 @@ end 1.1790213022362371e-16, 8.580657423476384e-17, 1.3082387431804115e-16, - 1.6182739965672862e-15, + 1.6182739965672862e-15 ], linf=[ 3.3306690738754696e-16, 2.220446049250313e-16, 5.273559366969494e-16, - 3.552713678800501e-15, + 3.552713678800501e-15 ], maxiters=1, initial_condition=initial_condition_constant) @@ -1200,13 +1253,13 @@ end 0.0021196114178949396, 0.010703549234544042, 0.01070354923454404, - 0.10719124037195142, + 0.10719124037195142 ], linf=[ 0.11987270645890724, 0.7468615461136827, 0.7468615461136827, - 3.910689155287799, + 3.910689155287799 ], maxiters=1) diff --git a/test/test_tree_2d_euleracoustics.jl b/test/test_tree_2d_euleracoustics.jl index e3a4d65f39..2ca893899b 100644 --- a/test/test_tree_2d_euleracoustics.jl +++ b/test/test_tree_2d_euleracoustics.jl @@ -22,7 +22,7 @@ EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") 13.000001753042364, 26.00000080243847, 38.00000884725549, - 51.000000003859995, + 51.000000003859995 ], linf=[ 0.22312716933051027, @@ -31,7 +31,7 @@ EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") 13.468872744263273, 26.54666679978679, 38.139032147739684, - 51.378134660241294, + 51.378134660241294 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 95e2ae5313..05d72c9612 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -40,14 +40,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.9174752929795251, 57942.83587826468, 0.1828847253029943, - 0.011127037850925347, + 0.011127037850925347 ], linf=[ 196.81051991521073, 7.8456811648529605, 158891.88930113698, 0.811379581519794, - 0.08011973559187913, + 0.08011973559187913 ], tspan=(0.0, 0.001)) # Ensure that we do not have excessive memory allocations @@ -69,14 +69,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 2.5455678559421346, 63229.190712645846, 0.19929478404550321, - 0.011068604228443425, + 0.011068604228443425 ], linf=[ 249.21708417382013, 40.33299887640794, 174205.0118831558, 0.6881458768113586, - 0.11274401158173972, + 0.11274401158173972 ], initial_refinement_level=3, tspan=(0.0, 0.001), @@ -91,6 +91,10 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -103,14 +107,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 1.9879932386864965, 59851.345150393994, 0.1871098818112499, - 0.010631432251136151, + 0.010631432251136151 ], linf=[ 212.71245739310544, 27.399221359958894, 158389.9681231281, 0.6524718882809865, - 0.10630137919864985, + 0.10630137919864985 ], initial_refinement_level=3, tspan=(0.0, 0.001)) @@ -120,6 +124,10 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -130,13 +138,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.050182236154087095, 0.050189894464434635, 0.2258715597305131, - 0.06175171559771687, + 0.06175171559771687 ], linf=[ 0.3108124923284472, 0.3107380389947733, 1.054035804988521, - 0.29347582879608936, + 0.29347582879608936 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -157,7 +165,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.004087155041747821, 0.008174310083495642, 0.016348620166991283, - 0.032697240333982566, + 0.032697240333982566 ], linf=[ 0.2488251110766228, @@ -166,7 +174,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.017452870465607374, 0.03490574093121475, 0.0698114818624295, - 0.139622963724859, + 0.139622963724859 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -185,14 +193,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.00012290225488321876, 0.00018867397906337653, 4.8542321753649044e-5, - 9.708464350729809e-5, + 9.708464350729809e-5 ], linf=[ 0.0006722819239133315, 0.0006722819239128874, 0.0012662292789555885, 0.0002843844182700561, - 0.0005687688365401122, + 0.0005687688365401122 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -211,14 +219,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 2.266177386666318e-6, 6.593514692980009e-6, 8.836308667348217e-7, - 1.7672617334696433e-6, + 1.7672617334696433e-6 ], linf=[ 1.4713170997993075e-5, 1.4713170997104896e-5, 5.115618808515521e-5, 5.3639516094383666e-6, - 1.0727903218876733e-5, + 1.0727903218876733e-5 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -237,14 +245,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 1.862173764098385e-6, 5.942585713809631e-6, 6.216263279534722e-7, - 1.2432526559069443e-6, + 1.2432526559069443e-6 ], linf=[ 1.6235495582606063e-5, 1.6235495576388814e-5, 5.854523678827661e-5, 5.790274858807898e-6, - 1.1580549717615796e-5, + 1.1580549717615796e-5 ], volume_flux=flux_chandrashekar) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_2d_eulerpolytropic.jl b/test/test_tree_2d_eulerpolytropic.jl index 545cf7274f..dd6bb5700c 100644 --- a/test/test_tree_2d_eulerpolytropic.jl +++ b/test/test_tree_2d_eulerpolytropic.jl @@ -15,11 +15,11 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") "elixir_eulerpolytropic_convergence.jl"), l2=[ 0.0016689832177626373, 0.0025920263793094526, - 0.003281074494626679, + 0.003281074494626679 ], linf=[ 0.010994883201896677, 0.013309526619350365, - 0.02008032661117376, + 0.02008032661117376 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_tree_2d_fdsbp.jl b/test/test_tree_2d_fdsbp.jl index d477cab056..ae0bb4157d 100644 --- a/test/test_tree_2d_fdsbp.jl +++ b/test/test_tree_2d_fdsbp.jl @@ -56,13 +56,13 @@ end 1.7088389997042244e-6, 1.7437997855125774e-6, 1.7437997855350776e-6, - 5.457223460127621e-6, + 5.457223460127621e-6 ], linf=[ 9.796504903736292e-6, 9.614745892783105e-6, 9.614745892783105e-6, - 4.026107182575345e-5, + 4.026107182575345e-5 ], tspan=(0.0, 0.1)) @@ -82,13 +82,13 @@ end 2.1149087345799973e-6, 1.9391438806845798e-6, 1.9391438806759794e-6, - 5.842833764682604e-6, + 5.842833764682604e-6 ], linf=[ 1.3679037540903494e-5, 1.1770587849069258e-5, 1.1770587848403125e-5, - 4.68952678644996e-5, + 4.68952678644996e-5 ], tspan=(0.0, 0.1), flux_splitting=splitting_lax_friedrichs) @@ -108,13 +108,13 @@ end 1.708838999643608e-6, 1.7437997854485807e-6, 1.7437997854741082e-6, - 5.457223460116349e-6, + 5.457223460116349e-6 ], linf=[ 9.796504911285808e-6, 9.614745899888533e-6, 9.614745899444443e-6, - 4.02610718399643e-5, + 4.02610718399643e-5 ], tspan=(0.0, 0.1), flux_splitting=splitting_drikakis_tsangaris) @@ -135,13 +135,13 @@ end 0.02607850081951497, 0.020357717558016252, 0.028510191844948945, - 0.02951535039734857, + 0.02951535039734857 ], linf=[ 0.12185328623662173, 0.1065055387595834, 0.06257122956937419, - 0.11992349951978643, + 0.11992349951978643 ], tspan=(0.0, 0.1)) @@ -161,13 +161,13 @@ end 0.0005330228930711585, 0.028475888529345014, 0.02847513865894387, - 0.056259951995581196, + 0.056259951995581196 ], linf=[ 0.007206088611304784, 0.31690373882847234, 0.31685665067192326, - 0.7938167296134893, + 0.7938167296134893 ], tspan=(0.0, 0.25)) diff --git a/test/test_tree_2d_hypdiff.jl b/test/test_tree_2d_hypdiff.jl index 8c5973cbf0..21a20ff2d4 100644 --- a/test/test_tree_2d_hypdiff.jl +++ b/test/test_tree_2d_hypdiff.jl @@ -15,12 +15,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") l2=[ 0.00015687751817403066, 0.001025986772216324, - 0.0010259867722164071, + 0.0010259867722164071 ], linf=[ 0.001198695637957381, 0.006423873515531753, - 0.006423873515533529, + 0.006423873515533529 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -28,6 +28,10 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -38,12 +42,12 @@ end l2=[ 8.618132355121019e-8, 5.619399844384306e-7, - 5.619399844844044e-7, + 5.619399844844044e-7 ], linf=[ 1.1248618588430072e-6, 8.622436487026874e-6, - 8.622436487915053e-6, + 8.622436487915053e-6 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -60,12 +64,12 @@ end l2=[ 8.523077653954864e-6, 2.8779323653020624e-5, - 5.454942769125663e-5, + 5.454942769125663e-5 ], linf=[ 5.522740952468297e-5, 0.00014544895978971679, - 0.00032396328684924924, + 0.00032396328684924924 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -82,12 +86,12 @@ end l2=[ 5.868147556427088e-6, 3.80517927324465e-5, - 3.805179273249344e-5, + 3.805179273249344e-5 ], linf=[ 3.701965498725812e-5, 0.0002122422943138247, - 0.00021224229431116015, + 0.00021224229431116015 ], atol=2.0e-12) #= required for CI on macOS =# # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_2d_linearizedeuler.jl b/test/test_tree_2d_linearizedeuler.jl index 7bdb83e328..b1d34895a6 100644 --- a/test/test_tree_2d_linearizedeuler.jl +++ b/test/test_tree_2d_linearizedeuler.jl @@ -15,13 +15,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 0.00020601485381444888, 0.00013380483421751216, 0.0001338048342174503, - 0.00020601485381444888, + 0.00020601485381444888 ], linf=[ 0.0011006084408365924, 0.0005788678074691855, 0.0005788678074701847, - 0.0011006084408365924, + 0.0011006084408365924 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -39,13 +39,13 @@ end 0.048185623945503485, 0.01941899333212175, 0.019510224816991825, - 0.048185623945503485, + 0.048185623945503485 ], linf=[ 1.0392165942153189, 0.18188777290819994, 0.1877028372108587, - 1.0392165942153189, + 1.0392165942153189 ]) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index 66b47138a4..ed6b7f6b52 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -21,7 +21,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 1.2542675002588144e-6, 1.2542675002747718e-6, 1.8705223407238346e-6, - 4.651717010670585e-7, + 4.651717010670585e-7 ], linf=[ 0.00026806333988971254, @@ -32,7 +32,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") 8.130129322880819e-6, 8.130129322769797e-6, 1.2406302192291552e-5, - 2.373765544951732e-6, + 2.373765544951732e-6 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -55,7 +55,7 @@ end 1.07029565814218e-6, 1.0702956581404748e-6, 1.3291748105236525e-6, - 4.6172239295786824e-7, + 4.6172239295786824e-7 ], linf=[ 9.865325754310206e-6, @@ -66,7 +66,7 @@ end 7.789533065905019e-6, 7.789533065905019e-6, 1.0933531593274037e-5, - 2.340244047768378e-6, + 2.340244047768378e-6 ], volume_flux=(flux_derigs_etal, flux_nonconservative_powell)) # Ensure that we do not have excessive memory allocations @@ -90,7 +90,7 @@ end 1.456369119716533e-6, 1.4115666913995062e-6, 1.804758237422838e-6, - 8.320469738087189e-7, + 8.320469738087189e-7 ], linf=[ 3.670661330201774e-5, @@ -101,7 +101,7 @@ end 1.0906323046233624e-5, 1.0603954940346938e-5, 1.5900499596113726e-5, - 5.978772247650426e-6, + 5.978772247650426e-6 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -125,7 +125,7 @@ end 0.01745369341302589, 0.017454552320664566, 0.026873190440613117, - 5.336243933079389e-16, + 5.336243933079389e-16 ], linf=[ 0.23623816236321427, @@ -136,7 +136,7 @@ end 0.09398098096581875, 0.09470282020962917, 0.15277253978297378, - 4.307694418935709e-15, + 4.307694418935709e-15 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -159,7 +159,7 @@ end 0.23028914748088603, 0.34413527376463915, 0.0, - 0.003178793090381426, + 0.003178793090381426 ], linf=[ 1.2749969218080568, @@ -170,7 +170,7 @@ end 0.6473347557712643, 0.9691773375490476, 0.0, - 0.05729832038724348, + 0.05729832038724348 ], tspan=(0.0, 0.09)) # Ensure that we do not have excessive memory allocations @@ -194,7 +194,7 @@ end 0.15688413207147794, 0.24293641543490646, 0.0, - 0.003246181006326598, + 0.003246181006326598 ], linf=[ 0.560316034595759, @@ -205,7 +205,7 @@ end 0.3981375420906146, 0.673472146198816, 0.0, - 0.04879208429337193, + 0.04879208429337193 ], tspan=(0.0, 0.06), surface_flux=(flux_hlle, @@ -231,7 +231,7 @@ end 3.9171737639099993e-16, 2.445565690318772e-16, 3.6588423152083e-17, - 9.971153407737885e-17, + 9.971153407737885e-17 ], linf=[ 2.220446049250313e-16, @@ -242,7 +242,7 @@ end 8.881784197001252e-16, 4.440892098500626e-16, 1.1102230246251565e-16, - 4.779017148551244e-16, + 4.779017148551244e-16 ], maxiters=1, initial_condition=initial_condition_constant, @@ -268,7 +268,7 @@ end 0.2147235065899803, 0.23558337696054493, 0.0, - 0.0032515115395693483, + 0.0032515115395693483 ], linf=[ 11.003677581472843, @@ -279,7 +279,7 @@ end 1.3283750501377847, 1.4365828094434892, 0.0, - 0.07886241196068537, + 0.07886241196068537 ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -303,7 +303,7 @@ end 2.359493623565687, 1.4030741420730297, 0.0, - 0.029613599942667133, + 0.029613599942667133 ], linf=[ 1.581630420824181, @@ -314,7 +314,7 @@ end 13.07679044647926, 9.14612176426092, 0.0, - 0.5154756722488522, + 0.5154756722488522 ], tspan=(0.0, 0.003), # Calling the AnalysisCallback before iteration 9 causes the interpolation @@ -341,7 +341,7 @@ end 8.4091669534557805e-03, 5.2156364913231732e-03, 0.0000000000000000e+00, - 2.0786952301129021e-04, + 2.0786952301129021e-04 ], linf=[ 3.8778760255775635e-01, @@ -352,15 +352,19 @@ end 1.0264404591009069e-01, 1.0655686942176350e-01, 0.0000000000000000e+00, - 6.1013422157115546e-03, + 6.1013422157115546e-03 ], tspan=(0.0, 0.003)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end diff --git a/test/test_tree_2d_shallowwater.jl b/test/test_tree_2d_shallowwater.jl index bcad663008..97e586c719 100644 --- a/test/test_tree_2d_shallowwater.jl +++ b/test/test_tree_2d_shallowwater.jl @@ -16,13 +16,13 @@ EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") 0.9911802019934329, 0.7340106828033273, 0.7446338002084801, - 0.5875351036989047, + 0.5875351036989047 ], linf=[ 2.0120253138457564, 2.991158989293406, 2.6557412817714035, - 3.0, + 3.0 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -41,13 +41,13 @@ end 0.9130579602987144, 1.0602847041965408e-14, 1.082225645390032e-14, - 0.9130579602987147, + 0.9130579602987147 ], linf=[ 2.113062037615659, 4.6613606802974e-14, 5.4225772771633196e-14, - 2.1130620376156584, + 2.1130620376156584 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -67,13 +67,13 @@ end 0.9130579602987144, 1.0602847041965408e-14, 1.082225645390032e-14, - 0.9130579602987147, + 0.9130579602987147 ], linf=[ 2.113062037615659, 4.6613606802974e-14, 5.4225772771633196e-14, - 2.1130620376156584, + 2.1130620376156584 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -92,13 +92,13 @@ end 0.9130579602987147, 9.68729463970494e-15, 9.694538537436981e-15, - 0.9130579602987147, + 0.9130579602987147 ], linf=[ 2.1130620376156584, 2.3875905654916432e-14, 2.2492839032269154e-14, - 2.1130620376156584, + 2.1130620376156584 ], surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), @@ -120,13 +120,13 @@ end 0.9130579602987146, 1.0323158914614244e-14, 1.0276096319430528e-14, - 0.9130579602987147, + 0.9130579602987147 ], linf=[ 2.11306203761566, 4.063916419044386e-14, 3.694484044448245e-14, - 2.1130620376156584, + 2.1130620376156584 ], surface_flux=(flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal), @@ -147,13 +147,13 @@ end 0.001868474306068482, 0.01731687445878443, 0.017649083171490863, - 6.274146767717023e-5, + 6.274146767717023e-5 ], linf=[ 0.016962486402209986, 0.08768628853889782, 0.09038488750767648, - 0.0001819675955490041, + 0.0001819675955490041 ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -173,13 +173,13 @@ end 0.0018596727473552813, 0.017306217777629147, 0.016367646997420396, - 6.274146767723934e-5, + 6.274146767723934e-5 ], linf=[ 0.016548007102923368, 0.08726160568822783, 0.09043621622245013, - 0.0001819675955490041, + 0.0001819675955490041 ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -198,13 +198,13 @@ end 0.0018952610547425214, 0.016943425162728183, 0.017556784292859465, - 6.274146767717414e-5, + 6.274146767717414e-5 ], linf=[ 0.0151635341334182, 0.07967467926956129, 0.08400050790965174, - 0.0001819675955490041, + 0.0001819675955490041 ], tspan=(0.0, 0.025), surface_flux=(flux_hll, @@ -225,13 +225,13 @@ end 0.0018957692481057034, 0.016943229710439864, 0.01755623297390675, - 6.274146767717414e-5, + 6.274146767717414e-5 ], linf=[ 0.015156105797771602, 0.07964811135780492, 0.0839787097210376, - 0.0001819675955490041, + 0.0001819675955490041 ], tspan=(0.0, 0.025), surface_flux=(FluxHLL(min_max_speed_naive), @@ -252,13 +252,13 @@ end 0.002471853426064005, 0.05619168608950033, 0.11844727575152562, - 6.274146767730281e-5, + 6.274146767730281e-5 ], linf=[ 0.014332922987500218, 0.2141204806174546, 0.5392313755637872, - 0.0001819675955490041, + 0.0001819675955490041 ], surface_flux=(flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal), @@ -279,13 +279,13 @@ end 0.1351723240085936, 0.20010881416550014, 0.2001088141654999, - 2.719538414346464e-7, + 2.719538414346464e-7 ], linf=[ 0.5303608302490757, 0.5080987791967457, 0.5080987791967506, - 1.1301675764130437e-6, + 1.1301675764130437e-6 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_3d_euler.jl b/test/test_tree_3d_euler.jl index 47669dce2f..03ff2c5378 100644 --- a/test/test_tree_3d_euler.jl +++ b/test/test_tree_3d_euler.jl @@ -17,14 +17,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 0.009776048833895767, 0.00977604883389591, 0.009776048833895733, - 0.01506687097416608, + 0.01506687097416608 ], linf=[ 0.03285848350791731, 0.0321792316408982, 0.032179231640894645, 0.032179231640895534, - 0.0655408023333299, + 0.0655408023333299 ], # With the default `maxiters = 1` in coverage tests, # there would be no time series to check against. @@ -51,21 +51,21 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 1.952073047561595, 1.9520730475615966, 1.9520730475615953, - 3.814390510967551, + 3.814390510967551 ], [ 2.0506452262144363, 2.050727319703708, 2.0507273197037073, 2.0507273197037077, - 4.203653999433724, + 4.203653999433724 ], [ 2.046982357537558, 2.0463728824399654, 2.0463728824399654, 2.0463728824399645, - 4.190033459318115, + 4.190033459318115 ]] @test point_data≈exact_data atol=1e-1 @test point_data ≈ ref_data @@ -78,14 +78,14 @@ end 0.032062252638283974, 0.032062252638283974, 0.03206225263828395, - 0.12228177813586687, + 0.12228177813586687 ], linf=[ 0.0693648413632646, 0.0622101894740843, 0.06221018947408474, 0.062210189474084965, - 0.24196451799555962, + 0.24196451799555962 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -104,14 +104,14 @@ end 0.009776048833894784, 0.009776048833894784, 0.009776048833894765, - 0.015066870974164096, + 0.015066870974164096 ], linf=[ 0.03285848350791687, 0.032179231640897754, 0.0321792316408942, 0.0321792316408982, - 0.06554080233333615, + 0.06554080233333615 ], volume_integral=VolumeIntegralFluxDifferencing(flux_central)) # Ensure that we do not have excessive memory allocations @@ -129,12 +129,12 @@ end l2=[ 0.0003637241020254673, 0.00039555708663848046, 0.00039555708663832644, 0.0003955570866385083, - 0.0007811613481643962, + 0.0007811613481643962 ], linf=[ 0.0024000660244567484, 0.002963541002521053, 0.0029635410025201647, 0.002963541002522385, - 0.007191437359379549, + 0.007191437359379549 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -153,14 +153,14 @@ end 0.0018659907926698422, 0.0018659907926698589, 0.0018659907926698747, - 0.0034549095578444056, + 0.0034549095578444056 ], linf=[ 0.011355360771142298, 0.011526889155693887, 0.011526889155689002, 0.011526889155701436, - 0.02299726519821288, + 0.02299726519821288 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -179,14 +179,14 @@ end 0.003828192061340465, 0.0038281920613404694, 0.0038281920613404672, - 0.005742288092010652, + 0.005742288092010652 ], linf=[ 0.07390396464027349, 0.07390396464027305, 0.07390396464027305, 0.07390396464027305, - 0.11085594696041134, + 0.11085594696041134 ], tspan=(0.0, 0.1), coverage_override=(maxiters = 6, initial_refinement_level = 0, @@ -208,14 +208,14 @@ end 0.03133384111621587, 0.03133384111621582, 0.04378599329988925, - 0.015796137903453026, + 0.015796137903453026 ], linf=[ 0.0013935237751798724, 0.0724080091006194, 0.07240800910061806, 0.12795921224174792, - 0.07677156293692633, + 0.07677156293692633 ], tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations @@ -235,14 +235,14 @@ end 0.016179934130642552, 0.01617993413064253, 0.016172648598753545, - 0.09261669328795467, + 0.09261669328795467 ], linf=[ 0.3954458125573179, 0.26876916180359345, 0.26876916180359345, 0.26933123042178553, - 1.3724137121660251, + 1.3724137121660251 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -264,14 +264,14 @@ end 0.012771561294571411, 0.01277156129457143, 0.012770635779336643, - 0.08091898488262424, + 0.08091898488262424 ], linf=[ 0.4047819603427084, 0.27493532130155474, 0.2749353213015551, 0.2749304638368023, - 1.4053942765487641, + 1.4053942765487641 ], maxiters=10, coverage_override=(maxiters = 2,)) @@ -292,14 +292,14 @@ end 0.057196526814004715, 0.05719652681400473, 0.057196526814004736, - 0.08579479022100575, + 0.08579479022100575 ], linf=[ 0.27415246703018203, 0.2741524670301829, 0.2741524670301827, 0.27415246703018226, - 0.41122870054527816, + 0.41122870054527816 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -318,14 +318,14 @@ end 0.016632068583699623, 0.016632068583699623, 0.01662548715216875, - 0.0913477018048886, + 0.0913477018048886 ], linf=[ 0.4372549540810414, 0.28613118232798984, 0.28613118232799006, 0.28796686065271876, - 1.5072828647309124, + 1.5072828647309124 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -344,14 +344,14 @@ end 6.059779958716338e-16, 4.916596221090319e-16, 9.739943366304456e-16, - 3.7485908743251566e-15, + 3.7485908743251566e-15 ], linf=[ 2.4424906541753444e-15, 3.733124920302089e-15, 4.440892098500626e-15, 5.329070518200751e-15, - 2.4868995751603507e-14, + 2.4868995751603507e-14 ], initial_condition=initial_condition_constant) # Ensure that we do not have excessive memory allocations @@ -371,14 +371,14 @@ end 0.016649800693500427, 0.01664980069350042, 0.01664379306708522, - 0.09137248646784184, + 0.09137248646784184 ], linf=[ 0.4373399329742198, 0.28434487167605427, 0.28434487167605427, 0.28522678968890774, - 1.532471676033761, + 1.532471676033761 ], surface_flux=flux_chandrashekar, volume_flux=flux_chandrashekar) # Ensure that we do not have excessive memory allocations @@ -398,14 +398,14 @@ end 0.016675487948639846, 0.016675487948639853, 0.016668992714991282, - 0.091455613470441, + 0.091455613470441 ], linf=[ 0.43348628145015766, 0.28853549062014217, 0.28853549062014217, 0.2903943042772536, - 1.5236557526482426, + 1.5236557526482426 ], surface_flux=flux_kennedy_gruber, volume_flux=flux_kennedy_gruber) @@ -426,14 +426,14 @@ end 0.016637655557848952, 0.01663765555784895, 0.01663105921013437, - 0.09136239054024566, + 0.09136239054024566 ], linf=[ 0.43692416928732536, 0.28622033209064734, 0.28622033209064746, 0.2881197143457632, - 1.506534270303663, + 1.506534270303663 ], surface_flux=flux_shima_etal, volume_flux=flux_shima_etal) # Ensure that we do not have excessive memory allocations @@ -453,14 +453,14 @@ end 0.2640486962336911, 0.0354927658652858, 0.03549276586528571, - 1.0777274757408568, + 1.0777274757408568 ], linf=[ 9.558543313792217, 49.4518309553356, 10.319859082570309, 10.319859082570487, - 195.1066220797401, + 195.1066220797401 ], tspan=(0.0, 0.2), # Let this test run longer to cover some lines in the positivity preserving limiter @@ -483,14 +483,14 @@ end 0.0023166296394624025, 0.002316629639462401, 0.0023166296394624038, - 0.010200581509653256, + 0.010200581509653256 ], linf=[ 0.06344190883105805, 0.6292607955969378, 0.6292607955969377, 0.6292607955969377, - 2.397746252817731, + 2.397746252817731 ], maxiters=5, max_level=6, surface_flux=FluxHLL(min_max_speed_naive), @@ -513,14 +513,14 @@ end 0.0037168004033428146, 0.0037168004033428094, 0.0037168004033428514, - 0.011119869089205635, + 0.011119869089205635 ], linf=[ 0.13982864363612468, 0.786004687738243, 0.786004687738243, 0.7860046877382431, - 1.7082524045150382, + 1.7082524045150382 ], tspan=(0.0, 0.01), surface_flux=flux_hlle) diff --git a/test/test_tree_3d_eulergravity.jl b/test/test_tree_3d_eulergravity.jl index 1b5e715f77..a1eedd1444 100644 --- a/test/test_tree_3d_eulergravity.jl +++ b/test/test_tree_3d_eulergravity.jl @@ -17,14 +17,14 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 0.00047204222332596204, 0.00047204222332608705, 0.0004720422233259819, - 0.0010987026250960728, + 0.0010987026250960728 ], linf=[ 0.003496616916238704, 0.003764418290373106, 0.003764418290377103, 0.0037644182903766588, - 0.008370424899251105, + 0.008370424899251105 ], resid_tol=1.0e-4, tspan=(0.0, 0.2)) # Ensure that we do not have excessive memory allocations diff --git a/test/test_tree_3d_fdsbp.jl b/test/test_tree_3d_fdsbp.jl index e0e2bfe4b8..4cac601171 100644 --- a/test/test_tree_3d_fdsbp.jl +++ b/test/test_tree_3d_fdsbp.jl @@ -57,14 +57,14 @@ end 2.2499169224681058e-5, 2.24991692246826e-5, 2.2499169224684707e-5, - 5.814121361417382e-5, + 5.814121361417382e-5 ], linf=[ 9.579357410749445e-5, 9.544871933409027e-5, 9.54487193367548e-5, 9.544871933453436e-5, - 0.0004192294529472562, + 0.0004192294529472562 ], tspan=(0.0, 0.2)) @@ -85,14 +85,14 @@ end 4.1320630860402814e-5, 4.132063086040211e-5, 4.132063086039092e-5, - 8.502518355874354e-5, + 8.502518355874354e-5 ], linf=[ 0.0001963934848161486, 0.00020239883896255861, 0.0002023988389729947, 0.00020239883896766564, - 0.00052605624510349, + 0.00052605624510349 ], tspan=(0.0, 0.2), solver=DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), @@ -115,14 +115,14 @@ end 0.0004691301922633193, 0.00046913019226332234, 0.0006630180220973541, - 0.0015732759680929076, + 0.0015732759680929076 ], linf=[ 3.4253965106145756e-5, 0.0010033197685090707, 0.0010033197685091054, 0.0018655642702542635, - 0.008479800046757191, + 0.008479800046757191 ], tspan=(0.0, 0.0075), abstol=1.0e-9, reltol=1.0e-9) diff --git a/test/test_tree_3d_hypdiff.jl b/test/test_tree_3d_hypdiff.jl index 5c9dacbd87..6bf57e08c2 100644 --- a/test/test_tree_3d_hypdiff.jl +++ b/test/test_tree_3d_hypdiff.jl @@ -16,13 +16,13 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 0.001530331609036682, 0.011314177033289238, 0.011314177033289402, - 0.011314177033289631, + 0.011314177033289631 ], linf=[ 0.02263459033909354, 0.10139777904683545, 0.10139777904683545, - 0.10139777904683545, + 0.10139777904683545 ], initial_refinement_level=2) # Ensure that we do not have excessive memory allocations @@ -31,6 +31,10 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -41,13 +45,13 @@ end 0.0015377731806850128, 0.01137685274151801, 0.011376852741518175, - 0.011376852741518494, + 0.011376852741518494 ], linf=[ 0.022715420630041172, 0.10183745338964201, 0.10183745338964201, - 0.1018374533896429, + 0.1018374533896429 ], initial_refinement_level=2, surface_flux=flux_godunov) # Ensure that we do not have excessive memory allocations @@ -56,6 +60,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -66,13 +74,13 @@ end 0.00022868320512754316, 0.0007974309948540525, 0.0015035143230654987, - 0.0015035143230655293, + 0.0015035143230655293 ], linf=[ 0.0016405001653623241, 0.0029870057159104594, 0.009410031618285686, - 0.009410031618287462, + 0.009410031618287462 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -80,6 +88,10 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) + # Larger values for allowed allocations due to usage of custom + # integrator which are not *recorded* for the methods from + # OrdinaryDiffEq.jl + # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877 @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end diff --git a/test/test_tree_3d_linearizedeuler.jl b/test/test_tree_3d_linearizedeuler.jl index 00f8d62dad..0390b0cbcf 100644 --- a/test/test_tree_3d_linearizedeuler.jl +++ b/test/test_tree_3d_linearizedeuler.jl @@ -14,12 +14,12 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") l2=[ 0.020380328336745232, 0.027122442311921492, 0.02712244231192152, 8.273108096127844e-17, - 0.020380328336745232, + 0.020380328336745232 ], linf=[ 0.2916021983572774, 0.32763703462270843, 0.32763703462270855, 1.641012595221666e-15, - 0.2916021983572774, + 0.2916021983572774 ], tspan=(0.0, 1.0)) diff --git a/test/test_tree_3d_mhd.jl b/test/test_tree_3d_mhd.jl index 74107d462d..98016cb519 100644 --- a/test/test_tree_3d_mhd.jl +++ b/test/test_tree_3d_mhd.jl @@ -21,7 +21,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 0.010391801950005755, 0.010391801950005759, 0.010393502246627087, - 2.524766553484067e-16, + 2.524766553484067e-16 ], linf=[ 0.28173002819718196, @@ -32,7 +32,7 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") 0.10950981489747313, 0.10950981489747136, 0.11517234329681891, - 2.0816911067714202e-15, + 2.0816911067714202e-15 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -55,7 +55,7 @@ end 1.0340110783830874e-15, 1.1779095371939702e-15, 9.961878521814573e-16, - 8.1201730630719145e-16, + 8.1201730630719145e-16 ], linf=[ 2.4424906541753444e-15, @@ -66,7 +66,7 @@ end 1.7763568394002505e-14, 1.0436096431476471e-14, 2.042810365310288e-14, - 7.057203733035201e-15, + 7.057203733035201e-15 ], atol=1000 * eps(), initial_condition=initial_condition_constant) @@ -91,7 +91,7 @@ end 0.00916500047763897, 0.005069863732625444, 0.011503011541926135, - 0.003988175543749985, + 0.003988175543749985 ], linf=[ 0.01188593784273051, @@ -102,7 +102,7 @@ end 0.03316343064943483, 0.011539436992528018, 0.04896687646520839, - 0.018714054039927555, + 0.018714054039927555 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -125,7 +125,7 @@ end 0.00900886245212482, 0.004926537542780259, 0.01153285554590683, - 0.0037842060148666886, + 0.0037842060148666886 ], linf=[ 0.012982853115883541, @@ -136,7 +136,7 @@ end 0.03198699034954189, 0.009761077061886558, 0.04433669321441455, - 0.01618905441148782, + 0.01618905441148782 ], volume_flux=(flux_derigs_etal, flux_nonconservative_powell)) # Ensure that we do not have excessive memory allocations @@ -160,7 +160,7 @@ end 0.007328739509868727, 0.00309794018112387, 0.009026356949274878, - 0.0035732583778049776, + 0.0035732583778049776 ], linf=[ 0.013734346970999622, @@ -171,7 +171,7 @@ end 0.055120532123884625, 0.018202716205672487, 0.06133688282205586, - 0.019888161885935608, + 0.019888161885935608 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -197,7 +197,7 @@ end 0.021125605214031118, 0.03295607553556973, 0.03296235755245784, - 7.16035229384135e-6, + 7.16035229384135e-6 ], linf=[ 0.017894703320895378, @@ -208,7 +208,7 @@ end 0.05381260695579509, 0.0884774018719996, 0.07784546966765199, - 7.71609149516089e-5, + 7.71609149516089e-5 ], initial_condition=function initial_condition_orszag_tang(x, t, equations::IdealGlmMhdEquations3D) @@ -269,7 +269,7 @@ end 0.007355137041002365, 0.0073551370410023425, 0.00735520932001833, - 0.000506140942330923, + 0.000506140942330923 ], linf=[ 0.28040713666979633, @@ -280,7 +280,7 @@ end 0.08770240288089526, 0.08770240288089792, 0.08773409387876674, - 0.050221095224119834, + 0.050221095224119834 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) diff --git a/test/test_unit.jl b/test/test_unit.jl index 7d38dadf88..fe765f1253 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1292,7 +1292,7 @@ end 0.5011914484393387, 0.8829127712445113, 0.43024132987932817, - 0.7560616633050348, + 0.7560616633050348 ] equations = CompressibleEulerEquations2D(1.4) @@ -1450,7 +1450,7 @@ end SVector(1.5, -0.2, 0.1, 5.0)] fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, - flux_hllc, flux_chandrashekar, + flux_hllc, flux_chandrashekar ] for f_std in fluxes @@ -1475,7 +1475,7 @@ end SVector(1.5, -0.2, 0.1, 0.2, 5.0)] fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, FluxLMARS(340), flux_hll, FluxHLL(min_max_speed_davis), flux_hlle, - flux_hllc, flux_chandrashekar, + flux_hllc, flux_chandrashekar ] for f_std in fluxes @@ -1514,7 +1514,7 @@ end flux_central, flux_hindenlang_gassner, FluxHLL(min_max_speed_davis), - flux_hlle, + flux_hlle ] for f_std in fluxes @@ -1541,7 +1541,7 @@ end flux_central, flux_hindenlang_gassner, FluxHLL(min_max_speed_davis), - flux_hlle, + flux_hlle ] for f_std in fluxes diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index 43b911cc66..43b18b48e7 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -18,11 +18,11 @@ isdir(outdir) && rm(outdir, recursive = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_periodic.jl"), l2=[ 0.0001099216141882387, 0.0001303795774982892, - 0.00013037957749794242, 0.0002993727892598759, + 0.00013037957749794242, 0.0002993727892598759 ], linf=[ 0.006407280810928562, 0.009836067015418948, - 0.009836067015398076, 0.021903519038095176, + 0.009836067015398076, 0.021903519038095176 ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -38,11 +38,11 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), l2=[ 3.3937365073416665e-14, 2.44759188939065e-13, - 1.4585198700082895e-13, 4.716940764877479e-13, + 1.4585198700082895e-13, 4.716940764877479e-13 ], linf=[ 7.774003663030271e-12, 9.183176441496244e-11, - 4.5685344396417804e-11, 1.0534506600379245e-10, + 4.5685344396417804e-11, 1.0534506600379245e-10 ], tspan=(0.0, 0.1), atol=3.0e-13) @@ -62,13 +62,13 @@ end 0.040189107976346644, 0.04256154998030852, 0.03734120743842209, - 0.10057425897733507, + 0.10057425897733507 ], linf=[ 0.24455374304626365, 0.2970686406973577, 0.29339040847600434, - 0.5915610037764794, + 0.5915610037764794 ], tspan=(0.0, 0.25), surface_flux=FluxHLL(min_max_speed_naive)) @@ -88,13 +88,13 @@ end 0.0007213418215265047, 0.0006752337675043779, 0.0006437485997536973, - 0.0014782883071363362, + 0.0014782883071363362 ], linf=[ 0.004301288971032324, 0.005243995459478956, 0.004685630332338153, - 0.01750217718347713, + 0.01750217718347713 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -113,13 +113,13 @@ end 0.0007213418215265047, 0.0006752337675043779, 0.0006437485997536973, - 0.0014782883071363362, + 0.0014782883071363362 ], linf=[ 0.004301288971032324, 0.005243995459478956, 0.004685630332338153, - 0.01750217718347713, + 0.01750217718347713 ], # With the default `maxiters = 1` in coverage tests, # there would be no time steps after the restart. @@ -140,13 +140,13 @@ end 0.06594600495903137, 0.10803914821786433, 0.10805946357846291, - 0.1738171782368222, + 0.1738171782368222 ], linf=[ 0.31880214280781305, 0.3468488554333352, 0.34592958184413264, - 0.784555926860546, + 0.784555926860546 ], tspan=(0.0, 1.0)) # Ensure that we do not have excessive memory allocations @@ -179,13 +179,13 @@ end 2.19945600e-01, 1.71050453e-01, 1.71050453e-01, - 1.21719195e+00, + 1.21719195e+00 ], linf=[ 7.44218635e-01, 7.02887039e-01, 7.02887039e-01, - 6.11732719e+00, + 6.11732719e+00 ], tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations @@ -204,13 +204,13 @@ end 6.984024099236519e-5, 6.289022520363763e-5, 6.550951878107466e-5, - 0.00016222767700879948, + 0.00016222767700879948 ], linf=[ 0.0005367823248620951, 0.000671293180158461, 0.0005656680962440319, - 0.0013910024779804075, + 0.0013910024779804075 ], tspan=(0.0, 0.2), # With the default `maxiters = 1` in coverage tests, @@ -304,13 +304,13 @@ end 0.6107326269462766, 0.48666631722018877, 0.48309775159067053, - 0.29467422718511704, + 0.29467422718511704 ], linf=[ 2.776782342826098, 3.2158378644333707, 3.652920889487258, - 2.052861364219655, + 2.052861364219655 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -330,13 +330,13 @@ end Float32(0.6107326269462766), Float32(0.48666631722018877), Float32(0.48309775159067053), - Float32(0.29467422718511704), + Float32(0.29467422718511704) ], linf=[ Float32(2.776782342826098), 3.2162943f0, # this needs to be adapted 3.6683278f0, # this needed to be adapted - Float32(2.052861364219655), + Float32(2.052861364219655) ], tspan=(0.0f0, 0.25f0), RealT=Float32) @@ -356,13 +356,13 @@ end 1.2164292510839076, 2.6118925543469468e-12, 2.459878823146057e-12, - 1.2164292510839079, + 1.2164292510839079 ], linf=[ 1.5138512282315846, 4.706289937431355e-11, 4.913910192312011e-11, - 1.513851228231574, + 1.513851228231574 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations @@ -381,13 +381,13 @@ end 1.2164292510839063, 1.2676379081600215e-12, 1.255855785593831e-12, - 1.2164292510839074, + 1.2164292510839074 ], linf=[ 1.5138512282315604, 1.658245722058109e-11, 1.8665562182185795e-11, - 1.5138512282315737, + 1.5138512282315737 ], surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), @@ -409,13 +409,13 @@ end 1.2164292510839083, 2.590643638636187e-12, 2.388742604639019e-12, - 1.2164292510839079, + 1.2164292510839079 ], linf=[ 1.5138512282315792, 4.761278694199934e-11, 4.910549479958249e-11, - 1.513851228231574, + 1.513851228231574 ], surface_flux=(flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal), @@ -436,13 +436,13 @@ end 0.001118134082248467, 0.044560486817464634, 0.01430926600634214, - 5.089218476759981e-6, + 5.089218476759981e-6 ], linf=[ 0.007798727223654822, 0.34782952734839157, 0.11161614702628064, - 2.6407324614341476e-5, + 2.6407324614341476e-5 ], tspan=(0.0, 0.025)) # Ensure that we do not have excessive memory allocations @@ -461,13 +461,13 @@ end 0.0011196838135485918, 0.01542895635133927, 0.017082803023121197, - 5.089218476759981e-6, + 5.089218476759981e-6 ], linf=[ 0.014299541415654371, 0.12783948113206955, 0.17626489583921323, - 2.6407324614341476e-5, + 2.6407324614341476e-5 ], surface_flux=(FluxHydrostaticReconstruction(flux_hll, hydrostatic_reconstruction_audusse_etal), @@ -489,13 +489,13 @@ end 0.001118046975499805, 0.04455969246244461, 0.014298120235633432, - 5.089218476759981e-6, + 5.089218476759981e-6 ], linf=[ 0.007776521213640031, 0.34768318303226353, 0.11075311228066198, - 2.6407324614341476e-5, + 2.6407324614341476e-5 ], surface_flux=(flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal), @@ -516,13 +516,13 @@ end 0.0011196838135486059, 0.015428956351339451, 0.017082803023120943, - 5.089218476759981e-6, + 5.089218476759981e-6 ], linf=[ 0.01429954141565526, 0.12783948113205668, 0.176264895839215, - 2.6407324614341476e-5, + 2.6407324614341476e-5 ], surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), @@ -543,13 +543,13 @@ end 1.1577518608950964e-5, 4.761947272222427e-13, 4.546045873135486e-13, - 1.157751860893347e-5, + 1.157751860893347e-5 ], linf=[ 8.394063879002545e-5, 1.1211566736150389e-10, 1.0890426250906834e-10, - 8.394063879602065e-5, + 8.394063879602065e-5 ], tspan=(0.0, 2.0)) # Ensure that we do not have excessive memory allocations @@ -567,11 +567,11 @@ end "elixir_shallowwater_wall_bc_shockcapturing.jl"), l2=[ 0.0442113635677511, 0.1537465759364839, 0.16003586586203947, - 6.225080477067782e-8, + 6.225080477067782e-8 ], linf=[ 0.6347820607387928, 2.0078125433846736, 2.530726684667019, - 3.982097165344811e-7, + 3.982097165344811e-7 ], tspan=(0.0, 0.05)) # Ensure that we do not have excessive memory allocations @@ -591,13 +591,13 @@ end 0.612551520607341, 0.5039173660221961, 0.49136517934903523, - 0.29467422718511704, + 0.29467422718511704 ], linf=[ 2.7636771472622197, 3.236168963021072, 3.3363936775653826, - 2.052861364219655, + 2.052861364219655 ], tspan=(0.0, 0.25)) # Ensure that we do not have excessive memory allocations diff --git a/utils/trixi-format-file.jl b/utils/trixi-format-file.jl index 9b9a0e4949..fabfcf21fd 100755 --- a/utils/trixi-format-file.jl +++ b/utils/trixi-format-file.jl @@ -2,7 +2,7 @@ using Pkg Pkg.activate(; temp = true, io = devnull) -Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.45"); preserve = PRESERVE_ALL, +Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.60"); preserve = PRESERVE_ALL, io = devnull) using JuliaFormatter: format_file diff --git a/utils/trixi-format.jl b/utils/trixi-format.jl index 63f1407880..59021c22c0 100644 --- a/utils/trixi-format.jl +++ b/utils/trixi-format.jl @@ -2,7 +2,7 @@ using Pkg Pkg.activate(; temp = true, io = devnull) -Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.45"); preserve = PRESERVE_ALL, +Pkg.add(PackageSpec(name = "JuliaFormatter", version = "1.0.60"); preserve = PRESERVE_ALL, io = devnull) using JuliaFormatter: format From 5895118c51f730fbd7880e359facfd519a3d1bc3 Mon Sep 17 00:00:00 2001 From: Benjamin Bolm <74359358+bennibolm@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:51:40 +0200 Subject: [PATCH 423/423] Add tests for alpha analysis (#132) * Add tests for alpha analysis * Add comments; Fix two tests * Fix test * Update alpha tests * Rm not needed code * Simplify test --- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 4 ++ .../elixir_euler_double_mach.jl | 4 ++ .../elixir_euler_double_mach_MCL.jl | 4 ++ .../elixir_euler_blast_wave_MCL.jl | 6 ++- src/callbacks_step/limiting_analysis.jl | 8 +-- src/callbacks_step/limiting_analysis_2d.jl | 15 ++++-- test/test_p4est_2d.jl | 17 +++++++ test/test_structured_2d.jl | 49 +++++++++++++++++++ test/test_tree_2d_euler.jl | 46 +++++++++++++++++ 9 files changed, 144 insertions(+), 9 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 6fcb3b0fa9..f346f6ad59 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -86,10 +86,14 @@ save_solution = SaveSolutionCallback(interval = 300, stepsize_callback = StepsizeCallback(cfl = 0.5) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + limiting_analysis_callback, stepsize_callback) ############################################################################### diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 33be05c615..12bc936b1c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -153,9 +153,13 @@ save_solution = SaveSolutionCallback(interval = 1000, stepsize_callback = StepsizeCallback(cfl = 0.9) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, + limiting_analysis_callback, save_solution) ############################################################################### diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 68290ac31f..9c2a03a26f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -155,9 +155,13 @@ save_solution = SaveSolutionCallback(interval = 1000, stepsize_callback = StepsizeCallback(cfl = 0.9) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, + limiting_analysis_callback, save_solution) ############################################################################### diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl index ba5f27d9f9..78a4a72ed6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_MCL.jl @@ -48,7 +48,7 @@ limiter_mcl = SubcellLimiterMCL(equations, basis; positivity_limiter_pressure_exact = false, entropy_limiter_semidiscrete = true, smoothness_indicator = true, - Plotting = false) + Plotting = true) volume_integral = VolumeIntegralSubcellLimiting(limiter_mcl; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) @@ -82,9 +82,13 @@ save_solution = SaveSolutionCallback(interval = 500, stepsize_callback = StepsizeCallback(cfl = 0.9) +limiting_analysis_callback = LimitingAnalysisCallback(output_directory = "out", + interval = 1) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + limiting_analysis_callback, stepsize_callback) ############################################################################### diff --git a/src/callbacks_step/limiting_analysis.jl b/src/callbacks_step/limiting_analysis.jl index 5bbf8c8b80..5dce041b54 100644 --- a/src/callbacks_step/limiting_analysis.jl +++ b/src/callbacks_step/limiting_analysis.jl @@ -145,7 +145,7 @@ end @unpack output_directory = limiting_analysis_callback @unpack alpha = limiter.cache.subcell_limiter_coefficients - alpha_avg = analyze_coefficient_IDP(mesh, equations, dg, cache, limiter) + alpha_avg = analyze_coefficient(mesh, equations, dg, cache, limiter) open("$output_directory/alphas.txt", "a") do f println(f, iter, ", ", time, ", ", maximum(alpha), ", ", alpha_avg) @@ -156,6 +156,8 @@ end dg, cache, limiter::SubcellLimiterMCL, time, iter) + @assert limiter.Plotting "Parameter `Plotting` needs to be activated for analysis of limiting factor with `LimitingAnalysisCallback`" + @unpack output_directory = limiting_analysis_callback @unpack weights = dg.basis @unpack alpha, alpha_pressure, alpha_entropy, @@ -163,8 +165,8 @@ end n_vars = nvariables(equations) - alpha_min_avg, alpha_mean_avg = analyze_coefficient_MCL(mesh, equations, dg, cache, - limiter) + alpha_min_avg, alpha_mean_avg = analyze_coefficient(mesh, equations, dg, cache, + limiter) open("$output_directory/alphas_min.txt", "a") do f print(f, iter, ", ", time) diff --git a/src/callbacks_step/limiting_analysis_2d.jl b/src/callbacks_step/limiting_analysis_2d.jl index ef547c0196..2b77257228 100644 --- a/src/callbacks_step/limiting_analysis_2d.jl +++ b/src/callbacks_step/limiting_analysis_2d.jl @@ -5,7 +5,8 @@ @muladd begin #! format: noindent -function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, limiter) +function analyze_coefficient(mesh::TreeMesh2D, equations, dg, cache, + limiter::SubcellLimiterIDP) @unpack weights = dg.basis @unpack alpha = limiter.cache.subcell_limiter_coefficients @@ -22,7 +23,9 @@ function analyze_coefficient_IDP(mesh::TreeMesh2D, equations, dg, cache, limiter return alpha_avg / total_volume end -function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, limiter) +function analyze_coefficient(mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + equations, dg, cache, + limiter::SubcellLimiterIDP) @unpack weights = dg.basis @unpack alpha = limiter.cache.subcell_limiter_coefficients @@ -39,7 +42,8 @@ function analyze_coefficient_IDP(mesh::StructuredMesh{2}, equations, dg, cache, return alpha_avg / total_volume end -function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter) +function analyze_coefficient(mesh::TreeMesh2D, equations, dg, cache, + limiter::SubcellLimiterMCL) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients @@ -83,8 +87,9 @@ function analyze_coefficient_MCL(mesh::TreeMesh2D, equations, dg, cache, limiter return alpha_avg ./ total_volume, alpha_mean_avg ./ total_volume end -function analyze_coefficient_MCL(mesh::StructuredMesh{2}, equations, dg, cache, - limiter) +function analyze_coefficient(mesh::Union{StructuredMesh{2}, P4estMesh{2}}, + equations, dg, cache, + limiter::SubcellLimiterMCL) @unpack weights = dg.basis @unpack alpha, alpha_mean, alpha_pressure, alpha_mean_pressure, alpha_entropy, alpha_mean_entropy = limiter.cache.subcell_limiter_coefficients diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index a8c20ee3bd..c3c844b9ee 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -335,6 +335,7 @@ end end @trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + rm(joinpath("out", "alphas.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ @@ -350,6 +351,22 @@ end 6.268843623142863 ], tspan=(0.0, 0.3)) + # Test alphas.txt + lines = readlines(joinpath("out", "alphas.txt")) + @test lines[1] == + "# iter, simu_time, alpha_max, alpha_avg" + cmd = string(Base.julia_cmd()) + coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + if coverage + # Run with coverage takes 1 time step. + @test occursin(r"1, 0.00404[0-9]*, 1.0, 0.96795", lines[end]) + else + # Run without coverage takes 85 time steps. + @test startswith(lines[end], "85, 0.3, 1.0, 0.57771") + end + @test count(",", lines[end]) == 3 + @test !any(occursin.(r"NaN", lines)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 8254712cf3..1e797e2015 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -719,6 +719,7 @@ end end @trixi_testset "elixir_euler_double_mach.jl" begin + rm(joinpath("out", "alphas.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach.jl"), l2=[ 0.87417841433288, @@ -734,6 +735,22 @@ end ], initial_refinement_level=2, tspan=(0.0, 0.05)) + # Test alphas.txt + lines = readlines(joinpath("out", "alphas.txt")) + @test lines[1] == + "# iter, simu_time, alpha_max, alpha_avg" + cmd = string(Base.julia_cmd()) + coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + if coverage + # Run with coverage takes 1 time steps. + @test occursin(r"1, 0.0002[0-9]*, 1.0, 0.9809", lines[end]) + else + # Run without coverage takes 193 time steps. + @test startswith(lines[end], "193, 0.05, 1.0, 0.3160") + end + @test count(",", lines[end]) == 3 + @test !any(occursin.(r"NaN", lines)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -749,6 +766,8 @@ end end @trixi_testset "elixir_euler_double_mach_MCL.jl" begin + rm(joinpath("out", "alphas_mean.txt"), force = true) + rm(joinpath("out", "alphas_min.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_MCL.jl"), l2=[ 0.8887316108902574, @@ -764,6 +783,36 @@ end ], initial_refinement_level=2, tspan=(0.0, 0.05)) + # Test alphas_mean.txt + lines = readlines(joinpath("out", "alphas_mean.txt")) + @test lines[1] == + "# iter, simu_time, alpha_min_rho, alpha_avg_rho, alpha_min_rho_v1, alpha_avg_rho_v1, alpha_min_rho_v2, alpha_avg_rho_v2, alpha_min_rho_e, alpha_avg_rho_e" + cmd = string(Base.julia_cmd()) + coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + if coverage + # Run with coverage takes 1 time steps. + @test startswith(lines[end], "1, 0.0002") + else + # Run without coverage takes 191 time steps. + @test startswith(lines[end], "191, 0.05, 3.70") + end + @test count(",", lines[end]) == 9 + @test !any(occursin.(r"NaN", lines)) + + # Test alphas_min.txt + lines = readlines(joinpath("out", "alphas_min.txt")) + @test lines[1] == + "# iter, simu_time, alpha_min_rho, alpha_avg_rho, alpha_min_rho_v1, alpha_avg_rho_v1, alpha_min_rho_v2, alpha_avg_rho_v2, alpha_min_rho_e, alpha_avg_rho_e" + if coverage + # Run with coverage takes 1 time steps. + @test startswith(lines[end], "1, 0.0002") # TODO + else + # Run without coverage takes 191 time steps. + @test startswith(lines[end], "191, 0.05, -0.0, 0.7216") + end + @test count(",", lines[end]) == 9 + @test !any(occursin.(r"NaN", lines)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index 65448da0e3..2874439b47 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -532,6 +532,7 @@ end @trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin rm(joinpath("out", "deviations.txt"), force = true) + rm(joinpath("out", "alphas.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_sc_subcell.jl"), l2=[ @@ -563,6 +564,20 @@ end # Run without coverage takes 381 time steps. @test startswith(lines[end], "381") end + + # Test alphas.txt + lines = readlines(joinpath("out", "alphas.txt")) + @test lines[1] == + "# iter, simu_time, alpha_max, alpha_avg" + if coverage + # Run with coverage takes 6 time steps. + @test occursin(r"6, 0.014[0-9]*, 1.0, 0.953", lines[end]) + else + # Run without coverage takes 381 time steps. + @test startswith(lines[end], "381, 1.0, 1.0, 0.544") + end + @test count(",", lines[end]) == 3 + @test !any(occursin.(r"NaN", lines)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -579,6 +594,8 @@ end @trixi_testset "elixir_euler_sedov_blast_wave_MCL.jl" begin rm(joinpath("out", "deviations.txt"), force = true) + rm(joinpath("out", "alphas_mean.txt"), force = true) + rm(joinpath("out", "alphas_min.txt"), force = true) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_MCL.jl"), l2=[ 0.4740321851943766, @@ -596,6 +613,7 @@ end initial_refinement_level=4, coverage_override=(maxiters = 6,), save_errors=true) + # Test deviations.txt lines = readlines(joinpath("out", "deviations.txt")) @test lines[1] == "# iter, simu_time, rho_min, rho_max, rho_v1_min, rho_v1_max, rho_v2_min, rho_v2_max, rho_e_min, rho_e_max, pressure_min" @@ -609,6 +627,34 @@ end # Run without coverage takes 349 time steps. @test startswith(lines[end], "349") end + + # Test alphas_mean.txt + lines = readlines(joinpath("out", "alphas_mean.txt")) + @test lines[1] == + "# iter, simu_time, alpha_min_rho, alpha_avg_rho, alpha_min_rho_v1, alpha_avg_rho_v1, alpha_min_rho_v2, alpha_avg_rho_v2, alpha_min_rho_e, alpha_avg_rho_e, alpha_min_pressure, alpha_avg_pressure, alpha_min_entropy, alpha_avg_entropy" + if coverage + # Run with coverage takes 6 time steps. + @test startswith(lines[end], "6, 0.014") + else + # Run without coverage takes 349 time steps. + @test startswith(lines[end], "349, 1.0, 0.0002") + end + @test count(",", lines[end]) == 13 + @test !any(occursin.(r"NaN", lines)) + + # Test alphas_min.txt + lines = readlines(joinpath("out", "alphas_min.txt")) + @test lines[1] == + "# iter, simu_time, alpha_min_rho, alpha_avg_rho, alpha_min_rho_v1, alpha_avg_rho_v1, alpha_min_rho_v2, alpha_avg_rho_v2, alpha_min_rho_e, alpha_avg_rho_e, alpha_min_pressure, alpha_avg_pressure, alpha_min_entropy, alpha_avg_entropy" + if coverage + # Run with coverage takes 6 time steps. + @test startswith(lines[end], "6, 0.014") + else + # Run without coverage takes 349 time steps. + @test startswith(lines[end], "349, 1.0, -0.0, 0.773") + end + @test count(",", lines[end]) == 13 + @test !any(occursin.(r"NaN", lines)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let