Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgsem_tree/dg_2d_subcell_limiters.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_subcell_limiting(mesh::Union{TreeMesh{2}, StructuredMesh{2},
9
P4estMesh{2}},
10
equations,
11
volume_integral::VolumeIntegralSubcellLimiting,
12
dg::DG, cache_containers, uEltype)
13
cache = NamedTuple()
14
15
fhat1_L_threaded, fhat1_R_threaded,
16
fhat2_L_threaded, fhat2_R_threaded = create_f_threaded(mesh, equations, dg,
17
uEltype)
18
19
A3d = Array{uEltype, 3}
20
flux_temp_threaded = A3d[A3d(undef, nvariables(equations),
21
nnodes(dg), nnodes(dg))
22
for _ in 1:Threads.maxthreadid()]
23
fhat_temp_threaded = A3d[A3d(undef, nvariables(equations),
24
nnodes(dg), nnodes(dg))
25
for _ in 1:Threads.maxthreadid()]
26
27
n_elements = nelements(cache_containers.elements)
28
antidiffusive_fluxes = ContainerAntidiffusiveFlux2D{uEltype}(n_elements,
29
nvariables(equations),
30
nnodes(dg))
31
32
if have_nonconservative_terms(equations) == true
33
A4d = Array{uEltype, 4}
34
35
# Extract the nonconservative flux as a dispatch argument for `n_nonconservative_terms`
36
_, volume_flux_noncons = volume_integral.volume_flux_dg
37
38
flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations),
39
n_nonconservative_terms(volume_flux_noncons),
40
nnodes(dg), nnodes(dg))
41
for _ in 1:Threads.maxthreadid()]
42
fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations),
43
n_nonconservative_terms(volume_flux_noncons),
44
nnodes(dg), nnodes(dg))
45
for _ in 1:Threads.maxthreadid()]
46
phi_threaded = A4d[A4d(undef, nvariables(equations),
47
n_nonconservative_terms(volume_flux_noncons),
48
nnodes(dg), nnodes(dg))
49
for _ in 1:Threads.maxthreadid()]
50
cache = (; cache..., flux_nonconservative_temp_threaded,
51
fhat_nonconservative_temp_threaded, phi_threaded)
52
end
53
54
# The limiter cache was created with 0 elements
55
resize_subcell_limiter_cache!(dg.volume_integral.limiter, n_elements)
56
57
return (; cache..., antidiffusive_fluxes,
58
fhat1_L_threaded, fhat1_R_threaded,
59
fhat2_L_threaded, fhat2_R_threaded,
60
flux_temp_threaded, fhat_temp_threaded)
61
end
62
63
# Subcell limiting currently only implemented for certain mesh types
64
@inline function volume_integral_kernel!(du, u, element,
65
MeshT::Type{<:Union{TreeMesh{2},
66
StructuredMesh{2},
67
P4estMesh{2}}},
68
have_nonconservative_terms, equations,
69
volume_integral::VolumeIntegralSubcellLimiting,
70
dg::DGSEM, cache)
71
@unpack inverse_weights = dg.basis # Plays role of inverse DG-subcell sizes
72
@unpack volume_flux_dg, volume_flux_fv, limiter = volume_integral
73
74
# high-order DG fluxes
75
@unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache
76
77
fhat1_L = fhat1_L_threaded[Threads.threadid()]
78
fhat1_R = fhat1_R_threaded[Threads.threadid()]
79
fhat2_L = fhat2_L_threaded[Threads.threadid()]
80
fhat2_R = fhat2_R_threaded[Threads.threadid()]
81
calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, MeshT,
82
have_nonconservative_terms, equations, volume_flux_dg, dg, element,
83
cache)
84
85
# low-order FV fluxes
86
@unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache
87
88
fstar1_L = fstar1_L_threaded[Threads.threadid()]
89
fstar2_L = fstar2_L_threaded[Threads.threadid()]
90
fstar1_R = fstar1_R_threaded[Threads.threadid()]
91
fstar2_R = fstar2_R_threaded[Threads.threadid()]
92
calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, MeshT,
93
have_nonconservative_terms, equations, volume_flux_fv, dg, element,
94
cache)
95
96
# antidiffusive flux
97
calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,
98
fstar1_L, fstar1_R, fstar2_L, fstar2_R,
99
u, MeshT, have_nonconservative_terms, equations, limiter,
100
dg,
101
element, cache)
102
103
# Calculate volume integral contribution of low-order FV flux
104
for j in eachnode(dg), i in eachnode(dg)
105
for v in eachvariable(equations)
106
du[v, i, j, element] += inverse_weights[i] *
107
(fstar1_L[v, i + 1, j] - fstar1_R[v, i, j]) +
108
inverse_weights[j] *
109
(fstar2_L[v, i, j + 1] - fstar2_R[v, i, j])
110
end
111
end
112
113
return nothing
114
end
115
116
# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element
117
# (**without non-conservative terms**).
118
#
119
# See also `flux_differencing_kernel!`.
120
@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,
121
::Type{<:TreeMesh{2}},
122
have_nonconservative_terms::False,
123
equations,
124
volume_flux, dg::DGSEM, element, cache)
125
@unpack weights, derivative_split = dg.basis
126
@unpack flux_temp_threaded = cache
127
128
flux_temp = flux_temp_threaded[Threads.threadid()]
129
130
# The FV-form fluxes are calculated in a recursive manner, i.e.:
131
# fhat_(0,1) = w_0 * FVol_0,
132
# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,
133
# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).
134
135
# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated
136
# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`
137
# and saved in in `flux_temp`.
138
139
# Split form volume flux in orientation 1: x direction
140
flux_temp .= zero(eltype(flux_temp))
141
142
for j in eachnode(dg), i in eachnode(dg)
143
u_node = get_node_vars(u, equations, dg, i, j, element)
144
145
# All diagonal entries of `derivative_split` are zero. Thus, we can skip
146
# the computation of the diagonal terms. In addition, we use the symmetry
147
# of the `volume_flux` to save half of the possible two-point flux
148
# computations.
149
for ii in (i + 1):nnodes(dg)
150
u_node_ii = get_node_vars(u, equations, dg, ii, j, element)
151
flux1 = volume_flux(u_node, u_node_ii, 1, equations)
152
multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,
153
equations, dg, i, j)
154
multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,
155
equations, dg, ii, j)
156
end
157
end
158
159
# FV-form flux `fhat` in x direction
160
for j in eachnode(dg), i in 1:(nnodes(dg) - 1)
161
for v in eachvariable(equations)
162
fhat1_L[v, i + 1, j] = fhat1_L[v, i, j] + weights[i] * flux_temp[v, i, j]
163
fhat1_R[v, i + 1, j] = fhat1_L[v, i + 1, j]
164
end
165
end
166
167
# Split form volume flux in orientation 2: y direction
168
flux_temp .= zero(eltype(flux_temp))
169
170
for j in eachnode(dg), i in eachnode(dg)
171
u_node = get_node_vars(u, equations, dg, i, j, element)
172
for jj in (j + 1):nnodes(dg)
173
u_node_jj = get_node_vars(u, equations, dg, i, jj, element)
174
flux2 = volume_flux(u_node, u_node_jj, 2, equations)
175
multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,
176
equations, dg, i, j)
177
multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,
178
equations, dg, i, jj)
179
end
180
end
181
182
# FV-form flux `fhat` in y direction
183
for j in 1:(nnodes(dg) - 1), i in eachnode(dg)
184
for v in eachvariable(equations)
185
fhat2_L[v, i, j + 1] = fhat2_L[v, i, j] + weights[j] * flux_temp[v, i, j]
186
fhat2_R[v, i, j + 1] = fhat2_L[v, i, j + 1]
187
end
188
end
189
190
return nothing
191
end
192
193
# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element
194
# (**with non-conservative terms in "local * symmetric" form**).
195
#
196
# See also `flux_differencing_kernel!`.
197
#
198
# The calculation of the non-conservative staggered "fluxes" requires non-conservative
199
# terms that can be written as a product of local and a symmetric contributions. See, e.g.,
200
#
201
# - Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts
202
# Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
203
#
204
@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,
205
::Type{<:TreeMesh{2}}, have_nonconservative_terms::True,
206
equations,
207
volume_flux::Tuple{F_CONS, F_NONCONS}, dg::DGSEM,
208
element,
209
cache) where {
210
F_CONS <: Function,
211
F_NONCONS <:
212
FluxNonConservative{NonConservativeSymmetric()}
213
}
214
@unpack weights, derivative_split = dg.basis
215
@unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache
216
@unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache
217
218
volume_flux_cons, volume_flux_noncons = volume_flux
219
220
flux_temp = flux_temp_threaded[Threads.threadid()]
221
flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()]
222
223
fhat_temp = fhat_temp_threaded[Threads.threadid()]
224
fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()]
225
phi = phi_threaded[Threads.threadid()]
226
227
# The FV-form fluxes are calculated in a recursive manner, i.e.:
228
# fhat_(0,1) = w_0 * FVol_0,
229
# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,
230
# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).
231
232
# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated
233
# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`
234
# and saved in in `flux_temp`.
235
236
# Split form volume flux in orientation 1: x direction
237
flux_temp .= zero(eltype(flux_temp))
238
flux_noncons_temp .= zero(eltype(flux_noncons_temp))
239
240
for j in eachnode(dg), i in eachnode(dg)
241
u_node = get_node_vars(u, equations, dg, i, j, element)
242
243
# All diagonal entries of `derivative_split` are zero. Thus, we can skip
244
# the computation of the diagonal terms. In addition, we use the symmetry
245
# of `volume_flux_cons` and `volume_flux_noncons` to save half of the possible two-point flux
246
# computations.
247
for ii in (i + 1):nnodes(dg)
248
u_node_ii = get_node_vars(u, equations, dg, ii, j, element)
249
flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations)
250
multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,
251
equations, dg, i, j)
252
multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,
253
equations, dg, ii, j)
254
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
255
# We multiply by 0.5 because that is done in other parts of Trixi
256
flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations,
257
NonConservativeSymmetric(), noncons)
258
multiply_add_to_node_vars!(flux_noncons_temp,
259
0.5f0 * derivative_split[i, ii],
260
flux1_noncons,
261
equations, dg, noncons, i, j)
262
multiply_add_to_node_vars!(flux_noncons_temp,
263
0.5f0 * derivative_split[ii, i],
264
flux1_noncons,
265
equations, dg, noncons, ii, j)
266
end
267
end
268
end
269
270
# FV-form flux `fhat` in x direction
271
fhat_temp[:, 1, :] .= zero(eltype(fhat1_L))
272
fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L))
273
274
# Compute local contribution to non-conservative flux
275
for j in eachnode(dg), i in eachnode(dg)
276
u_local = get_node_vars(u, equations, dg, i, j, element)
277
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
278
set_node_vars!(phi,
279
volume_flux_noncons(u_local, 1, equations,
280
NonConservativeLocal(), noncons),
281
equations, dg, noncons, i, j)
282
end
283
end
284
285
for j in eachnode(dg), i in 1:(nnodes(dg) - 1)
286
# Conservative part
287
for v in eachvariable(equations)
288
value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j]
289
fhat_temp[v, i + 1, j] = value
290
fhat1_L[v, i + 1, j] = value
291
fhat1_R[v, i + 1, j] = value
292
end
293
# Nonconservative part
294
for noncons in 1:n_nonconservative_terms(volume_flux_noncons),
295
v in eachvariable(equations)
296
297
value = fhat_noncons_temp[v, noncons, i, j] +
298
weights[i] * flux_noncons_temp[v, noncons, i, j]
299
fhat_noncons_temp[v, noncons, i + 1, j] = value
300
301
fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value
302
fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] +
303
phi[v, noncons, i + 1, j] * value
304
end
305
end
306
307
# Split form volume flux in orientation 2: y direction
308
flux_temp .= zero(eltype(flux_temp))
309
flux_noncons_temp .= zero(eltype(flux_noncons_temp))
310
311
for j in eachnode(dg), i in eachnode(dg)
312
u_node = get_node_vars(u, equations, dg, i, j, element)
313
for jj in (j + 1):nnodes(dg)
314
u_node_jj = get_node_vars(u, equations, dg, i, jj, element)
315
flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations)
316
multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,
317
equations, dg, i, j)
318
multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,
319
equations, dg, i, jj)
320
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
321
# We multiply by 0.5 because that is done in other parts of Trixi
322
flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations,
323
NonConservativeSymmetric(), noncons)
324
multiply_add_to_node_vars!(flux_noncons_temp,
325
0.5 * derivative_split[j, jj],
326
flux2_noncons,
327
equations, dg, noncons, i, j)
328
multiply_add_to_node_vars!(flux_noncons_temp,
329
0.5 * derivative_split[jj, j],
330
flux2_noncons,
331
equations, dg, noncons, i, jj)
332
end
333
end
334
end
335
336
# FV-form flux `fhat` in y direction
337
fhat_temp[:, :, 1] .= zero(eltype(fhat1_L))
338
fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L))
339
340
# Compute local contribution to non-conservative flux
341
for j in eachnode(dg), i in eachnode(dg)
342
u_local = get_node_vars(u, equations, dg, i, j, element)
343
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
344
set_node_vars!(phi,
345
volume_flux_noncons(u_local, 2, equations,
346
NonConservativeLocal(), noncons),
347
equations, dg, noncons, i, j)
348
end
349
end
350
351
for j in 1:(nnodes(dg) - 1), i in eachnode(dg)
352
# Conservative part
353
for v in eachvariable(equations)
354
value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j]
355
fhat_temp[v, i, j + 1] = value
356
fhat2_L[v, i, j + 1] = value
357
fhat2_R[v, i, j + 1] = value
358
end
359
# Nonconservative part
360
for noncons in 1:n_nonconservative_terms(volume_flux_noncons),
361
v in eachvariable(equations)
362
363
value = fhat_noncons_temp[v, noncons, i, j] +
364
weights[j] * flux_noncons_temp[v, noncons, i, j]
365
fhat_noncons_temp[v, noncons, i, j + 1] = value
366
367
fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value
368
fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] +
369
phi[v, noncons, i, j + 1] * value
370
end
371
end
372
373
return nothing
374
end
375
376
# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element
377
# (**with non-conservative terms in "local * jump" form**).
378
#
379
# See also `flux_differencing_kernel!`.
380
#
381
# The calculation of the non-conservative staggered "fluxes" requires non-conservative
382
# terms that can be written as a product of local and jump contributions.
383
@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u,
384
::Type{<:TreeMesh{2}}, nonconservative_terms::True,
385
equations,
386
volume_flux::Tuple{F_CONS, F_NONCONS}, dg::DGSEM,
387
element,
388
cache) where {
389
F_CONS <: Function,
390
F_NONCONS <:
391
FluxNonConservative{NonConservativeJump()}
392
}
393
@unpack weights, derivative_split = dg.basis
394
@unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache
395
@unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache
396
397
volume_flux_cons, volume_flux_noncons = volume_flux
398
399
flux_temp = flux_temp_threaded[Threads.threadid()]
400
flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()]
401
402
fhat_temp = fhat_temp_threaded[Threads.threadid()]
403
fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()]
404
phi = phi_threaded[Threads.threadid()]
405
406
# The FV-form fluxes are calculated in a recursive manner, i.e.:
407
# fhat_(0,1) = w_0 * FVol_0,
408
# fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1,
409
# with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i).
410
411
# To use the symmetry of the `volume_flux`, the split form volume flux is precalculated
412
# like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing`
413
# and saved in in `flux_temp`.
414
415
# Split form volume flux in orientation 1: x direction
416
flux_temp .= zero(eltype(flux_temp))
417
flux_noncons_temp .= zero(eltype(flux_noncons_temp))
418
419
for j in eachnode(dg), i in eachnode(dg)
420
u_node = get_node_vars(u, equations, dg, i, j, element)
421
422
# All diagonal entries of `derivative_split` are zero. Thus, we can skip
423
# the computation of the diagonal terms. In addition, we use the symmetry
424
# of `volume_flux_cons` and skew-symmetry of `volume_flux_noncons` to save half of the possible two-point flux
425
# computations.
426
for ii in (i + 1):nnodes(dg)
427
u_node_ii = get_node_vars(u, equations, dg, ii, j, element)
428
flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations)
429
multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1,
430
equations, dg, i, j)
431
multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1,
432
equations, dg, ii, j)
433
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
434
# We multiply by 0.5 because that is done in other parts of Trixi
435
flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations,
436
NonConservativeJump(),
437
noncons)
438
multiply_add_to_node_vars!(flux_noncons_temp,
439
0.5f0 * derivative_split[i, ii],
440
flux1_noncons,
441
equations, dg, noncons, i, j)
442
# Note the sign flip due to skew-symmetry when argument order is swapped
443
multiply_add_to_node_vars!(flux_noncons_temp,
444
-0.5f0 * derivative_split[ii, i],
445
flux1_noncons,
446
equations, dg, noncons, ii, j)
447
end
448
end
449
end
450
451
# FV-form flux `fhat` in x direction
452
fhat_temp[:, 1, :] .= zero(eltype(fhat1_L))
453
fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L))
454
455
# Compute local contribution to non-conservative flux
456
for j in eachnode(dg), i in eachnode(dg)
457
u_local = get_node_vars(u, equations, dg, i, j, element)
458
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
459
set_node_vars!(phi,
460
volume_flux_noncons(u_local, 1, equations,
461
NonConservativeLocal(), noncons),
462
equations, dg, noncons, i, j)
463
end
464
end
465
466
for j in eachnode(dg), i in 1:(nnodes(dg) - 1)
467
# Conservative part
468
for v in eachvariable(equations)
469
value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j]
470
fhat_temp[v, i + 1, j] = value
471
fhat1_L[v, i + 1, j] = value
472
fhat1_R[v, i + 1, j] = value
473
end
474
# Nonconservative part
475
for noncons in 1:n_nonconservative_terms(volume_flux_noncons),
476
v in eachvariable(equations)
477
478
value = fhat_noncons_temp[v, noncons, i, j] +
479
weights[i] * flux_noncons_temp[v, noncons, i, j]
480
fhat_noncons_temp[v, noncons, i + 1, j] = value
481
482
fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value
483
fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] +
484
phi[v, noncons, i + 1, j] * value
485
end
486
end
487
488
# Apply correction term to the flux-differencing formula for nonconservative local * jump fluxes.
489
for j in eachnode(dg)
490
u_0 = get_node_vars(u, equations, dg, 1, j, element)
491
for i in 2:(nnodes(dg) - 1)
492
u_i = get_node_vars(u, equations, dg, i, j, element)
493
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
494
phi_jump = volume_flux_noncons(u_0, u_i, 1, equations,
495
NonConservativeJump(), noncons)
496
497
for v in eachvariable(equations)
498
# The factor of 2 is missing on each term because Trixi multiplies all the non-cons terms with 0.5
499
fhat1_R[v, i, j] -= phi[v, noncons, i, j] * phi_jump[v]
500
fhat1_L[v, i + 1, j] -= phi[v, noncons, i, j] * phi_jump[v]
501
end
502
end
503
end
504
u_N = get_node_vars(u, equations, dg, nnodes(dg), j, element)
505
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
506
phi_jump = volume_flux_noncons(u_0, u_N, 1, equations,
507
NonConservativeJump(), noncons)
508
509
for v in eachvariable(equations)
510
# The factor of 2 is missing because Trixi multiplies all the non-cons terms with 0.5
511
fhat1_R[v, nnodes(dg), j] -= phi[v, noncons, nnodes(dg), j] *
512
phi_jump[v]
513
end
514
end
515
end
516
517
########
518
519
# Split form volume flux in orientation 2: y direction
520
flux_temp .= zero(eltype(flux_temp))
521
flux_noncons_temp .= zero(eltype(flux_noncons_temp))
522
523
for j in eachnode(dg), i in eachnode(dg)
524
u_node = get_node_vars(u, equations, dg, i, j, element)
525
for jj in (j + 1):nnodes(dg)
526
u_node_jj = get_node_vars(u, equations, dg, i, jj, element)
527
flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations)
528
multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2,
529
equations, dg, i, j)
530
multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2,
531
equations, dg, i, jj)
532
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
533
# We multiply by 0.5 because that is done in other parts of Trixi
534
flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations,
535
NonConservativeJump(),
536
noncons)
537
multiply_add_to_node_vars!(flux_noncons_temp,
538
0.5 * derivative_split[j, jj],
539
flux2_noncons,
540
equations, dg, noncons, i, j)
541
# Note the sign flip due to skew-symmetry when argument order is swapped
542
multiply_add_to_node_vars!(flux_noncons_temp,
543
-0.5 * derivative_split[jj, j],
544
flux2_noncons,
545
equations, dg, noncons, i, jj)
546
end
547
end
548
end
549
550
# FV-form flux `fhat` in y direction
551
fhat_temp[:, :, 1] .= zero(eltype(fhat1_L))
552
fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L))
553
554
# Compute local contribution to non-conservative flux
555
for j in eachnode(dg), i in eachnode(dg)
556
u_local = get_node_vars(u, equations, dg, i, j, element)
557
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
558
set_node_vars!(phi,
559
volume_flux_noncons(u_local, 2, equations,
560
NonConservativeLocal(), noncons),
561
equations, dg, noncons, i, j)
562
end
563
end
564
565
for j in 1:(nnodes(dg) - 1), i in eachnode(dg)
566
# Conservative part
567
for v in eachvariable(equations)
568
value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j]
569
fhat_temp[v, i, j + 1] = value
570
fhat2_L[v, i, j + 1] = value
571
fhat2_R[v, i, j + 1] = value
572
end
573
# Nonconservative part
574
for noncons in 1:n_nonconservative_terms(volume_flux_noncons),
575
v in eachvariable(equations)
576
577
value = fhat_noncons_temp[v, noncons, i, j] +
578
weights[j] * flux_noncons_temp[v, noncons, i, j]
579
fhat_noncons_temp[v, noncons, i, j + 1] = value
580
581
fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value
582
fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] +
583
phi[v, noncons, i, j + 1] * value
584
end
585
end
586
587
# Apply correction term to the flux-differencing formula for nonconservative local * jump fluxes.
588
for i in eachnode(dg)
589
u_0 = get_node_vars(u, equations, dg, i, 1, element)
590
for j in 2:(nnodes(dg) - 1)
591
u_j = get_node_vars(u, equations, dg, i, j, element)
592
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
593
phi_jump = volume_flux_noncons(u_0, u_j, 2, equations,
594
NonConservativeJump(), noncons)
595
596
for v in eachvariable(equations)
597
# The factor of 2 is missing on each term because Trixi multiplies all the non-cons terms with 0.5
598
fhat2_R[v, i, j] -= phi[v, noncons, i, j] * phi_jump[v]
599
fhat2_L[v, i, j + 1] -= phi[v, noncons, i, j] * phi_jump[v]
600
end
601
end
602
end
603
u_N = get_node_vars(u, equations, dg, i, nnodes(dg), element)
604
for noncons in 1:n_nonconservative_terms(volume_flux_noncons)
605
phi_jump = volume_flux_noncons(u_0, u_N, 2, equations,
606
NonConservativeJump(), noncons)
607
608
for v in eachvariable(equations)
609
# The factor of 2 is missing cause Trixi multiplies all the non-cons terms with 0.5
610
fhat2_R[v, i, nnodes(dg)] -= phi[v, noncons, i, nnodes(dg)] *
611
phi_jump[v]
612
end
613
end
614
end
615
616
return nothing
617
end
618
619
# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems.
620
@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,
621
fstar1_L, fstar1_R, fstar2_L, fstar2_R, u,
622
::Type{<:Union{TreeMesh{2}, StructuredMesh{2},
623
P4estMesh{2}}},
624
have_nonconservative_terms::False, equations,
625
limiter::SubcellLimiterIDP, dg, element, cache)
626
@unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes
627
628
# Due to the use of LGL nodes, the DG staggered fluxes `fhat` and FV fluxes `fstar` are equal
629
# on the element interfaces. So, they are not computed in the volume integral and set to zero
630
# in their respective computation.
631
# The antidiffusive fluxes are therefore zero on the element interfaces and don't need to be
632
# computed either. They are set to zero directly after resizing the container.
633
# This applies to the indices `i=1` and `i=nnodes(dg)+1` for `antidiffusive_flux1_L` and
634
# `antidiffusive_flux1_R` and analogously for the second direction.
635
636
for j in eachnode(dg), i in 2:nnodes(dg)
637
for v in eachvariable(equations)
638
antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] -
639
fstar1_L[v, i, j]
640
antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j,
641
element]
642
end
643
end
644
for j in 2:nnodes(dg), i in eachnode(dg)
645
for v in eachvariable(equations)
646
antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] -
647
fstar2_L[v, i, j]
648
antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j,
649
element]
650
end
651
end
652
653
return nothing
654
end
655
656
# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems.
657
@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R,
658
fstar1_L, fstar1_R, fstar2_L, fstar2_R, u,
659
::Type{<:Union{TreeMesh{2}, StructuredMesh{2},
660
P4estMesh{2}}},
661
have_nonconservative_terms::True, equations,
662
limiter::SubcellLimiterIDP, dg, element, cache)
663
@unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes
664
665
for j in eachnode(dg), i in 2:nnodes(dg)
666
for v in eachvariable(equations)
667
antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] -
668
fstar1_L[v, i, j]
669
antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] -
670
fstar1_R[v, i, j]
671
end
672
end
673
for j in 2:nnodes(dg), i in eachnode(dg)
674
for v in eachvariable(equations)
675
antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] -
676
fstar2_L[v, i, j]
677
antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] -
678
fstar2_R[v, i, j]
679
end
680
end
681
682
return nothing
683
end
684
end # @muladd
685
686