Path: blob/main/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl
5591 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67function create_cache_subcell_limiting(mesh::Union{TreeMesh{2}, StructuredMesh{2},8P4estMesh{2}},9equations,10volume_integral::VolumeIntegralSubcellLimiting,11dg::DG, cache_containers, uEltype)12cache = NamedTuple()1314fhat1_L_threaded, fhat1_R_threaded,15fhat2_L_threaded, fhat2_R_threaded = create_f_threaded(mesh, equations, dg,16uEltype)1718A3d = Array{uEltype, 3}19flux_temp_threaded = A3d[A3d(undef, nvariables(equations),20nnodes(dg), nnodes(dg))21for _ in 1:Threads.maxthreadid()]22fhat_temp_threaded = A3d[A3d(undef, nvariables(equations),23nnodes(dg), nnodes(dg))24for _ in 1:Threads.maxthreadid()]2526n_elements = nelements(cache_containers.elements)27antidiffusive_fluxes = ContainerAntidiffusiveFlux2D{uEltype}(n_elements,28nvariables(equations),29nnodes(dg))3031if have_nonconservative_terms(equations) == true32A4d = Array{uEltype, 4}3334# Extract the nonconservative flux as a dispatch argument for `n_nonconservative_terms`35_, volume_flux_noncons = volume_integral.volume_flux_dg3637flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations),38n_nonconservative_terms(volume_flux_noncons),39nnodes(dg), nnodes(dg))40for _ in 1:Threads.maxthreadid()]41fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations),42n_nonconservative_terms(volume_flux_noncons),43nnodes(dg), nnodes(dg))44for _ in 1:Threads.maxthreadid()]45phi_threaded = A4d[A4d(undef, nvariables(equations),46n_nonconservative_terms(volume_flux_noncons),47nnodes(dg), nnodes(dg))48for _ in 1:Threads.maxthreadid()]49cache = (; cache..., flux_nonconservative_temp_threaded,50fhat_nonconservative_temp_threaded, phi_threaded)51end5253# The limiter cache was created with 0 elements54resize_subcell_limiter_cache!(dg.volume_integral.limiter, n_elements)5556return (; cache..., antidiffusive_fluxes,57fhat1_L_threaded, fhat1_R_threaded,58fhat2_L_threaded, fhat2_R_threaded,59flux_temp_threaded, fhat_temp_threaded)60end6162# Subcell limiting currently only implemented for certain mesh types63@inline function volume_integral_kernel!(du, u, element,64MeshT::Type{<:Union{TreeMesh{2},65StructuredMesh{2},66P4estMesh{2}}},67have_nonconservative_terms, equations,68volume_integral::VolumeIntegralSubcellLimiting,69dg::DGSEM, cache)70@unpack inverse_weights = dg.basis # Plays role of inverse DG-subcell sizes71@unpack volume_flux_dg, volume_flux_fv, limiter = volume_integral7273# high-order DG fluxes74@unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache7576fhat1_L = fhat1_L_threaded[Threads.threadid()]77fhat1_R = fhat1_R_threaded[Threads.threadid()]78fhat2_L = fhat2_L_threaded[Threads.threadid()]79fhat2_R = fhat2_R_threaded[Threads.threadid()]80calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, MeshT,81have_nonconservative_terms, equations, volume_flux_dg, dg, element,82cache)8384# low-order FV fluxes85@unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache8687fstar1_L = fstar1_L_threaded[Threads.threadid()]88fstar2_L = fstar2_L_threaded[Threads.threadid()]89fstar1_R = fstar1_R_threaded[Threads.threadid()]90fstar2_R = fstar2_R_threaded[Threads.threadid()]91calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, MeshT,92have_nonconservative_terms, equations, volume_flux_fv, dg, element,93cache)9495# antidiffusive flux96calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,97fstar1_L, fstar1_R, fstar2_L, fstar2_R,98u, MeshT, have_nonconservative_terms, equations, limiter,99dg,100element, cache)101102# Calculate volume integral contribution of low-order FV flux103for j in eachnode(dg), i in eachnode(dg)104for v in eachvariable(equations)105du[v, i, j, element] += inverse_weights[i] *106(fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) +107inverse_weights[j] *108(fstar2_L[v, i, j + 1] - fstar2_R[v, i, j])109end110end111112return nothing113end114115# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element116# (**without non-conservative terms**).117#118# See also `flux_differencing_kernel!`.119@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,120::Type{<:TreeMesh{2}},121have_nonconservative_terms::False,122equations,123volume_flux, dg::DGSEM, element, cache)124@unpack weights, derivative_split = dg.basis125@unpack flux_temp_threaded = cache126127flux_temp = flux_temp_threaded[Threads.threadid()]128129# The FV-form fluxes are calculated in a recursive manner, i.e.:130# fhat_(0,1) = w_0 * FVol_0,131# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,132# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).133134# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated135# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`136# and saved in in `flux_temp`.137138# Split form volume flux in orientation 1: x direction139flux_temp .= zero(eltype(flux_temp))140141for j in eachnode(dg), i in eachnode(dg)142u_node = get_node_vars(u, equations, dg, i, j, element)143144# All diagonal entries of `derivative_split` are zero. Thus, we can skip145# the computation of the diagonal terms. In addition, we use the symmetry146# of the `volume_flux` to save half of the possible two-point flux147# computations.148for ii in (i + 1):nnodes(dg)149u_node_ii = get_node_vars(u, equations, dg, ii, j, element)150flux1 = volume_flux(u_node, u_node_ii, 1, equations)151multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,152equations, dg, i, j)153multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,154equations, dg, ii, j)155end156end157158# FV-form flux `fhat` in x direction159for j in eachnode(dg), i in 1:(nnodes(dg) - 1)160for v in eachvariable(equations)161fhat1_L[v, i + 1, j] = fhat1_L[v, i, j] + weights[i] * flux_temp[v, i, j]162fhat1_R[v, i + 1, j] = fhat1_L[v, i + 1, j]163end164end165166# Split form volume flux in orientation 2: y direction167flux_temp .= zero(eltype(flux_temp))168169for j in eachnode(dg), i in eachnode(dg)170u_node = get_node_vars(u, equations, dg, i, j, element)171for jj in (j + 1):nnodes(dg)172u_node_jj = get_node_vars(u, equations, dg, i, jj, element)173flux2 = volume_flux(u_node, u_node_jj, 2, equations)174multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,175equations, dg, i, j)176multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,177equations, dg, i, jj)178end179end180181# FV-form flux `fhat` in y direction182for j in 1:(nnodes(dg) - 1), i in eachnode(dg)183for v in eachvariable(equations)184fhat2_L[v, i, j + 1] = fhat2_L[v, i, j] + weights[j] * flux_temp[v, i, j]185fhat2_R[v, i, j + 1] = fhat2_L[v, i, j + 1]186end187end188189return nothing190end191192# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element193# (**with non-conservative terms in "local * symmetric" form**).194#195# See also `flux_differencing_kernel!`.196#197# The calculation of the non-conservative staggered "fluxes" requires non-conservative198# terms that can be written as a product of local and a symmetric contributions. See, e.g.,199#200# - Rueda-RamÃrez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts201# Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.202#203@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,204::Type{<:TreeMesh{2}}, have_nonconservative_terms::True,205equations,206volume_flux::Tuple{F_CONS, F_NONCONS}, dg::DGSEM,207element,208cache) where {209F_CONS <: Function,210F_NONCONS <:211FluxNonConservative{NonConservativeSymmetric()}212}213@unpack weights, derivative_split = dg.basis214@unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache215@unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache216217volume_flux_cons, volume_flux_noncons = volume_flux218219flux_temp = flux_temp_threaded[Threads.threadid()]220flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()]221222fhat_temp = fhat_temp_threaded[Threads.threadid()]223fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()]224phi = phi_threaded[Threads.threadid()]225226# The FV-form fluxes are calculated in a recursive manner, i.e.:227# fhat_(0,1) = w_0 * FVol_0,228# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,229# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).230231# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated232# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`233# and saved in in `flux_temp`.234235# Split form volume flux in orientation 1: x direction236flux_temp .= zero(eltype(flux_temp))237flux_noncons_temp .= zero(eltype(flux_noncons_temp))238239for j in eachnode(dg), i in eachnode(dg)240u_node = get_node_vars(u, equations, dg, i, j, element)241242# All diagonal entries of `derivative_split` are zero. Thus, we can skip243# the computation of the diagonal terms. In addition, we use the symmetry244# of `volume_flux_cons` and `volume_flux_noncons` to save half of the possible two-point flux245# computations.246for ii in (i + 1):nnodes(dg)247u_node_ii = get_node_vars(u, equations, dg, ii, j, element)248flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations)249multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,250equations, dg, i, j)251multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,252equations, dg, ii, j)253for noncons in 1:n_nonconservative_terms(volume_flux_noncons)254# We multiply by 0.5 because that is done in other parts of Trixi255flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations,256NonConservativeSymmetric(), noncons)257multiply_add_to_node_vars!(flux_noncons_temp,2580.5f0 * derivative_split[i, ii],259flux1_noncons,260equations, dg, noncons, i, j)261multiply_add_to_node_vars!(flux_noncons_temp,2620.5f0 * derivative_split[ii, i],263flux1_noncons,264equations, dg, noncons, ii, j)265end266end267end268269# FV-form flux `fhat` in x direction270fhat_temp[:, 1, :] .= zero(eltype(fhat1_L))271fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L))272273# Compute local contribution to non-conservative flux274for j in eachnode(dg), i in eachnode(dg)275u_local = get_node_vars(u, equations, dg, i, j, element)276for noncons in 1:n_nonconservative_terms(volume_flux_noncons)277set_node_vars!(phi,278volume_flux_noncons(u_local, 1, equations,279NonConservativeLocal(), noncons),280equations, dg, noncons, i, j)281end282end283284for j in eachnode(dg), i in 1:(nnodes(dg) - 1)285# Conservative part286for v in eachvariable(equations)287value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j]288fhat_temp[v, i + 1, j] = value289fhat1_L[v, i + 1, j] = value290fhat1_R[v, i + 1, j] = value291end292# Nonconservative part293for noncons in 1:n_nonconservative_terms(volume_flux_noncons),294v in eachvariable(equations)295296value = fhat_noncons_temp[v, noncons, i, j] +297weights[i] * flux_noncons_temp[v, noncons, i, j]298fhat_noncons_temp[v, noncons, i + 1, j] = value299300fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value301fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] +302phi[v, noncons, i + 1, j] * value303end304end305306# Split form volume flux in orientation 2: y direction307flux_temp .= zero(eltype(flux_temp))308flux_noncons_temp .= zero(eltype(flux_noncons_temp))309310for j in eachnode(dg), i in eachnode(dg)311u_node = get_node_vars(u, equations, dg, i, j, element)312for jj in (j + 1):nnodes(dg)313u_node_jj = get_node_vars(u, equations, dg, i, jj, element)314flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations)315multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,316equations, dg, i, j)317multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,318equations, dg, i, jj)319for noncons in 1:n_nonconservative_terms(volume_flux_noncons)320# We multiply by 0.5 because that is done in other parts of Trixi321flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations,322NonConservativeSymmetric(), noncons)323multiply_add_to_node_vars!(flux_noncons_temp,3240.5 * derivative_split[j, jj],325flux2_noncons,326equations, dg, noncons, i, j)327multiply_add_to_node_vars!(flux_noncons_temp,3280.5 * derivative_split[jj, j],329flux2_noncons,330equations, dg, noncons, i, jj)331end332end333end334335# FV-form flux `fhat` in y direction336fhat_temp[:, :, 1] .= zero(eltype(fhat1_L))337fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L))338339# Compute local contribution to non-conservative flux340for j in eachnode(dg), i in eachnode(dg)341u_local = get_node_vars(u, equations, dg, i, j, element)342for noncons in 1:n_nonconservative_terms(volume_flux_noncons)343set_node_vars!(phi,344volume_flux_noncons(u_local, 2, equations,345NonConservativeLocal(), noncons),346equations, dg, noncons, i, j)347end348end349350for j in 1:(nnodes(dg) - 1), i in eachnode(dg)351# Conservative part352for v in eachvariable(equations)353value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j]354fhat_temp[v, i, j + 1] = value355fhat2_L[v, i, j + 1] = value356fhat2_R[v, i, j + 1] = value357end358# Nonconservative part359for noncons in 1:n_nonconservative_terms(volume_flux_noncons),360v in eachvariable(equations)361362value = fhat_noncons_temp[v, noncons, i, j] +363weights[j] * flux_noncons_temp[v, noncons, i, j]364fhat_noncons_temp[v, noncons, i, j + 1] = value365366fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value367fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] +368phi[v, noncons, i, j + 1] * value369end370end371372return nothing373end374375# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element376# (**with non-conservative terms in "local * jump" form**).377#378# See also `flux_differencing_kernel!`.379#380# The calculation of the non-conservative staggered "fluxes" requires non-conservative381# terms that can be written as a product of local and jump contributions.382@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,383::Type{<:TreeMesh{2}}, nonconservative_terms::True,384equations,385volume_flux::Tuple{F_CONS, F_NONCONS}, dg::DGSEM,386element,387cache) where {388F_CONS <: Function,389F_NONCONS <:390FluxNonConservative{NonConservativeJump()}391}392@unpack weights, derivative_split = dg.basis393@unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache394@unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache395396volume_flux_cons, volume_flux_noncons = volume_flux397398flux_temp = flux_temp_threaded[Threads.threadid()]399flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()]400401fhat_temp = fhat_temp_threaded[Threads.threadid()]402fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()]403phi = phi_threaded[Threads.threadid()]404405# The FV-form fluxes are calculated in a recursive manner, i.e.:406# fhat_(0,1) = w_0 * FVol_0,407# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,408# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).409410# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated411# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`412# and saved in in `flux_temp`.413414# Split form volume flux in orientation 1: x direction415flux_temp .= zero(eltype(flux_temp))416flux_noncons_temp .= zero(eltype(flux_noncons_temp))417418for j in eachnode(dg), i in eachnode(dg)419u_node = get_node_vars(u, equations, dg, i, j, element)420421# All diagonal entries of `derivative_split` are zero. Thus, we can skip422# the computation of the diagonal terms. In addition, we use the symmetry423# of `volume_flux_cons` and skew-symmetry of `volume_flux_noncons` to save half of the possible two-point flux424# computations.425for ii in (i + 1):nnodes(dg)426u_node_ii = get_node_vars(u, equations, dg, ii, j, element)427flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations)428multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,429equations, dg, i, j)430multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,431equations, dg, ii, j)432for noncons in 1:n_nonconservative_terms(volume_flux_noncons)433# We multiply by 0.5 because that is done in other parts of Trixi434flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations,435NonConservativeJump(),436noncons)437multiply_add_to_node_vars!(flux_noncons_temp,4380.5f0 * derivative_split[i, ii],439flux1_noncons,440equations, dg, noncons, i, j)441# Note the sign flip due to skew-symmetry when argument order is swapped442multiply_add_to_node_vars!(flux_noncons_temp,443-0.5f0 * derivative_split[ii, i],444flux1_noncons,445equations, dg, noncons, ii, j)446end447end448end449450# FV-form flux `fhat` in x direction451fhat_temp[:, 1, :] .= zero(eltype(fhat1_L))452fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L))453454# Compute local contribution to non-conservative flux455for j in eachnode(dg), i in eachnode(dg)456u_local = get_node_vars(u, equations, dg, i, j, element)457for noncons in 1:n_nonconservative_terms(volume_flux_noncons)458set_node_vars!(phi,459volume_flux_noncons(u_local, 1, equations,460NonConservativeLocal(), noncons),461equations, dg, noncons, i, j)462end463end464465for j in eachnode(dg), i in 1:(nnodes(dg) - 1)466# Conservative part467for v in eachvariable(equations)468value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j]469fhat_temp[v, i + 1, j] = value470fhat1_L[v, i + 1, j] = value471fhat1_R[v, i + 1, j] = value472end473# Nonconservative part474for noncons in 1:n_nonconservative_terms(volume_flux_noncons),475v in eachvariable(equations)476477value = fhat_noncons_temp[v, noncons, i, j] +478weights[i] * flux_noncons_temp[v, noncons, i, j]479fhat_noncons_temp[v, noncons, i + 1, j] = value480481fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value482fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] +483phi[v, noncons, i + 1, j] * value484end485end486487# Apply correction term to the flux-differencing formula for nonconservative local * jump fluxes.488for j in eachnode(dg)489u_0 = get_node_vars(u, equations, dg, 1, j, element)490for i in 2:(nnodes(dg) - 1)491u_i = get_node_vars(u, equations, dg, i, j, element)492for noncons in 1:n_nonconservative_terms(volume_flux_noncons)493phi_jump = volume_flux_noncons(u_0, u_i, 1, equations,494NonConservativeJump(), noncons)495496for v in eachvariable(equations)497# The factor of 2 is missing on each term because Trixi multiplies all the non-cons terms with 0.5498fhat1_R[v, i, j] -= phi[v, noncons, i, j] * phi_jump[v]499fhat1_L[v, i + 1, j] -= phi[v, noncons, i, j] * phi_jump[v]500end501end502end503u_N = get_node_vars(u, equations, dg, nnodes(dg), j, element)504for noncons in 1:n_nonconservative_terms(volume_flux_noncons)505phi_jump = volume_flux_noncons(u_0, u_N, 1, equations,506NonConservativeJump(), noncons)507508for v in eachvariable(equations)509# The factor of 2 is missing because Trixi multiplies all the non-cons terms with 0.5510fhat1_R[v, nnodes(dg), j] -= phi[v, noncons, nnodes(dg), j] *511phi_jump[v]512end513end514end515516########517518# Split form volume flux in orientation 2: y direction519flux_temp .= zero(eltype(flux_temp))520flux_noncons_temp .= zero(eltype(flux_noncons_temp))521522for j in eachnode(dg), i in eachnode(dg)523u_node = get_node_vars(u, equations, dg, i, j, element)524for jj in (j + 1):nnodes(dg)525u_node_jj = get_node_vars(u, equations, dg, i, jj, element)526flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations)527multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,528equations, dg, i, j)529multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,530equations, dg, i, jj)531for noncons in 1:n_nonconservative_terms(volume_flux_noncons)532# We multiply by 0.5 because that is done in other parts of Trixi533flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations,534NonConservativeJump(),535noncons)536multiply_add_to_node_vars!(flux_noncons_temp,5370.5 * derivative_split[j, jj],538flux2_noncons,539equations, dg, noncons, i, j)540# Note the sign flip due to skew-symmetry when argument order is swapped541multiply_add_to_node_vars!(flux_noncons_temp,542-0.5 * derivative_split[jj, j],543flux2_noncons,544equations, dg, noncons, i, jj)545end546end547end548549# FV-form flux `fhat` in y direction550fhat_temp[:, :, 1] .= zero(eltype(fhat1_L))551fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L))552553# Compute local contribution to non-conservative flux554for j in eachnode(dg), i in eachnode(dg)555u_local = get_node_vars(u, equations, dg, i, j, element)556for noncons in 1:n_nonconservative_terms(volume_flux_noncons)557set_node_vars!(phi,558volume_flux_noncons(u_local, 2, equations,559NonConservativeLocal(), noncons),560equations, dg, noncons, i, j)561end562end563564for j in 1:(nnodes(dg) - 1), i in eachnode(dg)565# Conservative part566for v in eachvariable(equations)567value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j]568fhat_temp[v, i, j + 1] = value569fhat2_L[v, i, j + 1] = value570fhat2_R[v, i, j + 1] = value571end572# Nonconservative part573for noncons in 1:n_nonconservative_terms(volume_flux_noncons),574v in eachvariable(equations)575576value = fhat_noncons_temp[v, noncons, i, j] +577weights[j] * flux_noncons_temp[v, noncons, i, j]578fhat_noncons_temp[v, noncons, i, j + 1] = value579580fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value581fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] +582phi[v, noncons, i, j + 1] * value583end584end585586# Apply correction term to the flux-differencing formula for nonconservative local * jump fluxes.587for i in eachnode(dg)588u_0 = get_node_vars(u, equations, dg, i, 1, element)589for j in 2:(nnodes(dg) - 1)590u_j = get_node_vars(u, equations, dg, i, j, element)591for noncons in 1:n_nonconservative_terms(volume_flux_noncons)592phi_jump = volume_flux_noncons(u_0, u_j, 2, equations,593NonConservativeJump(), noncons)594595for v in eachvariable(equations)596# The factor of 2 is missing on each term because Trixi multiplies all the non-cons terms with 0.5597fhat2_R[v, i, j] -= phi[v, noncons, i, j] * phi_jump[v]598fhat2_L[v, i, j + 1] -= phi[v, noncons, i, j] * phi_jump[v]599end600end601end602u_N = get_node_vars(u, equations, dg, i, nnodes(dg), element)603for noncons in 1:n_nonconservative_terms(volume_flux_noncons)604phi_jump = volume_flux_noncons(u_0, u_N, 2, equations,605NonConservativeJump(), noncons)606607for v in eachvariable(equations)608# The factor of 2 is missing cause Trixi multiplies all the non-cons terms with 0.5609fhat2_R[v, i, nnodes(dg)] -= phi[v, noncons, i, nnodes(dg)] *610phi_jump[v]611end612end613end614615return nothing616end617618# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems.619@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,620fstar1_L, fstar1_R, fstar2_L, fstar2_R, u,621::Type{<:Union{TreeMesh{2}, StructuredMesh{2},622P4estMesh{2}}},623have_nonconservative_terms::False, equations,624limiter::SubcellLimiterIDP, dg, element, cache)625@unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes626627# Due to the use of LGL nodes, the DG staggered fluxes `fhat` and FV fluxes `fstar` are equal628# on the element interfaces. So, they are not computed in the volume integral and set to zero629# in their respective computation.630# The antidiffusive fluxes are therefore zero on the element interfaces and don't need to be631# computed either. They are set to zero directly after resizing the container.632# This applies to the indices `i=1` and `i=nnodes(dg)+1` for `antidiffusive_flux1_L` and633# `antidiffusive_flux1_R` and analogously for the second direction.634635for j in eachnode(dg), i in 2:nnodes(dg)636for v in eachvariable(equations)637antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] -638fstar1_L[v, i, j]639antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j,640element]641end642end643for j in 2:nnodes(dg), i in eachnode(dg)644for v in eachvariable(equations)645antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] -646fstar2_L[v, i, j]647antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j,648element]649end650end651652return nothing653end654655# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems.656@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,657fstar1_L, fstar1_R, fstar2_L, fstar2_R, u,658::Type{<:Union{TreeMesh{2}, StructuredMesh{2},659P4estMesh{2}}},660have_nonconservative_terms::True, equations,661limiter::SubcellLimiterIDP, dg, element, cache)662@unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes663664for j in eachnode(dg), i in 2:nnodes(dg)665for v in eachvariable(equations)666antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] -667fstar1_L[v, i, j]668antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] -669fstar1_R[v, i, j]670end671end672for j in 2:nnodes(dg), i in eachnode(dg)673for v in eachvariable(equations)674antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] -675fstar2_L[v, i, j]676antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] -677fstar2_R[v, i, j]678end679end680681return nothing682end683end # @muladd684685686