Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove normal_direction_ll for nonconservative terms #2062

Merged
merged 17 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions examples/structured_2d_dgsem/elixir_mhd_coupled.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ equations = IdealGlmMhdEquations2D(gamma)

cells_per_dimension = (32, 64)

# Extend the definition of the non-conservative Powell flux functions.
import Trixi.flux_nonconservative_powell
function flux_nonconservative_powell(u_ll, u_rr,
normal_direction_ll::AbstractVector,
equations::IdealGlmMhdEquations2D)
flux_nonconservative_powell(u_ll, u_rr, normal_direction_ll, normal_direction_ll,
equations)
end
volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell)
solver = DGSEM(polydeg = 3,
surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell),
Expand Down
4 changes: 2 additions & 2 deletions src/basic_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ struct BoundaryConditionDoNothing end
orientation_or_normal_direction,
direction::Integer, x, t, surface_flux,
equations)
return flux(u_inner, orientation_or_normal_direction, equations)
return surface_flux(u_inner, u_inner, orientation_or_normal_direction, equations)
amrueda marked this conversation as resolved.
Show resolved Hide resolved
end

# This version can be called by hyperbolic solvers on unstructured, curved meshes
@inline function (::BoundaryConditionDoNothing)(u_inner,
outward_direction::AbstractVector,
x, t, surface_flux, equations)
return flux(u_inner, outward_direction, equations)
return surface_flux(u_inner, u_inner, outward_direction, equations)
amrueda marked this conversation as resolved.
Show resolved Hide resolved
end

# This version can be called by parabolic solvers
Expand Down
27 changes: 8 additions & 19 deletions src/equations/ideal_glm_mhd_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,13 @@ end
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
equations::IdealGlmMhdEquations2D)
flux_nonconservative_powell(u_ll, u_rr,
normal_direction_ll ::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of
Powell and the Galilean nonconservative term associated with the GLM multiplier
of the [`IdealGlmMhdEquations2D`](@ref).

On curvilinear meshes, this nonconservative flux depends on both the
contravariant vector (normal direction) at the current node and the averaged
one. This is different from numerical fluxes used to discretize conservative
terms.

## References
amrueda marked this conversation as resolved.
Show resolved Hide resolved
- Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs,
Florian Hindenlang, Joachim Saur
Expand Down Expand Up @@ -254,8 +248,7 @@ terms.
end

@inline function flux_nonconservative_powell(u_ll, u_rr,
normal_direction_ll::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::IdealGlmMhdEquations2D)
rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll
rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr
Expand All @@ -265,14 +258,9 @@ end
v3_ll = rho_v3_ll / rho_ll
v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll

# Note that `v_dot_n_ll` uses the `normal_direction_ll` (contravariant vector
# at the same node location) while `B_dot_n_rr` uses the averaged normal
# direction. The reason for this is that `v_dot_n_ll` depends only on the left
# state and multiplies some gradient while `B_dot_n_rr` is used to compute
# the divergence of B.
v_dot_n_ll = v1_ll * normal_direction_ll[1] + v2_ll * normal_direction_ll[2]
B_dot_n_rr = B1_rr * normal_direction_average[1] +
B2_rr * normal_direction_average[2]
v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2]
B_dot_n_rr = B1_rr * normal_direction[1] +
B2_rr * normal_direction[2]

# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)
# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})
Expand Down Expand Up @@ -300,8 +288,9 @@ of the [`IdealGlmMhdEquations2D`](@ref).

This implementation uses a non-conservative term that can be written as the product
of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm
et al. (`flux_nonconservative_powell`) for conforming meshes but it yields different
results on non-conforming meshes(!).
et al. [`flux_nonconservative_powell`](@ref) for conforming meshes but it yields different
results on non-conforming meshes(!). On curvilinear meshes this formulation applies the
local normal direction compared to the averaged one used in [`flux_nonconservative_powell`](@ref).
patrickersing marked this conversation as resolved.
Show resolved Hide resolved

The two other flux functions with the same name return either the local
or symmetric portion of the non-conservative flux based on the type of the
Expand Down
26 changes: 7 additions & 19 deletions src/equations/ideal_glm_mhd_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,13 @@ end
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
equations::IdealGlmMhdEquations3D)
flux_nonconservative_powell(u_ll, u_rr,
normal_direction_ll ::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::IdealGlmMhdEquations3D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of
Powell and the Galilean nonconservative term associated with the GLM multiplier
of the [`IdealGlmMhdEquations3D`](@ref).

On curvilinear meshes, this nonconservative flux depends on both the
contravariant vector (normal direction) at the current node and the averaged
one. This is different from numerical fluxes used to discretize conservative
terms.

## References
amrueda marked this conversation as resolved.
Show resolved Hide resolved
- Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs,
Florian Hindenlang, Joachim Saur
Expand Down Expand Up @@ -292,8 +286,7 @@ terms.
end

@inline function flux_nonconservative_powell(u_ll, u_rr,
normal_direction_ll::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::IdealGlmMhdEquations3D)
rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll
rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr
Expand All @@ -303,16 +296,11 @@ end
v3_ll = rho_v3_ll / rho_ll
v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll

# Note that `v_dot_n_ll` uses the `normal_direction_ll` (contravariant vector
# at the same node location) while `B_dot_n_rr` uses the averaged normal
# direction. The reason for this is that `v_dot_n_ll` depends only on the left
# state and multiplies some gradient while `B_dot_n_rr` is used to compute
# the divergence of B.
v_dot_n_ll = v1_ll * normal_direction_ll[1] + v2_ll * normal_direction_ll[2] +
v3_ll * normal_direction_ll[3]
B_dot_n_rr = B1_rr * normal_direction_average[1] +
B2_rr * normal_direction_average[2] +
B3_rr * normal_direction_average[3]
v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] +
v3_ll * normal_direction[3]
B_dot_n_rr = B1_rr * normal_direction[1] +
B2_rr * normal_direction[2] +
B3_rr * normal_direction[3]

# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)
# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2,3}, 0, 0, 0, v_{1,2,3})
Expand Down
30 changes: 12 additions & 18 deletions src/equations/shallow_water_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,7 @@ end
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
equations::ShallowWaterEquations2D)
flux_nonconservative_wintermeyer_etal(u_ll, u_rr,
normal_direction_ll ::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term
Expand Down Expand Up @@ -303,26 +302,24 @@ Further details are available in the papers:
end

@inline function flux_nonconservative_wintermeyer_etal(u_ll, u_rr,
normal_direction_ll::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)
# Pull the necessary left and right state information
h_ll = waterheight(u_ll, equations)
b_jump = u_rr[4] - u_ll[4]

# Bottom gradient nonconservative term: (0, g h b_x, g h b_y, 0)
return SVector(0,
normal_direction_average[1] * equations.gravity * h_ll * b_jump,
normal_direction_average[2] * equations.gravity * h_ll * b_jump,
normal_direction[1] * equations.gravity * h_ll * b_jump,
normal_direction[2] * equations.gravity * h_ll * b_jump,
0)
end

"""
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
equations::ShallowWaterEquations2D)
flux_nonconservative_fjordholm_etal(u_ll, u_rr,
normal_direction_ll ::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux discretizing the nonconservative (source) term of
Expand Down Expand Up @@ -365,8 +362,7 @@ and for curvilinear 2D case in the paper:
end

@inline function flux_nonconservative_fjordholm_etal(u_ll, u_rr,
normal_direction_ll::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)
# Pull the necessary left and right state information
h_ll, _, _, b_ll = u_ll
Expand All @@ -376,8 +372,8 @@ end
b_jump = b_rr - b_ll

# Bottom gradient nonconservative term: (0, g h b_x, g h b_y, 0)
f2 = normal_direction_average[1] * equations.gravity * h_average * b_jump
f3 = normal_direction_average[2] * equations.gravity * h_average * b_jump
f2 = normal_direction[1] * equations.gravity * h_average * b_jump
f3 = normal_direction[2] * equations.gravity * h_average * b_jump

# First and last equations do not have a nonconservative flux
f1 = f4 = 0
Expand Down Expand Up @@ -424,8 +420,7 @@ end
flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer,
equations::ShallowWaterEquations2D)
flux_nonconservative_audusse_etal(u_ll, u_rr,
normal_direction_ll ::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term.
Expand Down Expand Up @@ -467,8 +462,7 @@ Further details for the hydrostatic reconstruction and its motivation can be fou
end

@inline function flux_nonconservative_audusse_etal(u_ll, u_rr,
normal_direction_ll::AbstractVector,
normal_direction_average::AbstractVector,
normal_direction::AbstractVector,
equations::ShallowWaterEquations2D)
# Pull the water height and bottom topography on the left
h_ll, _, _, b_ll = u_ll
Expand All @@ -479,8 +473,8 @@ end
# Copy the reconstructed water height for easier to read code
h_ll_star = u_ll_star[1]

f2 = normal_direction_average[1] * equations.gravity * (h_ll^2 - h_ll_star^2)
f3 = normal_direction_average[2] * equations.gravity * (h_ll^2 - h_ll_star^2)
f2 = normal_direction[1] * equations.gravity * (h_ll^2 - h_ll_star^2)
f3 = normal_direction[2] * equations.gravity * (h_ll^2 - h_ll_star^2)

# First and last equations do not have a nonconservative flux
f1 = f4 = 0
Expand Down
20 changes: 7 additions & 13 deletions src/solvers/dgmulti/dg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,7 @@ function calc_interface_flux!(cache, surface_integral::SurfaceIntegralWeakForm,
# Two notes on the use of `flux_nonconservative`:
# 1. In contrast to other mesh types, only one nonconservative part needs to be
# computed since we loop over the elements, not the unique interfaces.
# 2. In general, nonconservative fluxes can depend on both the contravariant
# vectors (normal direction) at the current node and the averaged ones. However,
# both are the same at watertight interfaces, so we pass `normal` twice.
nonconservative_part = flux_nonconservative(uM, uP, normal, normal,
equations)
nonconservative_part = flux_nonconservative(uM, uP, normal, equations)
# The factor 0.5 is necessary for the nonconservative fluxes based on the
# interpretation of global SBP operators.
flux_face_values[idM] = (conservative_part + 0.5 * nonconservative_part) *
Expand Down Expand Up @@ -556,14 +552,12 @@ function calc_single_boundary_flux!(cache, t, boundary_condition, boundary_key,
surface_flux, equations)

# Compute pointwise nonconservative numerical flux at the boundary.
# In general, nonconservative fluxes can depend on both the contravariant
# vectors (normal direction) at the current node and the averaged ones.
# However, there is only one `face_normal` at boundaries, which we pass in twice.
# Note: This does not set any type of boundary condition for the nonconservative term
noncons_flux_at_face_node = nonconservative_flux(u_face_values[i, f],
u_face_values[i, f],
face_normal, face_normal,
equations)
noncons_flux_at_face_node = boundary_condition(u_face_values[i, f],
face_normal,
face_coordinates,
t,
nonconservative_flux,
equations)

flux_face_values[i, f] = (cons_flux_at_face_node +
0.5 * noncons_flux_at_face_node) * Jf[i, f]
Expand Down
10 changes: 2 additions & 8 deletions src/solvers/dgmulti/flux_differencing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,7 @@ end
du_i = du[i]
for j in col_ids
u_j = u[j]
# The `normal_direction::AbstractVector` has to be passed in twice.
# This is because on curved meshes, nonconservative fluxes are
# evaluated using both the normal and its average at interfaces.
f_ij = volume_flux(u_i, u_j, normal_direction, normal_direction, equations)
f_ij = volume_flux(u_i, u_j, normal_direction, equations)
du_i = du_i + 2 * A[i, j] * f_ij
end
du[i] = du_i
Expand Down Expand Up @@ -176,11 +173,8 @@ end
for id in nzrange(A_base, i)
A_ij = vals[id]
j = rows[id]
# The `normal_direction::AbstractVector` has to be passed in twice.
# This is because on curved meshes, nonconservative fluxes are
# evaluated using both the normal and its average at interfaces.
u_j = u[j]
f_ij = volume_flux(u_i, u_j, normal_direction, normal_direction, equations)
f_ij = volume_flux(u_i, u_j, normal_direction, equations)
du_i = du_i + 2 * A_ij * f_ij
end
du[i] = du_i
Expand Down
18 changes: 5 additions & 13 deletions src/solvers/dgsem_p4est/dg_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,8 @@ end
flux_ = surface_flux(u_ll, u_rr, normal_direction, equations)

# Compute both nonconservative fluxes
# In general, nonconservative fluxes can depend on both the contravariant
# vectors (normal direction) at the current node and the averaged ones.
# However, both are the same at watertight interfaces, so we pass the
# `normal_direction` twice.
noncons_primary = nonconservative_flux(u_ll, u_rr, normal_direction,
normal_direction, equations)
noncons_secondary = nonconservative_flux(u_rr, u_ll, normal_direction,
normal_direction, equations)
noncons_primary = nonconservative_flux(u_ll, u_rr, normal_direction, equations)
noncons_secondary = nonconservative_flux(u_rr, u_ll, normal_direction, equations)

# Store the flux with nonconservative terms on the primary and secondary elements
for v in eachvariable(equations)
Expand Down Expand Up @@ -369,9 +363,8 @@ end
flux_ = boundary_condition(u_inner, normal_direction, x, t, surface_flux, equations)

# Compute pointwise nonconservative numerical flux at the boundary.
# Note: This does not set any type of boundary condition for the nonconservative term
noncons_ = nonconservative_flux(u_inner, u_inner, normal_direction,
normal_direction, equations)
noncons_ = boundary_condition(u_inner, normal_direction, x, t, nonconservative_flux,
equations)

# Copy flux to element storage in the correct orientation
for v in eachvariable(equations)
Expand Down Expand Up @@ -554,8 +547,7 @@ end
# The nonconservative flux is scaled by a factor of 0.5 based on
# the interpretation of global SBP operators coupled discontinuously via
# central fluxes/SATs
noncons = nonconservative_flux(u_ll, u_rr, normal_direction, normal_direction,
equations)
noncons = nonconservative_flux(u_ll, u_rr, normal_direction, equations)

flux_plus_noncons = flux + 0.5f0 * noncons

Expand Down
Loading
Loading