|
| 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 perform_idp_correction!(u, dt, |
| 9 | + mesh::P4estMesh{3}, |
| 10 | + equations, dg, cache) |
| 11 | + @unpack inverse_weights = dg.basis # Plays role of DG subcell sizes |
| 12 | + @unpack antidiffusive_flux1_L, antidiffusive_flux1_R, antidiffusive_flux2_L, antidiffusive_flux2_R, antidiffusive_flux3_L, antidiffusive_flux3_R = cache.antidiffusive_fluxes |
| 13 | + @unpack alpha = dg.volume_integral.limiter.cache.subcell_limiter_coefficients |
| 14 | + |
| 15 | + @threaded for element in eachelement(dg, cache) |
| 16 | + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) |
| 17 | + # Sign switch as in apply_jacobian! |
| 18 | + inverse_jacobian = -get_inverse_jacobian(cache.elements.inverse_jacobian, |
| 19 | + mesh, i, j, k, element) |
| 20 | + |
| 21 | + # Note: For LGL nodes, the high-order and low-order fluxes at element interfaces are equal. |
| 22 | + # Therefore, the antidiffusive fluxes are zero. |
| 23 | + # To avoid accessing zero entries, we directly use zero vectors instead. |
| 24 | + if i > 1 # Not at "left" boundary node |
| 25 | + alpha1 = max(alpha[i - 1, j, k, element], alpha[i, j, k, element]) |
| 26 | + alpha_flux1 = (1 - alpha1) * |
| 27 | + get_node_vars(antidiffusive_flux1_R, equations, dg, |
| 28 | + i, j, k, element) |
| 29 | + else # At "left" boundary node |
| 30 | + alpha_flux1 = zero(SVector{nvariables(equations), eltype(u)}) |
| 31 | + end |
| 32 | + if i < nnodes(dg) # Not at "right" boundary node |
| 33 | + alpha1_ip1 = max(alpha[i, j, k, element], alpha[i + 1, j, k, element]) |
| 34 | + alpha_flux1_ip1 = (1 - alpha1_ip1) * |
| 35 | + get_node_vars(antidiffusive_flux1_L, equations, dg, |
| 36 | + i + 1, j, k, element) |
| 37 | + else # At "right" boundary node |
| 38 | + alpha_flux1_ip1 = zero(SVector{nvariables(equations), eltype(u)}) |
| 39 | + end |
| 40 | + if j > 1 # Not at "bottom" boundary node |
| 41 | + alpha2 = max(alpha[i, j - 1, k, element], alpha[i, j, k, element]) |
| 42 | + alpha_flux2 = (1 - alpha2) * |
| 43 | + get_node_vars(antidiffusive_flux2_R, equations, dg, |
| 44 | + i, j, k, element) |
| 45 | + else # At "bottom" boundary node |
| 46 | + alpha_flux2 = zero(SVector{nvariables(equations), eltype(u)}) |
| 47 | + end |
| 48 | + if j < nnodes(dg) # Not at "top" boundary node |
| 49 | + alpha2_jp1 = max(alpha[i, j, k, element], alpha[i, j + 1, k, element]) |
| 50 | + alpha_flux2_jp1 = (1 - alpha2_jp1) * |
| 51 | + get_node_vars(antidiffusive_flux2_L, equations, dg, |
| 52 | + i, j + 1, k, element) |
| 53 | + else # At "top" boundary node |
| 54 | + alpha_flux2_jp1 = zero(SVector{nvariables(equations), eltype(u)}) |
| 55 | + end |
| 56 | + if k > 1 # Not at "front" boundary node |
| 57 | + alpha3 = max(alpha[i, j, k - 1, element], alpha[i, j, k, element]) |
| 58 | + alpha_flux3 = (1 - alpha3) * |
| 59 | + get_node_vars(antidiffusive_flux3_R, equations, dg, |
| 60 | + i, j, k, element) |
| 61 | + else # At "front" boundary node |
| 62 | + alpha_flux3 = zero(SVector{nvariables(equations), eltype(u)}) |
| 63 | + end |
| 64 | + if k < nnodes(dg) # Not at "back" boundary node |
| 65 | + alpha3_kp1 = max(alpha[i, j, k, element], alpha[i, j, k + 1, element]) |
| 66 | + alpha_flux3_kp1 = (1 - alpha3_kp1) * |
| 67 | + get_node_vars(antidiffusive_flux3_L, equations, dg, |
| 68 | + i, j, k + 1, element) |
| 69 | + else # At "back" boundary node |
| 70 | + alpha_flux3_kp1 = zero(SVector{nvariables(equations), eltype(u)}) |
| 71 | + end |
| 72 | + |
| 73 | + for v in eachvariable(equations) |
| 74 | + u[v, i, j, k, element] += dt * inverse_jacobian * |
| 75 | + (inverse_weights[i] * |
| 76 | + (alpha_flux1_ip1[v] - alpha_flux1[v]) + |
| 77 | + inverse_weights[j] * |
| 78 | + (alpha_flux2_jp1[v] - alpha_flux2[v]) + |
| 79 | + inverse_weights[k] * |
| 80 | + (alpha_flux3_kp1[v] - alpha_flux3[v])) |
| 81 | + end |
| 82 | + end |
| 83 | + end |
| 84 | + |
| 85 | + return nothing |
| 86 | +end |
| 87 | +end # @muladd |
0 commit comments