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

L2 Mortars for Parabolic Terms on TreeMeshes #1571

Merged
merged 64 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
0bbe913
First try mortars for parabolic terms
DanielDoehring Jul 17, 2023
fb4efa9
Use correct interface values in calc_fstar!
DanielDoehring Jul 17, 2023
db048cb
Format parabolic 2d dgsem
DanielDoehring Jul 17, 2023
f8c3403
Remove unused function parameters
DanielDoehring Jul 18, 2023
e9d16c7
L2 Mortars for 3D DGSEM TreeMesh
DanielDoehring Jul 18, 2023
a9185a5
Format
DanielDoehring Jul 18, 2023
90ce643
Back to original example
DanielDoehring Jul 18, 2023
b37774e
Dispatch 2D DGSEm rhs_parabolic for p4est and classic tree
DanielDoehring Jul 18, 2023
2149cfd
Re-use standard prolong2mortars in gradient comp
DanielDoehring Jul 18, 2023
e0fda81
Merge branch 'main' into MortarsParabolic
ranocha Jul 18, 2023
06a8488
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 19, 2023
e3ad723
Back to original version
DanielDoehring Jul 19, 2023
b751d40
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jul 19, 2023
567938c
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 19, 2023
7e732c7
Add tests for L2 mortars for hyp-para
DanielDoehring Jul 20, 2023
1a26201
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jul 20, 2023
f5b1e62
remove whitespaces
DanielDoehring Jul 20, 2023
e6969cf
Use original analysis callback
DanielDoehring Jul 20, 2023
46ec996
Test Taylor-Green with different integrator
DanielDoehring Jul 20, 2023
051b2bf
Remove whitespace
DanielDoehring Jul 21, 2023
04199a4
check coverage status
DanielDoehring Jul 23, 2023
db785d9
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 23, 2023
290a41f
Stick to CK2N54 for 3D test
DanielDoehring Jul 24, 2023
ac37b7e
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 24, 2023
6dc252b
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 25, 2023
491c923
Add more explicit dispatch
DanielDoehring Jul 25, 2023
5b5d433
Less invasive treatment for mortars and p4est
DanielDoehring Jul 25, 2023
bb68ee3
Revert "Add more explicit dispatch"
DanielDoehring Jul 25, 2023
073612e
Merge branch 'MortarsParabolicP4estCompat' into MortarsParabolic
DanielDoehring Jul 25, 2023
7f816e2
More explicit dispatch
DanielDoehring Jul 25, 2023
6cdca4a
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 25, 2023
e05d112
Remove additional end
DanielDoehring Jul 25, 2023
38e731d
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jul 25, 2023
a17b1bd
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 26, 2023
5247b4e
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 26, 2023
e539f41
Merge branch 'main' into MortarsParabolic
ranocha Jul 28, 2023
c1db7ac
Remove doubled implementations
DanielDoehring Jul 28, 2023
be3b067
kepp main updated with true main
DanielDoehring Jul 28, 2023
3a82e4a
Add comment
DanielDoehring Jul 29, 2023
83b54f8
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jul 29, 2023
5650162
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 29, 2023
e66b831
comment parabolic 3d
DanielDoehring Jul 29, 2023
1c8efd5
Merge branch 'main' into MortarsParabolic
DanielDoehring Jul 30, 2023
b7bd74f
whitespace
DanielDoehring Jul 30, 2023
797d2d5
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jul 30, 2023
06a4196
Avoid allocations in parabolic boundary fluxes
DanielDoehring Jul 31, 2023
7f9c752
Merge branch 'main' into main
DanielDoehring Jul 31, 2023
6ac6011
Merge branch 'main' into MortarsParabolic
DanielDoehring Aug 1, 2023
c9bb0ee
Update src/solvers/dgsem_tree/dg_2d_parabolic.jl
DanielDoehring Aug 1, 2023
d7f2568
Update src/solvers/dgsem_tree/dg_3d_parabolic.jl
DanielDoehring Aug 1, 2023
a1f3e99
Update src/solvers/dgsem_tree/dg_3d_parabolic.jl
DanielDoehring Aug 1, 2023
207b253
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Aug 1, 2023
9dff7de
revert alloc BC (other PR)
DanielDoehring Aug 2, 2023
0936b3b
Revert alloc BC (other PR)
DanielDoehring Aug 2, 2023
67e064a
Name & News
DanielDoehring Aug 2, 2023
0b51b32
Update NEWS.md
DanielDoehring Aug 2, 2023
d13bf12
Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl
DanielDoehring Aug 8, 2023
15fe6b2
Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl
DanielDoehring Aug 8, 2023
1caa657
Check allocations
DanielDoehring Aug 8, 2023
ac15951
Merge branch 'MortarsParabolic' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Aug 8, 2023
f433665
Merge branch 'main' into MortarsParabolic
DanielDoehring Aug 8, 2023
2b1124d
Merge branch 'main' into MortarsParabolic
DanielDoehring Aug 8, 2023
f5974f0
Merge branch 'main' into MortarsParabolic
ranocha Aug 9, 2023
28ebfac
Merge branch 'main' into MortarsParabolic
DanielDoehring Aug 9, 2023
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
347 changes: 344 additions & 3 deletions src/solvers/dgsem_tree/dg_2d_parabolic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,18 @@ function rhs_parabolic!(du, u, t, mesh::Union{TreeMesh{2}, P4estMesh{2}},
dg.surface_integral, dg)
end

# TODO: parabolic; extend to mortars
@assert nmortars(dg, cache) == 0
# Prolong solution to mortars
@trixi_timeit timer() "prolong2mortars" begin
prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic,
dg.mortar, dg.surface_integral, dg)
end

# Calculate mortar fluxes
@trixi_timeit timer() "mortar flux" begin
calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh,
equations_parabolic,
dg.mortar, dg.surface_integral, dg, cache)
end

# Calculate surface integrals
@trixi_timeit timer() "surface integral" begin
Expand Down Expand Up @@ -500,6 +510,325 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra
return nothing
end

function prolong2mortars!(cache, flux_viscous::Tuple{AbstractArray, AbstractArray},
mesh::TreeMesh{2},
equations_parabolic::AbstractEquationsParabolic,
mortar_l2::LobattoLegendreMortarL2, surface_integral,
dg::DGSEM)
flux_viscous_x, flux_viscous_y = flux_viscous
@threaded for mortar in eachmortar(dg, cache)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
large_element = cache.mortars.neighbor_ids[3, mortar]
upper_element = cache.mortars.neighbor_ids[2, mortar]
lower_element = cache.mortars.neighbor_ids[1, mortar]

# Copy solution small to small
if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[2, v, l, mortar] = flux_viscous_x[v, 1, l,
upper_element]
cache.mortars.u_lower[2, v, l, mortar] = flux_viscous_x[v, 1, l,
lower_element]
end
end
else
# L2 mortars in y-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[2, v, l, mortar] = flux_viscous_y[v, l, 1,
upper_element]
cache.mortars.u_lower[2, v, l, mortar] = flux_viscous_y[v, l, 1,
lower_element]
end
end
end
else # large_sides[mortar] == 2 -> small elements on left side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[1, v, l, mortar] = flux_viscous_x[v,
nnodes(dg),
l,
upper_element]
cache.mortars.u_lower[1, v, l, mortar] = flux_viscous_x[v,
nnodes(dg),
l,
lower_element]
end
end
else
# L2 mortars in y-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[1, v, l, mortar] = flux_viscous_y[v, l,
nnodes(dg),
upper_element]
cache.mortars.u_lower[1, v, l, mortar] = flux_viscous_y[v, l,
nnodes(dg),
lower_element]
end
end
end
end

# Interpolate large element face data to small interface locations
if cache.mortars.large_sides[mortar] == 1 # -> large element on left side
leftright = 1
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
u_large = view(flux_viscous_x, :, nnodes(dg), :, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
else
# L2 mortars in y-direction
u_large = view(flux_viscous_y, :, :, nnodes(dg), large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
end
else # large_sides[mortar] == 2 -> large element on right side
leftright = 2
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
u_large = view(flux_viscous_x, :, 1, :, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
else
# L2 mortars in y-direction
u_large = view(flux_viscous_y, :, :, 1, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
end
end
end

return nothing
end

# TODO: This is essentially not different from the implementation in standard 2D.
# Only difference: defined `u_transformed` (equivalent of `u`) as AbstractArray.
function prolong2mortars!(cache, u_transformed::AbstractArray,
mesh::TreeMesh{2},
equations_parabolic::AbstractEquationsParabolic,
mortar_l2::LobattoLegendreMortarL2, surface_integral,
dg::DGSEM)
@threaded for mortar in eachmortar(dg, cache)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
large_element = cache.mortars.neighbor_ids[3, mortar]
upper_element = cache.mortars.neighbor_ids[2, mortar]
lower_element = cache.mortars.neighbor_ids[1, mortar]

# Copy solution small to small
if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[2, v, l, mortar] = u_transformed[v, 1, l,
upper_element]
cache.mortars.u_lower[2, v, l, mortar] = u_transformed[v, 1, l,
lower_element]
end
end
else
# L2 mortars in y-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[2, v, l, mortar] = u_transformed[v, l, 1,
upper_element]
cache.mortars.u_lower[2, v, l, mortar] = u_transformed[v, l, 1,
lower_element]
end
end
end
else # large_sides[mortar] == 2 -> small elements on left side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[1, v, l, mortar] = u_transformed[v,
nnodes(dg),
l,
upper_element]
cache.mortars.u_lower[1, v, l, mortar] = u_transformed[v,
nnodes(dg),
l,
lower_element]
end
end
else
# L2 mortars in y-direction
for l in eachnode(dg)
for v in eachvariable(equations_parabolic)
cache.mortars.u_upper[1, v, l, mortar] = u_transformed[v, l,
nnodes(dg),
upper_element]
cache.mortars.u_lower[1, v, l, mortar] = u_transformed[v, l,
nnodes(dg),
lower_element]
end
end
end
end

# Interpolate large element face data to small interface locations
if cache.mortars.large_sides[mortar] == 1 # -> large element on left side
leftright = 1
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
u_large = view(u_transformed, :, nnodes(dg), :, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
else
# L2 mortars in y-direction
u_large = view(u_transformed, :, :, nnodes(dg), large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
end
else # large_sides[mortar] == 2 -> large element on right side
leftright = 2
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
u_large = view(u_transformed, :, 1, :, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
else
# L2 mortars in y-direction
u_large = view(u_transformed, :, :, 1, large_element)
element_solutions_to_mortars!(cache.mortars, mortar_l2, leftright,
mortar, u_large)
end
end
end

return nothing
end

# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms.
# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for
# hyperbolic terms with conserved terms only, i.e., no nonconservative terms.
function calc_mortar_flux!(surface_flux_values,
mesh::TreeMesh{2},
equations_parabolic::AbstractEquationsParabolic,
mortar_l2::LobattoLegendreMortarL2,
surface_integral, dg::DG, cache)
@unpack surface_flux = surface_integral
@unpack u_lower, u_upper, orientations = cache.mortars
@unpack fstar_upper_threaded, fstar_lower_threaded = cache

@threaded for mortar in eachmortar(dg, cache)
# Choose thread-specific pre-allocated container
fstar_upper = fstar_upper_threaded[Threads.threadid()]
fstar_lower = fstar_lower_threaded[Threads.threadid()]

# Calculate fluxes
orientation = orientations[mortar]
calc_fstar!(fstar_upper, equations_parabolic, surface_flux, dg, u_upper, mortar,
orientation)
calc_fstar!(fstar_lower, equations_parabolic, surface_flux, dg, u_lower, mortar,
orientation)

mortar_fluxes_to_elements!(surface_flux_values,
mesh, equations_parabolic, mortar_l2, dg, cache,
mortar, fstar_upper, fstar_lower)
end

return nothing
end

@inline function calc_fstar!(destination::AbstractArray{<:Any, 2},
equations_parabolic::AbstractEquationsParabolic,
surface_flux, dg::DGSEM,
u_interfaces, interface, orientation)
for i in eachnode(dg)
# Call pointwise two-point numerical flux function
u_ll, u_rr = get_surface_node_vars(u_interfaces, equations_parabolic, dg, i,
interface)
# TODO: parabolic; only BR1 at the moment
flux = 0.5 * (u_ll + u_rr)

DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
# Copy flux to left and right element storage
set_node_vars!(destination, flux, equations_parabolic, dg, i)
end
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

return nothing
end

@inline function mortar_fluxes_to_elements!(surface_flux_values,
mesh::TreeMesh{2},
equations_parabolic::AbstractEquationsParabolic,
mortar_l2::LobattoLegendreMortarL2,
dg::DGSEM, cache,
mortar, fstar_upper, fstar_lower)
large_element = cache.mortars.neighbor_ids[3, mortar]
upper_element = cache.mortars.neighbor_ids[2, mortar]
lower_element = cache.mortars.neighbor_ids[1, mortar]

# Copy flux small to small
if cache.mortars.large_sides[mortar] == 1 # -> small elements on right side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
direction = 1
else
# L2 mortars in y-direction
direction = 3
end
else # large_sides[mortar] == 2 -> small elements on left side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
direction = 2
else
# L2 mortars in y-direction
direction = 4
end
end
surface_flux_values[:, :, direction, upper_element] .= fstar_upper
surface_flux_values[:, :, direction, lower_element] .= fstar_lower

# Project small fluxes to large element
if cache.mortars.large_sides[mortar] == 1 # -> large element on left side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
direction = 2
else
# L2 mortars in y-direction
direction = 4
end
else # large_sides[mortar] == 2 -> large element on right side
if cache.mortars.orientations[mortar] == 1
# L2 mortars in x-direction
direction = 1
else
# L2 mortars in y-direction
direction = 3
end
end

# TODO: Taal performance
# for v in eachvariable(equations)
# # The code below is semantically equivalent to
# # surface_flux_values[v, :, direction, large_element] .=
# # (mortar_l2.reverse_upper * fstar_upper[v, :] + mortar_l2.reverse_lower * fstar_lower[v, :])
# # but faster and does not allocate.
# # Note that `true * some_float == some_float` in Julia, i.e. `true` acts as
# # a universal `one`. Hence, the second `mul!` means "add the matrix-vector
# # product to the current value of the destination".
# @views mul!(surface_flux_values[v, :, direction, large_element],
# mortar_l2.reverse_upper, fstar_upper[v, :])
# @views mul!(surface_flux_values[v, :, direction, large_element],
# mortar_l2.reverse_lower, fstar_lower[v, :], true, true)
# end
# The code above could be replaced by the following code. However, the relative efficiency
# depends on the types of fstar_upper/fstar_lower and dg.l2mortar_reverse_upper.
# Using StaticArrays for both makes the code above faster for common test cases.
multiply_dimensionwise!(view(surface_flux_values, :, :, direction, large_element),
mortar_l2.reverse_upper, fstar_upper,
mortar_l2.reverse_lower, fstar_lower)

return nothing
end

# Calculate the gradient of the transformed variables
function calc_gradient!(gradients, u_transformed, t,
mesh::TreeMesh{2}, equations_parabolic,
Expand Down Expand Up @@ -589,7 +918,19 @@ function calc_gradient!(gradients, u_transformed, t,
dg.surface_integral, dg)
end

# TODO: parabolic; mortars
# Prolong solution to mortars
@trixi_timeit timer() "prolong2mortars" begin
prolong2mortars!(cache, u_transformed, mesh, equations_parabolic,
dg.mortar, dg.surface_integral, dg)
end

# Calculate mortar fluxes
@trixi_timeit timer() "mortar flux" begin
calc_mortar_flux!(surface_flux_values,
mesh,
equations_parabolic,
dg.mortar, dg.surface_integral, dg, cache)
end
jlchan marked this conversation as resolved.
Show resolved Hide resolved

# Calculate surface integrals
@trixi_timeit timer() "surface integral" begin
Expand Down
Loading
Loading