From 5767ceabceb1af86e2f07ad5acba1258239ead67 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:09:14 +0100 Subject: [PATCH 01/22] Start to align both entropy limiters --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 3d831e4fa39..6aa550dfa70 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -365,8 +365,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, - entropy_spec, initial_check_entropy_spec_newton_idp, - final_check_standard_newton_idp, inverse_jacobian, + entropy_spec, initial_check_local_onesided_newton_idp, + final_check_local_onesided_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) end end @@ -389,8 +389,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, - entropy_math, initial_check_entropy_math_newton_idp, - final_check_standard_newton_idp, inverse_jacobian, + entropy_math, initial_check_local_onesided_newton_idp, + final_check_local_onesided_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) end end @@ -573,7 +573,7 @@ end if isvalid(u_curr, equations) goal = goal_function_newton_idp(variable, bound, u_curr, equations) - initial_check(bound, goal, newton_abstol) && return nothing + initial_check(variable, bound, goal, newton_abstol) && return nothing end # Newton iterations @@ -608,7 +608,7 @@ end # Check new beta for condition and update bounds goal = goal_function_newton_idp(variable, bound, u_curr, equations) - if initial_check(bound, goal, newton_abstol) + if initial_check(variable, bound, goal, newton_abstol) # New beta fulfills condition beta_L = beta else @@ -652,11 +652,11 @@ end ### Auxiliary routines for Newton's bisection method ### # Initial checks -@inline function initial_check_entropy_spec_newton_idp(bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_spec), bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function initial_check_entropy_math_newton_idp(bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_math), bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end @@ -672,7 +672,7 @@ end # Final checks # final check for entropy limiting -@inline function final_check_standard_newton_idp(bound, goal, newton_abstol) +@inline function final_check_local_onesided_newton_idp(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end From 9e0a2e7ebe5f535d668ff68563e0a5aa2f1cc063 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:18:30 +0100 Subject: [PATCH 02/22] Adapt calc_bounds_onesided! --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 6aa550dfa70..9f6e7d72ce3 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -179,13 +179,17 @@ end return nothing end -@inline function calc_bounds_onesided!(var_minmax, minmax, typeminmax, variable, u, t, - semi) +@inline function calc_bounds_onesided!(var_minmax, minmax, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) + # Reset bounds for j in eachnode(dg), i in eachnode(dg) - var_minmax[i, j, element] = typeminmax(eltype(var_minmax)) + if minmax === max + var_minmax[i, j, element] = typemin(eltype(var_minmax)) + else + var_minmax[i, j, element] = typemax(eltype(var_minmax)) + end end # Calculate bounds at Gauss-Lobatto nodes using u @@ -357,7 +361,7 @@ end _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_min = variable_bounds[:spec_entropy_min] - calc_bounds_onesided!(s_min, min, typemax, entropy_spec, u, t, semi) + calc_bounds_onesided!(s_min, min, entropy_spec, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -381,7 +385,7 @@ end _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients s_max = variable_bounds[:math_entropy_max] - calc_bounds_onesided!(s_max, max, typemin, entropy_math, u, t, semi) + calc_bounds_onesided!(s_max, max, entropy_math, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) From 3b22e0c752fce7908054dfbd88725b24c07ff1a5 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:20:31 +0100 Subject: [PATCH 03/22] Add wrapper function for entropy limiting --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9f6e7d72ce3..7a5b2d0f39c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -52,12 +52,10 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) end if limiter.spec_entropy - @trixi_timeit timer() "spec_entropy" idp_spec_entropy!(alpha, limiter, u, t, dt, - semi) + @trixi_timeit timer() "spec_entropy" idp_local_onesided!(alpha, limiter, u, t, dt, semi, entropy_spec) end if limiter.math_entropy - @trixi_timeit timer() "math_entropy" idp_math_entropy!(alpha, limiter, u, t, dt, - semi) + @trixi_timeit timer() "math_entropy" idp_local_onesided!(alpha, limiter, u, t, dt, semi, entropy_math) end # Calculate alpha1 and alpha2 @@ -357,6 +355,16 @@ end ############################################################################## # Local minimum limiting of specific entropy +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable) + if variable === entropy_spec + idp_spec_entropy!(alpha, limiter, u, t, dt, semi) + else + idp_math_entropy!(alpha, limiter, u, t, dt, semi) + end + + return nothing +end + @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients From f32c8eafc7e3cb00737b26b9d2fafbd12eea70cd Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:24:42 +0100 Subject: [PATCH 04/22] Rename keys in Dict --- src/callbacks_stage/subcell_bounds_check.jl | 4 ++-- src/callbacks_stage/subcell_bounds_check_2d.jl | 8 ++++---- src/solvers/dgsem_tree/subcell_limiters.jl | 4 ++-- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index e3b8afb9391..5c61bd8ebcc 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -145,11 +145,11 @@ end end if spec_entropy println("spec. entropy:\n- lower bound: ", - idp_bounds_delta_global[:spec_entropy_min]) + idp_bounds_delta_global[Symbol("entropy_spec", "_", "min")]) end if math_entropy println("math. entropy:\n- upper bound: ", - idp_bounds_delta_global[:math_entropy_max]) + idp_bounds_delta_global[Symbol("entropy_math", "_", "max")]) end if positivity for v in limiter.positivity_variables_cons diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 61920565dde..a2154eafa86 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -44,7 +44,7 @@ end end if spec_entropy - key = :spec_entropy_min + key = Symbol("entropy_spec", "_", "min") deviation_threaded = idp_bounds_delta_local[key] @threaded for element in eachelement(solver, cache) deviation = deviation_threaded[stride_size * Threads.threadid()] @@ -57,7 +57,7 @@ end end if math_entropy - key = :math_entropy_max + key = Symbol("entropy_math", "_", "max") deviation_threaded = idp_bounds_delta_local[key] @threaded for element in eachelement(solver, cache) deviation = deviation_threaded[stride_size * Threads.threadid()] @@ -125,10 +125,10 @@ end end if spec_entropy - print(f, ", ", idp_bounds_delta_local[:spec_entropy_min][stride_size]) + print(f, ", ", idp_bounds_delta_local[Symbol("entropy_spec", "_", "min")][stride_size]) end if math_entropy - print(f, ", ", idp_bounds_delta_local[:math_entropy_max][stride_size]) + print(f, ", ", idp_bounds_delta_local[Symbol("entropy_math", "_", "max")][stride_size]) end if positivity for v in limiter.positivity_variables_cons diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index bd865b8e1e4..af5056a3bb3 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -106,10 +106,10 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end end if spec_entropy - bound_keys = (bound_keys..., :spec_entropy_min) + bound_keys = (bound_keys..., Symbol("entropy_spec", "_", "min")) end if math_entropy - bound_keys = (bound_keys..., :math_entropy_max) + bound_keys = (bound_keys..., Symbol("entropy_math", "_", "max")) end for v in positivity_variables_cons_ if !(v in local_minmax_variables_cons_) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 7a5b2d0f39c..fac64bf0e07 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -368,7 +368,7 @@ end @inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_min = variable_bounds[:spec_entropy_min] + s_min = variable_bounds[Symbol("entropy_spec", "_", "min")] calc_bounds_onesided!(s_min, min, entropy_spec, u, t, semi) # Perform Newton's bisection method to find new alpha @@ -392,7 +392,7 @@ end @inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_max = variable_bounds[:math_entropy_max] + s_max = variable_bounds[Symbol("entropy_math", "_", "max")] calc_bounds_onesided!(s_max, max, entropy_math, u, t, semi) # Perform Newton's bisection method to find new alpha From ea8d7fce8e40eb3b7e796ef33b12d560af5ee43e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:32:56 +0100 Subject: [PATCH 05/22] use variable and bound_function as parameter --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index fac64bf0e07..6f52f06907e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -357,19 +357,19 @@ end @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable) if variable === entropy_spec - idp_spec_entropy!(alpha, limiter, u, t, dt, semi) + idp_spec_entropy!(alpha, limiter, u, t, dt, semi, variable, min) else - idp_math_entropy!(alpha, limiter, u, t, dt, semi) + idp_math_entropy!(alpha, limiter, u, t, dt, semi, variable, max) end return nothing end -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi) +@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, variable, bound_function) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_min = variable_bounds[Symbol("entropy_spec", "_", "min")] - calc_bounds_onesided!(s_min, min, entropy_spec, u, t, semi) + s_min = variable_bounds[Symbol(string(variable), "_", string(bound_function))] + calc_bounds_onesided!(s_min, bound_function, variable, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) @@ -389,11 +389,11 @@ end ############################################################################### # Local maximum limiting of mathematical entropy -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi) +@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, variable, bound_function) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_max = variable_bounds[Symbol("entropy_math", "_", "max")] - calc_bounds_onesided!(s_max, max, entropy_math, u, t, semi) + s_max = variable_bounds[Symbol(string(variable), "_", string(bound_function))] + calc_bounds_onesided!(s_max, bound_function, variable, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) From e45d29e204e585230865c9b238c49cbd11e4887d Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 2 Feb 2024 13:42:47 +0100 Subject: [PATCH 06/22] Use same function for both entropies --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 38 ++++--------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 6f52f06907e..d510f884fa2 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -357,51 +357,27 @@ end @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable) if variable === entropy_spec - idp_spec_entropy!(alpha, limiter, u, t, dt, semi, variable, min) + idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, min) else - idp_math_entropy!(alpha, limiter, u, t, dt, semi, variable, max) + idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, max) end return nothing end -@inline function idp_spec_entropy!(alpha, limiter, u, t, dt, semi, variable, bound_function) +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, bound_function) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_min = variable_bounds[Symbol(string(variable), "_", string(bound_function))] - calc_bounds_onesided!(s_min, bound_function, variable, u, t, semi) + var_minmax = variable_bounds[Symbol(string(variable), "_", string(bound_function))] + calc_bounds_onesided!(var_minmax, bound_function, variable, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_min[i, j, element], u_local, i, j, element, - entropy_spec, initial_check_local_onesided_newton_idp, - final_check_local_onesided_newton_idp, inverse_jacobian, - dt, equations, dg, cache, limiter) - end - end - - return nothing -end - -############################################################################### -# Local maximum limiting of mathematical entropy - -@inline function idp_math_entropy!(alpha, limiter, u, t, dt, semi, variable, bound_function) - _, equations, dg, cache = mesh_equations_solver_cache(semi) - (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - s_max = variable_bounds[Symbol(string(variable), "_", string(bound_function))] - calc_bounds_onesided!(s_max, bound_function, variable, u, t, semi) - - # Perform Newton's bisection method to find new alpha - @threaded for element in eachelement(dg, cache) - inverse_jacobian = cache.elements.inverse_jacobian[element] - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, s_max[i, j, element], u_local, i, j, element, - entropy_math, initial_check_local_onesided_newton_idp, + newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, i, j, element, + variable, initial_check_local_onesided_newton_idp, final_check_local_onesided_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) end From a475855f8c496d231565ead012da224aad6b5948 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:08:09 +0100 Subject: [PATCH 07/22] First working version of general onesided limiting --- ...euler_blast_wave_sc_subcell_nonperiodic.jl | 3 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 3 +- src/callbacks_stage/subcell_bounds_check.jl | 29 ++++---- .../subcell_bounds_check_2d.jl | 48 ++++++------- src/solvers/dgsem_tree/subcell_limiters.jl | 70 +++++++++++-------- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 42 +++++------ 6 files changed, 97 insertions(+), 98 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index 6ff381b896c..4d135b8fd05 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -42,7 +42,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; local_minmax_variables_cons = ["rho"], - math_entropy = true) + local_onesided_variables_nonlinear = [(Trixi.entropy_math, + max)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index 64cae963158..cc34e3f1e11 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,8 @@ volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; local_minmax_variables_cons = ["rho"], - spec_entropy = true) + local_onesided_variables_nonlinear = [(Trixi.entropy_spec, + min)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 5c61bd8ebcc..33a454862d7 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -77,7 +77,7 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_minmax, positivity, local_onesided) = limiter (; output_directory) = callback variables = varnames(cons2cons, semi.equations) @@ -90,11 +90,10 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi print(f, ", " * variable_string * "_min, " * variable_string * "_max") end end - if spec_entropy - print(f, ", specEntr_min") - end - if math_entropy - print(f, ", mathEntr_max") + if local_onesided + for (variable, operator) in limiter.local_onesided_variables_nonlinear + print(f, ", " * string(variable) * "_" * string(operator)) + end end if positivity for v in limiter.positivity_variables_cons @@ -126,7 +125,7 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_minmax, positivity, local_onesided) = limiter (; idp_bounds_delta_global) = limiter.cache variables = varnames(cons2cons, semi.equations) @@ -143,13 +142,15 @@ end idp_bounds_delta_global[Symbol(v_string, "_max")]) end end - if spec_entropy - println("spec. entropy:\n- lower bound: ", - idp_bounds_delta_global[Symbol("entropy_spec", "_", "min")]) - end - if math_entropy - println("math. entropy:\n- upper bound: ", - idp_bounds_delta_global[Symbol("entropy_math", "_", "max")]) + if local_onesided + for (variable, operator) in limiter.local_onesided_variables_nonlinear + variable_string = string(variable) + operator_string = string(operator) + println("$(variable_string):") + println("- $operator_string bound: ", + idp_bounds_delta_global[Symbol(variable_string, "_", + operator_string)]) + end end if positivity for v in limiter.positivity_variables_cons diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index a2154eafa86..e61c864c1ca 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -8,7 +8,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors) - (; local_minmax, positivity, spec_entropy, math_entropy) = solver.volume_integral.limiter + (; local_minmax, positivity, local_onesided) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta_local, idp_bounds_delta_global) = limiter.cache @@ -43,30 +43,21 @@ end end end - if spec_entropy - key = Symbol("entropy_spec", "_", "min") - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] - for j in eachnode(solver), i in eachnode(solver) - s = entropy_spec(get_node_vars(u, equations, solver, i, j, element), - equations) - deviation = max(deviation, variable_bounds[key][i, j, element] - s) - end - deviation_threaded[stride_size * Threads.threadid()] = deviation - end - end - if math_entropy - key = Symbol("entropy_math", "_", "max") - deviation_threaded = idp_bounds_delta_local[key] - @threaded for element in eachelement(solver, cache) - deviation = deviation_threaded[stride_size * Threads.threadid()] - for j in eachnode(solver), i in eachnode(solver) - s = entropy_math(get_node_vars(u, equations, solver, i, j, element), + if local_onesided + foreach(limiter.local_onesided_variables_nonlinear) do (variable, operator) + key = Symbol(string(variable), "_", string(operator)) + factor = operator === max ? 1.0 : -1.0 + deviation_threaded = idp_bounds_delta_local[key] + @threaded for element in eachelement(solver, cache) + deviation = deviation_threaded[stride_size * Threads.threadid()] + for j in eachnode(solver), i in eachnode(solver) + v = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation = max(deviation, s - variable_bounds[key][i, j, element]) + deviation = max(deviation, + factor * (v - variable_bounds[key][i, j, element])) + end + deviation_threaded[stride_size * Threads.threadid()] = deviation end - deviation_threaded[stride_size * Threads.threadid()] = deviation end end if positivity @@ -124,11 +115,12 @@ idp_bounds_delta_local[Symbol(v_string, "_max")][stride_size]) end end - if spec_entropy - print(f, ", ", idp_bounds_delta_local[Symbol("entropy_spec", "_", "min")][stride_size]) - end - if math_entropy - print(f, ", ", idp_bounds_delta_local[Symbol("entropy_math", "_", "max")][stride_size]) + if local_onesided + for (variable, operator) in limiter.local_onesided_variables_nonlinear + print(f, ", ", + idp_bounds_delta_local[Symbol(string(variable), "_", + string(operator))][stride_size]) + end end if positivity for v in limiter.positivity_variables_cons diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index af5056a3bb3..11dcd049c9e 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -18,8 +18,7 @@ end positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, + local_onesided_variables_nonlinear = NTuple{2, Function}[], max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) @@ -29,11 +28,13 @@ including: - Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) -- One-sided limiting for specific and mathematical entropy (`spec_entropy`, `math_entropy`) +- One-sided limiting for nonlinear variables (e.g., `entropy_spec`, `entropy_math`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are -passed in a vector, e.g. `positivity_variables_nonlinear = [pressure]`. +passed - to ensure posivity use a plain vector, e.g. `positivity_variables_nonlinear = [pressure]`, +for a one-sided limiting pass the variable and the specific bound as a tuple within a vector, e.g. +`local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. @@ -58,7 +59,8 @@ where `d = #dimensions`). See equation (20) of Pazner (2020) and equation (30) o !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ -struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, Cache} <: +struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, + LimitingOnesidedVariablesNonlinear, Cache} <: AbstractSubcellLimiter local_minmax::Bool local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables @@ -66,8 +68,8 @@ struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, Cache} <: positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables positivity_correction_factor::RealT - spec_entropy::Bool - math_entropy::Bool + local_onesided::Bool + local_onesided_variables_nonlinear::LimitingOnesidedVariablesNonlinear cache::Cache max_iterations_newton::Int newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method @@ -80,16 +82,26 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - spec_entropy = false, - math_entropy = false, + local_onesided_variables_nonlinear = NTuple{2, Function}[], max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) local_minmax = (length(local_minmax_variables_cons) > 0) + local_onesided = (length(local_onesided_variables_nonlinear) > 0) positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) - if math_entropy && spec_entropy - error("Only one of the two can be selected: math_entropy/spec_entropy") + + # When passing `min` or `max` in the elixir the specific function of Base is used. + # To speed up the simulation, we replace it with `Trixi.max` and `Trixi.min` respectively. + local_onesided_variables_nonlinear_ = Tuple{Function, Function}[] + for (variable, operator) in local_onesided_variables_nonlinear + if operator === Base.max + push!(local_onesided_variables_nonlinear_, tuple(variable, max)) + elseif operator === Base.min + push!(local_onesided_variables_nonlinear_, tuple(variable, min)) + else + error("Operator $operator is not a valid input. Use `max` or `min` instead.") + end end local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, @@ -105,11 +117,11 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; Symbol(v_string, "_max")) end end - if spec_entropy - bound_keys = (bound_keys..., Symbol("entropy_spec", "_", "min")) - end - if math_entropy - bound_keys = (bound_keys..., Symbol("entropy_math", "_", "max")) + if local_onesided + for (variable, operator) in local_onesided_variables_nonlinear_ + bound_keys = (bound_keys..., + Symbol(string(variable), "_", string(operator))) + end end for v in positivity_variables_cons_ if !(v in local_minmax_variables_cons_) @@ -124,11 +136,13 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(positivity_variables_nonlinear), + typeof(local_onesided_variables_nonlinear_), typeof(cache)}(local_minmax, local_minmax_variables_cons_, positivity, positivity_variables_cons_, positivity_variables_nonlinear, positivity_correction_factor, - spec_entropy, math_entropy, + local_onesided, + local_onesided_variables_nonlinear_, cache, max_iterations_newton, newton_tolerances, gamma_constant_newton) @@ -136,10 +150,10 @@ end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_minmax, positivity, local_onesided) = limiter print(io, "SubcellLimiterIDP(") - if !(local_minmax || positivity || spec_entropy || math_entropy) + if !(local_minmax || positivity || local_onesided) print(io, "No limiter selected => pure DG method") else features = String[] @@ -149,11 +163,8 @@ function Base.show(io::IO, limiter::SubcellLimiterIDP) if positivity push!(features, "positivity") end - if spec_entropy - push!(features, "specific entropy") - end - if math_entropy - push!(features, "mathematical entropy") + if local_onesided + push!(features, "local onesided") end join(io, features, ", ") print(io, "Limiter=($features), ") @@ -164,12 +175,12 @@ end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, spec_entropy, math_entropy) = limiter + (; local_minmax, positivity, local_onesided) = limiter if get(io, :compact, false) show(io, limiter) else - if !(local_minmax || positivity || spec_entropy || math_entropy) + if !(local_minmax || positivity || local_onesided) setup = ["Limiter" => "No limiter selected => pure DG method"] else setup = ["Limiter" => ""] @@ -187,13 +198,10 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) "" => "- with positivity correction factor = $(limiter.positivity_correction_factor)", ] end - if spec_entropy - setup = [setup..., "" => "Local minimum limiting for specific entropy"] - end - if math_entropy + if local_onesided setup = [ setup..., - "" => "Local maximum limiting for mathematical entropy", + "" => "Local onesided limiting for nonlinear variables $(limiter.local_onesided_variables_nonlinear)", ] end setup = [ diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index d510f884fa2..23a42c542ab 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -45,17 +45,15 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE @trixi_timeit timer() "reset alpha" reset_du!(alpha, dg, semi.cache) if limiter.local_minmax - @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, limiter, - u, t, dt, semi) + @trixi_timeit timer() "local min/max" idp_local_minmax!(alpha, limiter, + u, t, dt, semi) end if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) end - if limiter.spec_entropy - @trixi_timeit timer() "spec_entropy" idp_local_onesided!(alpha, limiter, u, t, dt, semi, entropy_spec) - end - if limiter.math_entropy - @trixi_timeit timer() "math_entropy" idp_local_onesided!(alpha, limiter, u, t, dt, semi, entropy_math) + if limiter.local_onesided + @trixi_timeit timer() "local onesided" idp_local_onesided!(alpha, limiter, + u, t, dt, semi) end # Calculate alpha1 and alpha2 @@ -355,28 +353,28 @@ end ############################################################################## # Local minimum limiting of specific entropy -@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable) - if variable === entropy_spec - idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, min) - else - idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, max) +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi) + for (variable, operator) in limiter.local_onesided_variables_nonlinear + idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, operator) end return nothing end -@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, bound_function) +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable::F, + minmax) where {F} _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_minmax = variable_bounds[Symbol(string(variable), "_", string(bound_function))] - calc_bounds_onesided!(var_minmax, bound_function, variable, u, t, semi) + var_minmax = variable_bounds[Symbol(string(variable), "_", string(minmax))] + calc_bounds_onesided!(var_minmax, minmax, variable, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) inverse_jacobian = cache.elements.inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, i, j, element, + newton_loops_alpha!(alpha, var_minmax[i, j, element], u_local, + i, j, element, variable, initial_check_local_onesided_newton_idp, final_check_local_onesided_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) @@ -629,22 +627,20 @@ end end new_alpha = 1 - beta - if alpha[i, j, element] > new_alpha + newton_abstol - error("Alpha is getting smaller. old: $(alpha[i, j, element]), new: $new_alpha") - else - alpha[i, j, element] = new_alpha - end + alpha[i, j, element] = new_alpha return nothing end ### Auxiliary routines for Newton's bisection method ### # Initial checks -@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_spec), bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_spec), bound, + goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_math), bound, goal, newton_abstol) +@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_math), bound, + goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end From 2e71c82161cbb950911a5d64e0ccf23deed872fe Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:12:48 +0100 Subject: [PATCH 08/22] Rename minmax limiting to twosided limiting --- ...euler_blast_wave_sc_subcell_nonperiodic.jl | 2 +- ...lixir_euler_sedov_blast_wave_sc_subcell.jl | 2 +- ...ck_bubble_shockcapturing_subcell_minmax.jl | 4 +- src/callbacks_stage/subcell_bounds_check.jl | 16 ++++---- .../subcell_bounds_check_2d.jl | 14 +++---- src/solvers/dgsem_tree/subcell_limiters.jl | 40 +++++++++---------- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 18 ++++----- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl index 4d135b8fd05..00d3c69f2e6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -41,7 +41,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], + local_twosided_variables_cons = ["rho"], local_onesided_variables_nonlinear = [(Trixi.entropy_math, max)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl index cc34e3f1e11..d3bb6a819b5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -42,7 +42,7 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho"], + local_twosided_variables_cons = ["rho"], local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl index 4b606502ebe..b2d49ecbd48 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -86,8 +86,8 @@ volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - local_minmax_variables_cons = ["rho" * string(i) - for i in eachcomponent(equations)]) + local_twosided_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; volume_flux_dg = volume_flux, volume_flux_fv = surface_flux) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 33a454862d7..17ff739028e 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -77,15 +77,15 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi return nothing end - (; local_minmax, positivity, local_onesided) = limiter + (; local_twosided, positivity, local_onesided) = limiter (; output_directory) = callback variables = varnames(cons2cons, semi.equations) mkpath(output_directory) open("$output_directory/deviations.txt", "a") do f print(f, "# iter, simu_time") - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons variable_string = string(variables[v]) print(f, ", " * variable_string * "_min, " * variable_string * "_max") end @@ -97,7 +97,7 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end print(f, ", " * string(variables[v]) * "_min") @@ -125,15 +125,15 @@ end @inline function finalize_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) - (; local_minmax, positivity, local_onesided) = limiter + (; local_twosided, positivity, local_onesided) = limiter (; idp_bounds_delta_global) = limiter.cache variables = varnames(cons2cons, semi.equations) println("─"^100) println("Maximum deviation from bounds:") println("─"^100) - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) println("$(variables[v]):") println("- lower bound: ", @@ -154,7 +154,7 @@ end end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end println(string(variables[v]) * ":\n- positivity: ", diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index e61c864c1ca..aa10c35dce5 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -8,7 +8,7 @@ @inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, limiter::SubcellLimiterIDP, time, iter, output_directory, save_errors) - (; local_minmax, positivity, local_onesided) = solver.volume_integral.limiter + (; local_twosided, positivity, local_onesided) = solver.volume_integral.limiter (; variable_bounds) = limiter.cache.subcell_limiter_coefficients (; idp_bounds_delta_local, idp_bounds_delta_global) = limiter.cache @@ -21,8 +21,8 @@ # Since there are no processors with caches over 128B, we use `n = 128B / size(uEltype)` stride_size = div(128, sizeof(eltype(u))) # = n - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) key_min = Symbol(v_string, "_min") key_max = Symbol(v_string, "_max") @@ -62,7 +62,7 @@ end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end key = Symbol(string(v), "_min") @@ -106,8 +106,8 @@ # Print to output file open("$output_directory/deviations.txt", "a") do f print(f, iter, ", ", time) - if local_minmax - for v in limiter.local_minmax_variables_cons + if local_twosided + for v in limiter.local_twosided_variables_cons v_string = string(v) print(f, ", ", idp_bounds_delta_local[Symbol(v_string, "_min")][stride_size], @@ -124,7 +124,7 @@ end if positivity for v in limiter.positivity_variables_cons - if v in limiter.local_minmax_variables_cons + if v in limiter.local_twosided_variables_cons continue end print(f, ", ", diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 11dcd049c9e..7e2f5dee71c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -14,7 +14,7 @@ end """ SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = String[], + local_twosided_variables_cons = String[], positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, @@ -25,12 +25,12 @@ end Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) +- Local two-sided Zalesak-type limiting for conservative variables (`local_twosided_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) - One-sided limiting for nonlinear variables (e.g., `entropy_spec`, `entropy_math`) -Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` +Conservative variables to be limited are passed as a vector of strings, e.g. `local_twosided_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are passed - to ensure posivity use a plain vector, e.g. `positivity_variables_nonlinear = [pressure]`, for a one-sided limiting pass the variable and the specific bound as a tuple within a vector, e.g. @@ -62,8 +62,8 @@ where `d = #dimensions`). See equation (20) of Pazner (2020) and equation (30) o struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, LimitingOnesidedVariablesNonlinear, Cache} <: AbstractSubcellLimiter - local_minmax::Bool - local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables + local_twosided::Bool + local_twosided_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 @@ -78,7 +78,7 @@ end # this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; - local_minmax_variables_cons = String[], + local_twosided_variables_cons = String[], positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, @@ -86,7 +86,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) - local_minmax = (length(local_minmax_variables_cons) > 0) + local_twosided = (length(local_twosided_variables_cons) > 0) local_onesided = (length(local_onesided_variables_nonlinear) > 0) positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) @@ -104,14 +104,14 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end end - local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, - equations) + local_twosided_variables_cons_ = get_variable_index.(local_twosided_variables_cons, + equations) positivity_variables_cons_ = get_variable_index.(positivity_variables_cons, equations) bound_keys = () - if local_minmax - for v in local_minmax_variables_cons_ + if local_twosided + for v in local_twosided_variables_cons_ v_string = string(v) bound_keys = (bound_keys..., Symbol(v_string, "_min"), Symbol(v_string, "_max")) @@ -124,7 +124,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end end for v in positivity_variables_cons_ - if !(v in local_minmax_variables_cons_) + if !(v in local_twosided_variables_cons_) bound_keys = (bound_keys..., Symbol(string(v), "_min")) end end @@ -137,7 +137,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(positivity_variables_nonlinear), typeof(local_onesided_variables_nonlinear_), - typeof(cache)}(local_minmax, local_minmax_variables_cons_, + typeof(cache)}(local_twosided, local_twosided_variables_cons_, positivity, positivity_variables_cons_, positivity_variables_nonlinear, positivity_correction_factor, @@ -150,14 +150,14 @@ end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, local_onesided) = limiter + (; local_twosided, positivity, local_onesided) = limiter print(io, "SubcellLimiterIDP(") - if !(local_minmax || positivity || local_onesided) + if !(local_twosided || positivity || local_onesided) print(io, "No limiter selected => pure DG method") else features = String[] - if local_minmax + if local_twosided push!(features, "local min/max") end if positivity @@ -175,19 +175,19 @@ end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - (; local_minmax, positivity, local_onesided) = limiter + (; local_twosided, positivity, local_onesided) = limiter if get(io, :compact, false) show(io, limiter) else - if !(local_minmax || positivity || local_onesided) + if !(local_twosided || positivity || local_onesided) setup = ["Limiter" => "No limiter selected => pure DG method"] else setup = ["Limiter" => ""] - if local_minmax + if local_twosided setup = [ setup..., - "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_minmax_variables_cons)", + "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_twosided_variables_cons)", ] end if positivity diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 23a42c542ab..2d6c98e3887 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -44,9 +44,9 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE # TODO: Do not abuse `reset_du!` but maybe implement a generic `set_zero!` @trixi_timeit timer() "reset alpha" reset_du!(alpha, dg, semi.cache) - if limiter.local_minmax - @trixi_timeit timer() "local min/max" idp_local_minmax!(alpha, limiter, - u, t, dt, semi) + if limiter.local_twosided + @trixi_timeit timer() "local min/max" idp_local_twosided!(alpha, limiter, + u, t, dt, semi) end if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) @@ -281,15 +281,15 @@ end ############################################################################### # Local minimum/maximum limiting -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi) - for variable in limiter.local_minmax_variables_cons - idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi) + for variable in limiter.local_twosided_variables_cons + idp_local_twosided!(alpha, limiter, u, t, dt, semi, variable) end return nothing end -@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) +@inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi, variable) _, _, dg, cache = mesh_equations_solver_cache(semi) (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes (; inverse_weights) = dg.basis @@ -431,8 +431,8 @@ end end # Compute bound - if limiter.local_minmax && - variable in limiter.local_minmax_variables_cons && + if limiter.local_twosided && + variable in limiter.local_twosided_variables_cons && var_min[i, j, element] >= positivity_correction_factor * var # Local limiting is more restrictive that positivity limiting # => Skip positivity limiting for this node From 57247f82f50d8d788c8d16d97799e76f06ab4aa2 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:16:05 +0100 Subject: [PATCH 09/22] Update comment --- src/solvers/dgsem_tree/subcell_limiters.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 7e2f5dee71c..27aae369648 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -28,7 +28,7 @@ including: - Local two-sided Zalesak-type limiting for conservative variables (`local_twosided_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) -- One-sided limiting for nonlinear variables (e.g., `entropy_spec`, `entropy_math`) +- Local one-sided limiting for nonlinear variables (e.g., `entropy_spec`, `entropy_math`) Conservative variables to be limited are passed as a vector of strings, e.g. `local_twosided_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are From 5f93fa151bb1aaadcfcc3d295b99207226a2ca6b Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:20:02 +0100 Subject: [PATCH 10/22] Clean up default vector --- src/solvers/dgsem_tree/subcell_limiters.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 27aae369648..7d490298407 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -18,7 +18,7 @@ end positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - local_onesided_variables_nonlinear = NTuple{2, Function}[], + local_onesided_variables_nonlinear = [], max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) @@ -82,7 +82,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; positivity_variables_cons = String[], positivity_variables_nonlinear = [], positivity_correction_factor = 0.1, - local_onesided_variables_nonlinear = NTuple{2, Function}[], + local_onesided_variables_nonlinear = [], max_iterations_newton = 10, newton_tolerances = (1.0e-12, 1.0e-14), gamma_constant_newton = 2 * ndims(equations)) From 25a53743c2ddec2e5e6544f216888dfadcf7a2fb Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:28:47 +0100 Subject: [PATCH 11/22] Last stuff --- src/callbacks_stage/subcell_bounds_check.jl | 2 +- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index 17ff739028e..fa71acfe90b 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -146,7 +146,7 @@ end for (variable, operator) in limiter.local_onesided_variables_nonlinear variable_string = string(variable) operator_string = string(operator) - println("$(variable_string):") + println("$variable_string:") println("- $operator_string bound: ", idp_bounds_delta_global[Symbol(variable_string, "_", operator_string)]) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 2d6c98e3887..d8cd1910343 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -45,8 +45,8 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE @trixi_timeit timer() "reset alpha" reset_du!(alpha, dg, semi.cache) if limiter.local_twosided - @trixi_timeit timer() "local min/max" idp_local_twosided!(alpha, limiter, - u, t, dt, semi) + @trixi_timeit timer() "local twosided" idp_local_twosided!(alpha, limiter, + u, t, dt, semi) end if limiter.positivity @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) @@ -279,7 +279,7 @@ end end ############################################################################### -# Local minimum/maximum limiting +# Local two-sided limiting for conservative variables @inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi) for variable in limiter.local_twosided_variables_cons @@ -351,7 +351,7 @@ end end ############################################################################## -# Local minimum limiting of specific entropy +# Local one-sided limiting of nonlinear variables @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi) for (variable, operator) in limiter.local_onesided_variables_nonlinear From dccf645ea8594e8e9c597778319e0af3f6add228 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:49:48 +0100 Subject: [PATCH 12/22] Fix unit test --- test/test_unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index ce735015012..3c08353d7d7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,7 +416,7 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, true, true, + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, [(Trixi.entropy_spec, min)], "cache", 1, (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) From c506a9235f90652a964153c6855a0d0ee2929b23 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 17:58:01 +0100 Subject: [PATCH 13/22] fmt --- test/test_unit.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 3c08353d7d7..0df3be8e816 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -416,8 +416,9 @@ end indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, [(Trixi.entropy_spec, min)], - "cache", 1, (1.0, 1.0), 1.0) + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, + [(Trixi.entropy_spec, min)], "cache", + 1, (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test From fd8ed8a3a6525b27580a3d8818a90716dec21d06 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Mon, 19 Feb 2024 19:01:26 +0100 Subject: [PATCH 14/22] Fix tests --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 5 +++-- test/test_unit.jl | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index d8cd1910343..a28e934202b 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -644,7 +644,8 @@ end goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline initial_check_nonnegative_newton_idp(bound, goal, newton_abstol) = goal <= 0 +@inline initial_check_nonnegative_newton_idp(variable, bound, goal, newton_abstol) = goal <= + 0 # Goal and d(Goal)d(u) function @inline goal_function_newton_idp(variable, bound, u, equations) = bound - @@ -655,7 +656,7 @@ end end # Final checks -# final check for entropy limiting +# final check for one-sided local limiting @inline function final_check_local_onesided_newton_idp(bound, goal, newton_abstol) abs(goal) < max(newton_abstol, abs(bound) * newton_abstol) end diff --git a/test/test_unit.jl b/test/test_unit.jl index 0df3be8e816..716493a28c7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -417,7 +417,7 @@ end @test_nowarn show(stdout, indicator_hg) limiter_idp = SubcellLimiterIDP(true, [1], true, [1], ["variable"], 0.1, - [(Trixi.entropy_spec, min)], "cache", + true, [(Trixi.entropy_spec, min)], "cache", 1, (1.0, 1.0), 1.0) @test_nowarn show(stdout, limiter_idp) From 9adf2fce5014996189eb35571e052cc9a03926a6 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 20 Feb 2024 10:33:10 +0100 Subject: [PATCH 15/22] Correct order --- src/solvers/dgsem_tree/subcell_limiters.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 7d490298407..11821955529 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -92,7 +92,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; length(positivity_variables_nonlinear) > 0) # When passing `min` or `max` in the elixir the specific function of Base is used. - # To speed up the simulation, we replace it with `Trixi.max` and `Trixi.min` respectively. + # To speed up the simulation, we replace it with `Trixi.min` and `Trixi.max` respectively. local_onesided_variables_nonlinear_ = Tuple{Function, Function}[] for (variable, operator) in local_onesided_variables_nonlinear if operator === Base.max From e7acae287a7f303228e53f5fbefd4307b9f0a7ee Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 20 Feb 2024 11:37:02 +0100 Subject: [PATCH 16/22] Rework docstring --- src/solvers/dgsem_tree/subcell_limiters.jl | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 11821955529..025337f5566 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -28,17 +28,21 @@ including: - Local two-sided Zalesak-type limiting for conservative variables (`local_twosided_variables_cons`) - Positivity limiting for conservative variables (`positivity_variables_cons`) and nonlinear variables (`positivity_variables_nonlinear`) -- Local one-sided limiting for nonlinear variables (e.g., `entropy_spec`, `entropy_math`) +- Local one-sided limiting for nonlinear variables, e.g. `entropy_spec` and `entropy_math` +with `local_onesided_variables_nonlinear` -Conservative variables to be limited are passed as a vector of strings, e.g. `local_twosided_variables_cons = ["rho"]` -and `positivity_variables_cons = ["rho"]`. For nonlinear variables the specific functions are -passed - to ensure posivity use a plain vector, e.g. `positivity_variables_nonlinear = [pressure]`, -for a one-sided limiting pass the variable and the specific bound as a tuple within a vector, e.g. -`local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]`. +To use these three limiting options use the following structure: + +***Conservative variables*** to be limited are passed as a vector of strings, e.g. +`local_twosided_variables_cons = ["rho"]` and `positivity_variables_cons = ["rho"]`. +For ***nonlinear variables***, the wanted variable functions are passed within a vector: To ensure +positivity use a plain vector including the desired variables, e.g. `positivity_variables_nonlinear = [pressure]`. +For local one-sided limiting pass the variable function combined with the requested bound +(`min` or `max`) as a tuple, e.g. `local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. -The limiting of nonlinear variables uses a Newton-bisection method with a maximum of +Local and global limiting of nonlinear variables uses a Newton-bisection method with a maximum of `max_iterations_newton` iterations, relative and absolute tolerances of `newton_tolerances` and a provisional update constant `gamma_constant_newton` (`gamma_constant_newton>=2*d`, where `d = #dimensions`). See equation (20) of Pazner (2020) and equation (30) of Rueda-Ramírez et al. (2022). @@ -63,13 +67,13 @@ struct SubcellLimiterIDP{RealT <: Real, LimitingVariablesNonlinear, LimitingOnesidedVariablesNonlinear, Cache} <: AbstractSubcellLimiter local_twosided::Bool - local_twosided_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables + local_twosided_variables_cons::Vector{Int} # Local two-sided limiting for conservative variables positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_variables_nonlinear::LimitingVariablesNonlinear # Positivity for nonlinear variables positivity_correction_factor::RealT local_onesided::Bool - local_onesided_variables_nonlinear::LimitingOnesidedVariablesNonlinear + local_onesided_variables_nonlinear::LimitingOnesidedVariablesNonlinear # Local one-sided limiting for nonlinear variables cache::Cache max_iterations_newton::Int newton_tolerances::Tuple{RealT, RealT} # Relative and absolute tolerances for Newton's method @@ -187,7 +191,7 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) if local_twosided setup = [ setup..., - "" => "Local maximum/minimum limiting for conservative variables $(limiter.local_twosided_variables_cons)", + "" => "Local two-sided limiting for conservative variables $(limiter.local_twosided_variables_cons)", ] end if positivity @@ -199,10 +203,9 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) ] end if local_onesided - setup = [ - setup..., - "" => "Local onesided limiting for nonlinear variables $(limiter.local_onesided_variables_nonlinear)", - ] + for (variable, operator) in limiter.local_onesided_variables_nonlinear + setup = [setup..., "" => "Local $operator limiting for $variable"] + end end setup = [ setup..., From 967e5bd15961f7d0ad185ad2814c7615dc48b61e Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 27 Feb 2024 10:44:49 +0100 Subject: [PATCH 17/22] Rename operator to min_or_max --- src/callbacks_stage/subcell_bounds_check.jl | 12 ++--- .../subcell_bounds_check_2d.jl | 16 +++--- src/solvers/dgsem_tree/subcell_limiters.jl | 16 +++--- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 50 +++++++++---------- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl index fa71acfe90b..ba193ab2997 100644 --- a/src/callbacks_stage/subcell_bounds_check.jl +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -91,8 +91,8 @@ function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimi end end if local_onesided - for (variable, operator) in limiter.local_onesided_variables_nonlinear - print(f, ", " * string(variable) * "_" * string(operator)) + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + print(f, ", " * string(variable) * "_" * string(min_or_max)) end end if positivity @@ -143,13 +143,13 @@ end end end if local_onesided - for (variable, operator) in limiter.local_onesided_variables_nonlinear + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear variable_string = string(variable) - operator_string = string(operator) + minmax_string = string(min_or_max) println("$variable_string:") - println("- $operator_string bound: ", + println("- $minmax_string bound: ", idp_bounds_delta_global[Symbol(variable_string, "_", - operator_string)]) + minmax_string)]) end end if positivity diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index aa10c35dce5..1f8c350825a 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -44,17 +44,19 @@ end end if local_onesided - foreach(limiter.local_onesided_variables_nonlinear) do (variable, operator) - key = Symbol(string(variable), "_", string(operator)) - factor = operator === max ? 1.0 : -1.0 + foreach(limiter.local_onesided_variables_nonlinear) do (variable, min_or_max) + key = Symbol(string(variable), "_", string(min_or_max)) deviation_threaded = idp_bounds_delta_local[key] @threaded for element in eachelement(solver, cache) deviation = deviation_threaded[stride_size * Threads.threadid()] for j in eachnode(solver), i in eachnode(solver) v = variable(get_node_vars(u, equations, solver, i, j, element), equations) - deviation = max(deviation, - factor * (v - variable_bounds[key][i, j, element])) + if min_or_max === max + deviation = max(deviation, v - variable_bounds[key][i, j, element]) + else # min_or_max === min + deviation = max(deviation, variable_bounds[key][i, j, element] - v) + end end deviation_threaded[stride_size * Threads.threadid()] = deviation end @@ -116,10 +118,10 @@ end end if local_onesided - for (variable, operator) in limiter.local_onesided_variables_nonlinear + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear print(f, ", ", idp_bounds_delta_local[Symbol(string(variable), "_", - string(operator))][stride_size]) + string(min_or_max))][stride_size]) end end if positivity diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 025337f5566..d9c88d59e84 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -98,13 +98,13 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; # When passing `min` or `max` in the elixir the specific function of Base is used. # To speed up the simulation, we replace it with `Trixi.min` and `Trixi.max` respectively. local_onesided_variables_nonlinear_ = Tuple{Function, Function}[] - for (variable, operator) in local_onesided_variables_nonlinear - if operator === Base.max + for (variable, min_or_max) in local_onesided_variables_nonlinear + if min_or_max === Base.max push!(local_onesided_variables_nonlinear_, tuple(variable, max)) - elseif operator === Base.min + elseif min_or_max === Base.min push!(local_onesided_variables_nonlinear_, tuple(variable, min)) else - error("Operator $operator is not a valid input. Use `max` or `min` instead.") + error("Parameter $min_or_max is not a valid input. Use `max` or `min` instead.") end end @@ -122,9 +122,9 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; end end if local_onesided - for (variable, operator) in local_onesided_variables_nonlinear_ + for (variable, min_or_max) in local_onesided_variables_nonlinear_ bound_keys = (bound_keys..., - Symbol(string(variable), "_", string(operator))) + Symbol(string(variable), "_", string(min_or_max))) end end for v in positivity_variables_cons_ @@ -203,8 +203,8 @@ function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) ] end if local_onesided - for (variable, operator) in limiter.local_onesided_variables_nonlinear - setup = [setup..., "" => "Local $operator limiting for $variable"] + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + setup = [setup..., "" => "Local $min_or_max limiting for $variable"] end end setup = [ diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index a28e934202b..0e16a5407aa 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -175,13 +175,13 @@ end return nothing end -@inline function calc_bounds_onesided!(var_minmax, minmax, variable, u, t, semi) +@inline function calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) # Calc bounds inside elements @threaded for element in eachelement(dg, cache) # Reset bounds for j in eachnode(dg), i in eachnode(dg) - if minmax === max + if min_or_max === max var_minmax[i, j, element] = typemin(eltype(var_minmax)) else var_minmax[i, j, element] = typemax(eltype(var_minmax)) @@ -191,32 +191,32 @@ end # Calculate bounds at Gauss-Lobatto nodes using u for j in eachnode(dg), i in eachnode(dg) var = variable(get_node_vars(u, equations, dg, i, j, element), equations) - var_minmax[i, j, element] = minmax(var_minmax[i, j, element], var) + var_minmax[i, j, element] = min_or_max(var_minmax[i, j, element], var) if i > 1 - var_minmax[i - 1, j, element] = minmax(var_minmax[i - 1, j, element], - var) + var_minmax[i - 1, j, element] = min_or_max(var_minmax[i - 1, j, element], + var) end if i < nnodes(dg) - var_minmax[i + 1, j, element] = minmax(var_minmax[i + 1, j, element], - var) + var_minmax[i + 1, j, element] = min_or_max(var_minmax[i + 1, j, element], + var) end if j > 1 - var_minmax[i, j - 1, element] = minmax(var_minmax[i, j - 1, element], - var) + var_minmax[i, j - 1, element] = min_or_max(var_minmax[i, j - 1, element], + var) end if j < nnodes(dg) - var_minmax[i, j + 1, element] = minmax(var_minmax[i, j + 1, element], - var) + var_minmax[i, j + 1, element] = min_or_max(var_minmax[i, j + 1, element], + var) end end end # Values at element boundary - calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, semi, mesh) + calc_bounds_onesided_interface!(var_minmax, min_or_max, variable, u, t, semi, mesh) end -@inline function calc_bounds_onesided_interface!(var_minmax, minmax, variable, u, t, +@inline function calc_bounds_onesided_interface!(var_minmax, min_or_max, variable, u, t, semi, mesh::TreeMesh2D) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; boundary_conditions) = semi @@ -240,10 +240,10 @@ end var_right = variable(get_node_vars(u, equations, dg, index_right..., right), equations) - var_minmax[index_right..., right] = minmax(var_minmax[index_right..., - right], var_left) - var_minmax[index_left..., left] = minmax(var_minmax[index_left..., left], - var_right) + var_minmax[index_right..., right] = min_or_max(var_minmax[index_right..., + right], var_left) + var_minmax[index_left..., left] = min_or_max(var_minmax[index_left..., left], + var_right) end end @@ -270,8 +270,8 @@ end index..., element) var_outer = variable(u_outer, equations) - var_minmax[index..., element] = minmax(var_minmax[index..., element], - var_outer) + var_minmax[index..., element] = min_or_max(var_minmax[index..., element], + var_outer) end end @@ -279,7 +279,7 @@ end end ############################################################################### -# Local two-sided limiting for conservative variables +# Local two-sided limiting of conservative variables @inline function idp_local_twosided!(alpha, limiter, u, t, dt, semi) for variable in limiter.local_twosided_variables_cons @@ -354,19 +354,19 @@ end # Local one-sided limiting of nonlinear variables @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi) - for (variable, operator) in limiter.local_onesided_variables_nonlinear - idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, operator) + for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, min_or_max) end return nothing end @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable::F, - minmax) where {F} + min_or_max) where {F} _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients - var_minmax = variable_bounds[Symbol(string(variable), "_", string(minmax))] - calc_bounds_onesided!(var_minmax, minmax, variable, u, t, semi) + var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] + calc_bounds_onesided!(var_minmax, min_or_max, variable, u, t, semi) # Perform Newton's bisection method to find new alpha @threaded for element in eachelement(dg, cache) From d68044184f3f7f64510a78e9cd68e6430f8f69af Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 27 Feb 2024 11:22:08 +0100 Subject: [PATCH 18/22] Call initial check with min_or_max --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 0e16a5407aa..9acd2e25d7a 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -362,7 +362,7 @@ end end @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable::F, - min_or_max) where {F} + min_or_max::M) where {F, M} _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] @@ -374,8 +374,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, var_minmax[i, j, element], u_local, - i, j, element, - variable, initial_check_local_onesided_newton_idp, + i, j, element, variable, min_or_max, + initial_check_local_onesided_newton_idp, final_check_local_onesided_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) end @@ -494,7 +494,7 @@ end # Perform Newton's bisection method to find new alpha newton_loops_alpha!(alpha, var_min[i, j, element], u_local, i, j, element, - variable, initial_check_nonnegative_newton_idp, + variable, min, initial_check_nonnegative_newton_idp, final_check_nonnegative_newton_idp, inverse_jacobian, dt, equations, dg, cache, limiter) end @@ -503,7 +503,7 @@ end return nothing end -@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, inverse_jacobian, dt, equations, dg, cache, limiter) (; inverse_weights) = dg.basis @@ -515,7 +515,7 @@ end antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, equations, dt, limiter, antidiffusive_flux) # positive xi direction @@ -523,14 +523,14 @@ end inverse_weights[i] * get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, equations, dt, limiter, antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, equations, dt, limiter, antidiffusive_flux) # positive eta direction @@ -538,13 +538,13 @@ end inverse_weights[j] * get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, final_check, + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, equations, dt, limiter, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, variable, initial_check, +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, equations, dt, limiter, antidiffusive_flux) newton_reltol, newton_abstol = limiter.newton_tolerances @@ -559,7 +559,7 @@ end if isvalid(u_curr, equations) goal = goal_function_newton_idp(variable, bound, u_curr, equations) - initial_check(variable, bound, goal, newton_abstol) && return nothing + initial_check(min_or_max, bound, goal, newton_abstol) && return nothing end # Newton iterations @@ -594,7 +594,7 @@ end # Check new beta for condition and update bounds goal = goal_function_newton_idp(variable, bound, u_curr, equations) - if initial_check(variable, bound, goal, newton_abstol) + if initial_check(min_or_max, bound, goal, newton_abstol) # New beta fulfills condition beta_L = beta else @@ -634,18 +634,17 @@ end ### Auxiliary routines for Newton's bisection method ### # Initial checks -@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_spec), bound, +@inline function initial_check_local_onesided_newton_idp(::typeof(min), bound, goal, newton_abstol) goal <= max(newton_abstol, abs(bound) * newton_abstol) end -@inline function initial_check_local_onesided_newton_idp(::typeof(entropy_math), bound, +@inline function initial_check_local_onesided_newton_idp(::typeof(max), bound, goal, newton_abstol) goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline initial_check_nonnegative_newton_idp(variable, bound, goal, newton_abstol) = goal <= - 0 +@inline initial_check_nonnegative_newton_idp(min_or_max, bound, goal, newton_abstol) = goal <= 0 # Goal and d(Goal)d(u) function @inline goal_function_newton_idp(variable, bound, u, equations) = bound - From a6884c20d46800058a8ce1de1562f48306746b94 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 27 Feb 2024 11:24:40 +0100 Subject: [PATCH 19/22] fmt --- .../subcell_bounds_check_2d.jl | 6 ++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 51 ++++++++++--------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl index 1f8c350825a..4b8fb34c6b5 100644 --- a/src/callbacks_stage/subcell_bounds_check_2d.jl +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -53,9 +53,11 @@ v = variable(get_node_vars(u, equations, solver, i, j, element), equations) if min_or_max === max - deviation = max(deviation, v - variable_bounds[key][i, j, element]) + deviation = max(deviation, + v - variable_bounds[key][i, j, element]) else # min_or_max === min - deviation = max(deviation, variable_bounds[key][i, j, element] - v) + deviation = max(deviation, + variable_bounds[key][i, j, element] - v) end end deviation_threaded[stride_size * Threads.threadid()] = deviation diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 9acd2e25d7a..addce520a6d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -194,20 +194,20 @@ end var_minmax[i, j, element] = min_or_max(var_minmax[i, j, element], var) if i > 1 - var_minmax[i - 1, j, element] = min_or_max(var_minmax[i - 1, j, element], - var) + var_minmax[i - 1, j, element] = min_or_max(var_minmax[i - 1, j, + element], var) end if i < nnodes(dg) - var_minmax[i + 1, j, element] = min_or_max(var_minmax[i + 1, j, element], - var) + var_minmax[i + 1, j, element] = min_or_max(var_minmax[i + 1, j, + element], var) end if j > 1 - var_minmax[i, j - 1, element] = min_or_max(var_minmax[i, j - 1, element], - var) + var_minmax[i, j - 1, element] = min_or_max(var_minmax[i, j - 1, + element], var) end if j < nnodes(dg) - var_minmax[i, j + 1, element] = min_or_max(var_minmax[i, j + 1, element], - var) + var_minmax[i, j + 1, element] = min_or_max(var_minmax[i, j + 1, + element], var) end end end @@ -242,8 +242,8 @@ end var_minmax[index_right..., right] = min_or_max(var_minmax[index_right..., right], var_left) - var_minmax[index_left..., left] = min_or_max(var_minmax[index_left..., left], - var_right) + var_minmax[index_left..., left] = min_or_max(var_minmax[index_left..., + left], var_right) end end @@ -503,9 +503,10 @@ end return nothing end -@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, min_or_max, - initial_check, final_check, inverse_jacobian, dt, - equations, dg, cache, limiter) +@inline function newton_loops_alpha!(alpha, bound, u, i, j, element, variable, + min_or_max, initial_check, final_check, + inverse_jacobian, dt, equations, dg, cache, + limiter) (; inverse_weights) = dg.basis (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes @@ -515,37 +516,38 @@ end antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # positive xi direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[i] * get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # negative eta direction antidiffusive_flux = gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) - newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) # positive eta direction antidiffusive_flux = -gamma_constant_newton * inverse_jacobian * inverse_weights[j] * get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) - newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, final_check, - equations, dt, limiter, antidiffusive_flux) + newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, + final_check, equations, dt, limiter, antidiffusive_flux) return nothing end -@inline function newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, initial_check, - final_check, equations, dt, limiter, antidiffusive_flux) +@inline function newton_loop!(alpha, bound, u, i, j, element, variable, min_or_max, + initial_check, final_check, equations, dt, limiter, + antidiffusive_flux) newton_reltol, newton_abstol = limiter.newton_tolerances beta = 1 - alpha[i, j, element] @@ -644,7 +646,8 @@ end goal >= -max(newton_abstol, abs(bound) * newton_abstol) end -@inline initial_check_nonnegative_newton_idp(min_or_max, bound, goal, newton_abstol) = goal <= 0 +@inline initial_check_nonnegative_newton_idp(min_or_max, bound, goal, newton_abstol) = goal <= + 0 # Goal and d(Goal)d(u) function @inline goal_function_newton_idp(variable, bound, u, equations) = bound - From e85504dc6edc3669f3c57673fcba24d5ad0b81c7 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Tue, 27 Feb 2024 11:28:27 +0100 Subject: [PATCH 20/22] Implement suggestions --- src/solvers/dgsem_tree/subcell_limiters.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index d9c88d59e84..56fa4a1aa46 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -38,7 +38,8 @@ To use these three limiting options use the following structure: For ***nonlinear variables***, the wanted variable functions are passed within a vector: To ensure positivity use a plain vector including the desired variables, e.g. `positivity_variables_nonlinear = [pressure]`. For local one-sided limiting pass the variable function combined with the requested bound -(`min` or `max`) as a tuple, e.g. `local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]`. +(`min` or `max`) as a tuple. For instance, to impose a lower local bound on the specific entropy +use `local_onesided_variables_nonlinear = [(Trixi.entropy_spec, min)]`. The bounds are calculated using the low-order FV solution. The positivity limiter uses `positivity_correction_factor` such that `u^new >= positivity_correction_factor * u^FV`. @@ -103,6 +104,8 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; push!(local_onesided_variables_nonlinear_, tuple(variable, max)) elseif min_or_max === Base.min push!(local_onesided_variables_nonlinear_, tuple(variable, min)) + elseif min_or_max === Trixi.max || min_or_max === Trixi.min + push!(local_onesided_variables_nonlinear_, tuple(variable, min_or_max)) else error("Parameter $min_or_max is not a valid input. Use `max` or `min` instead.") end From a3472e5109ac5120a3f96d4fece12e040c2788c4 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Wed, 28 Feb 2024 16:21:01 +0100 Subject: [PATCH 21/22] Remove type stuff --- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index addce520a6d..ac75b88de29 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -361,8 +361,8 @@ end return nothing end -@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable::F, - min_or_max::M) where {F, M} +@inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, + min_or_max) _, equations, dg, cache = mesh_equations_solver_cache(semi) (; variable_bounds) = limiter.cache.subcell_limiter_coefficients var_minmax = variable_bounds[Symbol(string(variable), "_", string(min_or_max))] From 05ed2fd8b43233db7f9d0c88a05f2e6069762182 Mon Sep 17 00:00:00 2001 From: bennibolm Date: Fri, 1 Mar 2024 12:53:38 +0100 Subject: [PATCH 22/22] Fix allocations due to non-specialized routine --- src/solvers/dgsem_tree/subcell_limiters.jl | 3 ++- src/solvers/dgsem_tree/subcell_limiters_2d.jl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 56fa4a1aa46..7b06149148d 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -96,7 +96,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; positivity = (length(positivity_variables_cons) + length(positivity_variables_nonlinear) > 0) - # When passing `min` or `max` in the elixir the specific function of Base is used. + # When passing `min` or `max` in the elixir, the specific function of Base is used. # To speed up the simulation, we replace it with `Trixi.min` and `Trixi.max` respectively. local_onesided_variables_nonlinear_ = Tuple{Function, Function}[] for (variable, min_or_max) in local_onesided_variables_nonlinear @@ -110,6 +110,7 @@ function SubcellLimiterIDP(equations::AbstractEquations, basis; error("Parameter $min_or_max is not a valid input. Use `max` or `min` instead.") end end + local_onesided_variables_nonlinear_ = Tuple(local_onesided_variables_nonlinear_) local_twosided_variables_cons_ = get_variable_index.(local_twosided_variables_cons, equations) diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index ac75b88de29..e820bed667c 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -354,7 +354,7 @@ end # Local one-sided limiting of nonlinear variables @inline function idp_local_onesided!(alpha, limiter, u, t, dt, semi) - for (variable, min_or_max) in limiter.local_onesided_variables_nonlinear + foreach(limiter.local_onesided_variables_nonlinear) do (variable, min_or_max) idp_local_onesided!(alpha, limiter, u, t, dt, semi, variable, min_or_max) end