Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgmulti/volume_integral_adaptive.jl
5591 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
function create_cache(mesh::DGMultiMesh, equations,
9
dg::DGMulti{NDIMS, ElemType, <:Polynomial,
10
<:SurfaceIntegralWeakForm,
11
<:VolumeIntegralAdaptive{<:IndicatorEntropyChange,
12
<:VolumeIntegralWeakForm,
13
<:VolumeIntegralFluxDifferencing}},
14
RealT, uEltype) where {NDIMS, ElemType}
15
# Construct temporary solvers for each sub-integral to reuse the `create_cache` functions
16
17
# `VolumeIntegralAdaptive` for `DGMulti` currently limited to Weak Form & Flux Differencing combi
18
dg_WF = DG(dg.basis, dg.mortar, dg.surface_integral,
19
dg.volume_integral.volume_integral_default)
20
dg_FD = DG(dg.basis, dg.mortar, dg.surface_integral,
21
dg.volume_integral.volume_integral_stabilized)
22
23
cache_WF = create_cache(mesh, equations, dg_WF, RealT, uEltype)
24
cache_FD = create_cache(mesh, equations, dg_FD, RealT, uEltype)
25
26
# Set up structures required for `IndicatorEntropyChange`
27
rd = dg.basis
28
nvars = nvariables(equations)
29
30
# Required for entropy change computation (`entropy_change_reference_element`)
31
du_values = similar(cache_FD.solution_container.u_values)
32
33
# Thread-local buffer for face interpolation, which is required
34
# for computation of entropy potential at interpolated face nodes
35
# (`surface_integral_reference_element`)
36
u_face_local_threaded = [allocate_nested_array(uEltype, nvars, (rd.Nfq,), dg)
37
for _ in 1:Threads.maxthreadid()]
38
39
return (; cache_FD...,
40
# Weak-form-specific fields for the default volume integral
41
weak_differentiation_matrices = cache_WF.weak_differentiation_matrices,
42
flux_threaded = cache_WF.flux_threaded,
43
rotated_flux_threaded = cache_WF.rotated_flux_threaded, # For non-affine meshes
44
# Required for `IndicatorEntropyChange`
45
du_values, u_face_local_threaded)
46
end
47
48
# version for affine meshes (currently only supported one for `VolumeIntegralAdaptive`)
49
function calc_volume_integral!(du, u, mesh::DGMultiMesh,
50
have_nonconservative_terms::False, equations,
51
volume_integral::VolumeIntegralAdaptive{<:IndicatorEntropyChange},
52
dg::DGMultiFluxDiff, cache)
53
@unpack volume_integral_default, volume_integral_stabilized = volume_integral
54
@unpack maximum_entropy_increase = volume_integral.indicator
55
56
# For weak form integral
57
@unpack u_values = cache.solution_container
58
59
# For entropy production computation
60
rd = dg.basis
61
@unpack du_values = cache
62
63
# interpolate to quadrature points
64
apply_to_each_field(mul_by!(rd.Vq), u_values, u) # required for weak form trial
65
66
@threaded for e in eachelement(dg, cache)
67
# Try default volume integral first
68
volume_integral_kernel!(du, u, e, mesh,
69
have_nonconservative_terms, equations,
70
volume_integral_default, dg, cache)
71
72
# Interpolate `du` to quadrature points after WF integral for entropy production calculation
73
du_local = view(du, :, e)
74
du_values_local = view(du_values, :, e)
75
apply_to_each_field(mul_by!(rd.Vq), du_values_local, du_local) # required for entropy production calculation
76
77
# Compute entropy production of this volume integral
78
u_values_local = view(u_values, :, e)
79
dS_WF = -entropy_change_reference_element(du_values_local, u_values_local,
80
mesh, equations,
81
dg, cache)
82
83
dS_true = surface_integral_reference_element(entropy_potential, u, e,
84
mesh, equations, dg, cache)
85
86
entropy_change = dS_WF - dS_true
87
if entropy_change > maximum_entropy_increase # Recompute using EC FD volume integral
88
# Reset default volume integral contribution.
89
# Note that this assumes that the volume terms are computed first,
90
# before any surface terms are added.
91
fill!(du_local, zero(eltype(du_local)))
92
93
# Recompute using stabilized volume integral. Note that the calculation of this volume integral requires the calculation of the entropy projection, which is done in `rhs!` specialized on the `DGMultiFluxDiff` solver type.
94
volume_integral_kernel!(du, u, e, mesh,
95
have_nonconservative_terms, equations,
96
volume_integral_stabilized, dg, cache)
97
end
98
end
99
100
return nothing
101
end
102
end # @muladd
103
104