Path: blob/main/src/solvers/dgsem_p4est/dg_3d_subcell_limiters.jl
5616 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: noindent67# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element8# (**without non-conservative terms**).9#10# See also `flux_differencing_kernel!`.11@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fhat3_L, fhat3_R,12u, ::Type{<:P4estMesh{3}},13nonconservative_terms::False, equations,14volume_flux, dg::DGSEM, element, cache)15(; contravariant_vectors) = cache.elements16(; weights, derivative_split) = dg.basis17(; flux_temp_threaded) = cache1819flux_temp = flux_temp_threaded[Threads.threadid()]2021# The FV-form fluxes are calculated in a recursive manner, i.e.:22# fhat_(0,1) = w_0 * FVol_0,23# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,24# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).2526# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated27# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`28# and saved in in `flux_temp`.2930# Split form volume flux in orientation 1: x direction31flux_temp .= zero(eltype(flux_temp))3233for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)34u_node = get_node_vars(u, equations, dg, i, j, k, element)3536# pull the contravariant vectors in each coordinate direction37Ja1_node = get_contravariant_vector(1, contravariant_vectors,38i, j, k, element) # x direction3940# All diagonal entries of `derivative_split` are zero. Thus, we can skip41# the computation of the diagonal terms. In addition, we use the symmetry42# of the `volume_flux` to save half of the possible two-point flux43# computations.4445# x direction46for ii in (i + 1):nnodes(dg)47u_node_ii = get_node_vars(u, equations, dg, ii, j, k, element)48# pull the contravariant vectors and compute the average49Ja1_node_ii = get_contravariant_vector(1, contravariant_vectors,50ii, j, k, element)51Ja1_avg = 0.5f0 * (Ja1_node + Ja1_node_ii)5253# compute the contravariant sharp flux in the direction of the averaged contravariant vector54fluxtilde1 = volume_flux(u_node, u_node_ii, Ja1_avg, equations)55multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], fluxtilde1,56equations, dg, i, j, k)57multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], fluxtilde1,58equations, dg, ii, j, k)59end60end6162# FV-form flux `fhat` in x direction63for k in eachnode(dg), j in eachnode(dg), i in 1:(nnodes(dg) - 1)64for v in eachvariable(equations)65fhat1_L[v, i + 1, j, k] = fhat1_L[v, i, j, k] +66weights[i] * flux_temp[v, i, j, k]67fhat1_R[v, i + 1, j, k] = fhat1_L[v, i + 1, j, k]68end69end7071# Split form volume flux in orientation 2: y direction72flux_temp .= zero(eltype(flux_temp))7374for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)75u_node = get_node_vars(u, equations, dg, i, j, k, element)7677# pull the contravariant vectors in each coordinate direction78Ja2_node = get_contravariant_vector(2, contravariant_vectors,79i, j, k, element)8081# y direction82for jj in (j + 1):nnodes(dg)83u_node_jj = get_node_vars(u, equations, dg, i, jj, k, element)84# pull the contravariant vectors and compute the average85Ja2_node_jj = get_contravariant_vector(2, contravariant_vectors,86i, jj, k, element)87Ja2_avg = 0.5f0 * (Ja2_node + Ja2_node_jj)88# compute the contravariant sharp flux in the direction of the averaged contravariant vector89fluxtilde2 = volume_flux(u_node, u_node_jj, Ja2_avg, equations)90multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], fluxtilde2,91equations, dg, i, j, k)92multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], fluxtilde2,93equations, dg, i, jj, k)94end95end9697# FV-form flux `fhat` in y direction98for k in eachnode(dg), j in 1:(nnodes(dg) - 1), i in eachnode(dg)99for v in eachvariable(equations)100fhat2_L[v, i, j + 1, k] = fhat2_L[v, i, j, k] +101weights[j] * flux_temp[v, i, j, k]102fhat2_R[v, i, j + 1, k] = fhat2_L[v, i, j + 1, k]103end104end105106# Split form volume flux in orientation 3: z direction107flux_temp .= zero(eltype(flux_temp))108109for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)110u_node = get_node_vars(u, equations, dg, i, j, k, element)111112# pull the contravariant vectors in each coordinate direction113Ja3_node = get_contravariant_vector(3, contravariant_vectors,114i, j, k, element)115116# z direction117for kk in (k + 1):nnodes(dg)118u_node_kk = get_node_vars(u, equations, dg, i, j, kk, element)119# pull the contravariant vectors and compute the average120Ja3_node_kk = get_contravariant_vector(3, contravariant_vectors,121i, j, kk, element)122Ja3_avg = 0.5f0 * (Ja3_node + Ja3_node_kk)123# compute the contravariant sharp flux in the direction of the averaged contravariant vector124fluxtilde3 = volume_flux(u_node, u_node_kk, Ja3_avg, equations)125multiply_add_to_node_vars!(flux_temp, derivative_split[k, kk], fluxtilde3,126equations, dg, i, j, k)127multiply_add_to_node_vars!(flux_temp, derivative_split[kk, k], fluxtilde3,128equations, dg, i, j, kk)129end130end131132# FV-form flux `fhat` in z direction133for k in 1:(nnodes(dg) - 1), j in eachnode(dg), i in eachnode(dg)134for v in eachvariable(equations)135fhat3_L[v, i, j, k + 1] = fhat3_L[v, i, j, k] +136weights[k] * flux_temp[v, i, j, k]137fhat3_R[v, i, j, k + 1] = fhat3_L[v, i, j, k + 1]138end139end140141return nothing142end143144# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element145# (**with non-conservative terms in "local * symmetric" form**).146#147# See also `flux_differencing_kernel!`.148#149# The calculation of the non-conservative staggered "fluxes" requires non-conservative150# terms that can be written as a product of local and a symmetric contributions. See, e.g.,151#152# - Rueda-RamÃrez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts153# Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.154#155@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, fhat3_L, fhat3_R,156u, ::Type{<:P4estMesh{3}},157nonconservative_terms::True, equations,158volume_flux::Tuple{F_CONS, F_NONCONS}, dg::DGSEM,159element,160cache) where {161F_CONS <: Function,162F_NONCONS <:163FluxNonConservative{NonConservativeSymmetric()}164}165(; contravariant_vectors) = cache.elements166(; weights, derivative_split) = dg.basis167(; flux_temp_threaded, flux_nonconservative_temp_threaded) = cache168(; fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded) = cache169170volume_flux_cons, volume_flux_noncons = volume_flux171172flux_temp = flux_temp_threaded[Threads.threadid()]173flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()]174175fhat_temp = fhat_temp_threaded[Threads.threadid()]176fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()]177phi = phi_threaded[Threads.threadid()]178179# The FV-form fluxes are calculated in a recursive manner, i.e.:180# fhat_(0,1) = w_0 * FVol_0,181# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,182# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).183184# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated185# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`186# and saved in in `flux_temp`.187188# Split form volume flux in orientation 1: x direction189flux_temp .= zero(eltype(flux_temp))190flux_noncons_temp .= zero(eltype(flux_noncons_temp))191192for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)193u_node = get_node_vars(u, equations, dg, i, j, k, element)194195# pull the contravariant vectors in each coordinate direction196Ja1_node = get_contravariant_vector(1, contravariant_vectors,197i, j, k, element) # x direction198199# All diagonal entries of `derivative_split` are zero. Thus, we can skip200# the computation of the diagonal terms. In addition, we use the symmetry201# of `volume_flux_cons` and `volume_flux_noncons` to save half of the possible two-point flux202# computations.203for ii in (i + 1):nnodes(dg)204u_node_ii = get_node_vars(u, equations, dg, ii, j, k, element)205# pull the contravariant vectors and compute the average206Ja1_node_ii = get_contravariant_vector(1, contravariant_vectors,207ii, j, k, element)208Ja1_avg = 0.5f0 * (Ja1_node + Ja1_node_ii)209210# compute the contravariant sharp flux in the direction of the averaged contravariant vector211fluxtilde1 = volume_flux_cons(u_node, u_node_ii, Ja1_avg, equations)212multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], fluxtilde1,213equations, dg, i, j, k)214multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], fluxtilde1,215equations, dg, ii, j, k)216for noncons in 1:n_nonconservative_terms(volume_flux_noncons)217# We multiply by 0.5 because that is done in other parts of Trixi218flux1_noncons = volume_flux_noncons(u_node, u_node_ii, Ja1_avg,219equations,220NonConservativeSymmetric(), noncons)221multiply_add_to_node_vars!(flux_noncons_temp,2220.5f0 * derivative_split[i, ii],223flux1_noncons,224equations, dg, noncons, i, j, k)225multiply_add_to_node_vars!(flux_noncons_temp,2260.5f0 * derivative_split[ii, i],227flux1_noncons,228equations, dg, noncons, ii, j, k)229end230end231end232233# FV-form flux `fhat` in x direction234fhat_temp[:, 1, :, :] .= zero(eltype(fhat1_L))235fhat_noncons_temp[:, :, 1, :, :] .= zero(eltype(fhat1_L))236237# Compute local contribution to non-conservative flux238for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)239u_local = get_node_vars(u, equations, dg, i, j, k, element)240# pull the local contravariant vector241Ja1_node = get_contravariant_vector(1, contravariant_vectors, i, j, k, element)242for noncons in 1:n_nonconservative_terms(volume_flux_noncons)243set_node_vars!(phi,244volume_flux_noncons(u_local, Ja1_node, equations,245NonConservativeLocal(), noncons),246equations, dg, noncons, i, j, k)247end248end249250for k in eachnode(dg), j in eachnode(dg), i in 1:(nnodes(dg) - 1)251# Conservative part252for v in eachvariable(equations)253value = fhat_temp[v, i, j, k] + weights[i] * flux_temp[v, i, j, k]254fhat_temp[v, i + 1, j, k] = value255fhat1_L[v, i + 1, j, k] = value256fhat1_R[v, i + 1, j, k] = value257end258# Nonconservative part259for noncons in 1:n_nonconservative_terms(volume_flux_noncons),260v in eachvariable(equations)261262value = fhat_noncons_temp[v, noncons, i, j, k] +263weights[i] * flux_noncons_temp[v, noncons, i, j, k]264fhat_noncons_temp[v, noncons, i + 1, j, k] = value265266fhat1_L[v, i + 1, j, k] = fhat1_L[v, i + 1, j, k] +267phi[v, noncons, i, j, k] * value268fhat1_R[v, i + 1, j, k] = fhat1_R[v, i + 1, j, k] +269phi[v, noncons, i + 1, j, k] * value270end271end272273# Split form volume flux in orientation 2: y direction274flux_temp .= zero(eltype(flux_temp))275flux_noncons_temp .= zero(eltype(flux_noncons_temp))276277for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)278u_node = get_node_vars(u, equations, dg, i, j, k, element)279280# pull the contravariant vectors in each coordinate direction281Ja2_node = get_contravariant_vector(2, contravariant_vectors,282i, j, k, element)283284for jj in (j + 1):nnodes(dg)285u_node_jj = get_node_vars(u, equations, dg, i, jj, k, element)286# pull the contravariant vectors and compute the average287Ja2_node_jj = get_contravariant_vector(2, contravariant_vectors,288i, jj, k, element)289Ja2_avg = 0.5f0 * (Ja2_node + Ja2_node_jj)290# compute the contravariant sharp flux in the direction of the averaged contravariant vector291fluxtilde2 = volume_flux_cons(u_node, u_node_jj, Ja2_avg, equations)292multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], fluxtilde2,293equations, dg, i, j, k)294multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], fluxtilde2,295equations, dg, i, jj, k)296for noncons in 1:n_nonconservative_terms(volume_flux_noncons)297# We multiply by 0.5 because that is done in other parts of Trixi298flux2_noncons = volume_flux_noncons(u_node, u_node_jj, Ja2_avg,299equations,300NonConservativeSymmetric(), noncons)301multiply_add_to_node_vars!(flux_noncons_temp,3020.5f0 * derivative_split[j, jj],303flux2_noncons,304equations, dg, noncons, i, j, k)305multiply_add_to_node_vars!(flux_noncons_temp,3060.5f0 * derivative_split[jj, j],307flux2_noncons,308equations, dg, noncons, i, jj, k)309end310end311end312313# FV-form flux `fhat` in y direction314fhat_temp[:, :, 1, :] .= zero(eltype(fhat1_L))315fhat_noncons_temp[:, :, :, 1, :] .= zero(eltype(fhat1_L))316317# Compute local contribution to non-conservative flux318for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)319u_local = get_node_vars(u, equations, dg, i, j, k, element)320# pull the local contravariant vector321Ja2_node = get_contravariant_vector(2, contravariant_vectors, i, j, k, element)322for noncons in 1:n_nonconservative_terms(volume_flux_noncons)323set_node_vars!(phi,324volume_flux_noncons(u_local, Ja2_node, equations,325NonConservativeLocal(), noncons),326equations, dg, noncons, i, j, k)327end328end329330for k in eachnode(dg), j in 1:(nnodes(dg) - 1), i in eachnode(dg)331# Conservative part332for v in eachvariable(equations)333value = fhat_temp[v, i, j, k] + weights[j] * flux_temp[v, i, j, k]334fhat_temp[v, i, j + 1, k] = value335fhat2_L[v, i, j + 1, k] = value336fhat2_R[v, i, j + 1, k] = value337end338# Nonconservative part339for noncons in 1:n_nonconservative_terms(volume_flux_noncons),340v in eachvariable(equations)341342value = fhat_noncons_temp[v, noncons, i, j, k] +343weights[j] * flux_noncons_temp[v, noncons, i, j, k]344fhat_noncons_temp[v, noncons, i, j + 1, k] = value345346fhat2_L[v, i, j + 1, k] = fhat2_L[v, i, j + 1, k] +347phi[v, noncons, i, j, k] * value348fhat2_R[v, i, j + 1, k] = fhat2_R[v, i, j + 1, k] +349phi[v, noncons, i, j + 1, k] * value350end351end352353# Split form volume flux in orientation 3: z direction354flux_temp .= zero(eltype(flux_temp))355flux_noncons_temp .= zero(eltype(flux_noncons_temp))356357for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)358u_node = get_node_vars(u, equations, dg, i, j, k, element)359360# pull the contravariant vectors in each coordinate direction361Ja3_node = get_contravariant_vector(3, contravariant_vectors,362i, j, k, element)363364for kk in (k + 1):nnodes(dg)365u_node_kk = get_node_vars(u, equations, dg, i, j, kk, element)366# pull the contravariant vectors and compute the average367Ja3_node_kk = get_contravariant_vector(3, contravariant_vectors,368i, j, kk, element)369Ja3_avg = 0.5f0 * (Ja3_node + Ja3_node_kk)370# compute the contravariant sharp flux in the direction of the averaged contravariant vector371fluxtilde3 = volume_flux_cons(u_node, u_node_kk, Ja3_avg, equations)372multiply_add_to_node_vars!(flux_temp, derivative_split[k, kk], fluxtilde3,373equations, dg, i, j, k)374multiply_add_to_node_vars!(flux_temp, derivative_split[kk, k], fluxtilde3,375equations, dg, i, j, kk)376for noncons in 1:n_nonconservative_terms(volume_flux_noncons)377# We multiply by 0.5 because that is done in other parts of Trixi378flux3_noncons = volume_flux_noncons(u_node, u_node_kk, Ja3_avg,379equations,380NonConservativeSymmetric(), noncons)381multiply_add_to_node_vars!(flux_noncons_temp,3820.5f0 * derivative_split[k, kk],383flux3_noncons,384equations, dg, noncons, i, j, k)385multiply_add_to_node_vars!(flux_noncons_temp,3860.5f0 * derivative_split[kk, k],387flux3_noncons,388equations, dg, noncons, i, j, kk)389end390end391end392393# FV-form flux `fhat` in z direction394fhat_temp[:, :, :, 1] .= zero(eltype(fhat1_L))395fhat_noncons_temp[:, :, :, :, 1] .= zero(eltype(fhat1_L))396397# Compute local contribution to non-conservative flux398for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)399u_local = get_node_vars(u, equations, dg, i, j, k, element)400# pull the local contravariant vector401Ja3_node = get_contravariant_vector(3, contravariant_vectors, i, j, k, element)402for noncons in 1:n_nonconservative_terms(volume_flux_noncons)403set_node_vars!(phi,404volume_flux_noncons(u_local, Ja3_node, equations,405NonConservativeLocal(), noncons),406equations, dg, noncons, i, j, k)407end408end409410for k in 1:(nnodes(dg) - 1), j in eachnode(dg), i in eachnode(dg)411# Conservative part412for v in eachvariable(equations)413value = fhat_temp[v, i, j, k] + weights[k] * flux_temp[v, i, j, k]414fhat_temp[v, i, j, k + 1] = value415fhat3_L[v, i, j, k + 1] = value416fhat3_R[v, i, j, k + 1] = value417end418# Nonconservative part419for noncons in 1:n_nonconservative_terms(volume_flux_noncons),420v in eachvariable(equations)421422value = fhat_noncons_temp[v, noncons, i, j, k] +423weights[k] * flux_noncons_temp[v, noncons, i, j, k]424fhat_noncons_temp[v, noncons, i, j, k + 1] = value425426fhat3_L[v, i, j, k + 1] = fhat3_L[v, i, j, k + 1] +427phi[v, noncons, i, j, k] * value428fhat3_R[v, i, j, k + 1] = fhat3_R[v, i, j, k + 1] +429phi[v, noncons, i, j, k + 1] * value430end431end432433return nothing434end435end # @muladd436437438