From 03c95db6ffafc633f9c8bfd99009e02ecf0681af Mon Sep 17 00:00:00 2001 From: Benjamin Bolm Date: Wed, 12 Jan 2022 15:02:22 +0100 Subject: [PATCH 001/331] 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 00000000000..e5a34ab7a02 --- /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 895023c0f6b..842886eb4ba 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 86cbac1ee68..84dd9ddb0eb 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 5215db6edc0..d43d9a98866 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/331] 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 d43d9a98866..1f94dfcafdb 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/331] 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 84dd9ddb0eb..e5c568a0ba3 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 1f94dfcafdb..4dca6d80c54 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/331] 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 4dca6d80c54..df3f4e23abe 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/331] 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 df3f4e23abe..a4833754116 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/331] 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 e5c568a0ba3..a205a1c4292 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 a4833754116..870cfa66255 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/331] 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 842886eb4ba..b7008579f3e 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 870cfa66255..7c1511751b2 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 3f70a75a575..236c1f4835e 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 60230948c42..d7a6dd4f58a 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 00000000000..2af163f8d47 --- /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 9b0c7c7783a..131731d4520 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/331] 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 00000000000..78f443f2e3f --- /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 e5a34ab7a02..8e13f7f2aca 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 7c1511751b2..9d22aedbec6 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 d7a6dd4f58a..059efa7836b 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 2af163f8d47..4cf663d44c6 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/331] 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 9d22aedbec6..4c0ad825a49 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/331] 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 78f443f2e3f..5d4a7035bc5 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 8e13f7f2aca..353dfd197e9 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 4c0ad825a49..cb29bfe78b3 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 059efa7836b..17f87927215 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/331] 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 5d4a7035bc5..5e3f49eb24d 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 353dfd197e9..d5e50aa162e 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 b7008579f3e..55456c73e37 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 a205a1c4292..c9a9c2fb239 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 cb29bfe78b3..d4c996065cf 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/331] 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 d4c996065cf..270e640cfb4 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 17f87927215..e2dde992a0b 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/331] 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 d5e50aa162e..696e0003ddd 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 270e640cfb4..5e8ccdedd77 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 e2dde992a0b..3196ee02482 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/331] 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 5e8ccdedd77..099984e6eb2 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 4cf663d44c6..ea7b5a2f7d9 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/331] 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 c9a9c2fb239..04df284f533 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 099984e6eb2..9fa6b1693e8 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 236c1f4835e..c694aefe6b0 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 ea7b5a2f7d9..43d8b0af046 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/331] 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 bcbd3e671ec..6752a2472dc 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 9fa6b1693e8..dffa29fe1a1 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 43d8b0af046..4d4dee1a61b 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/331] 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 04df284f533..31b04df3ad4 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 3196ee02482..58d5c6f4c9e 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/331] 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 5e3f49eb24d..eb3626370ab 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 696e0003ddd..f3a939ab4a6 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 31b04df3ad4..fb037a9719f 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 6752a2472dc..759f018b6a9 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 dffa29fe1a1..ab7228179dd 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 c694aefe6b0..1fdd57accfa 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 58d5c6f4c9e..a14d26c706f 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 4d4dee1a61b..4bff038fd7a 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/331] 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 00000000000..d1f969685ea --- /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 759f018b6a9..17bf0e9a56b 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 ab7228179dd..3f05dbbb4f7 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 1fdd57accfa..22c08dab036 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 a14d26c706f..0c4c53bc3ca 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 4bff038fd7a..c20fa3b4936 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/331] 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 d1f969685ea..9b5513b5465 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 22c08dab036..4ae6788798e 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 0c4c53bc3ca..9e24cea7e73 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/331] 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 9e24cea7e73..844536aacc8 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/331] 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 3f05dbbb4f7..7bb2a4ec28a 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 844536aacc8..da518272063 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 c20fa3b4936..ef58327dee1 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/331] 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 fb037a9719f..fe053680860 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 17bf0e9a56b..f020be59ee7 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 7bb2a4ec28a..a857dd62147 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 da518272063..f405bea4798 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/331] 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 9b5513b5465..09bccf43493 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 f020be59ee7..da5621f21fe 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 f405bea4798..7d9a9f391e6 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/331] 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 a00a1b8965c..939f09d1750 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 7d9a9f391e6..ad0fcde021d 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/331] 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 f3a939ab4a6..6c114adffad 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 939f09d1750..2006b8e6295 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 d82322a5230..281ba4775cb 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/331] 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 da5621f21fe..ced5333307a 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 4ae6788798e..455f04df6ae 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 ad0fcde021d..ff32bb2d559 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 ef58327dee1..6260fc8480b 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/331] 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 eb3626370ab..be38e7079da 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 6c114adffad..4dbed9202e9 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 ff32bb2d559..1f617ba0af4 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 281ba4775cb..014ad4ab30c 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/331] 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 00000000000..1aec2a49af9 --- /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 09bccf43493..c5a5392222e 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 00000000000..184ab37080c --- /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 fea83db3d44..e046429a282 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 ced5333307a..7c4ddbb192e 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 a857dd62147..c5cb0e8fb8e 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 455f04df6ae..7a4aabc649d 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 1f617ba0af4..b11d5555bc6 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 6260fc8480b..2853f178f0c 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/331] 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 e046429a282..b33082a754f 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 b11d5555bc6..74ffbf9f582 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/331] 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 b33082a754f..7309cd532eb 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 74ffbf9f582..005402e868a 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/331] 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 7309cd532eb..e4b283fdac1 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/331] 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 c5cb0e8fb8e..aa4c674eed3 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 7a4aabc649d..1da8bd4ac73 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 005402e868a..00ec7b23fa5 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/331] 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 1aec2a49af9..c7818052fbe 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 00000000000..19e4febf540 --- /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 00ec7b23fa5..c551a37fa0b 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 2853f178f0c..bc3387fbd92 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/331] 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 be38e7079da..a448eeb9e63 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 00000000000..a48c38f6aac --- /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 00000000000..cc96284335c --- /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 c5a5392222e..e0f00b20aac 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 184ab37080c..5ce18658cd2 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 4dbed9202e9..b17d155c500 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 fe053680860..d7280416c57 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 014ad4ab30c..6e2c9aa4e87 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/331] 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 1da8bd4ac73..f1b29928ca4 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 c551a37fa0b..7336d04fc14 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/331] 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 d9929a197c7..8cd29d06768 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 f1b29928ca4..1300d452b42 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 7336d04fc14..79161ab98af 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/331] 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 5ce18658cd2..a4c1481e0ac 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 1300d452b42..4217cdc93c4 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 bc3387fbd92..9ec4c909f68 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 6e2c9aa4e87..77b1405f11e 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/331] 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 9ec4c909f68..a885ffc772b 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/331] 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 4217cdc93c4..0e30ee833d7 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 77b1405f11e..9cdddb7b134 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/331] 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 79161ab98af..2fc7d74d1fc 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/331] 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 8cd29d06768..6b0a0cf5950 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 aa4c674eed3..ab94b14844a 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 0e30ee833d7..a3fd5b46d88 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 a885ffc772b..1a29ac93dd5 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/331] 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 c7818052fbe..639f1371856 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 a448eeb9e63..e5a2bda7d34 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 a48c38f6aac..a806ebe8fde 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 cc96284335c..c8e07fc2a22 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 e0f00b20aac..8acf738dd15 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 a4c1481e0ac..b889d23f42c 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 6b0a0cf5950..8cd29d06768 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 ab94b14844a..92848411f83 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 2fc7d74d1fc..fc508c5d5a9 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 1a29ac93dd5..fe3fe75141c 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 9cdddb7b134..5169b10ffad 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/331] 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 5169b10ffad..b9241024e55 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/331] 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 639f1371856..f20d3c1cf5a 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 19e4febf540..01c276c332a 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 e5a2bda7d34..cca18b3dfd1 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 a806ebe8fde..2ff08a2fb1e 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 c8e07fc2a22..2e905559189 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 8acf738dd15..70505edde94 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 b889d23f42c..f7b638a4475 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 b17d155c500..9aea2be01b6 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 fe3fe75141c..8d6504d8a55 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/331] 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 2e905559189..d259808a426 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/331] 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 2b947e15944..9d3b1aa5936 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 92848411f83..d0e4bb847e7 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 a3fd5b46d88..cdec4a9bdf5 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 8d6504d8a55..7e533703607 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/331] 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 00000000000..af82ef83316 --- /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 00000000000..b10d064cf4b --- /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 00000000000..916ed9ae73c --- /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 6fa76e332f4..2cb9f89cf80 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 13e4f9dfa54..953e1e59bff 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 8cd29d06768..1a994ae413a 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 9d3b1aa5936..388a3f3f5e4 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 d0e4bb847e7..4145fa7d350 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/331] 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 314039b0fb6..df9ebfee749 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/331] 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 df9ebfee749..7be42255f54 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/331] 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 af82ef83316..98de6abf2f9 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 953e1e59bff..86370897228 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 388a3f3f5e4..9d3b1aa5936 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 4145fa7d350..52d92e00dec 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 22aed985cdc..aa0b82afeb9 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 d2b5f5c10d9..d979bc17d16 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/331] 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 b10d064cf4b..8299ade24a9 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/331] 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 fc508c5d5a9..6574d1d63e1 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 7e533703607..fd98197e107 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/331] 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 86370897228..5eb5fac57d8 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 52d92e00dec..46456272b39 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/331] 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 00000000000..3781744748d --- /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 00000000000..c9a9f89fe4c --- /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 98de6abf2f9..32c5264dd26 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 8299ade24a9..756fbfb3df1 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 916ed9ae73c..0d1feeb191d 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/331] 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 3781744748d..be227ecdd03 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 32c5264dd26..98de6abf2f9 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 756fbfb3df1..aef1c48245f 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 0d1feeb191d..916ed9ae73c 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 d979bc17d16..bca6f889228 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/331] 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 c9a9f89fe4c..2ece4cbd987 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 aef1c48245f..8af7c7c5d15 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 46456272b39..ddf38fd4eda 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/331] 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 5eb5fac57d8..ee6bc98f1c8 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 ddf38fd4eda..5a4b785b39c 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/331] 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 5a4b785b39c..d591fa66e7e 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/331] 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 be227ecdd03..13c6477edeb 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 98de6abf2f9..08a8479c8fb 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 8af7c7c5d15..4895f3c3375 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 916ed9ae73c..a546d1ce942 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 2cb9f89cf80..ff3e8c78d3e 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 ee6bc98f1c8..9bfdc554f75 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 1a994ae413a..f31bc11934c 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 d591fa66e7e..62a618fcb0d 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/331] 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 08a8479c8fb..e732597b06e 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 cca18b3dfd1..47c418ca7ae 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/331] 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 cca18b3dfd1..47c418ca7ae 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 8cd29d06768..75194f06c02 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 d0e4bb847e7..e9ccb357df2 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 6574d1d63e1..425a3a8c871 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 fd98197e107..402b9f29435 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/331] 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 6e841a75644..e4567497466 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/331] 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 e9ccb357df2..a5952858b6b 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/331] 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 3f34d21b542..62391395e72 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/331] 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 13c6477edeb..e8fcbb0af90 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 2ece4cbd987..f554f099142 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 f31bc11934c..b85ea3d852a 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 62391395e72..6277425b426 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 b25531fb251..c5bb333cfa9 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/331] 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 db31386e7c7..73880687a9c 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/331] 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 6277425b426..69481bf9b6c 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 c5bb333cfa9..630fc8921d3 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 db31386e7c7..73880687a9c 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/331] 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 9bfdc554f75..113841d5e43 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 821e4e744fe..424df4cb1cf 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 69481bf9b6c..58a5f2675dd 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/331] 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 75194f06c02..c308174c201 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 a5952858b6b..bc47b526089 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 425a3a8c871..502e537d1db 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 402b9f29435..1881cf15b0d 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/331] 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 9aea2be01b6..3c16339f6f3 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 bc47b526089..0bb8fce882f 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 1bab3bda767..d4f246b3802 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/331] 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 d4f246b3802..a5ac74bb6e6 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/331] 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 7ae5499f39a..0f20e7c4201 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/331] 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 1881cf15b0d..0e250d967f6 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/331] 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 ac29abe92f8..b0dc278cc06 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/331] 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 0f20e7c4201..e0b1d3e5eac 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 3c37b59c8d6..670983722d3 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 d58a6881d4e..c81394bdf54 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/331] 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 0e250d967f6..5ae1cc5aa54 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/331] 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 d259808a426..40e80bda061 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 e4b283fdac1..f889f1a5712 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 502e537d1db..55f41769915 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/331] 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 a5ac74bb6e6..bee54b1320d 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/331] 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 55f41769915..ba3c6c6d52f 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/331] 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 0bb8fce882f..24f9d4ded24 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 ba3c6c6d52f..17ebc9d2716 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/331] 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 abc054b572a..4e0296a0f00 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 24f9d4ded24..f5775712cba 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 17ebc9d2716..32e51a0e287 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/331] 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 32e51a0e287..1bfe8a7c1c3 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 5ae1cc5aa54..1f44c75a7a5 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/331] 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 00000000000..ba81f83e0ad --- /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 f257da07a44..6aba503691e 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 134173068b9..c816bdfe561 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 1b1586060e2..76f3898e844 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 39c6b3a6682..93fbd7abc2a 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 5384679af93..d1466ac021b 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 e508ebdb4bc..3bd4995fd49 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 00000000000..a6cecb351be --- /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 00000000000..aeceb7b7e6f --- /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 8fbebdf0467..3a09fec452b 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 57321677480..d8d1298fba6 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 c46ee9d5012..481279155fd 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 2a9791fe19c..90f612de010 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 00000000000..73a264544ca --- /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 00000000000..1273e25859e --- /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 00000000000..bb22f494374 --- /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 00000000000..8058e156969 --- /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 00000000000..f7039627238 --- /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 00000000000..0837cc2fd55 --- /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 00000000000..e538f701919 --- /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 00000000000..2ef0ffe766f --- /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 d259808a426..40e80bda061 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 00000000000..1145c22fcaf --- /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 00000000000..d94187eade1 --- /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 ff3e8c78d3e..2b768d157ee 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 2152727940c..bc23e831a45 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 d6ae7f9fceb..1116f3e6b66 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 da9b259114f..b154b9573e1 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 7a6d70162cb..9f677d1dc4d 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 65fd417c691..59b2d2e9113 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 89ec07558bc..400650ed885 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 e4b283fdac1..ff564b29e12 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 d919c600112..1b93674c8a2 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 39d8eb34f24..c5a3579ab3e 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 ad90969cf80..bb91cfbcb4e 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 00000000000..9f7758aa476 --- /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 dc3bfffba30..f5fbd8cb411 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 00000000000..340cf0e4294 --- /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 00000000000..2f1afe25a6d --- /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 e8094c94a49..0f2ae4b7c97 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 5c4138d920e..56c73c379b7 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 00000000000..c1f9534162a --- /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 d5c8f12d395..318a11b678e 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 e4d25920eac..25135b784f2 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 00000000000..50cfd8ab17d --- /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 abdc48513b1..d8fc85f8103 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 f28a46dc3f2..b7cf7271326 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 49bad9d8547..d1b40702024 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 e4103909646..68ff171b44f 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 8723c5c70e0..66df88f0e7c 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 3869c8c20db..1e7e18f8aa9 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 abc054b572a..4e0296a0f00 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 9d3b1aa5936..2f168d232b7 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 16495000561..469bc072a31 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 e0b1d3e5eac..2e8dbf33fd1 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 00000000000..ca6394172ad --- /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 10c198f9be1..2385b61f31f 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 611691f9f85..acd1b31d646 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 670983722d3..ea875840078 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 630fc8921d3..bd20af2391a 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 4128e1c6295..f2872652c8b 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 a52f717a612..465e051482c 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 00000000000..f253cdbd03d --- /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 5af93613a08..47a83fddf2a 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 e3317bd8000..416d6dca9c9 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 e92cf792d47..cab7f07da01 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 73b65951955..fba5f4df67f 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 e294d10746b..79a8e54e791 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 62513749c27..7135781d3a5 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 d406be33c3e..d3aa1ab0f7f 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 bb64ed5e8fe..e16fdde82f2 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 00000000000..d9c3967315a --- /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 a5ac74bb6e6..bee54b1320d 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/331] 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 1efa2146ca3..9072ac9bbc4 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 c1708ca6820..9caad409852 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 56c73c379b7..2313c0df0bb 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 d7280416c57..e9b34056821 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 1a351ed874b..c5269e47087 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 4e0296a0f00..e59baa44fe2 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 2f168d232b7..65bd56defa4 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 ba1c86b0bf4..873119820fe 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 ea875840078..befd008902b 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 bd20af2391a..0c778275a60 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 cab7f07da01..cb79263546b 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 8eae13f1b76..1eb0fa8343e 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/331] 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 00000000000..6ea41c0618b --- /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 00000000000..398fbc345c6 --- /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 47c418ca7ae..c1e34dc0769 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 70505edde94..d5d1543c43a 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 00000000000..408e2597385 --- /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 00000000000..a082b9bf893 --- /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 113841d5e43..3679f92ddf5 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 e59baa44fe2..3b7a872437b 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 65bd56defa4..247f20c0076 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 befd008902b..59a0f55535e 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 0c778275a60..760f64e35ce 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 cb79263546b..b27957d5e8e 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/331] 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 00000000000..4b24b5ffbf8 --- /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 f20d3c1cf5a..940ab9ec20d 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 01c276c332a..4bf6fa22580 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 2ff08a2fb1e..5d10a56b996 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/331] 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 3679f92ddf5..4401b2f28f7 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 424df4cb1cf..262df2f70db 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 b85ea3d852a..e3fc975f5bb 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 873119820fe..93b92d56926 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 59a0f55535e..41ae09d3d7d 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 760f64e35ce..75a604ec624 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/331] 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 4401b2f28f7..4593f128147 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 262df2f70db..c8cd7441e79 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/331] 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 a546d1ce942..00000000000 --- 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 3c16339f6f3..00000000000 --- 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/331] 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 4895f3c3375..3c225acaedf 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 41ae09d3d7d..b49e6574b49 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 b27957d5e8e..7bd269eaf10 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/331] 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 4593f128147..0a1a3431655 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 c8cd7441e79..3b3c8dfdd2d 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 93b92d56926..a63a8cde845 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/331] 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 e8fcbb0af90..f72673332f0 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 f554f099142..00000000000 --- 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/331] 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 c5269e47087..49ae869ce29 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 3b7a872437b..de565a58590 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 a63a8cde845..6d284978011 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 75a604ec624..9fe1fcbe634 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 7bd269eaf10..ba2e95d1b5e 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/331] 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 49ae869ce29..d5330e05f3f 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 de565a58590..488c0a9cb32 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 9fe1fcbe634..43306e59f82 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/331] 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 6ea41c0618b..2bbcbcd7593 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 398fbc345c6..1e9c8f9bacc 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 940ab9ec20d..cf49e4c43a6 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 4bf6fa22580..00000000000 --- 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 5d10a56b996..033dafef723 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 d5d1543c43a..2cdbcf94a22 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 408e2597385..db1ecfa5501 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 e3fc975f5bb..f135513f088 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/331] 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 247f20c0076..a3d06feb1d4 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 b49e6574b49..5791df83013 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/331] 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 d5330e05f3f..eb9506397b5 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 f135513f088..43409593618 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 ba2e95d1b5e..1bf76123dd3 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/331] 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 1bf76123dd3..82b1a48e97a 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/331] 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 82b1a48e97a..dbc64577409 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/331] 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 f72673332f0..d35262e1142 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 3c225acaedf..e6130cd0c37 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 6d284978011..7ce5d55c17e 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/331] 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 7ce5d55c17e..c02100c9b00 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/331] 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 43409593618..73732572245 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 c02100c9b00..e941b618f23 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 5791df83013..e593d580375 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 dbc64577409..acbaa5faaa5 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/331] 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 e593d580375..624c16c7e59 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 43306e59f82..f4810ba4fdb 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/331] 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 488c0a9cb32..4e70c0a69d9 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 e941b618f23..cb9f813b2d1 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 f4810ba4fdb..25913978ba8 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 acbaa5faaa5..32b4d03d609 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/331] 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 25913978ba8..b0ee2f5b060 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/331] 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 0a1a3431655..c5d47391a69 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 3b3c8dfdd2d..23a2ad590fb 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 eb9506397b5..9292ea845fc 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 73732572245..69e77300254 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 cb9f813b2d1..5fcb1315312 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 624c16c7e59..b48786e3579 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 b0ee2f5b060..e925d692942 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 32b4d03d609..7d8ca05b913 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/331] 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 9292ea845fc..4b3dd9234e4 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 4e70c0a69d9..ee2be0324f4 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/331] 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 4b3dd9234e4..b8809b65a2c 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/331] 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 23a2ad590fb..2ee0bfca160 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 b8809b65a2c..c3e981317b1 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 5fcb1315312..8e20138b48d 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/331] 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 c3e981317b1..729eda1887d 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 8e20138b48d..7c4ad72c3c5 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 e925d692942..ccb6934bfff 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 7d8ca05b913..c33492116b3 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/331] 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 7c4ad72c3c5..8136e454485 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 b48786e3579..60977a7fead 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/331] 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 8136e454485..312cc3132e2 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/331] 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 a3d06feb1d4..af7bb7ec0cf 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 312cc3132e2..1355e98e4d3 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 60977a7fead..830a74991ac 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 ccb6934bfff..746c3f0c038 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 c33492116b3..172fd73eb4b 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/331] 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 1355e98e4d3..e98d4a656d6 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/331] 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 d35262e1142..c57e51df1d1 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 e732597b06e..73fde7b6dd9 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 e6130cd0c37..e543bbd7322 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 172fd73eb4b..52ffa52826a 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/331] 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 746c3f0c038..3123313ef65 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 52ffa52826a..1f724e835e9 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/331] 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 1f724e835e9..cc09f927410 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/331] 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 3123313ef65..24edbe42973 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/331] 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 e98d4a656d6..9c216126773 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/331] 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 9c216126773..35650ee115c 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/331] 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 35650ee115c..bbb807fa5e0 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/331] 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 bbb807fa5e0..45d5ebc9d25 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/331] 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 45d5ebc9d25..f13298de77c 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/331] 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 f13298de77c..19f0cc04bf6 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/331] 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 f13298de77c..4129a09eef8 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/331] 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 59b2d2e9113..523e9384047 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 ef0d708d49a..5d81cdbffca 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/331] 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 5d81cdbffca..3d031ac9639 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/331] 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 3d031ac9639..f91da404cbc 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/331] 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 8984086f88c..ab35fffa627 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/331] 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 ab35fffa627..3ddfc89d58e 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/331] 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 3ddfc89d58e..949d66bac5b 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 d5e466b86d3..b51b19efa6a 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/331] 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 07ae056f970..a07314d54e2 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 6b47f211761..37e51e31305 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 68612347d39..ea1a172db3f 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 949d66bac5b..eac080df396 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/331] 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 c57e51df1d1..2e740080087 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 37e51e31305..07452ca8ee7 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 ea1a172db3f..ce2d5400809 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/331] 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 eac080df396..490f03e06e5 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/331] 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 b355cc46905..d948a7e5756 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 ee2be0324f4..2050a7b08f2 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/331] 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 490f03e06e5..aaefaa4c529 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 b51b19efa6a..03bc8f2a8de 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/331] 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 aaefaa4c529..9fc5b5a839e 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/331] 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 4b24b5ffbf8..d0b740d4227 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 cf49e4c43a6..9cc2020855f 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 07452ca8ee7..ad1e73b2750 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 d948a7e5756..2ebbaa9c407 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 2050a7b08f2..74ce40d0a86 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 9fc5b5a839e..f55fff54d49 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 24edbe42973..c38fe62beca 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/331] 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 758fe0648b2..4b80b0bd0c5 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 f55fff54d49..2cfdc31204d 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 03bc8f2a8de..45a44d30edb 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 c38fe62beca..8efe9ea03d3 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/331] 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 cc09f927410..16e9aacbd80 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/331] 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 2cfdc31204d..1f824ee13b2 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/331] 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 1f824ee13b2..ec2c8e369ef 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/331] 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 ec2c8e369ef..8445932416e 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 8efe9ea03d3..5a54aa6a7b4 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 16e9aacbd80..cbb240efdee 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/331] 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 5a54aa6a7b4..0a6d5871b50 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/331] 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 74ce40d0a86..b0a7d54d4fa 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 0a6d5871b50..2bc080fe2a7 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/331] 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 b0a7d54d4fa..f5861f922da 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 af7bb7ec0cf..c74024c26f6 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 8445932416e..e001d52ccc9 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 2bc080fe2a7..b655f7a45ed 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 cbb240efdee..15497eecd3b 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/331] 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 f5861f922da..6d55f69645e 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 b655f7a45ed..7566959584d 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 15497eecd3b..d7a4d1d1619 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/331] 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 e001d52ccc9..e7b884df515 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/331] 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 6d55f69645e..b6b322fb6d8 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 e001d52ccc9..58136752153 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 7566959584d..12e7a95a7e7 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 d7a4d1d1619..4d22a5c4b12 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/331] 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 4d22a5c4b12..0c6d018938b 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/331] 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 0c6d018938b..c20e2c2dadf 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/331] 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 6d55f69645e..40fa94b20fe 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 7566959584d..014b290f395 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 d7a4d1d1619..c2570896457 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/331] 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 c2570896457..a836f8d1e56 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/331] 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 7ffd63d40a6..d2061591a78 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 ce44ded9792..df1fb221c4a 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 fce0d2bb13d..cc9f6932995 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 5961c06ed88..48a960858b0 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/331] 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 d2061591a78..4adf32dde8b 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 cc9f6932995..f4428c529cf 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 48a960858b0..ca092cea370 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/331] 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 ca092cea370..c4b0ebb2902 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/331] 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 df1fb221c4a..e83ce8f0499 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 45a44d30edb..149f737a7d3 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/331] 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 e83ce8f0499..c4ccce13ce2 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 149f737a7d3..52788a97aa5 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 c4b0ebb2902..3c994d356e0 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/331] 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 c4ccce13ce2..41538edb894 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/331] 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 4b80b0bd0c5..10e639c92cc 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 41538edb894..871594a29b1 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 52788a97aa5..0a85ec03288 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 f4428c529cf..d99e356bc57 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/331] 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 10e639c92cc..1e0ffd1b5d3 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 871594a29b1..9158dcf8398 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 0a85ec03288..2d5f0a3ce87 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/331] 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 9158dcf8398..b0f716d2b82 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/331] 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 b0f716d2b82..b60920d666d 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/331] 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 4adf32dde8b..7e482917f06 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 d99e356bc57..3637597971a 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/331] 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 b60920d666d..b6fe38c751e 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/331] 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 2bbcbcd7593..ca1a07df349 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 00000000000..45acebe0047 --- /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 d0b740d4227..d27255d53ad 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 2e740080087..46fb754b176 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 9cc2020855f..7e319cb6a52 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 033dafef723..00000000000 --- 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 e543bbd7322..1ee01f9b7de 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 00000000000..e31a0476a43 --- /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 2cdbcf94a22..6a795707703 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 00000000000..c4951d804b6 --- /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 db1ecfa5501..df3da9655fa 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 a082b9bf893..dc4fd7733e7 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 2d5f0a3ce87..406f18f788f 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/331] 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 b6fe38c751e..b85cb0e0995 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 406f18f788f..b29b58c6cfa 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/331] 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 b85cb0e0995..0687f09dd6f 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/331] 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 0687f09dd6f..5c1031cf42f 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/331] 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 00000000000..0a926f439d3 --- /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 00000000000..c307a2b1667 --- /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 00000000000..917077e1ea0 --- /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 00000000000..ba4e29d0bc3 --- /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 00000000000..2be073b5588 --- /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 ca1a07df349..75ae9ef2c18 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 d27255d53ad..6529bb715af 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 46fb754b176..2a98547ec65 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 7e319cb6a52..8b6e9d76cc9 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 40e80bda061..00000000000 --- 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 00000000000..0c251edfe29 --- /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 00000000000..62babc4c0f6 --- /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 1ee01f9b7de..7cdc86483a0 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 f7b638a4475..00000000000 --- 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 c4951d804b6..87f6285e95b 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 df3da9655fa..635084a42b9 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 00000000000..2ff438084c1 --- /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 00000000000..31e9b958a20 --- /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 00000000000..d3234ef4860 --- /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 00000000000..1822b46f10e --- /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 00000000000..d2a4fb53612 --- /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 00000000000..f9206ea81fe --- /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 00000000000..743f47bb70e --- /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 00000000000..7bc0f4d332e --- /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 00000000000..b0a01b1a915 --- /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 00000000000..704012325b1 --- /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 00000000000..0f6e5e955da --- /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 00000000000..725f8ed5513 --- /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 a07314d54e2..36f7357a0f3 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 ad1e73b2750..78571483401 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 7e482917f06..a4a8f30036e 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 5c1031cf42f..2462f43cc37 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 3637597971a..d4e8726b185 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/331] 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 a4a8f30036e..0fe1c365b98 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 d4e8726b185..a33500cb625 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/331] 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 3c994d356e0..e4bb1989751 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/331] 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 0fe1c365b98..8da31842304 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 462e4693496..a21dbfca7a6 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 b29b58c6cfa..afefc534668 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 01431640e7a..775e3cfa321 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 e4bb1989751..dac598792ab 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/331] 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 775e3cfa321..3c681536a6f 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/331] 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 a21dbfca7a6..4f8325a54eb 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 dac598792ab..074bd1a67d8 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/331] 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 afefc534668..871aa9bc02f 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 3c681536a6f..aef3d3168f7 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/331] 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 5ee043b3232..cb27c828cf4 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 8a8a1b19963..42c831c98ba 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 00000000000..241e0698649 --- /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 3816b42c337..ab1b13d49da 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 5e7b4dbea49..cbeae1b62e6 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 e0e7268d8ee..5c77247ac6d 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 504bbe39259..e33328a8204 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 2ebbaa9c407..5f1aa57d17f 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 2c823042c7d..6c27e206321 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 df882befaba..a3346a4f15c 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 246165290ec..67a1be8deda 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 d605a848aad..a7c6a8b4746 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 fd8f76d168f..aef86e3de7d 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 acb89bc4526..283f8bdc74e 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 44be4438154..a966b3836f3 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 f75fedcf2a3..7c58ef89a6c 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 22d45abc762..9dceab38031 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/331] 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 c1e34dc0769..58423b55012 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 e4b37de13a3..fb9afeb25d7 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/331] 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 fb9afeb25d7..9a57ced2198 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/331] 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 6a795707703..37ae523a4bb 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 ddd9cab2889..855246b2053 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 2c54560558d..ca88d9bd31c 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 62707c695af..776de603fd0 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 074bd1a67d8..138bfebd43a 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 fb9afeb25d7..9a57ced2198 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/331] 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 cbeae1b62e6..1b3bb229ef9 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 ca88d9bd31c..43cfbc3dc8d 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/331] 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 43cfbc3dc8d..e059aa6e349 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/331] 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 761ae97d1b3..4b5878fecf0 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 dac598792ab..074bd1a67d8 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/331] 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 cbeae1b62e6..1b3bb229ef9 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 67a1be8deda..ddd9cab2889 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/331] 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 e059aa6e349..72e7211325a 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/331] 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 2ff438084c1..00000000000 --- 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 31e9b958a20..00000000000 --- 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 d3234ef4860..00000000000 --- 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 1822b46f10e..00000000000 --- 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 d2a4fb53612..00000000000 --- 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 f9206ea81fe..00000000000 --- 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 743f47bb70e..00000000000 --- 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 7bc0f4d332e..00000000000 --- 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 b0a01b1a915..00000000000 --- 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 704012325b1..00000000000 --- 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 0f6e5e955da..00000000000 --- 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 725f8ed5513..00000000000 --- 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/331] 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 0a926f439d3..180ef30fc4e 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 c307a2b1667..2604dd7800a 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 917077e1ea0..4fa9a2bbe74 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 ba4e29d0bc3..8ce4ed73ed7 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 2be073b5588..d1395c31bb5 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 75ae9ef2c18..e510cc8a7e5 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 45acebe0047..3eaec337d71 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 6529bb715af..604be7dac47 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 2a98547ec65..054fb9ac290 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 8b6e9d76cc9..2419623a75e 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 73fde7b6dd9..6d02a42dd13 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 0c251edfe29..33608f6cc87 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 62babc4c0f6..a9ebdbdcaf5 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 7cdc86483a0..1c8916e3ea6 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 37ae523a4bb..5bd11b1c19c 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 87f6285e95b..7625b5191c2 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 635084a42b9..1b376c7fe3b 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 e185874d344..0af95f187a2 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 00000000000..a97c2443601 --- /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 00000000000..ee6a4e39c46 --- /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 f23f96eccf8..188d0047e86 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 130523db0d6..c0e0fa9770f 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 855246b2053..4764db28f19 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 72e7211325a..980ba2d417c 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 138bfebd43a..8a9d132be68 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/331] 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 a97c2443601..bd1f323afc8 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 ee6a4e39c46..4137110d93f 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 8a9d132be68..234a88a80de 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/331] 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 9a57ced2198..fdd99c5a5ba 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/331] 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 423881fe05f..4655a0b9ef6 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 234a88a80de..57349fe2af2 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/331] 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 57349fe2af2..918031e0469 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/331] 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 180ef30fc4e..1836c2b73da 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 2604dd7800a..598f7529bf3 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 4fa9a2bbe74..53095749992 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 8ce4ed73ed7..2b8b2fe8f74 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 d1395c31bb5..1a0296db17e 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 e510cc8a7e5..10d6743d6bc 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 3eaec337d71..37f5d6d91c0 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 604be7dac47..1d88d71a6f4 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 054fb9ac290..6fed8ae11d9 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 2419623a75e..42c5b13db88 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 6d02a42dd13..999e79b6acb 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 58423b55012..3f8a894a458 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 33608f6cc87..facfae31695 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 a9ebdbdcaf5..cda56dca076 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 1c8916e3ea6..b333436a98a 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 5bd11b1c19c..f89ba88c09a 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 7625b5191c2..4ad228010f0 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 1b376c7fe3b..818999a0124 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/331] 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 1e9c8f9bacc..4838b88f229 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 dc4fd7733e7..355f548ba89 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/331] 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 918031e0469..7f1a04b11fc 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/331] 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 1836c2b73da..ce19d5594af 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 53095749992..e4580fcd5ac 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 10d6743d6bc..853641a577e 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 1d88d71a6f4..05e1e036781 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 4838b88f229..2b08f7d4e29 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 42c5b13db88..bc93be4febf 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 3f8a894a458..0fc986f8ad0 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 facfae31695..82e2d4729ef 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 f89ba88c09a..c4a91eba130 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 818999a0124..42f894c39a2 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 355f548ba89..fcff16c5bc5 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 d3fbdba8bc7..467fc90ee4c 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 00000000000..3379412b3f8 --- /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 bd1f323afc8..5141c07a7ed 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 188d0047e86..7c829a98c51 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 4764db28f19..71c6df55939 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 7f1a04b11fc..13187786b02 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/331] 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 73fde7b6dd9..b81c788a856 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 fdd99c5a5ba..85b94212c40 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/331] 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 85b94212c40..354898e0b5f 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/331] 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 5e958e9a11c..59576726c4a 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 85b94212c40..354898e0b5f 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/331] 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 5e958e9a11c..59576726c4a 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 85b94212c40..354898e0b5f 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/331] 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 3379412b3f8..e1550b77b5b 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 5141c07a7ed..6cc35ae5622 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 13187786b02..32c3f44e6a1 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/331] 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 00000000000..82f1b0f12c4 --- /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 71c6df55939..14a1225f82c 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 800dc31f84f..6314e3e438c 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/331] 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 8da31842304..e435c146ff5 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 71bca1a7846..b02ffea85f3 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 14a1225f82c..e0fc609f5db 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 980ba2d417c..79f00f6c267 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 776de603fd0..855c5ac00d9 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/331] 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 b02ffea85f3..a01f6064c06 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 6314e3e438c..5f0a8696749 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/331] 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 853641a577e..26c6ea596b5 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 2b08f7d4e29..6c7e7834495 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 0fc986f8ad0..af23199d775 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 6cc35ae5622..6a5c357aff2 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 4137110d93f..61294c23f06 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 e0fc609f5db..4f0f557a023 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 79f00f6c267..b726602ceb5 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 855c5ac00d9..ddce9d97f25 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 354898e0b5f..cd4550c5590 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/331] 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 4ad228010f0..dbb30336f33 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 42f894c39a2..4d9c8086fcf 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 9d616a61210..b0735c15a82 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 0b2c4ef4d5f..97a6f3241ea 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 00000000000..d01224dc682 --- /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 00000000000..ac8535f996b --- /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 e435c146ff5..395cfeb0e65 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 4f0f557a023..0c88464cf04 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 ddce9d97f25..190f89acbe8 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 32c3f44e6a1..dd63d1792ef 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/331] 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 75ae9ef2c18..b53bb0250af 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 feaf66c4a7f..7f9f1017c7c 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/331] 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 ddce9d97f25..09630ac828c 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/331] 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 82f1b0f12c4..2475ab5b3a7 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 5f0a8696749..2b8951b2791 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/331] 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 ce19d5594af..ae9f72da3c1 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 e4580fcd5ac..2da995f6b1d 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 1a0296db17e..5bacc7971ed 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 b2629e5ca63..6cd0ce7fb7f 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 05e1e036781..08652258164 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 6c7e7834495..540b78d9a92 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 bc93be4febf..38d8042dc48 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 59576726c4a..136d8839e53 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 af23199d775..c12054b3d78 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 82e2d4729ef..7f847c81dae 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 c4a91eba130..c2c3e5d813f 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 4ad228010f0..cec2298157e 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 42f894c39a2..c790b8a6399 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 fcff16c5bc5..89924b1cceb 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 2475ab5b3a7..b24c4138345 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 e1550b77b5b..8960a14f3d3 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 6a5c357aff2..c0fcfb294a9 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 61294c23f06..2c31f406623 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 c5d47391a69..20253b3f019 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 fe9154add72..b9977a9d4fc 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 1b3bb229ef9..a65aafef74d 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 5f1aa57d17f..934109c4936 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 a01f6064c06..2dac94866c5 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 c0e0fa9770f..47539f5991c 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 4f0f557a023..c0693a8aa7a 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 b726602ceb5..e1c85b407e0 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 09630ac828c..ed59f1545c6 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 32c3f44e6a1..3c08ea04b11 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/331] 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 8960a14f3d3..b22a707ce90 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 00000000000..9e066148c84 --- /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 934109c4936..31a399da18c 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/331] 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 9e066148c84..9e7c3657815 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 2c31f406623..75f45f41d03 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 c0693a8aa7a..3eb274de64b 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 ed59f1545c6..8990d7d823a 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 3c08ea04b11..0e1b8ffd871 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/331] 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 ae9f72da3c1..543846eb80b 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 598f7529bf3..fb2b0120dd5 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 2da995f6b1d..ab4ba667fec 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 2b8b2fe8f74..083e2a33d18 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 5bacc7971ed..25211ad7c05 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 6cd0ce7fb7f..d0cae7a4d73 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 37f5d6d91c0..3cba12047ee 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 08652258164..b72a88551ce 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 540b78d9a92..8235d51d897 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 6fed8ae11d9..3a3fa30bba0 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 38d8042dc48..e539ff43b5e 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 136d8839e53..29701cc0632 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 c12054b3d78..8193ddcdb1f 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 7f847c81dae..0c4930479b4 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 cda56dca076..1e33b664e1a 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 b333436a98a..464ae207822 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 c2c3e5d813f..71054ec9740 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 cec2298157e..c5268e3d3df 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 c790b8a6399..4ed757e38e8 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 89924b1cceb..cbe12a5e000 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 b24c4138345..0e9ff85b94b 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 b22a707ce90..27468dda17c 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 8990d7d823a..ee5f9c7e6d0 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 0e1b8ffd871..2afbbaf2447 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/331] 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 00000000000..69e502a1841 --- /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 0e9ff85b94b..e92cbde3527 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 27468dda17c..896add78ab3 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 2afbbaf2447..69f33c03111 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 cd4550c5590..36a24bc5aec 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/331] 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 9e7c3657815..7b138971030 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 75f45f41d03..61e7757fc37 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 b9977a9d4fc..27af7932f71 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 31a399da18c..985e38fdfb5 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 e435c146ff5..17a49bdebdc 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 3eb274de64b..474a6a16ad6 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 e1c85b407e0..7e955364d13 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 ee5f9c7e6d0..8a1a1ab9954 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 69f33c03111..959c0bd6537 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/331] 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 959c0bd6537..29482c6e7c0 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/331] 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 61e7757fc37..a7195d6767a 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 474a6a16ad6..4181b3a9a02 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 7e955364d13..cd0c40adf7c 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/331] 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 cd0c40adf7c..0e6bb07c2a7 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/331] 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 543846eb80b..47d4d334c9e 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 fb2b0120dd5..8cffae7ec45 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 ab4ba667fec..a42cf9ab371 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 083e2a33d18..a9d5321586f 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 25211ad7c05..45d256d963d 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 d0cae7a4d73..bb00fb74876 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 3cba12047ee..a6a187067f1 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 b72a88551ce..5f7a6b8852e 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 8235d51d897..d3476505105 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 3a3fa30bba0..e882314d0e2 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 e539ff43b5e..e3f1d283f9e 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 29701cc0632..7cbdb688589 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 8193ddcdb1f..8ee46141dc8 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 0c4930479b4..4c8fa1fca10 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 1e33b664e1a..21841f69df8 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 464ae207822..97fe311374f 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 71054ec9740..abd7767fe0a 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 c5268e3d3df..c8d008f4aa0 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 4ed757e38e8..9c605657c2d 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 69e502a1841..83da7dee8c6 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 cbe12a5e000..27bfa942dfe 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 e92cbde3527..c77667afaaf 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 c0fcfb294a9..2cde50d307b 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/331] 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 5f7a6b8852e..0e86db0c0cf 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/331] 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 ba1c0ed7b0c..0d3f5c3841e 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 2a395f53efb..6684e1a7e4f 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/331] 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 0d3f5c3841e..b1ca21d0635 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/331] 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 2dac94866c5..89efae1869f 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 5909d848bf2..376019c9d06 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/331] 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 47d4d334c9e..52b3e931c8f 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 a42cf9ab371..66496e62b28 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 bb00fb74876..d53dff44f48 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 0e86db0c0cf..dc1f8cb6767 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 d3476505105..fc20b05bb33 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 e3f1d283f9e..1a5de0aef40 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 8ee46141dc8..fa05049bcb9 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 4c8fa1fca10..8129d29006d 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 abd7767fe0a..0fb72177bd4 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 9c605657c2d..2c2920ed3a1 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 83da7dee8c6..ab527ebd2a4 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 27bfa942dfe..0dc0eb0228a 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 c77667afaaf..3bb3bf07a25 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 9d616a61210..8d35d389a31 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 00000000000..b1649ed1b39 --- /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 896add78ab3..00000000000 --- 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 7c829a98c51..4901feb6ae6 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 29482c6e7c0..e23f9597180 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/331] 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 52b3e931c8f..f601163b104 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 8cffae7ec45..d6dc886a291 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 66496e62b28..410b94acab6 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 a9d5321586f..746db116d57 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 45d256d963d..2a460464ac1 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 d53dff44f48..81d52aa387c 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 a6a187067f1..8c9baaed20e 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 dc1f8cb6767..db091f968ce 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 fc20b05bb33..d4eaa92e487 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 e882314d0e2..5d5b76a434d 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 1a5de0aef40..8dab1611aa8 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 7cbdb688589..81577ba5115 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 fa05049bcb9..3bb22415197 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 8129d29006d..c04aa60f941 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 21841f69df8..3bd33c3b2ca 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 97fe311374f..35ad491e15a 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 0fb72177bd4..1dfa60dd88b 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 c8d008f4aa0..7686f0b451a 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 2c2920ed3a1..e1fcf46c000 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 ab527ebd2a4..76948193f47 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 0dc0eb0228a..a5ec60f6679 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 3bb3bf07a25..e226f6907e6 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 8d35d389a31..ccae19895ce 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 b1649ed1b39..5afa5e237ed 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 2cde50d307b..32f003832bb 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 20253b3f019..fbf699b5346 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 a65aafef74d..a5b0ae1965a 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 47539f5991c..459a95d2dff 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 4181b3a9a02..5c0edd30ec1 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 0e6bb07c2a7..b096cdd4e2c 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 e23f9597180..e31973794ac 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/331] 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 47d4d334c9e..f601163b104 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 8cffae7ec45..d6dc886a291 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 a42cf9ab371..410b94acab6 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 a9d5321586f..746db116d57 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 45d256d963d..2a460464ac1 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 bb00fb74876..81d52aa387c 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 a6a187067f1..8c9baaed20e 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 0e86db0c0cf..db091f968ce 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 d3476505105..d4eaa92e487 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 e882314d0e2..5d5b76a434d 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 e3f1d283f9e..8dab1611aa8 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 7cbdb688589..81577ba5115 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 8ee46141dc8..3bb22415197 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 4c8fa1fca10..c04aa60f941 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 21841f69df8..3bd33c3b2ca 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 97fe311374f..35ad491e15a 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 abd7767fe0a..1dfa60dd88b 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 33881fc2129..cedb276c796 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 a64863121ba..40010a58aef 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 83da7dee8c6..76948193f47 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 27bfa942dfe..a5ec60f6679 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 c77667afaaf..e226f6907e6 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 b0735c15a82..b5b531c7282 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 00000000000..5afa5e237ed --- /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 896add78ab3..00000000000 --- 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 2cde50d307b..32f003832bb 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 7c829a98c51..4901feb6ae6 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 b1ca21d0635..2bd3a839048 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 20253b3f019..fbf699b5346 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 a65aafef74d..a5b0ae1965a 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 47539f5991c..459a95d2dff 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 376019c9d06..0d55a488b9a 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 0e6bb07c2a7..b096cdd4e2c 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 e60d3c0f400..dc16d0ca23b 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/331] 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 ccae19895ce..f6cb57c374c 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 5afa5e237ed..6471cc96d52 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/331] 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 81d52aa387c..411a797a8a5 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 1dfa60dd88b..a79dea1a220 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 76948193f47..310d4f68175 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 e226f6907e6..182bc6d8c76 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 32f003832bb..1d1925a1617 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 a7195d6767a..e594c2f01b1 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 b096cdd4e2c..32e271253c2 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 69a01526379..e0cadcd00b1 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/331] 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 f601163b104..ed352f44783 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 c04aa60f941..ddbcea0299a 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 a5ec60f6679..68c889d4e33 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 7f9f1017c7c..395036dcff5 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 36a24bc5aec..a32227b3563 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/331] 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 f601163b104..ed352f44783 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 c04aa60f941..ddbcea0299a 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 a5ec60f6679..68c889d4e33 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 7f9f1017c7c..395036dcff5 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 36a24bc5aec..a32227b3563 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/331] 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 ed352f44783..e59f70ee4c1 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 411a797a8a5..5f867befaa8 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 ddbcea0299a..93b064bc3df 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 a79dea1a220..1fe475aba10 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 310d4f68175..a2339db8ce8 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 68c889d4e33..6f1c64630ff 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 e594c2f01b1..3361a6e4e16 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/331] 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 e59f70ee4c1..19f524422d3 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 410b94acab6..cb433bb3898 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 5f867befaa8..528649e9ea6 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 db091f968ce..de89e9d70d8 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 d4eaa92e487..a439d578ac3 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 8dab1611aa8..31c0bcaaf50 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 3bb22415197..7e8d90c90c8 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 93b064bc3df..654d842ecd4 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 1fe475aba10..75c86e8230a 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 40010a58aef..1543e80f014 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 6f1c64630ff..55ccc01a363 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 182bc6d8c76..95806035f05 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 1d1925a1617..4c182feac1f 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 3361a6e4e16..6d51ec4f2b1 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 395cfeb0e65..876d0fc28c5 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 0d55a488b9a..7095f7d5952 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 32e271253c2..a0496ca2317 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 e0cadcd00b1..2897eb867fc 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/331] 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 6f1c64630ff..b2d6ed4f08c 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 1d1925a1617..7a4f4e6d7f3 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 32e271253c2..8b1531ada75 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 e0cadcd00b1..7029b07b642 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/331] 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 00000000000..f1a83a1823f --- /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 2897eb867fc..453b44e7e5a 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 2b8951b2791..2babe02cc8a 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/331] 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 7029b07b642..ac76d42ce7b 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/331] 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 6471cc96d52..9f50fbde4f7 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/331] 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 2b8951b2791..653be581e13 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/331] Fix format --- utils/trixi2txt.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index 8b04554eb09..12a3d46760e 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/331] 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 988ed616700..9edbd9e6240 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/331] 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 e59f70ee4c1..e1dd4abf8e5 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 410b94acab6..ad5b549d796 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 5f867befaa8..f12754e4375 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 db091f968ce..8563b2db131 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 d4eaa92e487..adbaa4d1d09 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 93b064bc3df..28e5d6c01fd 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 1fe475aba10..89c7d21521e 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 40010a58aef..f62e6168156 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 a2339db8ce8..974cd667ede 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 b2d6ed4f08c..299674e1200 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 182bc6d8c76..4a207873a91 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 673f8bbc2b7..297aba526fc 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 934f8f5ae13..c46bdc851d1 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 9edbd9e6240..bdac5518e9b 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 f08c0375ea5..b62e60b7c9b 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/331] 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 e1dd4abf8e5..17cc79fa4f3 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 f12754e4375..dd68e0d9aee 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 28e5d6c01fd..f5b69c2ff96 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 3d1851cd7b7..8f6b54459ef 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 bdac5518e9b..7e753a7d482 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 b62e60b7c9b..9c7cbcaa5ed 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 653be581e13..606afca1034 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/331] 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 2156e9bac32..2fa6a04237c 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/331] 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 adbaa4d1d09..a86b56cd214 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 fe820786db8..45069861a21 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/331] 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 45069861a21..cf766b7a988 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/331] 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 43268e72e62..585ac50d0d1 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 d6dc886a291..fa59e5e0d37 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 13137672314..a7f01ac2507 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 746db116d57..9c3d7c8943d 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 2a460464ac1..8999d435ecc 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 c177b972e91..3d361445462 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 8c9baaed20e..2d4f8f608a1 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 31d80f808ae..ff64933b839 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 9568546c1d8..347ae70570e 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 5d5b76a434d..f51b73dd497 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 fe6671a2d16..12c02599144 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 81577ba5115..0e5a85e00a8 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 904ae809caa..2c18b0186e2 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 4f3b20d697a..fbf695c4126 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 3bd33c3b2ca..d7e4250bb67 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 35ad491e15a..3be50d01995 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 38cf1d60002..66297c8eb72 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 cedb276c796..af239b7c1a3 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 70fadce9216..e8eaa5ea326 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 974cd667ede..65b8f72de37 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 670f49ce203..8ac4b2091f9 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 83aea4ee2a7..55c87cab3b1 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 aadf21f1e16..d3b41dfb339 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 61340d43304..a3a73b578c8 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 fb7e024786b..c85088ad938 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 965afdcc194..a3c7f6c047b 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 773aa3e1f42..1d56d725c8d 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 5d20ac2d240..600ff077518 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 f0ed4392133..65d280f33df 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 4b38980aa8e..4ef4a295311 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 08926aef189..5c11494ac98 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 ee1ee4f731f..fa1fc29f54f 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 450e00e731f..ae97929517b 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 871900bfbbb..f6744972962 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 c6eb69a2ed0..c64e63345d5 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 f541dccc4e4..2ebefac5737 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 b84cdc2a445..b6e4a743252 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 9864a859421..c54983509f3 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 67554330950..a34d4f63aaa 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 a6e12c980cc..1af9e849ee3 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 8d23336cb27..7ff8c5afed3 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/331] 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 c54983509f3..1bfc0a428be 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 a34d4f63aaa..48177fce79b 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/331] 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 c85088ad938..4211fe752d6 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 1bfc0a428be..fe8e61c7e92 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 1af9e849ee3..87275bcdfbe 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/331] 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 585ac50d0d1..5761e638e41 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 a7f01ac2507..ede3f6b3827 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 3d361445462..6b70438044e 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 ff64933b839..5d266629764 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 347ae70570e..13ed29db2ba 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 12c02599144..5b95fef374e 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 2c18b0186e2..0e44f62c7bd 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 fbf695c4126..bf6064dc219 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 66297c8eb72..42b529cb638 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 e8eaa5ea326..98861064415 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 65b8f72de37..810c37ff5bd 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 8ac4b2091f9..5c92414e66a 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 55c87cab3b1..1c6cbef533e 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 d3b41dfb339..4fe08a55129 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 a3a73b578c8..3b5a094f2ab 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 4211fe752d6..b6734f6d51a 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 fe8e61c7e92..51d0f6a6f21 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/331] 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 63c31a33f52..294450507a1 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 b6734f6d51a..f7c3aacc7e4 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/331] 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 5cf4c4ef78c..de4601a2203 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 f6744972962..a8e141f562a 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 00000000000..6d7c0a740ab --- /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 8f6b54459ef..f4b07b70cb8 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 00000000000..8faa10cb18d --- /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 2ebefac5737..550209833ee 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 b6e4a743252..2f7d5122a28 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 00000000000..064a9b86f94 --- /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 51d0f6a6f21..2eb0af87148 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 48177fce79b..085cb71ad0c 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 00000000000..a953180352a --- /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 00000000000..f66321e3936 --- /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/331] 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 2f7d5122a28..370d69746e3 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 064a9b86f94..9a41a4f23f7 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/331] 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 9a41a4f23f7..60a4ebfd211 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/331] 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 3b5a094f2ab..c710408f809 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 f7c3aacc7e4..69125ebecd9 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 a3c7f6c047b..23eb6c7b649 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 4ef4a295311..3ed78ee6db0 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/331] 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 3ed78ee6db0..1d56d7b58a4 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 87275bcdfbe..f3a9edb8e4d 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/331] 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 700707ced32..d60f0707fc2 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 a1a429cad97..6ebb288ea30 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 abaa3e7e037..74bfaa9c852 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 8e374d9ce99..4b96e1e2834 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 c22d4b90642..dd937ed213b 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 00000000000..3f72d319b0b --- /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 00000000000..181a2cb209f --- /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 d63be5573fd..1c154367138 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 600ff077518..a5e146f555c 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 23eb6c7b649..fffb743993a 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 65d280f33df..55e48cbaf83 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 1d56d7b58a4..a6b5c498c3d 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 e4fd0997eae..9204989e8be 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 00000000000..af7897d4586 --- /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 00000000000..dca846cac1e --- /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 a1f11717e69..f762fe5d5ee 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 0b770dff1ca..166b53bf615 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 6c0be43798a..66214025044 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 57bcb1212e1..32782d5478c 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 7e90a83a9ca..a04523d2fb4 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 6439cad69bb..2d26c1aff50 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 d79ddcbc512..8ab174d20b6 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 c5862579992..0da25230380 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 60a4ebfd211..0f0fb1a4b71 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 5b63b971cd8..2745d312b37 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 a953180352a..8dd17c2d6a9 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 f66321e3936..7db04ca83ff 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 f3a9edb8e4d..6dcfe93d7c6 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 1b0c745dbfd..f1adbaaf1df 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 1aaf23d576a..06a55100d62 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 e3bb1ed9fb1..1564a33dc41 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 67a27238969..d607962afa0 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/331] 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 8ab174d20b6..b1bd509fc7d 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/331] 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 742160b35f0..8e2d00fa687 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 6c095a8c0be411274b90d6b151fc969356bb714f Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 27 Sep 2023 12:02:53 +0200 Subject: [PATCH 258/331] 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 a5e146f555c..7b2740ff180 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 259/331] 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 8e2d00fa687..be1a1d3138b 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 8896b4a234a..5cfd7a446ca 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 260/331] 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 5cfd7a446ca..f48386aa8a6 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 261/331] 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 1d56d725c8d..600c11d9252 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 7b2740ff180..f66f8b8b3aa 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 b1bd509fc7d..a6d9f57758b 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 0f0fb1a4b71..e165308967f 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 8dd17c2d6a9..86d88c827f8 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 7db04ca83ff..a8fcc42c061 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 262/331] 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 00000000000..37294973315 --- /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 f6b91444578..6f1723e2a98 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 8fef1ee22c9..82d4844b166 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 9148b936312..576732b9219 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 c30d0a8e01a..679b6b33f25 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 70ff346740d..57053f97e02 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 09ab84ed11a..07736c6bfa3 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 a0ed889968a..fed3fb70dde 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 263/331] 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 82d4844b166..c032a778c3d 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 679b6b33f25..c30d0a8e01a 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 57053f97e02..7c8bdff4b0e 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 264/331] 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 37294973315..db362b74cdb 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 b65d03e7975..b4485217411 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 9bae563d85f..a941f750a68 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 c032a778c3d..9a26503397d 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 7c8bdff4b0e..f658f00fcf1 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 265/331] 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 db362b74cdb..31855449050 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 9a26503397d..f9290539e72 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 576732b9219..0784a834033 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 f658f00fcf1..4af22c2f0e3 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 266/331] 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 3e104da3e91..da9d34ef74a 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 267/331] 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 31855449050..d7ef23332fe 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 b4485217411..1346d8ff7af 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 f9290539e72..76cfc7b4335 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 268/331] 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 76cfc7b4335..fcd337d6467 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 269/331] Fixed bug --- src/Trixi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index 1346d8ff7af..14687cbb992 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 270/331] 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 a941f750a68..ac232a8bb32 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 fcd337d6467..09b1788ed8f 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 271/331] 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 4af22c2f0e3..adcb06837bf 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 272/331] 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 adcb06837bf..da5b438e424 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 273/331] 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 da5b438e424..3a9d898bc41 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 274/331] 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 ac232a8bb32..63151f5dff7 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 275/331] 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 09b1788ed8f..45aeba3ac2a 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 3a9d898bc41..17354cd27ba 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 276/331] 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 17354cd27ba..3731f322eee 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 277/331] 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 da9d34ef74a..c3911a741c4 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 278/331] 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 d7ef23332fe..10e06204629 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 279/331] 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 10e06204629..8ee8177949f 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 45aeba3ac2a..1e03aa451c9 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 c3911a741c4..42edabed8a7 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 280/331] 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 d95fbdbcfc9..782c8f253a9 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 a8fcc42c061..c71b3436749 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 281/331] 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 782c8f253a9..ddf769049c6 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 c71b3436749..9e120db4e33 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 282/331] 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 9e120db4e33..14ffef07fe8 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 283/331] 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 ddf769049c6..cc7b86ef679 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 14ffef07fe8..00a5996ef6e 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 284/331] 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 f66f8b8b3aa..6d2c7a74132 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 1e03aa451c9..64172db379c 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 0c9e1e7b4f9..5e2999054ca 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 285/331] 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 cc7b86ef679..8fd99bbfc6b 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 00a5996ef6e..0a778aa8813 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 286/331] 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 0a778aa8813..0055b2181b0 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 287/331] 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 be1a1d3138b..f776de954bc 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 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 288/331] 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 e63c288f120..95a841b4064 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 6d7c0a740ab..8d0894f2516 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 289/331] 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 14687cbb992..542342503da 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 3731f322eee..1bb91714861 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 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 290/331] 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 45aeba3ac2a..7d8e9f9eeb1 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 291/331] 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 00000000000..bb2df4f0fc6 --- /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 00000000000..1c8087811b8 --- /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 988d68773aef28e9cd906972910d1429041047b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Tue, 17 Oct 2023 15:58:03 +0200 Subject: [PATCH 292/331] Rewrote the non-conservative terms of multi-ion as the product of local and symmetric parts --- .../tree_2d_dgsem/elixir_mhdmultiion_rotor.jl | 22 +-- src/equations/ideal_mhd_multiion_2d.jl | 131 +++++++++--------- 2 files changed, 68 insertions(+), 85 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_mhdmultiion_rotor.jl b/examples/tree_2d_dgsem/elixir_mhdmultiion_rotor.jl index 6c7ded4dc73..a2521b96fa0 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmultiion_rotor.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmultiion_rotor.jl @@ -5,7 +5,10 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations equations = IdealMhdMultiIonEquations2D(gammas = (1.4, 1.4), - charge_to_mass = (1.0, 2.0)) + charge_to_mass = (1.0, 2.0), + gas_constants = (1.0, 1.0), + molar_masses = (1.0, 1.0), + collision_frequency = 1.0) """ initial_condition_rotor(x, t, equations::IdealMhdMultiIonEquations2D) @@ -104,7 +107,7 @@ mesh = TreeMesh(coordinates_min, coordinates_max, semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_collision) + source_terms=source_terms_collision_ion_ion) ############################################################################### @@ -126,26 +129,11 @@ save_solution = SaveSolutionCallback(interval=1000, stepsize_callback = StepsizeCallback(cfl=0.5) -amr_indicator = IndicatorLöhner(semi, - variable=density) - -amr_controller = ControllerThreeLevelCombined(semi, amr_indicator,indicator_sc, - base_level=4, - med_level =5, med_threshold=0.02, # med_level = current level - max_level =7, max_threshold=0.04, - max_threshold_secondary=0.2) - -amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - save_restart = SaveRestartCallback(interval=10000, save_final_restart=true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - amr_callback, save_solution, save_restart, stepsize_callback) diff --git a/src/equations/ideal_mhd_multiion_2d.jl b/src/equations/ideal_mhd_multiion_2d.jl index 620b859e0a3..e041801d355 100644 --- a/src/equations/ideal_mhd_multiion_2d.jl +++ b/src/equations/ideal_mhd_multiion_2d.jl @@ -335,10 +335,10 @@ The term is composed of three parts f = zero(MVector{nvariables(equations), eltype(u_ll)}) if orientation == 1 - # Entries of Powell term for induction equation (already in Trixi's non-conservative form) - f[1] = v1_plus_ll * B1_rr - f[2] = v2_plus_ll * B1_rr - f[3] = v3_plus_ll * B1_rr + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B1_avg + f[2] = v2_plus_ll * B1_avg + f[3] = v3_plus_ll * B1_avg for k in eachcomponent(equations) # Compute term 2 (MHD) @@ -360,28 +360,21 @@ The term is composed of three parts f5 += (B2_ll * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + B3_ll * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) ) - # Adjust non-conservative terms 2 and 3 to Trixi discretization: CHANGE!?! - f2 = 2 * f2 - charge_ratio_ll[k] * (0.5 * mag_norm_ll - B1_ll * B1_ll) - f3 = 2 * f3 + charge_ratio_ll[k] * B1_ll * B2_ll - f4 = 2 * f4 + charge_ratio_ll[k] * B1_ll * B3_ll - f5 =(2 * f5 - B2_ll * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) - - B3_ll * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) ) - - # Compute Powell term (already consistent with Trixi's non-conservative discretization) - f2 += charge_ratio_ll[k] * B1_ll * B1_rr - f3 += charge_ratio_ll[k] * B2_ll * B1_rr - f4 += charge_ratio_ll[k] * B3_ll * B1_rr - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_rr + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B1_avg + f3 += charge_ratio_ll[k] * B2_ll * B1_avg + f4 += charge_ratio_ll[k] * B3_ll * B1_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_avg # Append to the flux vector set_component!(f, k, 0, f2, f3, f4, f5, equations) end else #if orientation == 2 - # Entries of Powell term for induction equation (already in Trixi's non-conservative form) - f[1] = v1_plus_ll * B2_rr - f[2] = v2_plus_ll * B2_rr - f[3] = v3_plus_ll * B2_rr + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B2_avg + f[2] = v2_plus_ll * B2_avg + f[3] = v3_plus_ll * B2_avg for k in eachcomponent(equations) # Compute term 2 (MHD) @@ -402,26 +395,20 @@ The term is composed of three parts vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) f5 += (B1_ll * (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) + B3_ll * (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) ) - - # Adjust non-conservative terms 2 and 3 to Trixi discretization: CHANGE!?! - f2 = 2 * f2 + charge_ratio_ll[k] * B2_ll * B1_ll - f3 = 2 * f3 - charge_ratio_ll[k] * (0.5 * mag_norm_ll - B2_ll * B2_ll) - f4 = 2 * f4 + charge_ratio_ll[k] * B2_ll * B3_ll - f5 = (2 * f5 - B1_ll * (vk2_minus_ll * B1_ll - vk1_minus_ll * B2_ll) - - B3_ll * (vk2_minus_ll * B3_ll - vk3_minus_ll * B2_ll) ) - # Compute Powell term (already consistent with Trixi's non-conservative discretization) - f2 += charge_ratio_ll[k] * B1_ll * B2_rr - f3 += charge_ratio_ll[k] * B2_ll * B2_rr - f4 += charge_ratio_ll[k] * B3_ll * B2_rr - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_rr + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B2_avg + f3 += charge_ratio_ll[k] * B2_ll * B2_avg + f4 += charge_ratio_ll[k] * B3_ll * B2_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_avg # Append to the flux vector set_component!(f, k, 0, f2, f3, f4, f5, equations) end end - return SVector(f) + # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines + return SVector(2 * f) end """ @@ -439,9 +426,13 @@ The term is composed of three parts # Compute important averages mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) # Electron pressure pe_rr = equations.electron_pressure(u_rr, equations) + pe_ll = equations.electron_pressure(u_ll, equations) + pe_avg = 0.5 * (pe_ll + pe_rr) # Compute charge ratio of u_ll charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) @@ -460,69 +451,73 @@ The term is composed of three parts f = zero(MVector{nvariables(equations), eltype(u_ll)}) if orientation == 1 - # Entries of Powell term for induction equation (already in Trixi's non-conservative form) - f[1] = v1_plus_ll * B1_rr - f[2] = v2_plus_ll * B1_rr - f[3] = v3_plus_ll * B1_rr + B1_avg = 0.5 * (B1_ll + B1_rr) + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B1_avg + f[2] = v2_plus_ll * B1_avg + f[3] = v3_plus_ll * B1_avg for k in eachcomponent(equations) # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (0.5 * mag_norm_rr - B1_rr * B1_rr + pe_rr) - f3 = charge_ratio_ll[k] * (- B1_rr * B2_rr) - f4 = charge_ratio_ll[k] * (- B1_rr * B3_rr) - f5 = vk1_plus_ll[k] * pe_rr + f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - 0.5 * B1_ll * B1_ll - 0.5 * B1_rr * B1_rr + pe_avg) + f3 = charge_ratio_ll[k] * (- 0.5 * B1_ll * B2_ll - 0.5 * B1_rr * B2_rr) + f4 = charge_ratio_ll[k] * (- 0.5 * B1_ll * B3_ll - 0.5 * B1_rr * B3_rr) + f5 = vk1_plus_ll[k] * pe_avg # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - f5 += (B2_ll * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr) + - B3_ll * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr) ) - - # Compute Powell term (already consistent with Trixi's non-conservative discretization) - f2 += charge_ratio_ll[k] * B1_ll * B1_rr - f3 += charge_ratio_ll[k] * B2_ll * B1_rr - f4 += charge_ratio_ll[k] * B3_ll * B1_rr - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_rr + f5 += (B2_ll * (0.5 * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) + 0.5 * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr) ) + + B3_ll * (0.5 * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) + 0.5 * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr) ) ) - # It's not needed to adjust to Trixi's non-conservative form + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B1_avg + f3 += charge_ratio_ll[k] * B2_ll * B1_avg + f4 += charge_ratio_ll[k] * B3_ll * B1_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_avg # Append to the flux vector set_component!(f, k, 0, f2, f3, f4, f5, equations) end else #if orientation == 2 - # Entries of Powell term for induction equation (already in Trixi's non-conservative form) - f[1] = v1_plus_ll * B2_rr - f[2] = v2_plus_ll * B2_rr - f[3] = v3_plus_ll * B2_rr + B2_avg = 0.5 * (B2_ll + B2_rr) + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B2_avg + f[2] = v2_plus_ll * B2_avg + f[3] = v3_plus_ll * B2_avg for k in eachcomponent(equations) # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (- B2_rr * B1_rr) - f3 = charge_ratio_ll[k] * (- B2_rr * B2_rr + 0.5 * mag_norm_rr + pe_rr) - f4 = charge_ratio_ll[k] * (- B2_rr * B3_rr) - f5 = vk2_plus_ll[k] * pe_rr + f2 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B1_ll - 0.5 * B2_rr * B1_rr) + f3 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B2_ll - 0.5 * B2_rr * B2_rr + 0.5 * mag_norm_avg + pe_avg) + f4 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B3_ll - 0.5 * B2_rr * B3_rr) + f5 = vk2_plus_ll[k] * pe_avg # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - f5 += (B1_ll * (vk2_minus_rr * B1_rr - vk1_minus_rr * B2_rr) + - B3_ll * (vk2_minus_rr * B3_rr - vk3_minus_rr * B2_rr) ) - - # Compute Powell term (already consistent with Trixi's non-conservative discretization) - f2 += charge_ratio_ll[k] * B1_ll * B2_rr - f3 += charge_ratio_ll[k] * B2_ll * B2_rr - f4 += charge_ratio_ll[k] * B3_ll * B2_rr - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_rr + f5 += (B1_ll * (0.5 * (vk2_minus_ll * B1_ll - vk1_minus_ll * B2_ll) + 0.5 * (vk2_minus_rr * B1_rr - vk1_minus_rr * B2_rr)) + + B3_ll * (0.5 * (vk2_minus_ll * B3_ll - vk3_minus_ll * B2_ll) + 0.5 * (vk2_minus_rr * B3_rr - vk3_minus_rr * B2_rr)) ) - # It's not needed to adjust to Trixi's non-conservative form + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B2_avg + f3 += charge_ratio_ll[k] * B2_ll * B2_avg + f4 += charge_ratio_ll[k] * B3_ll * B2_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_avg # Append to the flux vector set_component!(f, k, 0, f2, f3, f4, f5, equations) end end - return SVector(f) + return SVector(2 * f) end """ From 7f478805705aabc517e1502a6d84bfa751c39355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 19 Oct 2023 15:10:22 +0200 Subject: [PATCH 293/331] Subcell limiting is possible for multi-ion MHD --- src/Trixi.jl | 3 +- src/equations/ideal_mhd_multiion_2d.jl | 325 ++++++++++++++++++++++++- 2 files changed, 325 insertions(+), 3 deletions(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index c84460c4b7c..fe035ff8e80 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -133,7 +133,6 @@ include("auxiliary/special_elixirs.jl") include("visualization/visualization.jl") # export types/functions that define the public API of Trixi.jl - export AcousticPerturbationEquations2D, CompressibleEulerEquations1D, CompressibleEulerEquations2D, CompressibleEulerEquations3D, @@ -219,7 +218,7 @@ export entropy, energy_total, energy_kinetic, energy_internal, energy_magnetic, enstrophy export lake_at_rest_error export ncomponents, eachcomponent -export get_component +export get_component, set_component!, magnetic_field, MVector export TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, T8codeMesh diff --git a/src/equations/ideal_mhd_multiion_2d.jl b/src/equations/ideal_mhd_multiion_2d.jl index e041801d355..2875de42d8f 100644 --- a/src/equations/ideal_mhd_multiion_2d.jl +++ b/src/equations/ideal_mhd_multiion_2d.jl @@ -54,6 +54,7 @@ end @inline Base.real(::IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT}) where {NVARS, NCOMP, RealT} = RealT have_nonconservative_terms(::IdealMhdMultiIonEquations2D) = True() +nnoncons(::IdealMhdMultiIonEquations2D) = 4 function varnames(::typeof(cons2cons), equations::IdealMhdMultiIonEquations2D) cons = ("B1", "B2", "B3") @@ -293,9 +294,10 @@ function electron_pressure_zero(u, equations::IdealMhdMultiIonEquations2D) end """ + flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations2D) Total entropy-conserving non-conservative two-point "flux"" as described in - Rueda-Ramírez et al. (2023) -The term is composed of three parts +The flux is composed of three terms that can be written as the product of local and symmetric parts * The Powell term: Implemented * The MHD term: Implemented * The "term 3": Implemented @@ -410,6 +412,314 @@ The term is composed of three parts # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines return SVector(2 * f) end +""" + flux_nonconservative_ruedaramirez_etal(u_ll, orientation::Integer, + equations::IdealMhdMultiIonEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) +Local part of the non-conservative two-point "flux"" as described in +- Rueda-Ramírez et al. (2023) +The flux is composed of three/four terms that can be written as the product of local and symmetric parts +* The Powell term: Implemented +* The MHD term: Implemented +* The "term 3/4": Implemented +""" +@inline function flux_nonconservative_ruedaramirez_etal(u_ll, orientation::Integer, + equations::IdealMhdMultiIonEquations2D, + nonconservative_type::NonConservativeLocal, + noncons_term::Integer) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(eltype(u_ll)) + for k in eachcomponent(equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] + end + charge_ratio_ll ./= total_electron_charge + + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if noncons_term == 1 + # Powell term + ############# + if orientation == 1 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll + f[2] = v2_plus_ll + f[3] = v3_plus_ll + + for k in eachcomponent(equations) + # Compute Powell term + f2 = charge_ratio_ll[k] * B1_ll + f3 = charge_ratio_ll[k] * B2_ll + f4 = charge_ratio_ll[k] * B3_ll + f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll + f[2] = v2_plus_ll + f[3] = v3_plus_ll + + for k in eachcomponent(equations) + # Compute Powell term + f2 = charge_ratio_ll[k] * B1_ll + f3 = charge_ratio_ll[k] * B2_ll + f4 = charge_ratio_ll[k] * B3_ll + f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 2 + # Term "2" (MHD) + ################ + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] + f3 = charge_ratio_ll[k] + f4 = charge_ratio_ll[k] + f5 = vk1_plus_ll[k] + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] + f3 = charge_ratio_ll[k] + f4 = charge_ratio_ll[k] + f5 = vk2_plus_ll[k] + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 3 + # Term "3" (multi-ion) + ###################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + f5 = B2_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + f5 = B1_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + elseif noncons_term == 4 + # Term "4" (multi-ion) + ###################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + f5 = B3_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + f5 = B3_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + end + # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines + return SVector(2 * f) +end +""" + flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) +Symmetric part of non-conservative two-point "flux"" as described in +- Rueda-Ramírez et al. (2023) +The flux is composed of three/four terms that can be written as the product of local and symmetric parts +* The Powell term: Implemented +* The MHD term: Implemented +* The "term 3/4": Implemented +""" +@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations2D, + nonconservative_type::NonConservativeSymmetric, + noncons_term::Integer) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + # Compute important averages + B1_avg = 0.5 *(B1_ll + B1_rr) + B2_avg = 0.5 *(B2_ll + B2_rr) + B3_avg = 0.5 *(B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + # Mean electron pressure + pe_mean = 0.5 * (equations.electron_pressure(u_ll, equations) + + equations.electron_pressure(u_rr, equations)) + + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if noncons_term == 1 + # Powell term + ############# + if orientation == 1 + # Entries of Powell term for induction equation + f[1] = B1_avg + f[2] = B1_avg + f[3] = B1_avg + for k in eachcomponent(equations) + # Append to the flux vector + set_component!(f, k, 0, B1_avg, B1_avg, B1_avg, B1_avg, equations) + end + + else #if orientation == 2 + # Entries of Powell term for induction equation + f[1] = B2_avg + f[2] = B2_avg + f[3] = B2_avg + for k in eachcomponent(equations) + # Append to the flux vector + set_component!(f, k, 0, B2_avg, B2_avg, B2_avg, B2_avg, equations) + end + end + elseif noncons_term == 2 + # Term 2 (MHD) + ############## + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = (0.5 * mag_norm_avg - B1_avg * B1_avg + pe_mean) + f3 = (- B1_avg * B2_avg) + f4 = (- B1_avg * B3_avg) + f5 = pe_mean + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = (- B2_avg * B1_avg) + f3 = (- B2_avg * B2_avg + 0.5 * mag_norm_avg + pe_mean) + f4 = (- B2_avg * B3_avg) + f5 = pe_mean + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 3 + # Term 3 (multi-ion) + #################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + + f5 = (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + + f5 = (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + elseif noncons_term == 4 + # Term 4 (multi-ion) + #################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + f5 = (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + f5 = (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + end + # We don't multiply by 2 because the local term is already multiplied by 2 + return SVector(f) +end """ Total central non-conservative two-point "flux"", where the symmetric parts are computed with standard averages @@ -787,6 +1097,19 @@ function cons2prim(u, equations::IdealMhdMultiIonEquations2D) return SVector(prim) end +@inline function is_valid_state(cons, equations::IdealMhdMultiIonEquations2D) + prim = cons2prim(cons, equations) + + for k in eachcomponent(equations) + rho, _, _, _, p = get_component(k, prim, equations) + if rho <= 0.0 || p <= 0.0 + return false + end + end + + return true +end + """ Convert conservative variables to entropy """ From 781e839cdf8cbe69edb1a3d3f473895f68ed15a3 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Fri, 20 Oct 2023 08:09:22 +0200 Subject: [PATCH 294/331] 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 7d8e9f9eeb1..1d8f3543603 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 1bb91714861..a09fe616227 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 295/331] 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 a09fe616227..a479771fc67 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 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 296/331] 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 8ee8177949f..62bb0c20437 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 857de70ca7b..1a478dac7ac 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 0237128415a..ce7e5180c12 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 3ae6df94d2d..8f0914debde 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 297/331] 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 0cd7a319f7b..c57c1f5db2b 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 f66f8b8b3aa..54f5d986711 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 7b416e4f587..6a10f92b891 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 298/331] 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 c57c1f5db2b..34507dced50 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 299/331] 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 54f5d986711..8334c108cf9 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 300/331] 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 34507dced50..9a033e72367 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 8334c108cf9..fe5be3d02b2 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 83459c108b4..19a744f38d5 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 301/331] 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 9a033e72367..0722e77d730 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 fe5be3d02b2..6fa1a6d026b 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 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 302/331] 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 8f0914debde..13d60285bf8 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 303/331] 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 a479771fc67..1d99cc2a3b8 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 304/331] 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 1d99cc2a3b8..080f24c6ce5 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 305/331] 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 d7ef23332fe..24db8698c32 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 306/331] 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 bb2df4f0fc6..00000000000 --- 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 1c8087811b8..00000000000 --- 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 307/331] 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 080f24c6ce5..583bee6653b 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 308/331] 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 46a549f5130..2faec6892d5 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 583bee6653b..1d7e4f1f326 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 309/331] 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 ce7e5180c12..bddb25b06ae 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 310/331] 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 8fd99bbfc6b..09d5dee0c32 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 311/331] 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 1d8f3543603..5c486880d55 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 bbec0ae1651..d6644036160 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 312/331] 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 13d60285bf8..76d75e5c1b5 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 313/331] 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 24db8698c32..f40da6676c2 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 f209e63a4df..c7f23719709 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 5c486880d55..1d5ea43a1ea 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 d6644036160..f364fa86e77 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 314/331] 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 eb95ff64c17..964dca642e2 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 315/331] 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 e165308967f..2ed7d7bf4b4 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 316/331] 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 f364fa86e77..b55b5124982 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 317/331] 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 1d5ea43a1ea..fa30c8870b1 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 318/331] 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 fa30c8870b1..7072fa37dfd 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 319/331] 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 7072fa37dfd..54a6c17b9d8 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 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 320/331] 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 2faec6892d5..63041e103a6 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 54a6c17b9d8..9e0f9357420 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 1d7e4f1f326..18b2f2097dc 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 321/331] 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 18b2f2097dc..3e03924f621 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 322/331] 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 9e0f9357420..e8de0cedde1 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 323/331] 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 3e03924f621..f8346ff8bed 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 324/331] 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 ede3f6b3827..3d34e28a4f7 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 9c3d7c8943d..2516d7e2054 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 8fd99bbfc6b..7acc950d293 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 2d09a1908e2..269355e749c 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 325/331] 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 a1607d86179..ed9c193725c 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 e4d79a19acb..a3fd43a45e5 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 081076ef0fa..04e72542066 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 a7bcc15f83a..c4ae285090b 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 aed29aebd7f..6e2f8852b53 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 a82b17b82d0..29d6c4dee5b 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 326/331] 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 a3fd43a45e5..405709242c6 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 04e72542066..8aa7d8b95d0 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 327/331] 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 c4ae285090b..77cf3a5d7d2 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 1c845f6883f53e7bdb1dfc4af8882c776d0e6f64 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 3 Nov 2023 16:13:52 +0100 Subject: [PATCH 328/331] 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 7e9c241c284..963f9a938ab 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 329/331] 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 81d18f4105e..a733cb7cc21 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 673708d8b89..1d52089ae3e 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 33427803afc..0960ba25d9f 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 9ffaee26c40..fd923348928 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 60e227204ca..2f28dbfcb17 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 d06ed05a621..09d66fe8aea 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 3566185d110..6abd7118fe3 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 489b23e37b2..56a24d25d07 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 8a79e9700ac..ce7b0e745a4 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 7e87d9f097d..d2f11f18507 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 76512f1e39f..c498e5468d3 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 bdd582610ea..cd498bf39b8 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 4bb05c0b062..e7830c4736b 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 39e3a0a0360..48662f4b12b 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 d41ca2c5b34..3a73089b566 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 b9a24dc2450..f534b5bc8ad 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 39e98d1a2c5..14de0bf0e8b 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 f5adc7bf83c..49c8b28eaf8 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 4b2a408c757..36494b268d6 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 dad898b99b6..5e8d9e6c8e4 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 c10b5e46a14..53661af259a 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 486a30b37f1..ecf5e94a86b 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 c4c83fff642..307bf5cbf4a 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 a1351cf8244..11670288526 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 bf5045ce8b0..663301e189f 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 9c8dfcb3801..3dc070a7296 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 23c9c2e8ed4..38cf3d7984b 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 86b5ae64348..87ffd0e0995 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 97b779ebaf9..7c55cbf0ccf 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 3551c863ff2..f7120d8091b 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 4f43f2571a3..e877e602547 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 d8c4df5dd64..67c84b50974 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 35f7aee8795..0eb38674689 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 253d2486468..fea43ad4d26 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 b167377af51..6e06b35c4f6 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 6b17d4bba65..bc963a3a2fd 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 9a237b2d2fc..5fa0ad7ce60 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 c14d6620803..c58d78d2581 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 7953838afeb..dedd8267a3b 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 841a080947e..5a2537be4e6 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 7e6d99c83b1..0a50b3644f0 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 0b2de85da48..ed235bf839c 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 55682f73fce..5497f13aa65 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 1cd075e84ea..0b5129e3c0f 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 b438fb8a29c..130def37997 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 6d8e7030ac0..66a5b7e0f5b 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 0e6e314ebd7..b47b0d61192 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 52917616a6a..4f43e122ab3 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 9f5b813639f..37fcc547f60 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 e3f33fb0d28..0ca4fdc2eb7 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 70a0e10c296..92928146d7b 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 667834ea108..0ec9fc222f2 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 e88baa2223d..38307a7d781 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 d5d8e0c78bf..539ddb45395 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 6ef551c486f..0cb18526f8d 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 d9a322b065a..09d018309a6 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 366be700f9f..36c5624ba97 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 7c7896ce372..8b8d05bade8 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 b34c73d2a4e..d55a59ca5ce 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 ba2ec827778..364e0296449 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 66bce781f60..93db7bfdbaf 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 58915a8f6a7..380db487356 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 b0c6086ad63..7aa14e25750 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 935f132ba4b..b4177fe8538 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 051f4defe54..e6566edb18a 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 b185a8ce39d..c7922fd3b75 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 0473fd2b23a..d56ecc233ff 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 fb87c361c18..cd280cf5bf6 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 a165d1ff132..02ffa5c7aff 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 07a8b36bb4c..cd641ca4af7 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 93ff17c7842..34b0e95834d 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 26d10cf8826..cd97d69d692 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 85fd0b9a2cf..6df9ac0b16a 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 27c8ceb130c..0274a89aec7 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 63e937620f0..34a43a5b534 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 463a26fca53..d9d774a7ffc 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 3450adfe861..24a781ca59e 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 630a269b4a1..f56fe3a429d 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 6fa285b5565..8df95a3cc21 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 c5e349934a2..28a300cd681 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 dd394091758..0de22eaea40 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 cd796c33e47..fc5e4da3ceb 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 ff101bea8aa..0fa3a28fe8b 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 8fe96ae3dec..6a62368ef99 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 fc95d427abb..3941a40b2e4 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 0109e58dfb3..c640b255b05 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 c5b9ccf2e38..d785013f5a9 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 316f36adc9b..aabfce0f66b 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 f2693c89583..ce1d2cd05bd 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 fb445616cd4..f081f6bb91a 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 8933224a2c7..b7be2320228 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 029c19380cf..df6e4e6349f 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 48fd37cc9d4..3aa44f9a773 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 82464f23964..cdabeb4c61a 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 e87e0b36b0a..1e0c579ffcf 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 313812fe08d..96566bc2373 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 9d7be21a5c1..4ffa100cc71 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 cbda7087052..97767f3e127 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 9aa5b7f4979..d5063838136 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 7d2e1f49276..1d7235fc214 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 1e54e411db6..2a56d23f4c0 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 fbaa7783d99..df7e1f375a9 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 155a2d19fc9..7785b4f9e18 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 2aad3a01566..e2e113b168d 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 b9a6d3f91ae..b70deb12318 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 82eaa21333a..19863faae8d 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 7dfee23a067..826c7ebaacb 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 d0db19ea635..50393d50a19 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 5761e638e41..57c2d2a7801 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 fa59e5e0d37..20a20a9c20b 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 3d34e28a4f7..d306b70cb75 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 2516d7e2054..c7df12f27af 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 2c91349ff98..29686bd3cb7 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 c4ddb887e5f..3aab4be979e 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 8999d435ecc..163cc6519a9 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 6b70438044e..639fb928754 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 bb5870ab9d5..6c254e8bd8b 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 efc3b6627c0..42094d7191c 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 2d4f8f608a1..06eaceb4f7c 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 5d266629764..def69ecc282 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 70d3e060dd0..6827848e185 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 94537ecef0d..f42d223611a 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 a9c08049f41..5d6b0908389 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 fdd189ffb55..f2e3c448893 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 13ed29db2ba..53c07261c36 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 505e28ecd8d..4a78b65ae0b 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 de15f6b2bc3..b96f1d3cd68 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 6730b1c4beb..ccb74fa4b68 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 ba77dca9a99..681b3bd781b 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 259875050c6..e8f2b2ecc3a 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 634738e5c8b..a6c31744ca5 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 084aeca90b9..6668014a0b6 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 44bc7a12b35..e65ed19221e 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 15cfe6698fc..bc198f18835 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 18f48080850..48fe37b9996 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 17836fa6b8f..61dd252fd83 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 b18b02e0b4c..8e492b1ba05 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 47ae6352485..5b0bb371fe8 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 749233b8c68..12d52f15160 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 fa8ae756566..1a20a9c8533 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 921c5310340..e81ad5d6430 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 0009eb31180..1330006760e 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 b0e71435767..1b01287100e 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 e0595437c99..1f2d9d2eeb6 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 d8c6ea4bb83..ebf1336c12c 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 8ddfd426553..eb358fa5da1 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 f4da8ee9470..6eb35078ef4 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 a8c2288e811..5b3cd6f3718 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 d669c2350a5..084e2ee962a 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 32649eacff4..6d6bb27e0c3 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 463f916fa2e..8040f79cafd 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 c19f440ebc7..b2d5097036f 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 dc371233bc8..1071c98ab7e 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 098deedb9d6..ff62e905429 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 d61062c772e..cba522f6366 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 0472bd25a71..72b8b3f1933 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 5c87ac7ef5c..df185834701 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 28518e7276a..62701f3ecf5 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 cebd9b11201..f57b8e730fe 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 6a25f94ca05..ae2039edde6 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 28ab7b7c768..d32b9d6f1f4 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 00b5314e19f..1f0b0e7e042 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 2318063c2be..9cba4936d22 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 d35dec6bc73..05f392624fd 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 fb36f8540f8..de2f5134a49 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 fe221ea5bd7..1fa07d4edda 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 746989dfe56..01ccbb2b517 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 f20bd4fd69e..0be9c8fbf4c 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 966661e8894..3fb96fb807b 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 106ccacf4f5..b67b2bc602e 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 ebe8fa7cebf..8a0241680b9 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 90547f8ddc1..08367505377 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 213206eb9e0..555910f69f0 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 3794e0c8d54..922ac3dd97d 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 42de0e18e51..acde04780ee 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 2444fe8611d..6d6316898b7 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 86f4a4bad04..1b37a8a2279 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 04d937a9a8f..73f8de15d82 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 7abb3b0d021..7fbec0c0055 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 81966194180..c093420cc7c 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 9a19807ae29..b9173ec9f49 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 827d8d25ce7..4da3b33a466 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 82bca93c707..1a66ac60b9b 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 c5727109d92..bb294af68cb 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 1f2e77006b1..e5da808f696 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 010788d48f5..b6f856fbc64 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 8c60b449e90..8c0317277b0 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 68556764293..3b366c35e0f 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 376f11d52a2..831fa7afedb 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 573bf6bc3e9..a1636c08478 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 69ea0551bed..71466f3138a 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 93cf3e0fdb2..37623e048ed 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 3f72d319b0b..33ad0d5271c 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 181a2cb209f..40030d53345 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 1daeab04a71..e833155a68e 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 1288bc5e66a..378079ca334 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 1469afec1ca..a3df37fb966 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 916bba76ece..a586562af7e 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 62346d7b5ab..511f33d1101 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 2f9f93f4335..af596a377f8 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 c8ef1c1b70b..cbc98a30f9f 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 e9f444aed27..fc76b4f034b 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 60770d158fa..b2e6a81401b 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 bec0b8ab69c..7236f1697d0 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 e07bc04d76a..649e5023f6d 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 ef707b803e9..e55fffc101e 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 8de46c61794..26a8960ab46 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 1f2498e0866..389a8566c97 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 035d3568a80..2d7c13d7e57 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 c7b0176dfdc..c58fc497e14 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 20508feba22..eeaae7a7843 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 f9f9297f7c8..7b6bfee946e 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 5c5192a3fbe..a28cd01120b 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 d34399a5576..615da951871 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 fa608e78693..b3fe55dccea 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 78102eaf874..918c0831fcd 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 0a0e2520581..71d4f1a9f68 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 0fdcbd22c44..d7265775114 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 84841877448..c3f971d2ffc 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 897d3569e10..aa042e7500e 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 42aee985889..abb8a5035be 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 e69cab29bb6..7b441775204 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 efd282dab1f..03a213689ec 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 f517b4eb1cf..7b67b811177 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 269ab8cdd04..0ec0bc3629a 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 2ddd3e92ed2..708cd0aa3a3 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 a716bd278b8..1f765ff3564 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 c3cd2ebeb20..8da542b0b5d 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 278dc85386d..4d3da47b04a 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 2a283fb9008..645c55ba438 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 b63a8d1f7bc..770629bb15e 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 be87f24f817..06982bb9a27 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 f51b73dd497..69148f5bdb6 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 c5790e455bc..1393f4a6cc8 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 5b95fef374e..3bf4f230d44 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 0da18b7120d..ccd7b54086b 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 0e5a85e00a8..3e90ef7da2e 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 6ce9268486c..d32c2e51b06 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 659788f2f5c..79d7474dc66 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 3f4862674d2..27398593efd 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 db2fffacb36..6c67f948636 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 a0fc9349696..a2392d05e5a 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 0e44f62c7bd..fab3a86e531 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 f4040732667..2b3659017a3 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 5b7365f860f..8bd5db00c9a 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 cb2a5b16816..984ac3ff1f6 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 21de07147ca..a9eb671929f 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 bf6064dc219..eccf13c6d2c 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 d7e4250bb67..d82aed8ba32 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 89d7422cfe6..96184b5ba47 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 a5e9d30e389..0f9e232fa14 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 88f65c3d689..e634a383cdf 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 4fdedf516ef..5e6b1e0cc0d 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 3be50d01995..548485a1abc 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 b8927c3fd6b..5c237835cc5 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 952fa372696..d2cab04223e 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 8e7484a96d4..5b2b80d84f3 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 e31a0476a43..dc54bb1fb3d 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 42b529cb638..8f07b7ca920 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 4c7dd7eb6cf..6fec4c1bf9b 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 512e5822374..5b8959b97d1 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 af239b7c1a3..a5e7532854e 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 5fd32da2e5c..39ea947f872 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 98861064415..b460b7a507b 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 f0a7ed0b953..40f19cbd4e2 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 810c37ff5bd..4e64cb3a91c 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 36d93147289..ec230145537 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 231486b11c9..28ab4cec1d3 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 9826a53d3d5..05ed7ba78cc 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 5c92414e66a..6d5281fcbc0 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 14e46ce7540..c87d6f49ba8 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 6f6eb25efa4..e9831c95526 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 637133b9b2f..858799d2d3d 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 dc6a326c5d5..026f6d1462c 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 99036c36451..d719e01fd7c 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 65a497374ed..99e4b090633 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 38b48b5d537..ea81bd049e4 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 d423b800fd0..bc4859e5760 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 62c5bab51ea..771343937a4 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 0715dfe35d6..d912a280e49 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 a3e5580b572..470e533ab8d 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 38510446cb1..f5ef51c108a 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 1c6cbef533e..4a8a70b5663 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 f817a91a58f..5f6cdb1e9c0 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 abf9735fd28..1700957d900 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 c144ef47a63..e70b91906b1 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 d0d706981a2..a1a0397a46c 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 fc825660f1e..1396481a3f1 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 f3cbc1cb664..b48bde0d155 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 40b16f41ef6..5a4f3074e4e 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 6a33b2fb0ee..1ba040405d1 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 a34e784e7ac..d00926cafad 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 14459fa4cb8..93272833b74 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 14fe201a291..fad03fab6ef 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 d9e59160e7d..377a07e947e 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 11dfeacde6a..229360f266e 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 af05fffaf54..a0909ca7580 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 5873388f798..173d3ed448f 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 460b24e02b2..7f26f270d6e 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 c6d880e9e9d..3109b1ce303 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 2e6429ad9b0..84361ef4f87 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 a7551f48937..4f1f8c5f2b7 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 ec2f3c21cdd..a7db9eeee96 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 3cd9c621ae3..fcaabdc7a58 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 55a4004f794..5ca21cc5e9c 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 b68e9e6c97e..57558224854 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 3314343ccca..7bd1ec0c647 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 06e8f06d3ca..4d92ea261e9 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 c3cbc858f7b..a3e38bf6d92 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 7c60e35b03e..349b3741869 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 eed0a350e7e..bc528ae7756 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 03dcf017266..2008019cc31 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 6d4f6fe518c..c92e885c161 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 c3da957b764..f7544b1e32e 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 402361c8823..f7c8ab3a249 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 ba4bcd25774..1495e6d8568 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 23efdcb7366..13023dfaba2 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 66cd27f6864..f50bd4e4f65 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 6fede2fa4ea..034411c2b54 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 6e599d9f42d..8716a9a6b78 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 2a6c291f0bf..123be02bd17 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 e63343852ab..4c41b84af33 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 c1bee8f9c4d..d0847cc8016 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 67664eed563..19a9bd18a8a 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 da91a70fe6d..3ea50423be7 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 0fab685b642..6a8f8d02590 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 5dc6e6338a7..4c30406680a 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 d820f47f25c..efc20c64f6d 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 7b24f152b6a..d27a19c7dcf 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 b7835ed061f..f81e013fc0a 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 f226a6b446d..9bd7f74c688 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 a8d112f5b05..0ce886620cc 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 2eeb280ae1f..170b292a42f 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 dbf5747784c..4789b46dacc 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 ee788321c66..cad8fc578c8 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 08fd1b998d5..88d7cbc7ba5 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 c9fc2dfed50..cf103dc26cf 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 3641878149a..87774ada266 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 3015f6c50a4..0a90615016c 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 3d338cd7f01..be31fbbc42c 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 3445e9fc433..f0246c30490 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 693f9ce9049..135ee673e44 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 6699ec9a4da..21ef661d0b6 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 c7744ce23bd..7bba154a925 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 beefb22ea1e..831e01519b6 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 269a0da2d50..ee38f62887d 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 b3835eb1287..0980ee56be3 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 191982bf2d6..9aab5e58788 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 e23f7ce5460..3ce166a7fa7 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 057ffcb031f..1f0088e82c9 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 6b4f6e310ce..f8a72b6f452 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 ebb0137a1bb..3ada9503c6a 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 5556831a59d..65bd9aa133d 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 241e0698649..22085a63510 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 6aafa1b5cc1..aa5b231ee13 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 d2495cff5cd..0354200ae42 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 2f8228dffb8..8f8e867dca8 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 274978d48b0..afef6c2c38f 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 9fbea47a9d5..cd6a1995757 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 2725142fd17..0f53aa62a18 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 36e119ab794..a2fec1a320a 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 796c99987a2..afd177f0740 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 6653f8662d9..4d6af65b8a4 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 570a2084691..e1cc0932969 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 5bfe1ae4e0e..b2abefe7eeb 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 6b31776b297..fdafed98c8d 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 d75079bb8d7..a40f92cac02 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 044b2549b01..1148f25fae3 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 138b256c08b..8e9d396d826 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 ee3650f3bb5..94202b81df0 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 e0b64802ff8..07668688406 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 65b0fcae462..6164f9d4a55 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 d9e71e4aa44..2cab68b1cb5 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 4295f93b342..9d70e9287cf 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 40bc9f2ab42..35b027c3a81 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 4700724c520..76b9642d595 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 645f985d10d..bf4d0be682a 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 0722e77d730..527bcb0750a 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 963f9a938ab..cf47c0fc534 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 1c27a5d5dcd..c724ada5041 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 9944e45e120..77df1ba45bf 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 068b0fe5bef4733d52ae79a5f14819b1f8cbb042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Mon, 6 Nov 2023 17:23:08 +0100 Subject: [PATCH 330/331] format --- src/equations/ideal_mhd_multiion_1d.jl | 1023 ++++++----- src/equations/ideal_mhd_multiion_2d.jl | 2288 +++++++++++++----------- 2 files changed, 1733 insertions(+), 1578 deletions(-) diff --git a/src/equations/ideal_mhd_multiion_1d.jl b/src/equations/ideal_mhd_multiion_1d.jl index 892b39188ed..cb3838d42a0 100644 --- a/src/equations/ideal_mhd_multiion_1d.jl +++ b/src/equations/ideal_mhd_multiion_1d.jl @@ -3,64 +3,75 @@ # we need to opt-in explicitly. # See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. @muladd begin - +#! format: noindent @doc raw""" IdealMhdMultiIonEquations1D The ideal compressible multi-ion MHD equations in one space dimension. """ -mutable struct IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT<:Real} <: AbstractIdealMhdMultiIonEquations{1, NVARS, NCOMP} - gammas ::SVector{NCOMP, RealT} # Heat capacity ratios - charge_to_mass ::SVector{NCOMP, RealT} # Charge to mass ratios - - function IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT}(gammas ::SVector{NCOMP, RealT}, - charge_to_mass::SVector{NCOMP, RealT}) where {NVARS, NCOMP, RealT<:Real} - - NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `charge_to_mass` have to be filled with at least one value")) - - new(gammas, charge_to_mass) - end +mutable struct IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT <: Real} <: + AbstractIdealMhdMultiIonEquations{1, NVARS, NCOMP} + gammas :: SVector{NCOMP, RealT} # Heat capacity ratios + charge_to_mass :: SVector{NCOMP, RealT} # Charge to mass ratios + + function IdealMhdMultiIonEquations1D{NVARS, NCOMP, + RealT}(gammas::SVector{NCOMP, RealT}, + charge_to_mass::SVector{NCOMP, RealT}) where + {NVARS, NCOMP, RealT <: Real} + NCOMP >= 1 || + throw(DimensionMismatch("`gammas` and `charge_to_mass` have to be filled with at least one value")) + + new(gammas, charge_to_mass) + end end function IdealMhdMultiIonEquations1D(; gammas, charge_to_mass) - _gammas = promote(gammas...) - _charge_to_mass = promote(charge_to_mass...) - RealT = promote_type(eltype(_gammas), eltype(_charge_to_mass)) + _gammas = promote(gammas...) + _charge_to_mass = promote(charge_to_mass...) + RealT = promote_type(eltype(_gammas), eltype(_charge_to_mass)) - NVARS = length(_gammas) * 5 + 3 - NCOMP = length(_gammas) + NVARS = length(_gammas) * 5 + 3 + NCOMP = length(_gammas) - __gammas = SVector(map(RealT, _gammas)) - __charge_to_mass = SVector(map(RealT, _charge_to_mass)) + __gammas = SVector(map(RealT, _gammas)) + __charge_to_mass = SVector(map(RealT, _charge_to_mass)) - return IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT}(__gammas, __charge_to_mass) + return IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT}(__gammas, __charge_to_mass) end -@inline Base.real(::IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT}) where {NVARS, NCOMP, RealT} = RealT +@inline function Base.real(::IdealMhdMultiIonEquations1D{NVARS, NCOMP, RealT}) where { + NVARS, + NCOMP, + RealT + } + RealT +end have_nonconservative_terms(::IdealMhdMultiIonEquations1D) = True() function varnames(::typeof(cons2cons), equations::IdealMhdMultiIonEquations1D) - - cons = ("B1", "B2", "B3") - for i in eachcomponent(equations) - cons = (cons..., tuple("rho_" * string(i),"rho_v1_" * string(i), "rho_v2_" * string(i), "rho_v3_" * string(i), "rho_e_" * string(i))...) - end - - return cons + cons = ("B1", "B2", "B3") + for i in eachcomponent(equations) + cons = (cons..., + tuple("rho_" * string(i), "rho_v1_" * string(i), "rho_v2_" * string(i), + "rho_v3_" * string(i), "rho_e_" * string(i))...) + end + + return cons end function varnames(::typeof(cons2prim), equations::IdealMhdMultiIonEquations1D) - prim = ("B1", "B2", "B3") - for i in eachcomponent(equations) - prim = (prim..., tuple("rho_" * string(i),"v1_" * string(i), "v2_" * string(i), "v3_" * string(i), "p_" * string(i))...) - end - - return prim + prim = ("B1", "B2", "B3") + for i in eachcomponent(equations) + prim = (prim..., + tuple("rho_" * string(i), "v1_" * string(i), "v2_" * string(i), + "v3_" * string(i), "p_" * string(i))...) + end + + return prim end - # """ # initial_condition_convergence_test(x, t, equations::IdealMhdMultiIonEquations1D) @@ -84,7 +95,6 @@ end # return prim2cons(vcat(prim_other, prim_rho), equations) # end - """ initial_condition_weak_blast_wave(x, t, equations::IdealMhdMultiIonEquations1D) @@ -94,99 +104,104 @@ A weak blast wave adapted from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_weak_blast_wave(x, t, equations::IdealMhdMultiIonEquations1D) - # 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 = (0) - x_norm = x[1] - inicenter[1] - r = sqrt(x_norm^2) - phi = atan(x_norm) - - # Calculate primitive variables - rho = zero(real(equations)) - if r > 0.5 - rho = 1.0 - else - rho = 1.1691 - end - v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) - p = r > 0.5 ? 1.0 : 1.245 - - prim = zero(MVector{nvariables(equations), real(equations)}) - prim[1] = 1.0 - prim[2] = 1.0 - prim[3] = 1.0 - for k in eachcomponent(equations) - set_component!(prim, k, 2^(k - 1) * (1 - 2)/(1 - 2^ncomponents(equations)) * rho, v1, 0, 0, p, equations) - end - - return prim2cons(SVector(prim), 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 = (0) + x_norm = x[1] - inicenter[1] + r = sqrt(x_norm^2) + phi = atan(x_norm) + + # Calculate primitive variables + rho = zero(real(equations)) + if r > 0.5 + rho = 1.0 + else + rho = 1.1691 + end + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + p = r > 0.5 ? 1.0 : 1.245 + + prim = zero(MVector{nvariables(equations), real(equations)}) + prim[1] = 1.0 + prim[2] = 1.0 + prim[3] = 1.0 + for k in eachcomponent(equations) + set_component!(prim, k, + 2^(k - 1) * (1 - 2) / (1 - 2^ncomponents(equations)) * rho, v1, + 0, 0, p, equations) + end + + return prim2cons(SVector(prim), equations) end # TODO: Add initial condition equilibrium # Calculate 1D flux in for a single point @inline function flux(u, orientation::Integer, equations::IdealMhdMultiIonEquations1D) - B1, B2, B3 = magnetic_field(u, equations) - - v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus = charge_averaged_velocities(u, equations) - - mag_en = 0.5*(B1^2 + B2^2 + B3^2) - - f = zero(MVector{nvariables(equations), eltype(u)}) - f[1] = 0.0 - f[2] = v1_plus * B2 - v2_plus * B1 - f[3] = v1_plus * B3 - v3_plus * B1 - - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) - - gamma = equations.gammas[k] - p = (gamma - 1) * (rho_e - kin_en - mag_en) - - f1 = rho_v1 - f2 = rho_v1 * v1 + p - f3 = rho_v1 * v2 - f4 = rho_v1 * v3 - f5 = (kin_en + gamma * p /(gamma - 1))*v1 + 2 * mag_en * vk1_plus[k] - B1*(vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) - end - - return SVector(f) + B1, B2, B3 = magnetic_field(u, equations) + + v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus = charge_averaged_velocities(u, + equations) + + mag_en = 0.5 * (B1^2 + B2^2 + B3^2) + + f = zero(MVector{nvariables(equations), eltype(u)}) + f[1] = 0.0 + f[2] = v1_plus * B2 - v2_plus * B1 + f[3] = v1_plus * B3 - v3_plus * B1 + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) + + gamma = equations.gammas[k] + p = (gamma - 1) * (rho_e - kin_en - mag_en) + + f1 = rho_v1 + f2 = rho_v1 * v1 + p + f3 = rho_v1 * v2 + f4 = rho_v1 * v3 + f5 = (kin_en + gamma * p / (gamma - 1)) * v1 + 2 * mag_en * vk1_plus[k] - + B1 * (vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end + + return SVector(f) end """ Standard source terms of the multi-ion MHD equations """ function source_terms_standard(u, x, t, equations::IdealMhdMultiIonEquations1D) - @unpack charge_to_mass = equations - B1, B2, B3 = magnetic_field(u, equations) - v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus = charge_averaged_velocities(u, equations) - - s = zero(MVector{nvariables(equations), eltype(u)}) - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v1_diff = v1_plus - v1 - v2_diff = v2_plus - v2 - v3_diff = v3_plus - v3 - r_rho = charge_to_mass[k] * rho - s2 = r_rho * (v2_diff * B3 - v3_diff * B2) - s3 = r_rho * (v3_diff * B1 - v1_diff * B3) - s4 = r_rho * (v1_diff * B2 - v2_diff * B1) - s5 = v1 * s2 + v2 * s3 + v3 * s4 - - set_component!(s, k, 0, s2, s3, s4, s5, equations) - end - - return SVector(s) + @unpack charge_to_mass = equations + B1, B2, B3 = magnetic_field(u, equations) + v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus = charge_averaged_velocities(u, + equations) + + s = zero(MVector{nvariables(equations), eltype(u)}) + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v1_diff = v1_plus - v1 + v2_diff = v2_plus - v2 + v3_diff = v3_plus - v3 + r_rho = charge_to_mass[k] * rho + s2 = r_rho * (v2_diff * B3 - v3_diff * B2) + s3 = r_rho * (v3_diff * B1 - v1_diff * B3) + s4 = r_rho * (v1_diff * B2 - v2_diff * B1) + s5 = v1 * s2 + v2 * s3 + v3 * s4 + + set_component!(s, k, 0, s2, s3, s4, s5, equations) + end + + return SVector(s) end """ @@ -197,70 +212,76 @@ The term is composed of three parts * The MHD term: Implemented without the electron pressure (TODO). * The "term 3": Implemented """ -@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations1D) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - # Compute important averages - B1_avg = 0.5 * (B1_ll + B1_rr) - B2_avg = 0.5 * (B2_ll + B2_rr) - B3_avg = 0.5 * (B3_ll + B3_rr) - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - # Compute charge ratio of u_ll - charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) - total_electron_charge = zero(eltype(u_ll)) - for k in eachcomponent(equations) - rho_k = u_ll[3 + (k - 1) * 5 + 1] - charge_ratio_ll[k] = rho_k * charge_to_mass[k] - total_electron_charge += charge_ratio_ll[k] - end - charge_ratio_ll ./= total_electron_charge - - # Compute auxiliary variables - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - # TODO: Add entries of Powell term for induction equation - for k in eachcomponent(equations) - # Compute Powell (only needed for non-constant B1) - # TODO - - # Compute term 2 (MHD) - # TODO: Add electron pressure term - f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - B1_avg * B1_avg) # + pe_mean) - f3 = charge_ratio_ll[k] * (- B1_avg * B2_avg) - f4 = charge_ratio_ll[k] * (- B1_avg * B3_avg) - f5 = zero(eltype(u_ll)) # TODO! charge_ratio_ll[k] * pe_mean - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - f5 += B2_ll * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + B3_ll * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) - - # Adjust non-conservative term to Trixi discretization: CHANGE!! - f2 = 2 * f2 - charge_ratio_ll[k] * (0.5 * mag_norm_ll - B1_ll * B1_ll) - f3 = 2 * f3 + charge_ratio_ll[k] * B1_ll * B2_ll - f4 = 2 * f4 + charge_ratio_ll[k] * B1_ll * B3_ll - f5 = 2 * f5 - B2_ll * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) - B3_ll * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - - return SVector(f) +@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, + orientation::Integer, + equations::IdealMhdMultiIonEquations1D) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + # Compute important averages + B1_avg = 0.5 * (B1_ll + B1_rr) + B2_avg = 0.5 * (B2_ll + B2_rr) + B3_avg = 0.5 * (B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(eltype(u_ll)) + for k in eachcomponent(equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] + end + charge_ratio_ll ./= total_electron_charge + + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + # TODO: Add entries of Powell term for induction equation + for k in eachcomponent(equations) + # Compute Powell (only needed for non-constant B1) + # TODO + + # Compute term 2 (MHD) + # TODO: Add electron pressure term + f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - B1_avg * B1_avg) # + pe_mean) + f3 = charge_ratio_ll[k] * (-B1_avg * B2_avg) + f4 = charge_ratio_ll[k] * (-B1_avg * B3_avg) + f5 = zero(eltype(u_ll)) # TODO! charge_ratio_ll[k] * pe_mean + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + f5 += B2_ll * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + + B3_ll * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) + + # Adjust non-conservative term to Trixi discretization: CHANGE!! + f2 = 2 * f2 - charge_ratio_ll[k] * (0.5 * mag_norm_ll - B1_ll * B1_ll) + f3 = 2 * f3 + charge_ratio_ll[k] * B1_ll * B2_ll + f4 = 2 * f4 + charge_ratio_ll[k] * B1_ll * B3_ll + f5 = 2 * f5 - B2_ll * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) - + B3_ll * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + return SVector(f) end """ @@ -270,55 +291,57 @@ The term is composed of three parts * The MHD term: Implemented without the electron pressure (TODO). * The "term 3": Implemented """ -@inline function flux_nonconservative_central(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations1D) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - # Compute important averages - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - - # Compute charge ratio of u_ll - charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) - total_electron_charge = zero(eltype(u_ll)) - for k in eachcomponent(equations) - rho_k = u_ll[3 + (k - 1) * 5 + 1] - charge_ratio_ll[k] = rho_k * charge_to_mass[k] - total_electron_charge += charge_ratio_ll[k] - end - charge_ratio_ll ./= total_electron_charge - - # Compute auxiliary variables - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - # TODO: Add entries of Powell term for induction equation - for k in eachcomponent(equations) - # Compute Powell (only needed for non-constant B1) - # TODO - - # Compute term 2 (MHD) - # TODO: Add electron pressure term - f2 = charge_ratio_ll[k] * (0.5 * mag_norm_rr - B1_rr * B1_rr) # + pe_mean) - f3 = charge_ratio_ll[k] * (- B1_rr * B2_rr) - f4 = charge_ratio_ll[k] * (- B1_rr * B3_rr) - f5 = zero(eltype(u_ll)) # TODO! charge_ratio_ll[k] * pe_mean - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - f5 += (B2_ll * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr) + - B3_ll * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr) ) - - # It's not needed to adjust to Trixi's non-conservative form - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - - return SVector(f) +@inline function flux_nonconservative_central(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations1D) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + # Compute important averages + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(eltype(u_ll)) + for k in eachcomponent(equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] + end + charge_ratio_ll ./= total_electron_charge + + # Compute auxiliary variables + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + # TODO: Add entries of Powell term for induction equation + for k in eachcomponent(equations) + # Compute Powell (only needed for non-constant B1) + # TODO + + # Compute term 2 (MHD) + # TODO: Add electron pressure term + f2 = charge_ratio_ll[k] * (0.5 * mag_norm_rr - B1_rr * B1_rr) # + pe_mean) + f3 = charge_ratio_ll[k] * (-B1_rr * B2_rr) + f4 = charge_ratio_ll[k] * (-B1_rr * B3_rr) + f5 = zero(eltype(u_ll)) # TODO! charge_ratio_ll[k] * pe_mean + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + f5 += (B2_ll * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr) + + B3_ll * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr)) + + # It's not needed to adjust to Trixi's non-conservative form + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + return SVector(f) end """ @@ -332,260 +355,278 @@ This flux (together with the MHD non-conservative term) is consistent in the cas divergence diminishing ideal magnetohydrodynamics equations for multi-ion [DOI: 10.1016/j.jcp.2018.03.002](https://doi.org/10.1016/j.jcp.2018.03.002) """ -function flux_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations1D) - @unpack gammas = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, equations) - - # Compute averages for global variables - v1_plus_avg = 0.5 * (v1_plus_ll + v1_plus_rr) - v2_plus_avg = 0.5 * (v2_plus_ll + v2_plus_rr) - v3_plus_avg = 0.5 * (v3_plus_ll + v3_plus_rr) - B1_avg = 0.5 * (B1_ll + B1_rr) - B2_avg = 0.5 * (B2_ll + B2_rr) - B3_avg = 0.5 * (B3_ll + B3_rr) - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - # Magnetic field components from f^MHD - f6 = zero(eltype(u_ll)) - f7 = v1_plus_avg * B2_avg - v2_plus_avg * B1_avg - f8 = v1_plus_avg * B3_avg - v3_plus_avg * B1_avg - - # Start building the flux - f[1] = f6 - f[2] = f7 - f[3] = f8 - - # Iterate over all components - for k in eachcomponent(equations) - # Unpack left and right states - rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, equations) - rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, equations) - - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v1_rr = rho_v1_rr / rho_rr - v2_rr = rho_v2_rr / rho_rr - v3_rr = rho_v3_rr / rho_rr - vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 - vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 - - p_ll = (gammas[k] - 1)*(rho_e_ll - 0.5*rho_ll*vel_norm_ll - 0.5*mag_norm_ll) - p_rr = (gammas[k] - 1)*(rho_e_rr - 0.5*rho_rr*vel_norm_rr - 0.5*mag_norm_rr) - beta_ll = 0.5*rho_ll/p_ll - beta_rr = 0.5*rho_rr/p_rr - # for convenience store vk_plus⋅B - vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + vk3_plus_ll[k] * B3_ll - vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + vk3_plus_rr[k] * B3_rr - - # Compute the necessary mean values needed for either direction - 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) - p_mean = 0.5 * rho_avg / beta_avg - v1_avg = 0.5 * (v1_ll + v1_rr) - v2_avg = 0.5 * (v2_ll + v2_rr) - v3_avg = 0.5 * (v3_ll + v3_rr) - vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) - vel_dot_mag_avg = 0.5 * (vel_dot_mag_ll + vel_dot_mag_rr) - vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) - vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) - vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) - # v_minus - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - - # Ignore orientation since it is always "1" in 1D - f1 = rho_mean*v1_avg - f2 = f1*v1_avg + p_mean - f3 = f1*v2_avg - f4 = f1*v3_avg - - # total energy flux is complicated and involves the previous eight components - v1_plus_mag_avg = 0.5*(vk1_plus_ll[k] * mag_norm_ll + vk1_plus_rr[k] * mag_norm_rr) - # Euler part - f5 = f1 * 0.5 * ( 1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg - # MHD part - f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v1_plus_mag_avg + B1_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) - + 0.5 * vk1_plus_avg * mag_norm_avg - vk1_plus_avg * B1_avg * B1_avg - vk2_plus_avg * B1_avg * B2_avg - vk3_plus_avg * B1_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) - - B2_avg * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) - B3_avg * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) ) # Terms coming from the non-conservative term 3 (induction equation!) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) - end - - return SVector(f) +function flux_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations1D) + @unpack gammas = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, + equations) + + # Compute averages for global variables + v1_plus_avg = 0.5 * (v1_plus_ll + v1_plus_rr) + v2_plus_avg = 0.5 * (v2_plus_ll + v2_plus_rr) + v3_plus_avg = 0.5 * (v3_plus_ll + v3_plus_rr) + B1_avg = 0.5 * (B1_ll + B1_rr) + B2_avg = 0.5 * (B2_ll + B2_rr) + B3_avg = 0.5 * (B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + # Magnetic field components from f^MHD + f6 = zero(eltype(u_ll)) + f7 = v1_plus_avg * B2_avg - v2_plus_avg * B1_avg + f8 = v1_plus_avg * B3_avg - v3_plus_avg * B1_avg + + # Start building the flux + f[1] = f6 + f[2] = f7 + f[3] = f8 + + # Iterate over all components + for k in eachcomponent(equations) + # Unpack left and right states + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, + equations) + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, + equations) + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + v3_rr = rho_v3_rr / rho_rr + vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 + vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 + + p_ll = (gammas[k] - 1) * + (rho_e_ll - 0.5 * rho_ll * vel_norm_ll - 0.5 * mag_norm_ll) + p_rr = (gammas[k] - 1) * + (rho_e_rr - 0.5 * rho_rr * vel_norm_rr - 0.5 * mag_norm_rr) + beta_ll = 0.5 * rho_ll / p_ll + beta_rr = 0.5 * rho_rr / p_rr + # for convenience store vk_plus⋅B + vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + + vk3_plus_ll[k] * B3_ll + vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + + vk3_plus_rr[k] * B3_rr + + # Compute the necessary mean values needed for either direction + 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) + p_mean = 0.5 * rho_avg / beta_avg + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + v3_avg = 0.5 * (v3_ll + v3_rr) + vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) + vel_dot_mag_avg = 0.5 * (vel_dot_mag_ll + vel_dot_mag_rr) + vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) + vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) + vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) + # v_minus + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + # Ignore orientation since it is always "1" in 1D + f1 = rho_mean * v1_avg + f2 = f1 * v1_avg + p_mean + f3 = f1 * v2_avg + f4 = f1 * v3_avg + + # total energy flux is complicated and involves the previous eight components + v1_plus_mag_avg = 0.5 * + (vk1_plus_ll[k] * mag_norm_ll + vk1_plus_rr[k] * mag_norm_rr) + # Euler part + f5 = f1 * 0.5 * (1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + f2 * v1_avg + + f3 * v2_avg + f4 * v3_avg + # MHD part + f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v1_plus_mag_avg + + B1_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) + + 0.5 * vk1_plus_avg * mag_norm_avg - vk1_plus_avg * B1_avg * B1_avg - + vk2_plus_avg * B1_avg * B2_avg - vk3_plus_avg * B1_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) + - + B2_avg * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) - + B3_avg * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg)) # Terms coming from the non-conservative term 3 (induction equation!) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end + + return SVector(f) end """ # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation !!!ATTENTION: This routine is provisional. TODO: Update with the right max_abs_speed """ -@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations1D) - # Calculate fast magnetoacoustic wave speeds - # left - cf_ll = calc_fast_wavespeed(u_ll, orientation, equations) - # right - cf_rr = calc_fast_wavespeed(u_rr, orientation, equations) - - # Calculate velocities (ignore orientation since it is always "1" in 1D) - v_ll = zero(eltype(u_ll)) - v_rr = zero(eltype(u_rr)) - for k in eachcomponent(equations) - rho, rho_v1, _ = get_component(k, u_ll, equations) - v_ll = max(v_ll, abs(rho_v1 / rho)) - rho, rho_v1, _ = get_component(k, u_rr, equations) - v_rr = max(v_rr, abs(rho_v1 / rho)) - end - - λ_max = max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations1D) + # Calculate fast magnetoacoustic wave speeds + # left + cf_ll = calc_fast_wavespeed(u_ll, orientation, equations) + # right + cf_rr = calc_fast_wavespeed(u_rr, orientation, equations) + + # Calculate velocities (ignore orientation since it is always "1" in 1D) + v_ll = zero(eltype(u_ll)) + v_rr = zero(eltype(u_rr)) + for k in eachcomponent(equations) + rho, rho_v1, _ = get_component(k, u_ll, equations) + v_ll = max(v_ll, abs(rho_v1 / rho)) + rho, rho_v1, _ = get_component(k, u_rr, equations) + v_rr = max(v_rr, abs(rho_v1 / rho)) + end + + λ_max = max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) end - @inline function max_abs_speeds(u, equations::IdealMhdMultiIonEquations1D) - v1 = zero(eltype(u)) - for k in eachcomponent(equations) - rho, rho_v1, _ = get_component(k, u, equations) - v1 = max(v1, abs(rho_v1 / rho)) - end + v1 = zero(eltype(u)) + for k in eachcomponent(equations) + rho, rho_v1, _ = get_component(k, u, equations) + v1 = max(v1, abs(rho_v1 / rho)) + end - cf_x_direction = calc_fast_wavespeed(u, 1, equations) + cf_x_direction = calc_fast_wavespeed(u, 1, equations) - return (abs(v1) + cf_x_direction, ) + return (abs(v1) + cf_x_direction,) end - """ Convert conservative variables to primitive """ function cons2prim(u, equations::IdealMhdMultiIonEquations1D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(u, equations) - - prim = zero(MVector{nvariables(equations), eltype(u)}) - prim[1] = B1 - prim[2] = B2 - prim[3] = B3 - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - srho = 1 / rho - v1 = srho * rho_v1 - v2 = srho * rho_v2 - v3 = srho * rho_v3 - - p = (gammas[k] - 1) * (rho_e - 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3 - + B1 * B1 + B2 * B2 + B3 * B3)) - - set_component!(prim, k, rho, v1, v2, v3, p, equations) - end - - return SVector(prim) + @unpack gammas = equations + B1, B2, B3 = magnetic_field(u, equations) + + prim = zero(MVector{nvariables(equations), eltype(u)}) + prim[1] = B1 + prim[2] = B2 + prim[3] = B3 + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + srho = 1 / rho + v1 = srho * rho_v1 + v2 = srho * rho_v2 + v3 = srho * rho_v3 + + p = (gammas[k] - 1) * (rho_e - + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3 + + B1 * B1 + B2 * B2 + B3 * B3)) + + set_component!(prim, k, rho, v1, v2, v3, p, equations) + end + + return SVector(prim) end """ Convert conservative variables to entropy """ @inline function cons2entropy(u, equations::IdealMhdMultiIonEquations1D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(u, equations) - - prim = cons2prim(u, equations) - entropy = zero(MVector{nvariables(equations), eltype(u)}) - rho_p_plus = zero(real(equations)) - for k in eachcomponent(equations) - rho, v1, v2, v3, p = get_component(k, prim, equations) - s = log(p) - gammas[k] * log(rho) - rho_p = rho / p - w1 = (gammas[k] - s) / (gammas[k] - 1) - 0.5 * rho_p * (v1^2 + v2^2 + v3^2) - w2 = rho_p * v1 - w3 = rho_p * v2 - w4 = rho_p * v3 - w5 = -rho_p - rho_p_plus += rho_p - - set_component!(entropy, k, w1, w2, w3, w4, w5, equations) - end - - # Additional non-conservative variables - entropy[1] = rho_p_plus * B1 - entropy[2] = rho_p_plus * B2 - entropy[3] = rho_p_plus * B3 - - return SVector(entropy) + @unpack gammas = equations + B1, B2, B3 = magnetic_field(u, equations) + + prim = cons2prim(u, equations) + entropy = zero(MVector{nvariables(equations), eltype(u)}) + rho_p_plus = zero(real(equations)) + for k in eachcomponent(equations) + rho, v1, v2, v3, p = get_component(k, prim, equations) + s = log(p) - gammas[k] * log(rho) + rho_p = rho / p + w1 = (gammas[k] - s) / (gammas[k] - 1) - 0.5 * rho_p * (v1^2 + v2^2 + v3^2) + w2 = rho_p * v1 + w3 = rho_p * v2 + w4 = rho_p * v3 + w5 = -rho_p + rho_p_plus += rho_p + + set_component!(entropy, k, w1, w2, w3, w4, w5, equations) + end + + # Additional non-conservative variables + entropy[1] = rho_p_plus * B1 + entropy[2] = rho_p_plus * B2 + entropy[3] = rho_p_plus * B3 + + return SVector(entropy) end - """ Convert primitive to conservative variables """ @inline function prim2cons(prim, equations::IdealMhdMultiIonEquations1D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(prim, equations) - - cons = zero(MVector{nvariables(equations), eltype(prim)}) - cons[1] = B1 - cons[2] = B2 - cons[3] = B3 - for k in eachcomponent(equations) - rho, v1, v2, v3, p = get_component(k, prim, equations) - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - - rho_e = p/(gammas[k] - 1.0) + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) + - 0.5 * (B1^2 + B2^2 + B3^2) - - set_component!(cons, k, rho, rho_v1, rho_v2, rho_v3, rho_e, equations) - end - - return SVector{nvariables(equations), real(equations)}(cons) + @unpack gammas = equations + B1, B2, B3 = magnetic_field(prim, equations) + + cons = zero(MVector{nvariables(equations), eltype(prim)}) + cons[1] = B1 + cons[2] = B2 + cons[3] = B3 + for k in eachcomponent(equations) + rho, v1, v2, v3, p = get_component(k, prim, equations) + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + + rho_e = p / (gammas[k] - 1.0) + + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) + + 0.5 * (B1^2 + B2^2 + B3^2) + + set_component!(cons, k, rho, rho_v1, rho_v2, rho_v3, rho_e, equations) + end + + return SVector{nvariables(equations), real(equations)}(cons) end """ Compute the fastest wave speed for ideal MHD equations: c_f, the fast magnetoacoustic eigenvalue !!! ATTENTION: This routine is provisional.. Change once the fastest wave speed is known!! """ -@inline function calc_fast_wavespeed(cons, direction, equations::IdealMhdMultiIonEquations1D) - B1, B2, B3 = magnetic_field(cons, equations) - - c_f = zero(cons[1]) - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, cons, equations) - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v_mag = sqrt(v1^2 + v2^2 + v3^2) - gamma = equations.gammas[k] - p = (gamma - 1)*(rho_e - 0.5 * rho * v_mag^2 - 0.5*(B1^2 + B2^2 + B3^2)) - a_square = gamma * p / rho - sqrt_rho = sqrt(rho) - - b1 = B1 / sqrt_rho - b2 = B2 / sqrt_rho - b3 = B3 / sqrt_rho - b_square = b1^2 + b2^2 + b3^2 - - c_f = max(c_f, sqrt(0.5*(a_square + b_square) + 0.5*sqrt((a_square + b_square)^2 - 4.0*a_square*b1^2))) - end - - return c_f +@inline function calc_fast_wavespeed(cons, direction, + equations::IdealMhdMultiIonEquations1D) + B1, B2, B3 = magnetic_field(cons, equations) + + c_f = zero(cons[1]) + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, cons, equations) + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_mag = sqrt(v1^2 + v2^2 + v3^2) + gamma = equations.gammas[k] + p = (gamma - 1) * (rho_e - 0.5 * rho * v_mag^2 - 0.5 * (B1^2 + B2^2 + B3^2)) + a_square = gamma * p / rho + sqrt_rho = sqrt(rho) + + b1 = B1 / sqrt_rho + b2 = B2 / sqrt_rho + b3 = B3 / sqrt_rho + b_square = b1^2 + b2^2 + b3^2 + + c_f = max(c_f, + sqrt(0.5 * (a_square + b_square) + + 0.5 * sqrt((a_square + b_square)^2 - 4.0 * a_square * b1^2))) + end + + return c_f end """ @@ -594,62 +635,64 @@ Routine to compute the charge-averaged velocities: * vk*_plus: Contribution of each species to the charge-averaged velocity """ @inline function charge_averaged_velocities(u, equations::IdealMhdMultiIonEquations1D) - total_electron_charge = zero(eltype(u)) - - vk1_plus = zero(MVector{ncomponents(equations), eltype(u)}) - vk2_plus = zero(MVector{ncomponents(equations), eltype(u)}) - vk3_plus = zero(MVector{ncomponents(equations), eltype(u)}) - - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, _ = get_component(k, u, equations::IdealMhdMultiIonEquations1D) - - total_electron_charge += rho * equations.charge_to_mass[k] - vk1_plus[k] = rho_v1 * equations.charge_to_mass[k] - vk2_plus[k] = rho_v2 * equations.charge_to_mass[k] - vk3_plus[k] = rho_v3 * equations.charge_to_mass[k] - end - vk1_plus ./= total_electron_charge - vk2_plus ./= total_electron_charge - vk3_plus ./= total_electron_charge - v1_plus = sum(vk1_plus) - v2_plus = sum(vk2_plus) - v3_plus = sum(vk3_plus) - - return v1_plus, v2_plus, v3_plus, SVector(vk1_plus), SVector(vk2_plus), SVector(vk3_plus) + total_electron_charge = zero(eltype(u)) + + vk1_plus = zero(MVector{ncomponents(equations), eltype(u)}) + vk2_plus = zero(MVector{ncomponents(equations), eltype(u)}) + vk3_plus = zero(MVector{ncomponents(equations), eltype(u)}) + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, _ = get_component(k, u, + equations::IdealMhdMultiIonEquations1D) + + total_electron_charge += rho * equations.charge_to_mass[k] + vk1_plus[k] = rho_v1 * equations.charge_to_mass[k] + vk2_plus[k] = rho_v2 * equations.charge_to_mass[k] + vk3_plus[k] = rho_v3 * equations.charge_to_mass[k] + end + vk1_plus ./= total_electron_charge + vk2_plus ./= total_electron_charge + vk3_plus ./= total_electron_charge + v1_plus = sum(vk1_plus) + v2_plus = sum(vk2_plus) + v3_plus = sum(vk3_plus) + + return v1_plus, v2_plus, v3_plus, SVector(vk1_plus), SVector(vk2_plus), + SVector(vk3_plus) end """ Get the flow variables of component k """ @inline function get_component(k, u, equations::IdealMhdMultiIonEquations1D) - # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. - return SVector(u[3 + (k - 1) * 5 + 1], - u[3 + (k - 1) * 5 + 2], - u[3 + (k - 1) * 5 + 3], - u[3 + (k - 1) * 5 + 4], - u[3 + (k - 1) * 5 + 5]) + # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. + return SVector(u[3 + (k - 1) * 5 + 1], + u[3 + (k - 1) * 5 + 2], + u[3 + (k - 1) * 5 + 3], + u[3 + (k - 1) * 5 + 4], + u[3 + (k - 1) * 5 + 5]) end """ Set the flow variables of component k """ -@inline function set_component!(u, k, u1, u2, u3, u4, u5, equations::IdealMhdMultiIonEquations1D) - # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. - u[3 + (k - 1) * 5 + 1] = u1 - u[3 + (k - 1) * 5 + 2] = u2 - u[3 + (k - 1) * 5 + 3] = u3 - u[3 + (k - 1) * 5 + 4] = u4 - u[3 + (k - 1) * 5 + 5] = u5 +@inline function set_component!(u, k, u1, u2, u3, u4, u5, + equations::IdealMhdMultiIonEquations1D) + # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. + u[3 + (k - 1) * 5 + 1] = u1 + u[3 + (k - 1) * 5 + 2] = u2 + u[3 + (k - 1) * 5 + 3] = u3 + u[3 + (k - 1) * 5 + 4] = u4 + u[3 + (k - 1) * 5 + 5] = u5 end magnetic_field(u, equations::IdealMhdMultiIonEquations1D) = SVector(u[1], u[2], u[3]) @inline function density(u, equations::IdealMhdMultiIonEquations1D) - rho = zero(eltype(u)) - for k in eachcomponent(equations) - rho += u[3 + (k - 1) * 5 + 1] - end - return rho + rho = zero(eltype(u)) + for k in eachcomponent(equations) + rho += u[3 + (k - 1) * 5 + 1] + end + return rho end - end # @muladd diff --git a/src/equations/ideal_mhd_multiion_2d.jl b/src/equations/ideal_mhd_multiion_2d.jl index b5102fe0ecc..99229dcd2d7 100644 --- a/src/equations/ideal_mhd_multiion_2d.jl +++ b/src/equations/ideal_mhd_multiion_2d.jl @@ -3,85 +3,130 @@ # we need to opt-in explicitly. # See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. @muladd begin - +#! format: noindent @doc raw""" IdealMhdMultiIonEquations2D The ideal compressible multi-ion MHD equations in two space dimensions. """ -mutable struct IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT<:Real, ElectronPressure, ElectronTemperature} <: AbstractIdealMhdMultiIonEquations{2, NVARS, NCOMP} - gammas ::SVector{NCOMP, RealT} # Heat capacity ratios - charge_to_mass ::SVector{NCOMP, RealT} # Charge to mass ratios - gas_constants ::SVector{NCOMP, RealT} # Specific gas constants - molar_masses ::SVector{NCOMP, RealT} # Molar masses (can be provided in any units as they are only used to compute ratios) - collision_frequency ::RealT # Single collision frequency scaled with molecular mass of ion 1 (TODO: Replace by matrix of collision frequencies) - ion_electron_collision_constants::SVector{NCOMP, RealT} # Constants for the ion-electron collision frequencies. The collision frequency is obtained as constant * (e * n_e) / T_e^1.5 - electron_pressure::ElectronPressure # Function to compute the electron pressure - electron_temperature::ElectronTemperature # Function to compute the electron temperature - - function IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT, ElectronPressure, ElectronTemperature}( - gammas::SVector{NCOMP, RealT}, - charge_to_mass::SVector{NCOMP, RealT}, - gas_constants::SVector{NCOMP, RealT}, - molar_masses::SVector{NCOMP, RealT}, - collision_frequency::RealT, - ion_electron_collision_constants::SVector{NCOMP, RealT}, - electron_pressure::ElectronPressure, - electron_temperature::ElectronTemperature) where {NVARS, NCOMP, RealT<:Real, ElectronPressure, ElectronTemperature} - - NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `charge_to_mass` have to be filled with at least one value")) - - new(gammas, charge_to_mass, gas_constants, molar_masses, collision_frequency, ion_electron_collision_constants, electron_pressure, electron_temperature) - end +mutable struct IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT <: Real, + ElectronPressure, ElectronTemperature} <: + AbstractIdealMhdMultiIonEquations{2, NVARS, NCOMP} + gammas::SVector{NCOMP, RealT} # Heat capacity ratios + charge_to_mass::SVector{NCOMP, RealT} # Charge to mass ratios + gas_constants::SVector{NCOMP, RealT} # Specific gas constants + molar_masses::SVector{NCOMP, RealT} # Molar masses (can be provided in any units as they are only used to compute ratios) + collision_frequency::RealT # Single collision frequency scaled with molecular mass of ion 1 (TODO: Replace by matrix of collision frequencies) + ion_electron_collision_constants::SVector{NCOMP, RealT} # Constants for the ion-electron collision frequencies. The collision frequency is obtained as constant * (e * n_e) / T_e^1.5 + electron_pressure::ElectronPressure # Function to compute the electron pressure + electron_temperature::ElectronTemperature # Function to compute the electron temperature + + function IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT, ElectronPressure, + ElectronTemperature}(gammas + ::SVector{NCOMP, RealT}, + charge_to_mass + ::SVector{NCOMP, RealT}, + gas_constants + ::SVector{NCOMP, RealT}, + molar_masses + ::SVector{NCOMP, RealT}, + collision_frequency + ::RealT, + ion_electron_collision_constants + ::SVector{NCOMP, RealT}, + electron_pressure + ::ElectronPressure, + electron_temperature + ::ElectronTemperature) where { + NVARS, + NCOMP, + RealT <: + Real, + ElectronPressure, + ElectronTemperature + } + NCOMP >= 1 || + throw(DimensionMismatch("`gammas` and `charge_to_mass` have to be filled with at least one value")) + + new(gammas, charge_to_mass, gas_constants, molar_masses, collision_frequency, + ion_electron_collision_constants, electron_pressure, electron_temperature) + end end -function IdealMhdMultiIonEquations2D(; gammas, charge_to_mass, gas_constants, molar_masses, collision_frequency, ion_electron_collision_constants, electron_pressure = electron_pressure_zero, electron_temperature = electron_pressure_zero) - _gammas = promote(gammas...) - _charge_to_mass = promote(charge_to_mass...) - _gas_constants = promote(gas_constants...) - _molar_masses = promote(molar_masses...) - _ion_electron_collision_constants = promote(ion_electron_collision_constants...) - RealT = promote_type(eltype(_gammas), eltype(_charge_to_mass), eltype(_gas_constants), eltype(_molar_masses), eltype(collision_frequency), eltype(_ion_electron_collision_constants)) - - NVARS = length(_gammas) * 5 + 3 - NCOMP = length(_gammas) - - __gammas = SVector(map(RealT, _gammas)) - __charge_to_mass = SVector(map(RealT, _charge_to_mass)) - __gas_constants = SVector(map(RealT, _gas_constants)) - __molar_masses = SVector(map(RealT, _molar_masses)) - __collision_frequency = map(RealT, collision_frequency) - __ion_electron_collision_constants = SVector(map(RealT, _ion_electron_collision_constants)) - - return IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT, typeof(electron_pressure), typeof(electron_temperature)}(__gammas, __charge_to_mass, __gas_constants, __molar_masses, __collision_frequency, __ion_electron_collision_constants, electron_pressure, electron_temperature) +function IdealMhdMultiIonEquations2D(; gammas, charge_to_mass, gas_constants, + molar_masses, collision_frequency, + ion_electron_collision_constants, + electron_pressure = electron_pressure_zero, + electron_temperature = electron_pressure_zero) + _gammas = promote(gammas...) + _charge_to_mass = promote(charge_to_mass...) + _gas_constants = promote(gas_constants...) + _molar_masses = promote(molar_masses...) + _ion_electron_collision_constants = promote(ion_electron_collision_constants...) + RealT = promote_type(eltype(_gammas), eltype(_charge_to_mass), + eltype(_gas_constants), eltype(_molar_masses), + eltype(collision_frequency), + eltype(_ion_electron_collision_constants)) + + NVARS = length(_gammas) * 5 + 3 + NCOMP = length(_gammas) + + __gammas = SVector(map(RealT, _gammas)) + __charge_to_mass = SVector(map(RealT, _charge_to_mass)) + __gas_constants = SVector(map(RealT, _gas_constants)) + __molar_masses = SVector(map(RealT, _molar_masses)) + __collision_frequency = map(RealT, collision_frequency) + __ion_electron_collision_constants = SVector(map(RealT, + _ion_electron_collision_constants)) + + return IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT, typeof(electron_pressure), + typeof(electron_temperature)}(__gammas, + __charge_to_mass, + __gas_constants, + __molar_masses, + __collision_frequency, + __ion_electron_collision_constants, + electron_pressure, + electron_temperature) end -@inline Base.real(::IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT}) where {NVARS, NCOMP, RealT} = RealT +@inline function Base.real(::IdealMhdMultiIonEquations2D{NVARS, NCOMP, RealT}) where { + NVARS, + NCOMP, + RealT + } + RealT +end have_nonconservative_terms(::IdealMhdMultiIonEquations2D) = True() nnoncons(::IdealMhdMultiIonEquations2D) = 4 function varnames(::typeof(cons2cons), equations::IdealMhdMultiIonEquations2D) - cons = ("B1", "B2", "B3") - for i in eachcomponent(equations) - cons = (cons..., tuple("rho_" * string(i),"rho_v1_" * string(i), "rho_v2_" * string(i), "rho_v3_" * string(i), "rho_e_" * string(i))...) - end - - return cons + cons = ("B1", "B2", "B3") + for i in eachcomponent(equations) + cons = (cons..., + tuple("rho_" * string(i), "rho_v1_" * string(i), "rho_v2_" * string(i), + "rho_v3_" * string(i), "rho_e_" * string(i))...) + end + + return cons end function varnames(::typeof(cons2prim), equations::IdealMhdMultiIonEquations2D) - prim = ("B1", "B2", "B3") - for i in eachcomponent(equations) - prim = (prim..., tuple("rho_" * string(i),"v1_" * string(i), "v2_" * string(i), "v3_" * string(i), "p_" * string(i))...) - end - - return prim -end + prim = ("B1", "B2", "B3") + for i in eachcomponent(equations) + prim = (prim..., + tuple("rho_" * string(i), "v1_" * string(i), "v2_" * string(i), + "v3_" * string(i), "p_" * string(i))...) + end -default_analysis_integrals(::IdealMhdMultiIonEquations2D) = (entropy_timederivative, Val(:l2_divb), Val(:linf_divb)) + return prim +end +function default_analysis_integrals(::IdealMhdMultiIonEquations2D) + (entropy_timederivative, Val(:l2_divb), Val(:linf_divb)) +end # """ # initial_condition_convergence_test(x, t, equations::IdealMhdMultiIonEquations2D) @@ -106,7 +151,6 @@ default_analysis_integrals(::IdealMhdMultiIonEquations2D) = (entropy_timederiva # return prim2cons(vcat(prim_other, prim_rho), equations) # end - """ initial_condition_weak_blast_wave(x, t, equations::IdealMhdMultiIonEquations2D) @@ -116,225 +160,235 @@ A weak blast wave adapted from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_weak_blast_wave(x, t, equations::IdealMhdMultiIonEquations2D) - # 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 = (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) - - # Calculate primitive variables - rho = zero(real(equations)) - if r > 0.5 - rho = 1.0 - else - rho = 1.1691 - end - 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 - - prim = zero(MVector{nvariables(equations), real(equations)}) - prim[1] = 1.0 - prim[2] = 1.0 - prim[3] = 1.0 - for k in eachcomponent(equations) - set_component!(prim, k, 2^(k-1) * (1 - 2)/(1 - 2^ncomponents(equations)) * rho, v1, v2, 0, p, equations) - end - - return prim2cons(SVector(prim), 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 = (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) + + # Calculate primitive variables + rho = zero(real(equations)) + if r > 0.5 + rho = 1.0 + else + rho = 1.1691 + end + 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 + + prim = zero(MVector{nvariables(equations), real(equations)}) + prim[1] = 1.0 + prim[2] = 1.0 + prim[3] = 1.0 + for k in eachcomponent(equations) + set_component!(prim, k, + 2^(k - 1) * (1 - 2) / (1 - 2^ncomponents(equations)) * rho, v1, + v2, 0, p, equations) + end + + return prim2cons(SVector(prim), equations) end # TODO: Add initial condition equilibrium # Calculate 1D flux in for a single point @inline function flux(u, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - B1, B2, B3 = magnetic_field(u, equations) - - v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, equations) + B1, B2, B3 = magnetic_field(u, equations) - mag_en = 0.5 * (B1^2 + B2^2 + B3^2) + v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, + equations) - f = zero(MVector{nvariables(equations), eltype(u)}) + mag_en = 0.5 * (B1^2 + B2^2 + B3^2) - if orientation == 1 - f[1] = 0 - f[2] = v1_plus * B2 - v2_plus * B1 - f[3] = v1_plus * B3 - v3_plus * B1 - - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) - - gamma = equations.gammas[k] - p = (gamma - 1) * (rho_e - kin_en - mag_en) - - f1 = rho_v1 - f2 = rho_v1*v1 + p - f3 = rho_v1*v2 - f4 = rho_v1*v3 - f5 = (kin_en + gamma * p/(gamma - 1))*v1 + 2 * mag_en * vk1_plus[k] - B1 * (vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) - end - - else #if orientation == 2 + f = zero(MVector{nvariables(equations), eltype(u)}) - f[1] = v2_plus * B1 - v1_plus * B2 - f[2] = 0 - f[3] = v2_plus * B3 - v3_plus * B2 + if orientation == 1 + f[1] = 0 + f[2] = v1_plus * B2 - v2_plus * B1 + f[3] = v1_plus * B3 - v3_plus * B1 + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) + + gamma = equations.gammas[k] + p = (gamma - 1) * (rho_e - kin_en - mag_en) + + f1 = rho_v1 + f2 = rho_v1 * v1 + p + f3 = rho_v1 * v2 + f4 = rho_v1 * v3 + f5 = (kin_en + gamma * p / (gamma - 1)) * v1 + 2 * mag_en * vk1_plus[k] - + B1 * (vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) - - gamma = equations.gammas[k] - p = (gamma - 1) * (rho_e - kin_en - mag_en) - - f1 = rho_v2 - f2 = rho_v2 * v1 - f3 = rho_v2 * v2 + p - f4 = rho_v2 * v3 - f5 = (kin_en + gamma*p/(gamma - 1))*v2 + 2 * mag_en * vk2_plus[k] - B2 * (vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) + else #if orientation == 2 + f[1] = v2_plus * B1 - v1_plus * B2 + f[2] = 0 + f[3] = v2_plus * B3 - v3_plus * B2 + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + kin_en = 0.5 * rho * (v1^2 + v2^2 + v3^2) + + gamma = equations.gammas[k] + p = (gamma - 1) * (rho_e - kin_en - mag_en) + + f1 = rho_v2 + f2 = rho_v2 * v1 + f3 = rho_v2 * v2 + p + f4 = rho_v2 * v3 + f5 = (kin_en + gamma * p / (gamma - 1)) * v2 + 2 * mag_en * vk2_plus[k] - + B2 * (vk1_plus[k] * B1 + vk2_plus[k] * B2 + vk3_plus[k] * B3) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end end - end - return SVector(f) + return SVector(f) end """ Standard source terms of the multi-ion MHD equations """ function source_terms_standard(u, x, t, equations::IdealMhdMultiIonEquations2D) - @unpack charge_to_mass = equations - B1, B2, B3 = magnetic_field(u, equations) - v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, equations) - - s = zero(MVector{nvariables(equations), eltype(u)}) - - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v1_diff = v1_plus - v1 - v2_diff = v2_plus - v2 - v3_diff = v3_plus - v3 - r_rho = charge_to_mass[k] * rho - s2 = r_rho * (v2_diff * B3 - v3_diff * B2) - s3 = r_rho * (v3_diff * B1 - v1_diff * B3) - s4 = r_rho * (v1_diff * B2 - v2_diff * B1) - s5 = v1 * s2 + v2 * s3 + v3 * s4 - - set_component!(s, k, 0, s2, s3, s4, s5, equations) - end - - return SVector(s) + @unpack charge_to_mass = equations + B1, B2, B3 = magnetic_field(u, equations) + v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, + equations) + + s = zero(MVector{nvariables(equations), eltype(u)}) + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v1_diff = v1_plus - v1 + v2_diff = v2_plus - v2 + v3_diff = v3_plus - v3 + r_rho = charge_to_mass[k] * rho + s2 = r_rho * (v2_diff * B3 - v3_diff * B2) + s3 = r_rho * (v3_diff * B1 - v1_diff * B3) + s4 = r_rho * (v1_diff * B2 - v2_diff * B1) + s5 = v1 * s2 + v2 * s3 + v3 * s4 + + set_component!(s, k, 0, s2, s3, s4, s5, equations) + end + + return SVector(s) end """ Ion-ion collision source terms, cf. Rueda-Ramirez et al. (2023) and Rubin et al. (2015) """ -function source_terms_collision_ion_ion(u, x, t, equations::IdealMhdMultiIonEquations2D) - S_std = source_terms_standard(u, x ,t, equations) - - s = zero(MVector{nvariables(equations), eltype(u)}) - @unpack gammas, gas_constants, molar_masses, collision_frequency = equations - - prim = cons2prim(u, equations) - - for k in eachcomponent(equations) - rho_k, v1_k, v2_k, v3_k, p_k = get_component(k, prim, equations) - T_k = p_k / (rho_k * gas_constants[k]) - - S_q1 = 0.0 - S_q2 = 0.0 - S_q3 = 0.0 - S_E = 0.0 - for l in eachcomponent(equations) - # Skip computation for same species - l == k && continue - - rho_l, v1_l, v2_l, v3_l, p_l = get_component(l, prim, equations) - T_l = p_l / (rho_l * gas_constants[l]) - - # Reduced temperature (without scaling with molar mass) - T_kl = (molar_masses[l] * T_k + molar_masses[k] * T_l) - - delta_v2 = (v1_l - v1_k)^2 + (v2_l - v2_k)^2 + (v3_l - v3_k)^2 - - # Scale T_kl with molar mass - T_kl /= (molar_masses[k] + molar_masses[l]) - - # Compute effective collision frequency - v_kl = ( collision_frequency * (rho_l * molar_masses[1] / molar_masses[l]) / T_kl^(3/2) ) - - # Correct the collision frequency with the drifting effect (NEW - Rambo & Denavit, Rambo & Procassini) - z2 = delta_v2 / (p_l / rho_l + p_k / rho_k) - v_kl /= (1 + (2.0 / (9.0 * pi))^(1.0/3.0) * z2 )^(1.5) - - S_q1 += rho_k * v_kl * (v1_l - v1_k) - S_q2 += rho_k * v_kl * (v2_l - v2_k) - S_q3 += rho_k * v_kl * (v3_l - v3_k) - - S_E += (3 * molar_masses[1] * gas_constants[1] * (T_l - T_k) - + molar_masses[l] * delta_v2) * v_kl * rho_k / (molar_masses[k] + molar_masses[l]) - end +function source_terms_collision_ion_ion(u, x, t, equations::IdealMhdMultiIonEquations2D) + S_std = source_terms_standard(u, x, t, equations) + + s = zero(MVector{nvariables(equations), eltype(u)}) + @unpack gammas, gas_constants, molar_masses, collision_frequency = equations + + prim = cons2prim(u, equations) + + for k in eachcomponent(equations) + rho_k, v1_k, v2_k, v3_k, p_k = get_component(k, prim, equations) + T_k = p_k / (rho_k * gas_constants[k]) + + S_q1 = 0.0 + S_q2 = 0.0 + S_q3 = 0.0 + S_E = 0.0 + for l in eachcomponent(equations) + # Skip computation for same species + l == k && continue + + rho_l, v1_l, v2_l, v3_l, p_l = get_component(l, prim, equations) + T_l = p_l / (rho_l * gas_constants[l]) + + # Reduced temperature (without scaling with molar mass) + T_kl = (molar_masses[l] * T_k + molar_masses[k] * T_l) + + delta_v2 = (v1_l - v1_k)^2 + (v2_l - v2_k)^2 + (v3_l - v3_k)^2 + + # Scale T_kl with molar mass + T_kl /= (molar_masses[k] + molar_masses[l]) + + # Compute effective collision frequency + v_kl = (collision_frequency * (rho_l * molar_masses[1] / molar_masses[l]) / + T_kl^(3 / 2)) + + # Correct the collision frequency with the drifting effect (NEW - Rambo & Denavit, Rambo & Procassini) + z2 = delta_v2 / (p_l / rho_l + p_k / rho_k) + v_kl /= (1 + (2.0 / (9.0 * pi))^(1.0 / 3.0) * z2)^(1.5) + + S_q1 += rho_k * v_kl * (v1_l - v1_k) + S_q2 += rho_k * v_kl * (v2_l - v2_k) + S_q3 += rho_k * v_kl * (v3_l - v3_k) + + S_E += (3 * molar_masses[1] * gas_constants[1] * (T_l - T_k) + + + molar_masses[l] * delta_v2) * v_kl * rho_k / + (molar_masses[k] + molar_masses[l]) + end - S_E += (v1_k * S_q1 + v2_k * S_q2 + v3_k * S_q3) - - set_component!(s, k, 0.0, S_q1, S_q2, S_q3, S_E, equations) - end - return SVector{nvariables(equations), real(equations)}(S_std .+ s) + S_E += (v1_k * S_q1 + v2_k * S_q2 + v3_k * S_q3) + + set_component!(s, k, 0.0, S_q1, S_q2, S_q3, S_E, equations) + end + return SVector{nvariables(equations), real(equations)}(S_std .+ s) end """ Ion-electron collision source terms, cf. Rueda-Ramirez et al. (2023) and Rubin et al. (2015) Here we assume v_e = v⁺ (no effect of currents on the electron velocity) """ -function source_terms_collision_ion_electron(u, x, t, equations::IdealMhdMultiIonEquations2D) +function source_terms_collision_ion_electron(u, x, t, + equations::IdealMhdMultiIonEquations2D) + s = zero(MVector{nvariables(equations), eltype(u)}) + @unpack gammas, gas_constants, molar_masses, ion_electron_collision_constants, electron_temperature = equations + + prim = cons2prim(u, equations) + T_e = electron_temperature(u, equations) + T_e32 = T_e^(3 / 2) - s = zero(MVector{nvariables(equations), eltype(u)}) - @unpack gammas, gas_constants, molar_masses, ion_electron_collision_constants, electron_temperature = equations - - prim = cons2prim(u, equations) - T_e = electron_temperature(u, equations) - T_e32 = T_e^(3/2) + v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, + equations) - v1_plus, v2_plus, v3_plus, vk1_plus, vk2_plus, vk3_plus, total_electron_charge = charge_averaged_velocities(u, equations) + for k in eachcomponent(equations) + rho_k, v1_k, v2_k, v3_k, p_k = get_component(k, prim, equations) + T_k = p_k / (rho_k * gas_constants[k]) - for k in eachcomponent(equations) - rho_k, v1_k, v2_k, v3_k, p_k = get_component(k, prim, equations) - T_k = p_k / (rho_k * gas_constants[k]) + # Compute effective collision frequency + v_ke = ion_electron_collision_constants[k] * total_electron_charge / T_e32 - # Compute effective collision frequency - v_ke = ion_electron_collision_constants[k] * total_electron_charge / T_e32 + S_q1 = rho_k * v_ke * (v1_plus - v1_k) + S_q2 = rho_k * v_ke * (v2_plus - v2_k) + S_q3 = rho_k * v_ke * (v3_plus - v3_k) - S_q1 = rho_k * v_ke * (v1_plus - v1_k) - S_q2 = rho_k * v_ke * (v2_plus - v2_k) - S_q3 = rho_k * v_ke * (v3_plus - v3_k) + S_E = 3 * molar_masses[1] * gas_constants[1] * (T_e - T_k) * v_ke * rho_k / + molar_masses[k] - S_E = 3 * molar_masses[1] * gas_constants[1] * (T_e - T_k) * v_ke * rho_k / molar_masses[k] + S_E += (v1_k * S_q1 + v2_k * S_q2 + v3_k * S_q3) - S_E += (v1_k * S_q1 + v2_k * S_q2 + v3_k * S_q3) - - set_component!(s, k, 0.0, S_q1, S_q2, S_q3, S_E, equations) - end - return SVector{nvariables(equations), real(equations)}(s) + set_component!(s, k, 0.0, S_q1, S_q2, S_q3, S_E, equations) + end + return SVector{nvariables(equations), real(equations)}(s) end - + function electron_pressure_zero(u, equations::IdealMhdMultiIonEquations2D) - return zero(u[1]) + return zero(u[1]) end """ @@ -346,115 +400,121 @@ The flux is composed of three terms that can be written as the product of local * The MHD term: Implemented * The "term 3": Implemented """ -@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - # Compute important averages - B1_avg = 0.5 *(B1_ll + B1_rr) - B2_avg = 0.5 *(B2_ll + B2_rr) - B3_avg = 0.5 *(B3_ll + B3_rr) - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - # Mean electron pressure - pe_mean = 0.5 * (equations.electron_pressure(u_ll, equations) + - equations.electron_pressure(u_rr, equations)) - - # Compute charge ratio of u_ll - charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) - total_electron_charge = zero(eltype(u_ll)) - for k in eachcomponent(equations) - rho_k = u_ll[3 + (k - 1) * 5 + 1] - charge_ratio_ll[k] = rho_k * charge_to_mass[k] - total_electron_charge += charge_ratio_ll[k] - end - charge_ratio_ll ./= total_electron_charge - - # Compute auxiliary variables - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - if orientation == 1 - # Entries of Powell term for induction equation - f[1] = v1_plus_ll * B1_avg - f[2] = v2_plus_ll * B1_avg - f[3] = v3_plus_ll * B1_avg - +@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, + orientation::Integer, + equations::IdealMhdMultiIonEquations2D) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + # Compute important averages + B1_avg = 0.5 * (B1_ll + B1_rr) + B2_avg = 0.5 * (B2_ll + B2_rr) + B3_avg = 0.5 * (B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + # Mean electron pressure + pe_mean = 0.5 * (equations.electron_pressure(u_ll, equations) + + equations.electron_pressure(u_rr, equations)) + + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(eltype(u_ll)) for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - B1_avg * B1_avg + pe_mean) - f3 = charge_ratio_ll[k] * (- B1_avg * B2_avg) - f4 = charge_ratio_ll[k] * (- B1_avg * B3_avg) - f5 = vk1_plus_ll[k] * pe_mean - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - f5 += (B2_ll * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + - B3_ll * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) ) - - # Compute Powell term - f2 += charge_ratio_ll[k] * B1_ll * B1_avg - f3 += charge_ratio_ll[k] * B2_ll * B1_avg - f4 += charge_ratio_ll[k] * B3_ll * B1_avg - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_avg - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] end + charge_ratio_ll ./= total_electron_charge - else #if orientation == 2 - # Entries of Powell term for induction equation - f[1] = v1_plus_ll * B2_avg - f[2] = v2_plus_ll * B2_avg - f[3] = v3_plus_ll * B2_avg + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, + equations) - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (- B2_avg * B1_avg) - f3 = charge_ratio_ll[k] * (- B2_avg * B2_avg + 0.5 * mag_norm_avg + pe_mean) - f4 = charge_ratio_ll[k] * (- B2_avg * B3_avg) - f5 = vk2_plus_ll[k] * pe_mean - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - f5 += (B1_ll * (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) + - B3_ll * (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) ) - - # Compute Powell term - f2 += charge_ratio_ll[k] * B1_ll * B2_avg - f3 += charge_ratio_ll[k] * B2_ll * B2_avg - f4 += charge_ratio_ll[k] * B3_ll * B2_avg - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_avg - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if orientation == 1 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B1_avg + f[2] = v2_plus_ll * B1_avg + f[3] = v3_plus_ll * B1_avg + + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - B1_avg * B1_avg + pe_mean) + f3 = charge_ratio_ll[k] * (-B1_avg * B2_avg) + f4 = charge_ratio_ll[k] * (-B1_avg * B3_avg) + f5 = vk1_plus_ll[k] * pe_mean + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + f5 += (B2_ll * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + + B3_ll * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg)) + + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B1_avg + f3 += charge_ratio_ll[k] * B2_ll * B1_avg + f4 += charge_ratio_ll[k] * B3_ll * B1_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * + B1_avg + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B2_avg + f[2] = v2_plus_ll * B2_avg + f[3] = v3_plus_ll * B2_avg + + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] * (-B2_avg * B1_avg) + f3 = charge_ratio_ll[k] * (-B2_avg * B2_avg + 0.5 * mag_norm_avg + pe_mean) + f4 = charge_ratio_ll[k] * (-B2_avg * B3_avg) + f5 = vk2_plus_ll[k] * pe_mean + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + f5 += (B1_ll * (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) + + B3_ll * (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg)) + + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B2_avg + f3 += charge_ratio_ll[k] * B2_ll * B2_avg + f4 += charge_ratio_ll[k] * B3_ll * B2_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * + B2_avg + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end end - end - # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines - return SVector(2 * f) + # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines + return SVector(2 * f) end """ flux_nonconservative_ruedaramirez_etal(u_ll, orientation::Integer, @@ -472,134 +532,135 @@ The flux is composed of three/four terms that can be written as the product of l equations::IdealMhdMultiIonEquations2D, nonconservative_type::NonConservativeLocal, noncons_term::Integer) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - - # Compute charge ratio of u_ll - charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) - total_electron_charge = zero(eltype(u_ll)) - for k in eachcomponent(equations) - rho_k = u_ll[3 + (k - 1) * 5 + 1] - charge_ratio_ll[k] = rho_k * charge_to_mass[k] - total_electron_charge += charge_ratio_ll[k] - end - charge_ratio_ll ./= total_electron_charge - - # Compute auxiliary variables - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - if noncons_term == 1 - # Powell term - ############# - if orientation == 1 - # Entries of Powell term for induction equation - f[1] = v1_plus_ll - f[2] = v2_plus_ll - f[3] = v3_plus_ll - - for k in eachcomponent(equations) - # Compute Powell term - f2 = charge_ratio_ll[k] * B1_ll - f3 = charge_ratio_ll[k] * B2_ll - f4 = charge_ratio_ll[k] * B3_ll - f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - - else #if orientation == 2 - # Entries of Powell term for induction equation - f[1] = v1_plus_ll - f[2] = v2_plus_ll - f[3] = v3_plus_ll - - for k in eachcomponent(equations) - # Compute Powell term - f2 = charge_ratio_ll[k] * B1_ll - f3 = charge_ratio_ll[k] * B2_ll - f4 = charge_ratio_ll[k] * B3_ll - f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - end - elseif noncons_term == 2 - # Term "2" (MHD) - ################ - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] - f3 = charge_ratio_ll[k] - f4 = charge_ratio_ll[k] - f5 = vk1_plus_ll[k] + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] - f3 = charge_ratio_ll[k] - f4 = charge_ratio_ll[k] - f5 = vk2_plus_ll[k] - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - end - elseif noncons_term == 3 - # Term "3" (multi-ion) - ###################### - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 3 (only needed for NCOMP>1) - f5 = B2_ll - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end - - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 3 (only needed for NCOMP>1) - f5 = B1_ll - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(eltype(u_ll)) + for k in eachcomponent(equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] end - elseif noncons_term == 4 - # Term "4" (multi-ion) - ###################### - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 4 (only needed for NCOMP>1) - f5 = B3_ll - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end - - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 4 (only needed for NCOMP>1) - f5 = B3_ll - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end + charge_ratio_ll ./= total_electron_charge + + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if noncons_term == 1 + # Powell term + ############# + if orientation == 1 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll + f[2] = v2_plus_ll + f[3] = v3_plus_ll + + for k in eachcomponent(equations) + # Compute Powell term + f2 = charge_ratio_ll[k] * B1_ll + f3 = charge_ratio_ll[k] * B2_ll + f4 = charge_ratio_ll[k] * B3_ll + f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + # Entries of Powell term for induction equation + f[1] = v1_plus_ll + f[2] = v2_plus_ll + f[3] = v3_plus_ll + + for k in eachcomponent(equations) + # Compute Powell term + f2 = charge_ratio_ll[k] * B1_ll + f3 = charge_ratio_ll[k] * B2_ll + f4 = charge_ratio_ll[k] * B3_ll + f5 = (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 2 + # Term "2" (MHD) + ################ + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] + f3 = charge_ratio_ll[k] + f4 = charge_ratio_ll[k] + f5 = vk1_plus_ll[k] + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] + f3 = charge_ratio_ll[k] + f4 = charge_ratio_ll[k] + f5 = vk2_plus_ll[k] + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 3 + # Term "3" (multi-ion) + ###################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + f5 = B2_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + f5 = B1_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + elseif noncons_term == 4 + # Term "4" (multi-ion) + ###################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + f5 = B3_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + f5 = B3_ll + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end end - end - # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines - return SVector(2 * f) + # We multiply by 2 to compensate the multiplication by 0.5 in the Trixi routines + return SVector(2 * f) end """ flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, @@ -613,156 +674,159 @@ The flux is composed of three/four terms that can be written as the product of l * The MHD term: Implemented * The "term 3/4": Implemented """ -@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, +@inline function flux_nonconservative_ruedaramirez_etal(u_ll, u_rr, + orientation::Integer, equations::IdealMhdMultiIonEquations2D, nonconservative_type::NonConservativeSymmetric, noncons_term::Integer) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - # Compute important averages - B1_avg = 0.5 *(B1_ll + B1_rr) - B2_avg = 0.5 *(B2_ll + B2_rr) - B3_avg = 0.5 *(B3_ll + B3_rr) - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - # Mean electron pressure - pe_mean = 0.5 * (equations.electron_pressure(u_ll, equations) + - equations.electron_pressure(u_rr, equations)) - - # Compute auxiliary variables - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - if noncons_term == 1 - # Powell term - ############# - if orientation == 1 - # Entries of Powell term for induction equation - f[1] = B1_avg - f[2] = B1_avg - f[3] = B1_avg - for k in eachcomponent(equations) - # Append to the flux vector - set_component!(f, k, 0, B1_avg, B1_avg, B1_avg, B1_avg, equations) - end - - else #if orientation == 2 - # Entries of Powell term for induction equation - f[1] = B2_avg - f[2] = B2_avg - f[3] = B2_avg - for k in eachcomponent(equations) - # Append to the flux vector - set_component!(f, k, 0, B2_avg, B2_avg, B2_avg, B2_avg, equations) - end - end - elseif noncons_term == 2 - # Term 2 (MHD) - ############## - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = (0.5 * mag_norm_avg - B1_avg * B1_avg + pe_mean) - f3 = (- B1_avg * B2_avg) - f4 = (- B1_avg * B3_avg) - f5 = pe_mean - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = (- B2_avg * B1_avg) - f3 = (- B2_avg * B2_avg + 0.5 * mag_norm_avg + pe_mean) - f4 = (- B2_avg * B3_avg) - f5 = pe_mean - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) - end - end - elseif noncons_term == 3 - # Term 3 (multi-ion) - #################### - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - - f5 = (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - - f5 = (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end - end - elseif noncons_term == 4 - # Term 4 (multi-ion) - #################### - if orientation == 1 - for k in eachcomponent(equations) - # Compute term 4 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - - f5 = (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end - - else #if orientation == 2 - for k in eachcomponent(equations) - # Compute term 4 (only needed for NCOMP>1) - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - - f5 = (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) - - # Append to the flux vector - set_component!(f, k, 0, 0, 0, 0, f5, equations) - end + # Compute important averages + B1_avg = 0.5 * (B1_ll + B1_rr) + B2_avg = 0.5 * (B2_ll + B2_rr) + B3_avg = 0.5 * (B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + # Mean electron pressure + pe_mean = 0.5 * (equations.electron_pressure(u_ll, equations) + + equations.electron_pressure(u_rr, equations)) + + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr = charge_averaged_velocities(u_rr, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if noncons_term == 1 + # Powell term + ############# + if orientation == 1 + # Entries of Powell term for induction equation + f[1] = B1_avg + f[2] = B1_avg + f[3] = B1_avg + for k in eachcomponent(equations) + # Append to the flux vector + set_component!(f, k, 0, B1_avg, B1_avg, B1_avg, B1_avg, equations) + end + + else #if orientation == 2 + # Entries of Powell term for induction equation + f[1] = B2_avg + f[2] = B2_avg + f[3] = B2_avg + for k in eachcomponent(equations) + # Append to the flux vector + set_component!(f, k, 0, B2_avg, B2_avg, B2_avg, B2_avg, equations) + end + end + elseif noncons_term == 2 + # Term 2 (MHD) + ############## + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = (0.5 * mag_norm_avg - B1_avg * B1_avg + pe_mean) + f3 = (-B1_avg * B2_avg) + f4 = (-B1_avg * B3_avg) + f5 = pe_mean + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = (-B2_avg * B1_avg) + f3 = (-B2_avg * B2_avg + 0.5 * mag_norm_avg + pe_mean) + f4 = (-B2_avg * B3_avg) + f5 = pe_mean + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + end + elseif noncons_term == 3 + # Term 3 (multi-ion) + #################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + + f5 = (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + + f5 = (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end + elseif noncons_term == 4 + # Term 4 (multi-ion) + #################### + if orientation == 1 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + f5 = (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + + else #if orientation == 2 + for k in eachcomponent(equations) + # Compute term 4 (only needed for NCOMP>1) + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + f5 = (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) + + # Append to the flux vector + set_component!(f, k, 0, 0, 0, 0, f5, equations) + end + end end - end - # We don't multiply by 2 because the local term is already multiplied by 2 - return SVector(f) + # We don't multiply by 2 because the local term is already multiplied by 2 + return SVector(f) end """ @@ -772,106 +836,119 @@ The term is composed of three parts * The MHD term: Implemented * The "term 3": Implemented """ -@inline function flux_nonconservative_central(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - @unpack charge_to_mass = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - # Compute important averages - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - # Electron pressure - pe_rr = equations.electron_pressure(u_rr, equations) - pe_ll = equations.electron_pressure(u_ll, equations) - pe_avg = 0.5 * (pe_ll + pe_rr) - - # Compute charge ratio of u_ll - charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) - total_electron_charge = zero(real(equations)) - for k in eachcomponent(equations) - rho_k = u_ll[3 + (k - 1) * 5 + 1] - charge_ratio_ll[k] = rho_k * charge_to_mass[k] - total_electron_charge += charge_ratio_ll[k] - end - charge_ratio_ll ./= total_electron_charge - - # Compute auxiliary variables - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - if orientation == 1 - B1_avg = 0.5 * (B1_ll + B1_rr) - # Entries of Powell term for induction equation - f[1] = v1_plus_ll * B1_avg - f[2] = v2_plus_ll * B1_avg - f[3] = v3_plus_ll * B1_avg +@inline function flux_nonconservative_central(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations2D) + @unpack charge_to_mass = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + # Compute important averages + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + # Electron pressure + pe_rr = equations.electron_pressure(u_rr, equations) + pe_ll = equations.electron_pressure(u_ll, equations) + pe_avg = 0.5 * (pe_ll + pe_rr) + + # Compute charge ratio of u_ll + charge_ratio_ll = zero(MVector{ncomponents(equations), eltype(u_ll)}) + total_electron_charge = zero(real(equations)) for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (0.5 * mag_norm_avg - 0.5 * B1_ll * B1_ll - 0.5 * B1_rr * B1_rr + pe_avg) - f3 = charge_ratio_ll[k] * (- 0.5 * B1_ll * B2_ll - 0.5 * B1_rr * B2_rr) - f4 = charge_ratio_ll[k] * (- 0.5 * B1_ll * B3_ll - 0.5 * B1_rr * B3_rr) - f5 = vk1_plus_ll[k] * pe_avg - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - f5 += (B2_ll * (0.5 * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) + 0.5 * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr) ) + - B3_ll * (0.5 * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) + 0.5 * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr) ) ) - - # Compute Powell term - f2 += charge_ratio_ll[k] * B1_ll * B1_avg - f3 += charge_ratio_ll[k] * B2_ll * B1_avg - f4 += charge_ratio_ll[k] * B3_ll * B1_avg - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B1_avg - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) + rho_k = u_ll[3 + (k - 1) * 5 + 1] + charge_ratio_ll[k] = rho_k * charge_to_mass[k] + total_electron_charge += charge_ratio_ll[k] end - else #if orientation == 2 - B2_avg = 0.5 * (B2_ll + B2_rr) - # Entries of Powell term for induction equation - f[1] = v1_plus_ll * B2_avg - f[2] = v2_plus_ll * B2_avg - f[3] = v3_plus_ll * B2_avg + charge_ratio_ll ./= total_electron_charge - for k in eachcomponent(equations) - # Compute term 2 (MHD) - f2 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B1_ll - 0.5 * B2_rr * B1_rr) - f3 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B2_ll - 0.5 * B2_rr * B2_rr + 0.5 * mag_norm_avg + pe_avg) - f4 = charge_ratio_ll[k] * (- 0.5 * B2_ll * B3_ll - 0.5 * B2_rr * B3_rr) - f5 = vk2_plus_ll[k] * pe_avg - - # Compute term 3 (only needed for NCOMP>1) - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - f5 += (B1_ll * (0.5 * (vk2_minus_ll * B1_ll - vk1_minus_ll * B2_ll) + 0.5 * (vk2_minus_rr * B1_rr - vk1_minus_rr * B2_rr)) + - B3_ll * (0.5 * (vk2_minus_ll * B3_ll - vk3_minus_ll * B2_ll) + 0.5 * (vk2_minus_rr * B3_rr - vk3_minus_rr * B2_rr)) ) - - # Compute Powell term - f2 += charge_ratio_ll[k] * B1_ll * B2_avg - f3 += charge_ratio_ll[k] * B2_ll * B2_avg - f4 += charge_ratio_ll[k] * B3_ll * B2_avg - f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * B2_avg - - # Append to the flux vector - set_component!(f, k, 0, f2, f3, f4, f5, equations) + # Compute auxiliary variables + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + if orientation == 1 + B1_avg = 0.5 * (B1_ll + B1_rr) + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B1_avg + f[2] = v2_plus_ll * B1_avg + f[3] = v3_plus_ll * B1_avg + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] * + (0.5 * mag_norm_avg - 0.5 * B1_ll * B1_ll - 0.5 * B1_rr * B1_rr + + pe_avg) + f3 = charge_ratio_ll[k] * (-0.5 * B1_ll * B2_ll - 0.5 * B1_rr * B2_rr) + f4 = charge_ratio_ll[k] * (-0.5 * B1_ll * B3_ll - 0.5 * B1_rr * B3_rr) + f5 = vk1_plus_ll[k] * pe_avg + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + f5 += (B2_ll * (0.5 * (vk1_minus_ll * B2_ll - vk2_minus_ll * B1_ll) + + 0.5 * (vk1_minus_rr * B2_rr - vk2_minus_rr * B1_rr)) + + B3_ll * (0.5 * (vk1_minus_ll * B3_ll - vk3_minus_ll * B1_ll) + + 0.5 * (vk1_minus_rr * B3_rr - vk3_minus_rr * B1_rr))) + + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B1_avg + f3 += charge_ratio_ll[k] * B2_ll * B1_avg + f4 += charge_ratio_ll[k] * B3_ll * B1_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * + B1_avg + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end + else #if orientation == 2 + B2_avg = 0.5 * (B2_ll + B2_rr) + # Entries of Powell term for induction equation + f[1] = v1_plus_ll * B2_avg + f[2] = v2_plus_ll * B2_avg + f[3] = v3_plus_ll * B2_avg + + for k in eachcomponent(equations) + # Compute term 2 (MHD) + f2 = charge_ratio_ll[k] * (-0.5 * B2_ll * B1_ll - 0.5 * B2_rr * B1_rr) + f3 = charge_ratio_ll[k] * + (-0.5 * B2_ll * B2_ll - 0.5 * B2_rr * B2_rr + 0.5 * mag_norm_avg + + pe_avg) + f4 = charge_ratio_ll[k] * (-0.5 * B2_ll * B3_ll - 0.5 * B2_rr * B3_rr) + f5 = vk2_plus_ll[k] * pe_avg + + # Compute term 3 (only needed for NCOMP>1) + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + f5 += (B1_ll * (0.5 * (vk2_minus_ll * B1_ll - vk1_minus_ll * B2_ll) + + 0.5 * (vk2_minus_rr * B1_rr - vk1_minus_rr * B2_rr)) + + B3_ll * (0.5 * (vk2_minus_ll * B3_ll - vk3_minus_ll * B2_ll) + + 0.5 * (vk2_minus_rr * B3_rr - vk3_minus_rr * B2_rr))) + + # Compute Powell term + f2 += charge_ratio_ll[k] * B1_ll * B2_avg + f3 += charge_ratio_ll[k] * B2_ll * B2_avg + f4 += charge_ratio_ll[k] * B3_ll * B2_avg + f5 += (v1_plus_ll * B1_ll + v2_plus_ll * B2_ll + v3_plus_ll * B3_ll) * + B2_avg + + # Append to the flux vector + set_component!(f, k, 0, f2, f3, f4, f5, equations) + end end - end - return SVector(2 * f) + return SVector(2 * f) end """ @@ -885,367 +962,401 @@ This flux (together with the MHD non-conservative term) is consistent in the cas divergence diminishing ideal magnetohydrodynamics equations for multi-ion [DOI: 10.1016/j.jcp.2018.03.002](https://doi.org/10.1016/j.jcp.2018.03.002) """ -function flux_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - @unpack gammas = equations - # Unpack left and right states to get the magnetic field - B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) - B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) - - v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, equations) - v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, equations) - - f = zero(MVector{nvariables(equations), eltype(u_ll)}) - - # Compute averages for global variables - v1_plus_avg = 0.5 * (v1_plus_ll + v1_plus_rr) - v2_plus_avg = 0.5 * (v2_plus_ll + v2_plus_rr) - v3_plus_avg = 0.5 * (v3_plus_ll + v3_plus_rr) - B1_avg = 0.5 * (B1_ll + B1_rr) - B2_avg = 0.5 * (B2_ll + B2_rr) - B3_avg = 0.5 * (B3_ll + B3_rr) - mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 - mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 - mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) - - if orientation == 1 - # Magnetic field components from f^MHD - f6 = 0 - f7 = v1_plus_avg * B2_avg - v2_plus_avg * B1_avg - f8 = v1_plus_avg * B3_avg - v3_plus_avg * B1_avg - - # Start building the flux - f[1] = f6 - f[2] = f7 - f[3] = f8 - - # Iterate over all components - for k in eachcomponent(equations) - # Unpack left and right states - rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, equations) - rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, equations) - - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v1_rr = rho_v1_rr / rho_rr - v2_rr = rho_v2_rr / rho_rr - v3_rr = rho_v3_rr / rho_rr - vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 - vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 - - p_ll = (gammas[k] - 1)*(rho_e_ll - 0.5 * rho_ll * vel_norm_ll - 0.5 * mag_norm_ll) - p_rr = (gammas[k] - 1)*(rho_e_rr - 0.5 * rho_rr * vel_norm_rr - 0.5 * mag_norm_rr) - beta_ll = 0.5 * rho_ll / p_ll - beta_rr = 0.5 * rho_rr / p_rr - # for convenience store vk_plus⋅B - vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + vk3_plus_ll[k] * B3_ll - vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + vk3_plus_rr[k] * B3_rr - - # Compute the necessary mean values needed for either direction - 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) - p_mean = 0.5 * rho_avg / beta_avg - v1_avg = 0.5 * (v1_ll + v1_rr) - v2_avg = 0.5 * (v2_ll + v2_rr) - v3_avg = 0.5 * (v3_ll + v3_rr) - vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) - vel_dot_mag_avg = 0.5*(vel_dot_mag_ll + vel_dot_mag_rr) - vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) - vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) - vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) - # v_minus - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - - # Ignore orientation since it is always "1" in 1D - f1 = rho_mean*v1_avg - f2 = f1 * v1_avg + p_mean - f3 = f1 * v2_avg - f4 = f1 * v3_avg - - # total energy flux is complicated and involves the previous eight components - v1_plus_mag_avg = 0.5*(vk1_plus_ll[k] * mag_norm_ll + vk1_plus_rr[k] * mag_norm_rr) - # Euler part - f5 = f1 * 0.5 * ( 1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg - # MHD part - f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v1_plus_mag_avg + B1_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) - + 0.5 * vk1_plus_avg * mag_norm_avg - vk1_plus_avg * B1_avg * B1_avg - vk2_plus_avg * B1_avg * B2_avg - vk3_plus_avg * B1_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) - - B2_avg * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) - B3_avg * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg) ) # Terms coming from the non-conservative term 3 (induction equation!) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) - end - else #if orientation == 2 - # Magnetic field components from f^MHD - f6 = v2_plus_avg * B1_avg - v1_plus_avg * B2_avg - f7 = 0 - f8 = v2_plus_avg * B3_avg - v3_plus_avg * B2_avg - - # Start building the flux - f[1] = f6 - f[2] = f7 - f[3] = f8 - - # Iterate over all components - for k in eachcomponent(equations) - # Unpack left and right states - rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, equations) - rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, equations) - - v1_ll = rho_v1_ll / rho_ll - v2_ll = rho_v2_ll / rho_ll - v3_ll = rho_v3_ll / rho_ll - v1_rr = rho_v1_rr / rho_rr - v2_rr = rho_v2_rr / rho_rr - v3_rr = rho_v3_rr / rho_rr - vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 - vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 - - p_ll = (gammas[k] - 1)*(rho_e_ll - 0.5 * rho_ll * vel_norm_ll - 0.5 * mag_norm_ll) - p_rr = (gammas[k] - 1)*(rho_e_rr - 0.5 * rho_rr * vel_norm_rr - 0.5 * mag_norm_rr) - beta_ll = 0.5 * rho_ll / p_ll - beta_rr = 0.5 * rho_rr / p_rr - # for convenience store vk_plus⋅B - vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + vk3_plus_ll[k] * B3_ll - vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + vk3_plus_rr[k] * B3_rr - - # Compute the necessary mean values needed for either direction - 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) - p_mean = 0.5 * rho_avg / beta_avg - v1_avg = 0.5 * (v1_ll + v1_rr) - v2_avg = 0.5 * (v2_ll + v2_rr) - v3_avg = 0.5 * (v3_ll + v3_rr) - vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) - vel_dot_mag_avg = 0.5 * (vel_dot_mag_ll + vel_dot_mag_rr) - vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) - vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) - vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) - # v_minus - vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] - vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] - vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] - vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] - vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] - vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] - vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) - vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) - vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) - - # Ignore orientation since it is always "1" in 1D - f1 = rho_mean*v2_avg - f2 = f1 * v1_avg - f3 = f1 * v2_avg + p_mean - f4 = f1 * v3_avg - - # total energy flux is complicated and involves the previous eight components - v2_plus_mag_avg = 0.5*(vk2_plus_ll[k] * mag_norm_ll + vk2_plus_rr[k] * mag_norm_rr) - # Euler part - f5 = f1 * 0.5 * ( 1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg - # MHD part - f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v2_plus_mag_avg + B2_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) - + 0.5 * vk2_plus_avg * mag_norm_avg - vk1_plus_avg * B2_avg * B1_avg - vk2_plus_avg * B2_avg * B2_avg - vk3_plus_avg * B2_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) - - B1_avg * (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) - B3_avg * (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg) ) # Terms coming from the non-conservative term 3 (induction equation!) - - set_component!(f, k, f1, f2, f3, f4, f5, equations) +function flux_ruedaramirez_etal(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations2D) + @unpack gammas = equations + # Unpack left and right states to get the magnetic field + B1_ll, B2_ll, B3_ll = magnetic_field(u_ll, equations) + B1_rr, B2_rr, B3_rr = magnetic_field(u_rr, equations) + + v1_plus_ll, v2_plus_ll, v3_plus_ll, vk1_plus_ll, vk2_plus_ll, vk3_plus_ll, _ = charge_averaged_velocities(u_ll, + equations) + v1_plus_rr, v2_plus_rr, v3_plus_rr, vk1_plus_rr, vk2_plus_rr, vk3_plus_rr, _ = charge_averaged_velocities(u_rr, + equations) + + f = zero(MVector{nvariables(equations), eltype(u_ll)}) + + # Compute averages for global variables + v1_plus_avg = 0.5 * (v1_plus_ll + v1_plus_rr) + v2_plus_avg = 0.5 * (v2_plus_ll + v2_plus_rr) + v3_plus_avg = 0.5 * (v3_plus_ll + v3_plus_rr) + B1_avg = 0.5 * (B1_ll + B1_rr) + B2_avg = 0.5 * (B2_ll + B2_rr) + B3_avg = 0.5 * (B3_ll + B3_rr) + mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2 + mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2 + mag_norm_avg = 0.5 * (mag_norm_ll + mag_norm_rr) + + if orientation == 1 + # Magnetic field components from f^MHD + f6 = 0 + f7 = v1_plus_avg * B2_avg - v2_plus_avg * B1_avg + f8 = v1_plus_avg * B3_avg - v3_plus_avg * B1_avg + + # Start building the flux + f[1] = f6 + f[2] = f7 + f[3] = f8 + + # Iterate over all components + for k in eachcomponent(equations) + # Unpack left and right states + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, + equations) + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, + equations) + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + v3_rr = rho_v3_rr / rho_rr + vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 + vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 + + p_ll = (gammas[k] - 1) * + (rho_e_ll - 0.5 * rho_ll * vel_norm_ll - 0.5 * mag_norm_ll) + p_rr = (gammas[k] - 1) * + (rho_e_rr - 0.5 * rho_rr * vel_norm_rr - 0.5 * mag_norm_rr) + beta_ll = 0.5 * rho_ll / p_ll + beta_rr = 0.5 * rho_rr / p_rr + # for convenience store vk_plus⋅B + vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + + vk3_plus_ll[k] * B3_ll + vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + + vk3_plus_rr[k] * B3_rr + + # Compute the necessary mean values needed for either direction + 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) + p_mean = 0.5 * rho_avg / beta_avg + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + v3_avg = 0.5 * (v3_ll + v3_rr) + vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) + vel_dot_mag_avg = 0.5 * (vel_dot_mag_ll + vel_dot_mag_rr) + vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) + vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) + vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) + # v_minus + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + # Ignore orientation since it is always "1" in 1D + f1 = rho_mean * v1_avg + f2 = f1 * v1_avg + p_mean + f3 = f1 * v2_avg + f4 = f1 * v3_avg + + # total energy flux is complicated and involves the previous eight components + v1_plus_mag_avg = 0.5 * (vk1_plus_ll[k] * mag_norm_ll + + vk1_plus_rr[k] * mag_norm_rr) + # Euler part + f5 = f1 * 0.5 * (1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg + # MHD part + f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v1_plus_mag_avg + + B1_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) + + 0.5 * vk1_plus_avg * mag_norm_avg - + vk1_plus_avg * B1_avg * B1_avg - vk2_plus_avg * B1_avg * B2_avg - + vk3_plus_avg * B1_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) + - + B2_avg * (vk1_minus_avg * B2_avg - vk2_minus_avg * B1_avg) - + B3_avg * (vk1_minus_avg * B3_avg - vk3_minus_avg * B1_avg)) # Terms coming from the non-conservative term 3 (induction equation!) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end + else #if orientation == 2 + # Magnetic field components from f^MHD + f6 = v2_plus_avg * B1_avg - v1_plus_avg * B2_avg + f7 = 0 + f8 = v2_plus_avg * B3_avg - v3_plus_avg * B2_avg + + # Start building the flux + f[1] = f6 + f[2] = f7 + f[3] = f8 + + # Iterate over all components + for k in eachcomponent(equations) + # Unpack left and right states + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll = get_component(k, u_ll, + equations) + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr = get_component(k, u_rr, + equations) + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + v3_rr = rho_v3_rr / rho_rr + vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2 + vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2 + + p_ll = (gammas[k] - 1) * + (rho_e_ll - 0.5 * rho_ll * vel_norm_ll - 0.5 * mag_norm_ll) + p_rr = (gammas[k] - 1) * + (rho_e_rr - 0.5 * rho_rr * vel_norm_rr - 0.5 * mag_norm_rr) + beta_ll = 0.5 * rho_ll / p_ll + beta_rr = 0.5 * rho_rr / p_rr + # for convenience store vk_plus⋅B + vel_dot_mag_ll = vk1_plus_ll[k] * B1_ll + vk2_plus_ll[k] * B2_ll + + vk3_plus_ll[k] * B3_ll + vel_dot_mag_rr = vk1_plus_rr[k] * B1_rr + vk2_plus_rr[k] * B2_rr + + vk3_plus_rr[k] * B3_rr + + # Compute the necessary mean values needed for either direction + 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) + p_mean = 0.5 * rho_avg / beta_avg + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + v3_avg = 0.5 * (v3_ll + v3_rr) + vel_norm_avg = 0.5 * (vel_norm_ll + vel_norm_rr) + vel_dot_mag_avg = 0.5 * (vel_dot_mag_ll + vel_dot_mag_rr) + vk1_plus_avg = 0.5 * (vk1_plus_ll[k] + vk1_plus_rr[k]) + vk2_plus_avg = 0.5 * (vk2_plus_ll[k] + vk2_plus_rr[k]) + vk3_plus_avg = 0.5 * (vk3_plus_ll[k] + vk3_plus_rr[k]) + # v_minus + vk1_minus_ll = v1_plus_ll - vk1_plus_ll[k] + vk2_minus_ll = v2_plus_ll - vk2_plus_ll[k] + vk3_minus_ll = v3_plus_ll - vk3_plus_ll[k] + vk1_minus_rr = v1_plus_rr - vk1_plus_rr[k] + vk2_minus_rr = v2_plus_rr - vk2_plus_rr[k] + vk3_minus_rr = v3_plus_rr - vk3_plus_rr[k] + vk1_minus_avg = 0.5 * (vk1_minus_ll + vk1_minus_rr) + vk2_minus_avg = 0.5 * (vk2_minus_ll + vk2_minus_rr) + vk3_minus_avg = 0.5 * (vk3_minus_ll + vk3_minus_rr) + + # Ignore orientation since it is always "1" in 1D + f1 = rho_mean * v2_avg + f2 = f1 * v1_avg + f3 = f1 * v2_avg + p_mean + f4 = f1 * v3_avg + + # total energy flux is complicated and involves the previous eight components + v2_plus_mag_avg = 0.5 * (vk2_plus_ll[k] * mag_norm_ll + + vk2_plus_rr[k] * mag_norm_rr) + # Euler part + f5 = f1 * 0.5 * (1 / (gammas[k] - 1) / beta_mean - vel_norm_avg) + + f2 * v1_avg + f3 * v2_avg + f4 * v3_avg + # MHD part + f5 += (f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5 * v2_plus_mag_avg + + B2_avg * vel_dot_mag_avg # Same terms as in Derigs (but with v_plus) + + 0.5 * vk2_plus_avg * mag_norm_avg - + vk1_plus_avg * B2_avg * B1_avg - vk2_plus_avg * B2_avg * B2_avg - + vk3_plus_avg * B2_avg * B3_avg # Additional terms coming from the MHD non-conservative term (momentum eqs) + - + B1_avg * (vk2_minus_avg * B1_avg - vk1_minus_avg * B2_avg) - + B3_avg * (vk2_minus_avg * B3_avg - vk3_minus_avg * B2_avg)) # Terms coming from the non-conservative term 3 (induction equation!) + + set_component!(f, k, f1, f2, f3, f4, f5, equations) + end end - end - return SVector(f) + return SVector(f) end """ # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation !!!ATTENTION: This routine is provisional. TODO: Update with the right max_abs_speed """ -@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - # Calculate fast magnetoacoustic wave speeds - # left - cf_ll = calc_fast_wavespeed(u_ll, orientation, equations) - # right - cf_rr = calc_fast_wavespeed(u_rr, orientation, equations) - - # Calculate velocities - v_ll = zero(eltype(u_ll)) - v_rr = zero(eltype(u_rr)) - if orientation == 1 - for k in eachcomponent(equations) - rho, rho_v1, _ = get_component(k, u_ll, equations) - v_ll = max(v_ll, abs(rho_v1 / rho)) - rho, rho_v1, _ = get_component(k, u_rr, equations) - v_rr = max(v_rr, abs(rho_v1 / rho)) - end - else #if orientation == 2 - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, _ = get_component(k, u_ll, equations) - v_ll = max(v_ll, abs(rho_v2 / rho)) - rho, rho_v1, rho_v2, _ = get_component(k, u_rr, equations) - v_rr = max(v_rr, abs(rho_v2 / rho)) +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::IdealMhdMultiIonEquations2D) + # Calculate fast magnetoacoustic wave speeds + # left + cf_ll = calc_fast_wavespeed(u_ll, orientation, equations) + # right + cf_rr = calc_fast_wavespeed(u_rr, orientation, equations) + + # Calculate velocities + v_ll = zero(eltype(u_ll)) + v_rr = zero(eltype(u_rr)) + if orientation == 1 + for k in eachcomponent(equations) + rho, rho_v1, _ = get_component(k, u_ll, equations) + v_ll = max(v_ll, abs(rho_v1 / rho)) + rho, rho_v1, _ = get_component(k, u_rr, equations) + v_rr = max(v_rr, abs(rho_v1 / rho)) + end + else #if orientation == 2 + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, _ = get_component(k, u_ll, equations) + v_ll = max(v_ll, abs(rho_v2 / rho)) + rho, rho_v1, rho_v2, _ = get_component(k, u_rr, equations) + v_rr = max(v_rr, abs(rho_v2 / rho)) + end end - end - λ_max = max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) + λ_max = max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) end - @inline function max_abs_speeds(u, equations::IdealMhdMultiIonEquations2D) - v1 = zero(real(equations)) - v2 = zero(real(equations)) - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, _ = get_component(k, u, equations) - v1 = max(v1, abs(rho_v1 / rho)) - v2 = max(v2, abs(rho_v2 / rho)) - end - - cf_x_direction = calc_fast_wavespeed(u, 1, equations) - cf_y_direction = calc_fast_wavespeed(u, 2, equations) - - return (abs(v1) + cf_x_direction, abs(v2) + cf_y_direction) -end + v1 = zero(real(equations)) + v2 = zero(real(equations)) + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, _ = get_component(k, u, equations) + v1 = max(v1, abs(rho_v1 / rho)) + v2 = max(v2, abs(rho_v2 / rho)) + end + cf_x_direction = calc_fast_wavespeed(u, 1, equations) + cf_y_direction = calc_fast_wavespeed(u, 2, equations) + + return (abs(v1) + cf_x_direction, abs(v2) + cf_y_direction) +end """ Convert conservative variables to primitive """ function cons2prim(u, equations::IdealMhdMultiIonEquations2D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(u, equations) - - prim = zero(MVector{nvariables(equations), eltype(u)}) - prim[1] = B1 - prim[2] = B2 - prim[3] = B3 - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - srho = 1 / rho - v1 = srho * rho_v1 - v2 = srho * rho_v2 - v3 = srho * rho_v3 - - p = (gammas[k] - 1) * (rho_e - 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3 - + B1 * B1 + B2 * B2 + B3 * B3)) - - set_component!(prim, k, rho, v1, v2, v3, p, equations) - end - - return SVector(prim) + @unpack gammas = equations + B1, B2, B3 = magnetic_field(u, equations) + + prim = zero(MVector{nvariables(equations), eltype(u)}) + prim[1] = B1 + prim[2] = B2 + prim[3] = B3 + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + srho = 1 / rho + v1 = srho * rho_v1 + v2 = srho * rho_v2 + v3 = srho * rho_v3 + + p = (gammas[k] - 1) * (rho_e - + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3 + + B1 * B1 + B2 * B2 + B3 * B3)) + + set_component!(prim, k, rho, v1, v2, v3, p, equations) + end + + return SVector(prim) end @inline function is_valid_state(cons, equations::IdealMhdMultiIonEquations2D) - prim = cons2prim(cons, equations) + prim = cons2prim(cons, equations) - for k in eachcomponent(equations) - rho, _, _, _, p = get_component(k, prim, equations) - if rho <= 0.0 || p <= 0.0 - return false + for k in eachcomponent(equations) + rho, _, _, _, p = get_component(k, prim, equations) + if rho <= 0.0 || p <= 0.0 + return false + end end - end - - return true + + return true end """ Convert conservative variables to entropy """ @inline function cons2entropy(u, equations::IdealMhdMultiIonEquations2D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(u, equations) - - prim = cons2prim(u, equations) - entropy = zero(MVector{nvariables(equations), eltype(u)}) - rho_p_plus = zero(real(equations)) - for k in eachcomponent(equations) - rho, v1, v2, v3, p = get_component(k, prim, equations) - s = log(p) - gammas[k] * log(rho) - rho_p = rho / p - w1 = (gammas[k] - s) / (gammas[k] - 1) - 0.5 * rho_p * (v1^2 + v2^2 + v3^2) - w2 = rho_p * v1 - w3 = rho_p * v2 - w4 = rho_p * v3 - w5 = -rho_p - rho_p_plus += rho_p - - set_component!(entropy, k, w1, w2, w3, w4, w5, equations) - end - - # Additional non-conservative variables - entropy[1] = rho_p_plus * B1 - entropy[2] = rho_p_plus * B2 - entropy[3] = rho_p_plus * B3 - - return SVector(entropy) -end + @unpack gammas = equations + B1, B2, B3 = magnetic_field(u, equations) + + prim = cons2prim(u, equations) + entropy = zero(MVector{nvariables(equations), eltype(u)}) + rho_p_plus = zero(real(equations)) + for k in eachcomponent(equations) + rho, v1, v2, v3, p = get_component(k, prim, equations) + s = log(p) - gammas[k] * log(rho) + rho_p = rho / p + w1 = (gammas[k] - s) / (gammas[k] - 1) - 0.5 * rho_p * (v1^2 + v2^2 + v3^2) + w2 = rho_p * v1 + w3 = rho_p * v2 + w4 = rho_p * v3 + w5 = -rho_p + rho_p_plus += rho_p + + set_component!(entropy, k, w1, w2, w3, w4, w5, equations) + end + + # Additional non-conservative variables + entropy[1] = rho_p_plus * B1 + entropy[2] = rho_p_plus * B2 + entropy[3] = rho_p_plus * B3 + return SVector(entropy) +end """ Convert primitive to conservative variables """ @inline function prim2cons(prim, equations::IdealMhdMultiIonEquations2D) - @unpack gammas = equations - B1, B2, B3 = magnetic_field(prim, equations) - - cons = zero(MVector{nvariables(equations), eltype(prim)}) - cons[1] = B1 - cons[2] = B2 - cons[3] = B3 - for k in eachcomponent(equations) - rho, v1, v2, v3, p = get_component(k, prim, equations) - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - - rho_e = p/(gammas[k] - 1.0) + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) + - 0.5 * (B1^2 + B2^2 + B3^2) - - set_component!(cons, k, rho, rho_v1, rho_v2, rho_v3, rho_e, equations) - end - - return SVector(cons) + @unpack gammas = equations + B1, B2, B3 = magnetic_field(prim, equations) + + cons = zero(MVector{nvariables(equations), eltype(prim)}) + cons[1] = B1 + cons[2] = B2 + cons[3] = B3 + for k in eachcomponent(equations) + rho, v1, v2, v3, p = get_component(k, prim, equations) + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + + rho_e = p / (gammas[k] - 1.0) + + 0.5 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) + + 0.5 * (B1^2 + B2^2 + B3^2) + + set_component!(cons, k, rho, rho_v1, rho_v2, rho_v3, rho_e, equations) + end + + return SVector(cons) end """ Compute the fastest wave speed for ideal MHD equations: c_f, the fast magnetoacoustic eigenvalue !!! ATTENTION: This routine is provisional.. Change once the fastest wave speed is known!! """ -@inline function calc_fast_wavespeed(cons, orientation::Integer, equations::IdealMhdMultiIonEquations2D) - B1, B2, B3 = magnetic_field(cons, equations) - - c_f = zero(real(equations)) - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, cons, equations) - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v_mag = sqrt(v1^2 + v2^2 + v3^2) - gamma = equations.gammas[k] - p = (gamma - 1)*(rho_e - 0.5*rho*v_mag^2 - 0.5*(B1^2 + B2^2 + B3^2)) - a_square = gamma * p / rho - sqrt_rho = sqrt(rho) - - b1 = B1 / sqrt_rho - b2 = B2 / sqrt_rho - b3 = B3 / sqrt_rho - b_square = b1^2 + b2^2 + b3^2 +@inline function calc_fast_wavespeed(cons, orientation::Integer, + equations::IdealMhdMultiIonEquations2D) + B1, B2, B3 = magnetic_field(cons, equations) - if orientation == 1 - c_f = max(c_f, sqrt(0.5 * (a_square + b_square) + 0.5 * sqrt((a_square + b_square)^2 - 4.0 * a_square*b1^2))) - else #if orientation == 2 - c_f = max(c_f, sqrt(0.5 * (a_square + b_square) + 0.5 * sqrt((a_square + b_square)^2 - 4.0 * a_square*b2^2))) + c_f = zero(real(equations)) + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, cons, equations) + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_mag = sqrt(v1^2 + v2^2 + v3^2) + gamma = equations.gammas[k] + p = (gamma - 1) * (rho_e - 0.5 * rho * v_mag^2 - 0.5 * (B1^2 + B2^2 + B3^2)) + a_square = gamma * p / rho + sqrt_rho = sqrt(rho) + + b1 = B1 / sqrt_rho + b2 = B2 / sqrt_rho + b3 = B3 / sqrt_rho + b_square = b1^2 + b2^2 + b3^2 + + if orientation == 1 + c_f = max(c_f, + sqrt(0.5 * (a_square + b_square) + + 0.5 * sqrt((a_square + b_square)^2 - 4.0 * a_square * b1^2))) + else #if orientation == 2 + c_f = max(c_f, + sqrt(0.5 * (a_square + b_square) + + 0.5 * sqrt((a_square + b_square)^2 - 4.0 * a_square * b2^2))) + end end - end - return c_f + return c_f end """ @@ -1254,104 +1365,105 @@ Routine to compute the Charge-averaged velocities: * vk*_plus: Contribution of each species to the charge-averaged velocity """ @inline function charge_averaged_velocities(u, equations::IdealMhdMultiIonEquations2D) - total_electron_charge = zero(real(equations)) - - vk1_plus = zero(MVector{ncomponents(equations), eltype(u)}) - vk2_plus = zero(MVector{ncomponents(equations), eltype(u)}) - vk3_plus = zero(MVector{ncomponents(equations), eltype(u)}) - - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, _ = get_component(k, u, equations::IdealMhdMultiIonEquations2D) - - total_electron_charge += rho * equations.charge_to_mass[k] - vk1_plus[k] = rho_v1 * equations.charge_to_mass[k] - vk2_plus[k] = rho_v2 * equations.charge_to_mass[k] - vk3_plus[k] = rho_v3 * equations.charge_to_mass[k] - end - vk1_plus ./= total_electron_charge - vk2_plus ./= total_electron_charge - vk3_plus ./= total_electron_charge - v1_plus = sum(vk1_plus) - v2_plus = sum(vk2_plus) - v3_plus = sum(vk3_plus) - - return v1_plus, v2_plus, v3_plus, SVector(vk1_plus), SVector(vk2_plus), SVector(vk3_plus), total_electron_charge + total_electron_charge = zero(real(equations)) + + vk1_plus = zero(MVector{ncomponents(equations), eltype(u)}) + vk2_plus = zero(MVector{ncomponents(equations), eltype(u)}) + vk3_plus = zero(MVector{ncomponents(equations), eltype(u)}) + + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, _ = get_component(k, u, + equations::IdealMhdMultiIonEquations2D) + + total_electron_charge += rho * equations.charge_to_mass[k] + vk1_plus[k] = rho_v1 * equations.charge_to_mass[k] + vk2_plus[k] = rho_v2 * equations.charge_to_mass[k] + vk3_plus[k] = rho_v3 * equations.charge_to_mass[k] + end + vk1_plus ./= total_electron_charge + vk2_plus ./= total_electron_charge + vk3_plus ./= total_electron_charge + v1_plus = sum(vk1_plus) + v2_plus = sum(vk2_plus) + v3_plus = sum(vk3_plus) + + return v1_plus, v2_plus, v3_plus, SVector(vk1_plus), SVector(vk2_plus), + SVector(vk3_plus), total_electron_charge end """ Get the flow variables of component k """ @inline function get_component(k, u, equations::IdealMhdMultiIonEquations2D) - # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. - return SVector(u[3 + (k - 1) * 5 + 1], - u[3 + (k - 1) * 5 + 2], - u[3 + (k - 1) * 5 + 3], - u[3 + (k - 1) * 5 + 4], - u[3 + (k - 1) * 5 + 5]) + # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. + return SVector(u[3 + (k - 1) * 5 + 1], + u[3 + (k - 1) * 5 + 2], + u[3 + (k - 1) * 5 + 3], + u[3 + (k - 1) * 5 + 4], + u[3 + (k - 1) * 5 + 5]) end """ Set the flow variables of component k """ -@inline function set_component!(u, k, u1, u2, u3, u4, u5, equations::IdealMhdMultiIonEquations2D) - # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. - u[3 + (k - 1) * 5 + 1] = u1 - u[3 + (k - 1) * 5 + 2] = u2 - u[3 + (k - 1) * 5 + 3] = u3 - u[3 + (k - 1) * 5 + 4] = u4 - u[3 + (k - 1) * 5 + 5] = u5 - - return u +@inline function set_component!(u, k, u1, u2, u3, u4, u5, + equations::IdealMhdMultiIonEquations2D) + # The first 3 entries of u contain the magnetic field. The following entries contain the density, momentum (3 entries), and energy of each component. + u[3 + (k - 1) * 5 + 1] = u1 + u[3 + (k - 1) * 5 + 2] = u2 + u[3 + (k - 1) * 5 + 3] = u3 + u[3 + (k - 1) * 5 + 4] = u4 + u[3 + (k - 1) * 5 + 5] = u5 + + return u end magnetic_field(u, equations::IdealMhdMultiIonEquations2D) = SVector(u[1], u[2], u[3]) @inline function density(u, equations::IdealMhdMultiIonEquations2D) - rho = zero(real(equations)) - for k in eachcomponent(equations) - rho += u[3 + (k - 1) * 5 + 1] - end - return rho + rho = zero(real(equations)) + for k in eachcomponent(equations) + rho += u[3 + (k - 1) * 5 + 1] + end + return rho end @inline function pressure(u, equations::IdealMhdMultiIonEquations2D) B1, B2, B3, _ = u p = zero(MVector{ncomponents(equations), real(equations)}) for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) v1 = rho_v1 / rho v2 = rho_v2 / rho v3 = rho_v3 / rho v_mag = sqrt(v1^2 + v2^2 + v3^2) gamma = equations.gammas[k] - p[k] = (gamma - 1)*(rho_e - 0.5*rho*v_mag^2 - 0.5*(B1^2 + B2^2 + B3^2)) - end + p[k] = (gamma - 1) * (rho_e - 0.5 * rho * v_mag^2 - 0.5 * (B1^2 + B2^2 + B3^2)) + end return SVector{ncomponents(equations), real(equations)}(p) end - """ Computes the sum of the densities times the sum of the pressures """ @inline function density_pressure(u, equations::IdealMhdMultiIonEquations2D) - B1, B2, B3 = magnetic_field(u, equations) - rho_total = zero(real(equations)) - p_total = zero(real(equations)) - for k in eachcomponent(equations) - rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) - - v1 = rho_v1 / rho - v2 = rho_v2 / rho - v3 = rho_v3 / rho - v_mag = sqrt(v1^2 + v2^2 + v3^2) - gamma = equations.gammas[k] - - p = (gamma - 1)*(rho_e - 0.5 * rho*v_mag^2 - 0.5*(B1^2 + B2^2 + B3^2)) - - rho_total += rho - p_total += p - end - return rho_total * p_total -end + B1, B2, B3 = magnetic_field(u, equations) + rho_total = zero(real(equations)) + p_total = zero(real(equations)) + for k in eachcomponent(equations) + rho, rho_v1, rho_v2, rho_v3, rho_e = get_component(k, u, equations) + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v3 = rho_v3 / rho + v_mag = sqrt(v1^2 + v2^2 + v3^2) + gamma = equations.gammas[k] + + p = (gamma - 1) * (rho_e - 0.5 * rho * v_mag^2 - 0.5 * (B1^2 + B2^2 + B3^2)) + rho_total += rho + p_total += p + end + return rho_total * p_total +end end # @muladd From 8c497394c9ff9cec968fc7415476e6252fea81a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Rueda-Ram=C3=ADrez?= Date: Thu, 9 Nov 2023 12:02:20 +0100 Subject: [PATCH 331/331] renamed nnoncons variable for multi-ion MHD 2D --- src/equations/ideal_mhd_multiion_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/equations/ideal_mhd_multiion_2d.jl b/src/equations/ideal_mhd_multiion_2d.jl index 88f41a5a392..625bcfb177f 100644 --- a/src/equations/ideal_mhd_multiion_2d.jl +++ b/src/equations/ideal_mhd_multiion_2d.jl @@ -94,7 +94,7 @@ end end have_nonconservative_terms(::IdealMhdMultiIonEquations2D) = True() -nnoncons(::IdealMhdMultiIonEquations2D) = 4 +n_nonconservative_terms(::IdealMhdMultiIonEquations2D) = 4 function varnames(::typeof(cons2cons), equations::IdealMhdMultiIonEquations2D) cons = ("B1", "B2", "B3")