diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl index d5d7338ba4..cf27cfb4d5 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach.jl @@ -71,13 +71,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for P4estMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, + normal_direction::AbstractVector, mesh::P4estMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -160,7 +159,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl index 45f7d12f60..f1266272e8 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -71,13 +71,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for P4estMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), - normal_direction::AbstractVector, direction, + normal_direction::AbstractVector, mesh::P4estMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -162,7 +161,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors = false),) +stage_callbacks = (BoundsCheckCallback(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 0000000000..a56dd46eb1 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,102 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end + +initial_condition = initial_condition_sedov_blast_wave + +# Get the DG approximation space +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_twosided_variables_cons = ["rho"], + local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, + min)], + max_iterations_newton = 40, # Default value of 10 iterations is too low to fulfill bounds. + bar_states = false) + +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +############################################################################### + +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg = polydeg, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl index 75b65fe1f2..5185e8625b 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_MCL.jl @@ -48,10 +48,10 @@ initial_condition = initial_condition_mach3_flow return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_supersonic_inflow), - normal_direction::AbstractVector, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) @@ -69,10 +69,10 @@ end return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_outflow), - orientation_or_normal, direction, - mesh::P4estMesh{2}, equations, dg, + orientation_or_normal, + mesh::P4estMesh{2}, equations, dg, cache, indices...) return u_inner end diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl index 5157480894..f136e9038e 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder_sc_subcell.jl @@ -13,7 +13,6 @@ # # Keywords: supersonic flow, shock capturing, AMR, unstructured curved mesh, positivity preservation, compressible Euler, 2D -using Downloads: download using OrdinaryDiffEq using Trixi @@ -48,10 +47,10 @@ initial_condition = initial_condition_mach3_flow return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_supersonic_inflow), - normal_direction::AbstractVector, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) @@ -69,10 +68,10 @@ end return flux end -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_outflow), - orientation_or_normal, direction, - mesh::P4estMesh{2}, equations, dg, + normal_direction::AbstractVector, + mesh::P4estMesh{2}, equations, dg, cache, indices...) return u_inner end @@ -91,28 +90,26 @@ boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, :Right => boundary_condition_outflow, :Left => boundary_condition_supersonic_inflow) +volume_flux = flux_ranocha_turbo surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons = ["rho"], + local_twosided_variables_cons = ["rho"], positivity_variables_nonlinear = [pressure], local_onesided_variables_nonlinear = [(Trixi.entropy_guermond_etal, min)], - max_iterations_newton = 100, + max_iterations_newton = 50, # Default value of 10 iterations is too low to fulfill bounds. bar_states = false) + volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Get the unstructured quad mesh from a file (downloads the file if not available locally) -default_mesh_file = joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp") -isfile(default_mesh_file) || - download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", - default_mesh_file) -mesh_file = default_mesh_file +mesh_file = Trixi.download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp")) mesh = P4estMesh{2}(mesh_file, initial_refinement_level = 0) @@ -134,21 +131,21 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval = 100, +save_solution = SaveSolutionCallback(interval = 1000, save_initial_solution = true, save_final_solution = true, solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl = 0.4) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - stepsize_callback, - save_solution) + save_solution, + stepsize_callback) -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep = false, callback = callbacks); + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl index 46b2d6930e..33be05c615 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach.jl @@ -76,13 +76,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for StructuredMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -162,7 +161,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl index 2b0acbd0c5..68290ac31f 100644 --- a/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl +++ b/examples/structured_2d_dgsem/elixir_euler_double_mach_MCL.jl @@ -76,13 +76,12 @@ boundary_condition_inflow_outflow = BoundaryConditionCharacteristic(initial_cond return flux end -# Note: Only for StructuredMesh -@inline function Trixi.get_boundary_outer_state(u_inner, cache, t, +@inline function Trixi.get_boundary_outer_state(u_inner, t, boundary_condition::typeof(boundary_condition_mixed_characteristic_wall), normal_direction::AbstractVector, direction, mesh::StructuredMesh{2}, equations::CompressibleEulerEquations2D, - dg, indices...) + dg, cache, indices...) x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, indices...) if x[1] < 1 / 6 # BoundaryConditionCharacteristic u_outer = Trixi.characteristic_boundary_value_function(initial_condition_double_mach_reflection, @@ -164,7 +163,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -stage_callbacks = (BoundsCheckCallback(save_errors = false),) +stage_callbacks = (BoundsCheckCallback(),) sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 0b7f7ee49a..c2dae0682c 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -403,6 +403,76 @@ Should be used together with [`StructuredMesh`](@ref). return boundary_flux end +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains requires the boundary +outer state. This function returns the boundary value for [`boundary_condition_slip_wall`](@ref) at +time `t` and for node with spatial indices `indices` and at the boundary with `normal_direction`. + +Should be used together with [`P4estMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) + u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction + + return SVector(u_inner[1], + u_inner[2] - 2.0 * u_normal[1], + u_inner[3] - 2.0 * u_normal[2], + u_inner[4]) +end + +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + +Should be used together with [`StructuredMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + normal_direction::AbstractVector, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + get_boundary_outer_state(u_inner, t, boundary_condition, normal_direction, + mesh, equations, dg, cache, indices...) +end + +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + orientation::Integer, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + +Should be used together with [`TreeMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, + boundary_condition::typeof(boundary_condition_slip_wall), + orientation::Integer, direction, + mesh, equations::CompressibleEulerEquations2D, + dg, cache, indices...) + return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) +end + # TODO: Add docstring when about to merge. # Using with TreeMesh{2} @inline function characteristic_boundary_value_function(outer_boundary_value_function, diff --git a/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl index f8a5ea24ec..1f3eea73d3 100644 --- a/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_p4est/dg_2d_subcell_limiters.jl @@ -166,9 +166,9 @@ end i_node, j_node, element) u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, normal_direction, - direction, mesh, equations, dg, + mesh, equations, dg, cache, i_node, j_node, element) lambda = max_abs_speed_naive(u_inner, u_outer, normal_direction, diff --git a/src/solvers/dgsem_p4est/subcell_limiters_2d.jl b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl index d014a7b038..7283cb6695 100644 --- a/src/solvers/dgsem_p4est/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_p4est/subcell_limiters_2d.jl @@ -13,6 +13,7 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, (; neighbor_ids, node_indices) = cache.interfaces index_range = eachnode(dg) + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get element and side index information on the primary element primary_element = neighbor_ids[1, interface] @@ -67,22 +68,25 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, end end - calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) + # Calc bounds at physical boundaries + calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) return nothing end -@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions::BoundaryConditionPeriodic, - mesh, equations, dg, cache) +@inline function calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions::BoundaryConditionPeriodic, + mesh::P4estMesh{2}, + equations, dg, cache) return nothing end -@inline function calc_bounds_twosided_interface_inner!(var_min, var_max, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) +@inline function calc_bounds_twosided_boundary!(var_min, var_max, variable, u, t, + boundary_conditions, + mesh::P4estMesh{2}, + equations, dg, cache) (; boundary_condition_types, boundary_indices) = boundary_conditions (; contravariant_vectors) = cache.elements @@ -109,9 +113,9 @@ end u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_condition, normal_direction, - direction, mesh, equations, dg, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, + normal_direction, + mesh, equations, dg, cache, i_node, j_node, element) var_outer = u_outer[variable] @@ -138,6 +142,7 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem index_range = eachnode(dg) index_end = last(index_range) + # Calc bounds at interfaces and periodic boundaries for interface in eachinterface(dg, cache) # Get element and side index information on the primary element primary_element = neighbor_ids[1, interface] @@ -186,23 +191,25 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem end end - calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, t, - boundary_conditions, - mesh, equations, dg, cache) + # Calc bounds at physical boundaries + calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions, + mesh, equations, dg, cache) return nothing end -@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, - t, - boundary_conditions::BoundaryConditionPeriodic, - mesh, equations, dg, cache) +@inline function calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions::BoundaryConditionPeriodic, + mesh::P4estMesh{2}, + equations, dg, cache) return nothing end -@inline function calc_bounds_onesided_interface_inner!(var_minmax, minmax, variable, u, - t, boundary_conditions, - mesh, equations, dg, cache) +@inline function calc_bounds_onesided_boundary!(var_minmax, minmax, variable, u, t, + boundary_conditions, + mesh::P4estMesh{2}, + equations, dg, cache) (; boundary_condition_types, boundary_indices) = boundary_conditions (; contravariant_vectors) = cache.elements @@ -229,9 +236,9 @@ end u_inner = get_node_vars(u, equations, dg, i_node, j_node, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, - boundary_condition, normal_direction, - direction, mesh, equations, dg, + u_outer = get_boundary_outer_state(u_inner, t, boundary_condition, + normal_direction, + mesh, equations, dg, cache, i_node, j_node, element) var_outer = variable(u_outer, equations) diff --git a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl index 3a1a560214..f8428197f4 100644 --- a/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_structured/dg_2d_subcell_limiters.jl @@ -244,9 +244,9 @@ end for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, equations) @@ -270,9 +270,9 @@ end Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, Ja1, @@ -301,9 +301,9 @@ end for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, equations) @@ -327,9 +327,9 @@ end Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, Ja2, diff --git a/src/solvers/dgsem_structured/subcell_limiters_2d.jl b/src/solvers/dgsem_structured/subcell_limiters_2d.jl index 83a979a16a..f1f3ee1bed 100644 --- a/src/solvers/dgsem_structured/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_structured/subcell_limiters_2d.jl @@ -59,9 +59,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) var_outer = u_outer[variable] @@ -76,9 +76,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) var_outer = u_outer[variable] @@ -96,9 +96,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) var_outer = u_outer[variable] @@ -113,9 +113,9 @@ function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) var_outer = u_outer[variable] @@ -180,9 +180,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem for j in eachnode(dg) Ja1 = get_contravariant_vector(1, contravariant_vectors, 1, j, element) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], Ja1, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) var_outer = variable(u_outer, equations) @@ -196,9 +196,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem Ja1 = get_contravariant_vector(1, contravariant_vectors, nnodes(dg), j, element) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], Ja1, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) var_outer = variable(u_outer, equations) @@ -215,9 +215,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem for i in eachnode(dg) Ja2 = get_contravariant_vector(2, contravariant_vectors, i, 1, element) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], Ja2, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) var_outer = variable(u_outer, equations) @@ -231,9 +231,9 @@ function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, sem Ja2 = get_contravariant_vector(2, contravariant_vectors, i, nnodes(dg), element) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], Ja2, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) var_outer = variable(u_outer, equations) diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 2e471f2254..f964bcd186 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -766,10 +766,10 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, 1, j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[1], orientation, 1, - mesh, equations, dg, + mesh, equations, dg, cache, 1, j, element) lambda1[1, j, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -787,10 +787,10 @@ end else # Element is on the left, boundary on the right for j in eachnode(dg) u_inner = get_node_vars(u, equations, dg, nnodes(dg), j, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[2], orientation, 2, - mesh, equations, dg, + mesh, equations, dg, cache, nnodes(dg), j, element) lambda1[nnodes(dg) + 1, j, element] = max_abs_speed_naive(u_inner, u_outer, @@ -813,10 +813,10 @@ end if neighbor_side == 2 # Element is on the right, boundary on the left for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, 1, element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[3], orientation, 3, - mesh, equations, dg, + mesh, equations, dg, cache, i, 1, element) lambda2[i, 1, element] = max_abs_speed_naive(u_inner, u_outer, orientation, equations) @@ -834,10 +834,10 @@ end else # Element is on the left, boundary on the right for i in eachnode(dg) u_inner = get_node_vars(u, equations, dg, i, nnodes(dg), element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[4], orientation, 4, - mesh, equations, dg, + mesh, equations, dg, cache, i, nnodes(dg), element) lambda2[i, nnodes(dg) + 1, element] = max_abs_speed_naive(u_inner, u_outer, @@ -1814,32 +1814,25 @@ end return nothing end -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_slip_wall), - orientation::Integer, direction, - mesh, equations::CompressibleEulerEquations2D, - dg, indices...) - return SVector(u_inner[1], -u_inner[2], -u_inner[3], u_inner[4]) -end - -@inline function get_boundary_outer_state(u_inner, cache, t, - boundary_condition::typeof(boundary_condition_slip_wall), - normal_direction::AbstractVector, direction, - mesh, equations::CompressibleEulerEquations2D, - dg, indices...) - factor = (normal_direction[1] * u_inner[2] + normal_direction[2] * u_inner[3]) - u_normal = (factor / sum(normal_direction .^ 2)) * normal_direction - - return SVector(u_inner[1], - u_inner[2] - 2.0 * u_normal[1], - u_inner[3] - 2.0 * u_normal[2], - u_inner[4]) -end - -@inline function get_boundary_outer_state(u_inner, cache, t, +""" + get_boundary_outer_state(u_inner, t, + boundary_condition::BoundaryConditionDirichlet, + orientation_or_normal, direction, + mesh, equations, dg, cache, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains requires the boundary +outer state. This function returns the boundary value for [`BoundaryConditionDirichlet`](@ref) at +time `t` and for node with spatial indices `indices` at the boundary with `orientation_or_normal` +and `direction`. + +Should be used together with [`TreeMesh`](@ref) or [`StructuredMesh`](@ref). + +!!! warning "Experimental implementation" + This is an experimental feature and may change in future releases. +""" +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionDirichlet, - orientation_or_normal, direction, mesh, - equations, dg, indices...) + orientation_or_normal, direction, + mesh, equations, dg, cache, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1848,12 +1841,12 @@ end return u_outer end -@inline function get_boundary_outer_state(u_inner, cache, t, +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionCharacteristic, orientation_or_normal, direction, mesh::Union{TreeMesh, StructuredMesh}, equations, - dg, indices...) + dg, cache, indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) @@ -1864,10 +1857,11 @@ end return u_outer end -@inline function get_boundary_outer_state(u_inner, cache, t, +@inline function get_boundary_outer_state(u_inner, t, boundary_condition::BoundaryConditionCharacteristic, - normal_direction::AbstractVector, direction, - mesh::P4estMesh, equations, dg, indices...) + normal_direction::AbstractVector, + mesh::P4estMesh, equations, dg, cache, + indices...) (; node_coordinates) = cache.elements x = get_node_coords(node_coordinates, equations, dg, indices...) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index f3908fbb49..f7d2b6d3ef 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -237,8 +237,14 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) ] end if positivity - string = "Positivity limiting for conservative variables $(limiter.positivity_variables_cons) and $(limiter.positivity_variables_nonlinear)" - setup = [setup..., "" => string] + if !isempty(limiter.positivity_variables_cons) + string = "conservative variables $(limiter.positivity_variables_cons)" + setup = [setup..., "" => "Positivity limiting for " * string] + end + if !isempty(limiter.positivity_variables_nonlinear) + string = "$(limiter.positivity_variables_nonlinear)" + setup = [setup..., "" => "Positivity limiting for " * string] + end setup = [ setup..., "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index c948d67314..4cba931e0f 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -179,10 +179,10 @@ end boundary_index += 2 end u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[boundary_index], orientation, boundary_index, - mesh, equations, dg, + mesh, equations, dg, cache, index..., element) var_outer = u_outer[variable] @@ -284,10 +284,10 @@ end boundary_index += 2 end u_inner = get_node_vars(u, equations, dg, index..., element) - u_outer = get_boundary_outer_state(u_inner, cache, t, + u_outer = get_boundary_outer_state(u_inner, t, boundary_conditions[boundary_index], orientation, boundary_index, - mesh, equations, dg, + mesh, equations, dg, cache, index..., element) var_outer = variable(u_outer, equations) diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index 63b53b5566..ede137769f 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -298,6 +298,32 @@ end end end +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2=[ + 0.45737877846538905, + 0.2852097276261684, + 0.28527281809798694, + 1.2881460122856072, + ], + linf=[ + 1.6444110425837906, + 1.6743368122678752, + 1.6760847980983236, + 6.268843623083507, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end + @trixi_testset "elixir_euler_sedov.jl with HLLC Flux" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[ @@ -542,28 +568,25 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder_sc_subcell.jl"), l2=[ - 0.015519026585326362, - 0.03624624063147592, - 0.015856390554735263, - 0.11035405581567337, + 0.11085870166618325, + 0.23309905989870722, + 0.13505351590735631, + 0.7932047512585592, ], linf=[ - 1.034507228088565, - 2.7694272511829157, - 1.760899156958975, - 7.7689019494557865, + 2.9808773737943564, + 4.209364526217892, + 6.265341002817672, + 24.077904874883338, ], - tspan=(0.0, 0.001), - skip_coverage=true) - if @isdefined sol # Skipped in coverage run - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 - end + tspan=(0.0, 0.02)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end @@ -582,17 +605,14 @@ end 2.271954486109792, 9.900660307619413, ], - tspan=(0.0, 0.001), - skip_coverage=true) - if @isdefined sol # Skipped in coverage run - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 - end + tspan=(0.0, 0.001)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 end end