• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

trixi-framework / Trixi.jl / 25071984038

28 Apr 2026 06:59PM UTC coverage: 82.771% (-14.4%) from 97.129%
25071984038

push

github

ranocha
set development version to v0.16.7-DEV

40010 of 48338 relevant lines covered (82.77%)

34288212.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/solvers/dgsem_tree/subcell_finite_volume_O2.jl
1
"""
2
    reconstruction_constant(u_ll, u_lr, u_rl, u_rr,
3
                            sc_interface_coords,
4
                            node_index, limiter, dg)
5

6
Returns the constant "reconstructed" values `u_lr, u_rl` at the interface `sc_interface_coords[node_index - 1]`.
7
Supposed to be used in conjunction with [`VolumeIntegralPureLGLFiniteVolumeO2`](@ref).
8
Formally first order accurate.
9
If a first-order finite volume scheme is desired, [`VolumeIntegralPureLGLFiniteVolume`](@ref) is an
10
equivalent, but more efficient choice.
11
"""
12
@inline function reconstruction_constant(u_ll, u_lr, u_rl, u_rr,
14,156,592✔
13
                                         sc_interface_coords, node_index,
14
                                         limiter, dg)
15
    return u_lr, u_rl
14,156,592✔
16
end
17

18
# Helper functions for reconstructions below
19
@inline function reconstruction_linear(u_lr, u_rl, s_l, s_r,
195,154,169✔
20
                                       x_lr, x_rl, sc_interface_coords, node_index)
21
    # Linear reconstruction at the interface
22
    u_lr = u_lr + s_l * (sc_interface_coords[node_index - 1] - x_lr)
195,154,169✔
23
    u_rl = u_rl + s_r * (sc_interface_coords[node_index - 1] - x_rl)
195,154,169✔
24

25
    return u_lr, u_rl
195,154,169✔
26
end
27

28
#             Reference element:             
29
#  -1 ------------------0------------------ 1 -> x
30
# Gauss-Lobatto-Legendre nodes (schematic for k = 3):
31
#   .          .                  .         .
32
#   ^          ^                  ^         ^
33
# Node indices:
34
#   1          2                  3         4
35
# The inner subcell boundaries are governed by the
36
# cumulative sum of the quadrature weights - 1 .
37
#  -1 ------------------0------------------ 1 -> x
38
#        w1-1      (w1+w2)-1   (w1+w2+w3)-1
39
#   |     |             |             |     |
40
# Note that only the inner boundaries are stored.
41
# Subcell interface indices, loop only over 2 -> nnodes(dg) = 4
42
#   1     2             3             4     5
43
#
44
# In general a four-point stencil is required, since we reconstruct the
45
# piecewise linear solution in both subcells next to the subcell interface.
46
# Since these subcell boundaries are not aligned with the DG nodes,
47
# on each neighboring subcell two linear solutions are reconstructed => 4 point stencil.
48
# For the outer interfaces the stencil shrinks since we do not consider values 
49
# outside the element (volume integral).
50
# 
51
# The left subcell node values are labelled `_ll` (left-left) and `_lr` (left-right), while
52
# the right subcell node values are labelled `_rl` (right-left) and `_rr` (right-right).
53

54
"""
55
    reconstruction_O2_full(u_ll, u_lr, u_rl, u_rr,
56
                           sc_interface_coords, node_index,
57
                           limiter, dg::DGSEM)
58

59
Returns the reconstructed values `u_lr, u_rl` at the interface `sc_interface_coords[node_index - 1]`.
60
Computes limited (linear) slopes on the subcells for a DGSEM element.
61
Supposed to be used in conjunction with [`VolumeIntegralPureLGLFiniteVolumeO2`](@ref).
62

63
The supplied `limiter` governs the choice of slopes given the nodal values
64
`u_ll`, `u_lr`, `u_rl`, and `u_rr` at the (Gauss-Lobatto Legendre) nodes.
65

66
**Symmetric** total-Variation-Diminishing (TVD) choices for the limiter are
67
    1) [`minmod`](@ref)
68
    2) [`monotonized_central`](@ref)
69
    3) [`superbee`](@ref)
70
    4) [`vanleer`](@ref)
71
    5) [`koren_symmetric`](@ref)
72
**Asymmetric** TVD limiters are also available, e.g.,
73
    1) [`koren`](@ref) for positive (right-going) velocities
74
    2) [`koren_flipped`](@ref) for negative (left-going) velocities
75

76
The reconstructed slopes are for `reconstruction_O2_full` not limited at the cell boundaries.
77
Formally second order accurate when used without a limiter, i.e., `limiter = `[`central_slope`](@ref).
78
This approach corresponds to equation (79) described in
79
- Rueda-Ramírez, Hennemann, Hindenlang, Winters, & Gassner (2021).
80
  "An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations.
81
   Part II: Subcell finite volume shock capturing"
82
  [JCP: 2021.110580](https://doi.org/10.1016/j.jcp.2021.110580)
83
"""
84
@inline function reconstruction_O2_full(u_ll, u_lr, u_rl, u_rr,
113,846,257✔
85
                                        sc_interface_coords, node_index,
86
                                        limiter, dg::DGSEM)
87
    @unpack nodes = dg.basis
113,846,257✔
88
    x_lr = nodes[node_index - 1]
113,846,257✔
89
    x_rl = nodes[node_index]
113,846,257✔
90

91
    # Slope between "middle" nodes
92
    s_m = (u_rl - u_lr) / (x_rl - x_lr)
113,846,257✔
93

94
    if node_index == 2 # Catch case ll == lr
113,846,257✔
95
        s_l = s_m # Use unlimited "central" slope
37,766,275✔
96
    else
97
        x_ll = nodes[node_index - 2]
76,079,982✔
98
        # Slope between "left" nodes
99
        s_lr = (u_lr - u_ll) / (x_lr - x_ll)
76,079,982✔
100
        # Select slope between extrapolated (left) and crossing (middle) slope
101
        s_l = limiter.(s_lr, s_m)
76,079,982✔
102
    end
103

104
    if node_index == nnodes(dg) # Catch case rl == rr
113,846,257✔
105
        s_r = s_m # Use unlimited "central" slope
37,766,275✔
106
    else
107
        x_rr = nodes[node_index + 1]
76,079,982✔
108
        # Slope between "right" nodes
109
        s_rl = (u_rr - u_rl) / (x_rr - x_rl)
76,079,982✔
110
        # Select slope between crossing (middle) and extrapolated (right) slope
111
        s_r = limiter.(s_m, s_rl)
76,079,982✔
112
    end
113

114
    return reconstruction_linear(u_lr, u_rl, s_l, s_r,
113,846,257✔
115
                                 x_lr, x_rl, sc_interface_coords, node_index)
116
end
117

118
"""
119
    reconstruction_O2_inner(u_ll, u_lr, u_rl, u_rr,
120
                            sc_interface_coords, node_index,
121
                            limiter, dg::DGSEM)
122

123
Returns the reconstructed values `u_lr, u_rl` at the interface `sc_interface_coords[node_index - 1]`.
124
Computes limited (linear) slopes on the *inner* subcells for a DGSEM element.
125
Supposed to be used in conjunction with [`VolumeIntegralPureLGLFiniteVolumeO2`](@ref).
126

127
The supplied `limiter` governs the choice of slopes given the nodal values
128
`u_ll`, `u_lr`, `u_rl`, and `u_rr` at the (Gauss-Lobatto Legendre) nodes.
129

130
**Symmetric** total-Variation-Diminishing (TVD) choices for the limiter are
131
    1) [`minmod`](@ref)
132
    2) [`monotonized_central`](@ref)
133
    3) [`superbee`](@ref)
134
    4) [`vanleer`](@ref)
135
    5) [`koren_symmetric`](@ref)
136
**Asymmetric** limiters are also available, e.g.,
137
    1) [`koren`](@ref) for dominantly positive velocities
138
    2) [`koren_flipped`](@ref) for dominantly negative velocities
139

140
For the outer, i.e., boundary subcells, constant values are used, i.e, no reconstruction.
141
This reduces the order of the scheme below 2.
142
This approach corresponds to equation (78) described in
143
- Rueda-Ramírez, Hennemann, Hindenlang, Winters, & Gassner (2021).
144
  "An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. 
145
   Part II: Subcell finite volume shock capturing"
146
  [JCP: 2021.110580](https://doi.org/10.1016/j.jcp.2021.110580)
147
"""
148
@inline function reconstruction_O2_inner(u_ll, u_lr, u_rl, u_rr,
81,307,912✔
149
                                         sc_interface_coords, node_index,
150
                                         limiter, dg::DGSEM)
151
    @unpack nodes = dg.basis
81,307,912✔
152
    x_lr = nodes[node_index - 1]
81,307,912✔
153
    x_rl = nodes[node_index]
81,307,912✔
154

155
    # Slope between "middle" nodes
156
    s_m = (u_rl - u_lr) / (x_rl - x_lr)
81,307,912✔
157

158
    if node_index == 2 # Catch case ll == lr
81,307,912✔
159
        # Do not reconstruct at the boundary
160
        s_l = zero(s_m)
26,285,694✔
161
    else
162
        x_ll = nodes[node_index - 2]
55,022,218✔
163
        # Slope between "left" nodes
164
        s_lr = (u_lr - u_ll) / (x_lr - x_ll)
55,022,218✔
165
        # Select slope between extrapolated (left) and crossing (middle) slope
166
        s_l = limiter.(s_lr, s_m)
55,022,218✔
167
    end
168

169
    if node_index == nnodes(dg) # Catch case rl == rr
81,307,912✔
170
        # Do not reconstruct at the boundary
171
        s_r = zero(s_m)
26,285,694✔
172
    else
173
        x_rr = nodes[node_index + 1]
55,022,218✔
174
        # Slope between "right" nodes
175
        s_rl = (u_rr - u_rl) / (x_rr - x_rl)
55,022,218✔
176
        # Select slope between crossing (middle) and extrapolated (right) slope
177
        s_r = limiter.(s_m, s_rl)
55,022,218✔
178
    end
179

180
    return reconstruction_linear(u_lr, u_rl, s_l, s_r,
81,307,912✔
181
                                 x_lr, x_rl, sc_interface_coords, node_index)
182
end
183

184
"""
185
    central_slope(sl, sr)
186

187
Central, non-TVD reconstruction given left and right slopes `sl` and `sr`.
188
Gives formally full order of accuracy at the expense of sacrificed nonlinear stability.
189
Similar in spirit to [`flux_central`](@ref).
190
"""
191
@inline function central_slope(sl, sr)
×
192
    return 0.5f0 * (sl + sr)
×
193
end
194

195
"""
196
    minmod(sl, sr)
197

198
Classic minmod limiter function for a TVD reconstruction given left and right slopes `sl` and `sr`.
199
There are many different ways how the minmod limiter can be implemented.
200
For reference, see for instance Eq. (6.27) in
201

202
- Randall J. LeVeque (2002)
203
  Finite Volume Methods for Hyperbolic Problems
204
  [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253)
205
"""
206
@inline function minmod(sl, sr)
772,123,556✔
207
    return 0.5f0 * (sign(sl) + sign(sr)) * min(abs(sl), abs(sr))
772,123,556✔
208
end
209

210
"""
211
    monotonized_central(sl, sr)
212

213
Monotonized central limiter function for a TVD reconstruction given left and right slopes `sl` and `sr`.
214
There are many different ways how the monotonized central limiter can be implemented.
215
For reference, see for instance Eq. (6.29) in
216

217
- Randall J. LeVeque (2002)
218
  Finite Volume Methods for Hyperbolic Problems
219
  [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253)
220
"""
221
@inline function monotonized_central(sl, sr)
84,697,920✔
222
    # Use recursive property of minmod function
223
    return minmod(0.5f0 * (sl + sr), 2 * minmod(sl, sr))
84,697,920✔
224
end
225

226
"""
227
    superbee(sl, sr)
228

229
Superbee limiter function for a TVD reconstruction given left and right slopes `sl` and `sr`.
230
There are many different ways how the superbee limiter can be implemented.
231
For reference, see for instance Eq. (6.28) in
232

233
- Randall J. LeVeque (2002)
234
  Finite Volume Methods for Hyperbolic Problems
235
  [DOI: 10.1017/CBO9780511791253](https://doi.org/10.1017/CBO9780511791253)
236
"""
237
@inline function superbee(sl, sr)
×
238
    return maxmod(minmod(sl, 2 * sr), minmod(2 * sl, sr))
×
239
end
240

241
"""
242
    vanleer(sl, sr)
243

244
Symmetric limiter by van Leer.
245
See for reference page 70 in 
246

247
- Siddhartha Mishra, Ulrik Skre Fjordholm and Rémi Abgrall
248
  Numerical methods for conservation laws and related equations.
249
  [Link](https://metaphor.ethz.ch/x/2019/hs/401-4671-00L/literature/mishra_hyperbolic_pdes.pdf)
250
"""
251
@inline function vanleer(sl, sr)
349,014,928✔
252
    if abs(sl) + abs(sr) > zero(sl)
349,014,928✔
253
        return (abs(sr) * sl + abs(sl) * sr) / (abs(sl) + abs(sr))
346,280,292✔
254
    else
255
        return zero(sl)
2,734,636✔
256
    end
257
end
258

259
"""
260
    koren(sl, sr)
261

262
**Asymmetric** limiter by Barry Koren, originally proposed in Chapter 5.2.2. of
263

264
- B. Koren (1993)
265
  A robust upwind discretization method for advection, diffusion and source terms.
266
  In: C.B. Vreugdenhil, B. Koren (eds): Numerical Methods for Advection-Diffusion Problems.
267
  Notes on Numerical Fluid Mechanics, Vol 15. Braunschweig/Wiesbaden.
268
  [URL](https://ir.cwi.nl/pub/2269/2269D.pdf)
269

270
A version in left/right slopes `sl, sr` is given by equations (14) and (15) in
271
- P. Jenny (2020)
272
  Time adaptive conservative finite volume method.
273
  [DOI:10.1016/j.jcp.2019.109067](https://doi.org/10.1016/j.jcp.2019.109067)
274

275
This limiter is biased for positive (right-going) velocities.
276
For the flipped version, which is biased for negative (left-going) velocities,
277
see [`koren_flipped`](@ref).
278
"""
279
@inline function koren(sl, sr)
32,704✔
280
    return minmod(2 * minmod(sl, sr), (sl + 2 * sr) / 3)
32,704✔
281
end
282

283
"""
284
    koren_flipped(sl, sr)
285

286
**Asymmetric** limiter by Barry Koren, flipped version biased for negative (left-going) velocities.
287
See [`koren`](@ref) for references.
288
"""
289
@inline function koren_flipped(sl, sr)
×
290
    return koren(sr, sl)
×
291
end
292

293
"""
294
    koren_symmetric(sl, sr)
295

296
**Symmetric** version of the [`koren`](@ref) limiter by Barry Koren.
297
Puts equal weight on left and right slopes.
298
"""
299
@inline function koren_symmetric(sl, sr)
×
300
    return minmod(2 * minmod(sl, sr), minmod(sl + 2 * sr, 2 * sl + sr) / 3)
×
301
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc