Path: blob/main/src/solvers/dgsem/calc_volume_integral.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: noindent67# The following `volume_integral_kernel!` and `calc_volume_integral!` functions are8# dimension and meshtype agnostic, i.e., valid for all 1D, 2D, and 3D meshes.910@inline function volume_integral_kernel!(du, u, element, MeshT,11have_nonconservative_terms, equations,12volume_integral::VolumeIntegralWeakForm,13dg, cache, alpha = true)14weak_form_kernel!(du, u, element, MeshT,15have_nonconservative_terms, equations,16dg, cache, alpha)1718return nothing19end2021@inline function volume_integral_kernel!(du, u, element, MeshT,22have_nonconservative_terms, equations,23volume_integral::VolumeIntegralFluxDifferencing,24dg, cache, alpha = true)25@unpack volume_flux = volume_integral # Volume integral specific data2627flux_differencing_kernel!(du, u, element, MeshT,28have_nonconservative_terms, equations,29volume_flux, dg, cache, alpha)3031return nothing32end3334@inline function volume_integral_kernel!(du, u, element, MeshT,35have_nonconservative_terms, equations,36volume_integral::VolumeIntegralPureLGLFiniteVolume,37dg::DGSEM, cache, alpha = true)38@unpack volume_flux_fv = volume_integral # Volume integral specific data3940fv_kernel!(du, u, MeshT,41have_nonconservative_terms, equations,42volume_flux_fv, dg, cache, element, alpha)4344return nothing45end4647@inline function volume_integral_kernel!(du, u, element, MeshT,48have_nonconservative_terms, equations,49volume_integral::VolumeIntegralPureLGLFiniteVolumeO2,50dg::DGSEM, cache, alpha = true)51# Unpack volume integral specific data52@unpack (sc_interface_coords, volume_flux_fv, reconstruction_mode, slope_limiter,53cons2recon, recon2cons) = volume_integral5455fvO2_kernel!(du, u, MeshT,56have_nonconservative_terms, equations,57volume_flux_fv, dg, cache, element,58sc_interface_coords, reconstruction_mode, slope_limiter,59cons2recon, recon2cons,60alpha)6162return nothing63end6465@inline function volume_integral_kernel!(du, u, element, MeshT,66have_nonconservative_terms, equations,67volume_integral::VolumeIntegralAdaptive{<:IndicatorEntropyChange},68dg::DGSEM, cache)69@unpack volume_integral_default, volume_integral_stabilized, indicator = volume_integral70@unpack maximum_entropy_increase = indicator7172volume_integral_kernel!(du, u, element, MeshT,73have_nonconservative_terms, equations,74volume_integral_default, dg, cache)7576# Compute entropy production of the default volume integral.77# Minus sign because of the flipped sign of the volume term in the DG RHS.78# No scaling by inverse Jacobian here, as there is no Jacobian multiplication79# in `integrate_reference_element`.80dS_default = -entropy_change_reference_element(du, u, element,81MeshT, equations, dg, cache)8283# Compute true entropy change given by surface integral of the entropy potential84dS_true = surface_integral_reference_element(entropy_potential, u, element,85MeshT, equations, dg, cache)8687entropy_change = dS_default - dS_true88if entropy_change > maximum_entropy_increase # Recompute using EC FD volume integral89# Reset default volume integral contribution.90# Note that this assumes that the volume terms are computed first,91# before any surface terms are added.92du[.., element] .= zero(eltype(du))9394volume_integral_kernel!(du, u, element, MeshT,95have_nonconservative_terms, equations,96volume_integral_stabilized, dg, cache)97end9899return nothing100end101102@inline function volume_integral_kernel!(du, u, element, MeshT,103have_nonconservative_terms, equations,104volume_integral::VolumeIntegralEntropyCorrection,105dg::DGSEM, cache)106@unpack volume_integral_default, volume_integral_stabilized, indicator = volume_integral107@unpack scaling = indicator108@unpack alpha = indicator.cache109du_element_threaded = indicator.cache.volume_integral_values_threaded110111# run default volume integral112volume_integral_kernel!(du, u, element, MeshT,113have_nonconservative_terms, equations,114volume_integral_default, dg, cache)115116# Check entropy production of "high order" volume integral.117#118# Note that, for `TreeMesh`, `dS_volume_integral` and `dS_true` are calculated119# on the reference element. For other mesh types, because ``dS_volume_integral`120# incorporates the scaled contravariant vectors, `dS_true` should121# be calculated on the physical element instead.122#123# Minus sign because of the flipped sign of the volume term in the DG RHS.124# No scaling by inverse Jacobian here, as there is no Jacobian multiplication125# in `integrate_reference_element`.126dS_volume_integral = -entropy_change_reference_element(du, u, element,127MeshT, equations,128dg, cache)129130# Compute true entropy change given by surface integral of the entropy potential131dS_true = surface_integral_reference_element(entropy_potential, u, element,132MeshT, equations, dg, cache)133134# This quantity should be ≤ 0 for an entropy stable volume integral, and135# exactly zero for an entropy conservative volume integral.136entropy_residual = dS_volume_integral - dS_true137138if entropy_residual > 0139# Store "high order" result140du_FD_element = du_element_threaded[Threads.threadid()]141@views du_FD_element .= du[.., element]142143# Reset pure flux-differencing volume integral144# Note that this assumes that the volume terms are computed first,145# before any surface terms are added.146du[.., element] .= zero(eltype(du))147148# Calculate entropy stable volume integral contribution149volume_integral_kernel!(du, u, element, MeshT,150have_nonconservative_terms, equations,151volume_integral_stabilized, dg, cache)152153dS_volume_integral_stabilized = -entropy_change_reference_element(du, u,154element,155MeshT,156equations, dg,157cache)158159# Calculate difference between high and low order FV entropy production;160# this should provide positive entropy dissipation if `entropy_residual > 0`,161# assuming the stabilized volume integral is entropy stable.162entropy_dissipation = dS_volume_integral_stabilized - dS_volume_integral163164# Calculate DG-FV blending factor165ratio = regularized_ratio(-entropy_residual, entropy_dissipation)166alpha_element = min(1, scaling * ratio) # TODO: replacing this with a differentiable version of `min`167168# Save blending coefficient for visualization169alpha[element] = alpha_element170171# Blend the high order method back in172@views du[.., element] .= alpha_element .* du[.., element] .+173(1 - alpha_element) .* du_FD_element174end175176return nothing177end178179function calc_volume_integral!(backend::Nothing, du, u, mesh,180have_nonconservative_terms, equations,181volume_integral, dg::DGSEM, cache)182@threaded for element in eachelement(dg, cache)183volume_integral_kernel!(du, u, element, typeof(mesh),184have_nonconservative_terms, equations,185volume_integral, dg, cache)186end187188return nothing189end190191function calc_volume_integral!(backend::Backend, du, u, mesh,192have_nonconservative_terms, equations,193volume_integral, dg::DGSEM, cache)194nelements(dg, cache) == 0 && return nothing195kernel! = volume_integral_KAkernel!(backend)196kernel_cache = kernel_filter_cache(cache)197kernel!(du, u, typeof(mesh), have_nonconservative_terms, equations,198volume_integral, dg, kernel_cache,199ndrange = nelements(dg, cache))200return nothing201end202203@kernel function volume_integral_KAkernel!(du, u, MeshT,204have_nonconservative_terms, equations,205volume_integral, dg::DGSEM, cache)206element = @index(Global)207volume_integral_kernel!(du, u, element, MeshT, have_nonconservative_terms,208equations, volume_integral, dg, cache)209end210211@inline function calc_volume_integral!(backend::Nothing, du, u, mesh,212have_nonconservative_terms, equations,213volume_integral::VolumeIntegralAdaptive{<:IndicatorHennemannGassner},214dg::DGSEM, cache)215@unpack volume_integral_default, volume_integral_stabilized, indicator = volume_integral216217# Calculate a-priori stabilization indicator218alpha = @trixi_timeit timer() "indicator" indicator(u, mesh, equations,219dg, cache)220221# For `Float64`, this gives 1.8189894035458565e-12222# For `Float32`, this gives 1.1920929f-5223RealT = eltype(alpha)224atol = max(100 * eps(RealT), eps(RealT)^convert(RealT, 0.75f0))225@threaded for element in eachelement(dg, cache)226alpha_element = alpha[element]227# Clip blending factor for values close to zero (-> default volume integral)228default_volume_integral = isapprox(alpha_element, 0, atol = atol)229230if default_volume_integral231volume_integral_kernel!(du, u, element, typeof(mesh),232have_nonconservative_terms, equations,233volume_integral_default, dg, cache)234else235volume_integral_kernel!(du, u, element, typeof(mesh),236have_nonconservative_terms, equations,237volume_integral_stabilized, dg, cache)238end239end240241return nothing242end243244function calc_volume_integral!(backend::Nothing, du, u, mesh,245have_nonconservative_terms, equations,246volume_integral::VolumeIntegralShockCapturingHGType,247dg::DGSEM, cache)248@unpack (indicator, volume_integral_default,249volume_integral_blend_high_order, volume_integral_blend_low_order) = volume_integral250251# Calculate DG-FV blending factors α a-priori for: u_{DG-FV} = u_DG * (1 - α) + u_FV * α252alpha = @trixi_timeit timer() "blending factors" indicator(u, mesh, equations,253dg, cache)254255# For `Float64`, this gives 1.8189894035458565e-12256# For `Float32`, this gives 1.1920929f-5257RealT = eltype(alpha)258atol = max(100 * eps(RealT), eps(RealT)^convert(RealT, 0.75f0))259@threaded for element in eachelement(dg, cache)260alpha_element = alpha[element]261# Clip blending factor for values close to zero (-> pure DG)262dg_only = isapprox(alpha_element, 0, atol = atol)263264if dg_only265volume_integral_kernel!(du, u, element, typeof(mesh),266have_nonconservative_terms, equations,267volume_integral_default, dg, cache)268else269# Calculate DG volume integral contribution270volume_integral_kernel!(du, u, element, typeof(mesh),271have_nonconservative_terms, equations,272volume_integral_blend_high_order, dg, cache,2731 - alpha_element)274275# Calculate FV volume integral contribution276volume_integral_kernel!(du, u, element, typeof(mesh),277have_nonconservative_terms, equations,278volume_integral_blend_low_order, dg, cache,279alpha_element)280end281end282283return nothing284end285286function calc_volume_integral!(backend::Nothing, du, u, mesh,287have_nonconservative_terms, equations,288volume_integral::VolumeIntegralEntropyCorrectionShockCapturingCombined,289dg::DGSEM, cache)290(; volume_integral_default, volume_integral_stabilized, indicator) = volume_integral291(; indicator_entropy_correction, indicator_shock_capturing) = indicator292(; scaling) = indicator_entropy_correction293du_element_threaded = indicator_entropy_correction.cache.volume_integral_values_threaded294295# Calculate DG-FV blending factors α a-priori for: u_{DG-FV} = u_DG * (1 - α) + u_FV * α296# Note that we also reuse the `alpha_shock_capturing` array to store the indicator values for visualization.297alpha_shock_capturing = @trixi_timeit timer() "blending factors" indicator_shock_capturing(u,298mesh,299equations,300dg,301cache)302303@threaded for element in eachelement(dg, cache)304# run default volume integral305volume_integral_kernel!(du, u, element, typeof(mesh),306have_nonconservative_terms, equations,307volume_integral_default, dg, cache)308309# Check entropy production of "high order" volume integral.310#311# Note that, for `TreeMesh`, both volume and surface integrals are calculated312# on the reference element. For other mesh types, because the volume integral313# incorporates the scaled contravariant vectors, the surface integral should314# be calculated on the physical element instead.315#316# Minus sign because of the flipped sign of the volume term in the DG RHS.317# No scaling by inverse Jacobian here, as there is no Jacobian multiplication318# in `integrate_reference_element`.319dS_volume_integral = -entropy_change_reference_element(du, u, element,320typeof(mesh), equations,321dg, cache)322323# Compute true entropy change given by surface integral of the entropy potential324dS_true = surface_integral_reference_element(entropy_potential, u, element,325typeof(mesh), equations, dg, cache)326327# This quantity should be ≤ 0 for an entropy stable volume integral, and328# exactly zero for an entropy conservative volume integral.329entropy_residual = dS_volume_integral - dS_true330331if entropy_residual > 0332# Store "high order" result333du_FD_element = du_element_threaded[Threads.threadid()]334@views du_FD_element .= du[.., element]335336# Reset pure flux-differencing volume integral337# Note that this assumes that the volume terms are computed first,338# before any surface terms are added.339du[.., element] .= zero(eltype(du))340341# Calculate entropy stable volume integral contribution342volume_integral_kernel!(du, u, element, typeof(mesh),343have_nonconservative_terms, equations,344volume_integral_stabilized, dg, cache)345346dS_volume_integral_stabilized = -entropy_change_reference_element(du, u,347element,348typeof(mesh),349equations,350dg,351cache)352353# Calculate difference between high and low order FV entropy production;354# this should provide positive entropy dissipation if `entropy_residual > 0`,355# assuming the stabilized volume integral is entropy stable.356entropy_dissipation = dS_volume_integral_stabilized - dS_volume_integral357358# Calculate DG-FV blending factor as the minimum between the entropy correction359# indicator and shock capturing indicator360# TODO: replacing this with a differentiable version of `min`361ratio = regularized_ratio(-entropy_residual, entropy_dissipation)362alpha_element = min(1, max(alpha_shock_capturing[element], scaling * ratio))363364# Save blending coefficient for visualization. Note that we overwrite the data365# in `alpha_shock_capturing[element]`.366alpha_shock_capturing[element] = alpha_element367368# Blend the high order method back in369@views du[.., element] .= alpha_element .* du[.., element] .+370(1 - alpha_element) .* du_FD_element371end372end373374return nothing375end376end # @muladd377378379