Skip to content

Commit

Permalink
First implementation of inherited metric terms. ONLY WORKS FOR polyde…
Browse files Browse the repository at this point in the history
…g_geo = polydeg_parent_metrics WHEN mimetic = true OR exact_jacobian = true!
  • Loading branch information
amrueda committed Jul 27, 2023
1 parent 0128933 commit e652a26
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 16 deletions.
158 changes: 158 additions & 0 deletions examples/p4est_3d_dgsem/elixir_test_mimetic_metrics_parent.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#using LinearAlgebra
using OrdinaryDiffEq
using Trixi
#using StaticArrays
#using Plots

###############################################################################
# semidiscretization of the linear advection equation

advection_velocity = (0.2, -0.7, 0.5)
equations = LinearScalarAdvectionEquation3D(advection_velocity)

# Mapping as described in https://arxiv.org/abs/2012.12040
function mapping(xi, eta, zeta)
# Transform input variables between -1 and 1 onto our crazy domain

y = eta + 0.1 * (cos(pi * xi) *
cos(pi * eta) *
cos(pi * zeta))

x = xi + 0.1 * (cos(pi * xi) *
cos(pi * y) *
cos(pi * zeta))

z = zeta + 0.1 * (cos(pi * x) *
cos(pi * y) *
cos(pi * zeta))

#= x = xi
y = eta
z = zeta =#
return SVector(x, y, z)
end

cells_per_dimension = (1, 1, 1) # The p4est implementation works with one tree per direction only


exact_jacobian = false
mimetic = false
final_time = 1e-3

initial_condition = initial_condition_constant

max_polydeg = 1
n_polydeg_geo = 4
errors_sol_inf = zeros(max_polydeg,n_polydeg_geo)
errors_sol_L2 = zeros(max_polydeg,n_polydeg_geo)
polydeg_geos = [2, 3, 5, 10]
#polydeg_geos = [5]

polydeg = 5

# Refine bottom left quadrant of each tree to level 3
function refine_fn(p8est, which_tree, quadrant)
quadrant_obj = unsafe_load(quadrant)
if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 2
# return true (refine)
return Cint(1)
else
# return false (don't refine)
return Cint(0)
end
end

for i in 1:n_polydeg_geo
for polydeg in 1:max_polydeg
polydeg_geo = polydeg_geos[i]

solver = DGSEM(polydeg, flux_lax_friedrichs)

# Create curved mesh with 8 x 8 x 8 elements
boundary_condition = BoundaryConditionDirichlet(initial_condition)
boundary_conditions = Dict(
:x_neg => boundary_condition,
:x_pos => boundary_condition,
:y_neg => boundary_condition,
:y_pos => boundary_condition,
:z_neg => boundary_condition,
:z_pos => boundary_condition
)
println("polydeg_geo: ", polydeg_geo)
#mesh = P4estMesh(cells_per_dimension; polydeg = polydeg_geo, mapping = mapping, mimetic = mimetic, exact_jacobian = exact_jacobian, initial_refinement_level = 0, periodicity = true)
mesh = P4estMesh(cells_per_dimension; polydeg = polydeg_geo, mapping = mapping, mimetic = mimetic, exact_jacobian = exact_jacobian, initial_refinement_level = 0, periodicity = false, polydeg_parent_metrics = polydeg_geo)

# Refine recursively until each bottom left quadrant of a tree has level 3
# The mesh will be rebalanced before the simulation starts
refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t}))
Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL)

# A semidiscre tization collects data structures and functions for the spatial discretization
#semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions = boundary_conditions)

# Create ODE problem with time span from 0.0 to 1.0
ode = semidiscretize(semi, (0.0, final_time));

summary_callback = SummaryCallback()

# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results
analysis_callback = AnalysisCallback(semi, interval=100)

# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step
stepsize_callback = StepsizeCallback(cfl=0.1)

# The SaveSolutionCallback allows to save the solution to a file in regular intervals
save_solution = SaveSolutionCallback(interval=100,
solution_variables=cons2prim)

#= amr_indicator = IndicatorHennemannGassner(semi,
alpha_max=1.0,
alpha_min=0.0001,
alpha_smooth=false,
variable=Trixi.energy_total)
amr_controller = ControllerThreeLevel(semi, amr_indicator,
base_level=4,
max_level=6, max_threshold=0.01)
#= amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first),
base_level=4,
med_level=5, med_threshold=0.1,
max_level=6, max_threshold=0.6) =#
amr_callback = AMRCallback(semi, amr_controller,
interval=5,
adapt_initial_condition=true,
adapt_initial_condition_only_refine=true) =#

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback, save_solution)


###############################################################################
# run the simulation

# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks
sol = solve(ode, Euler(), #CarpenterKennedy2N54(williamson_condition=false),
dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep=false, callback=callbacks);


summary_callback()
errors = analysis_callback(sol)

errors_sol_L2[polydeg, i] = errors.l2[1]
errors_sol_inf[polydeg, i] = errors.linf[1]
end
end
#=end
for i in 1:n_polydeg_geo
plot!(errors_sol_inf[:,i], xaxis=:log, yaxis=:log, label = "polydeg_geo="*string(polydeg_geos[i]), linewidth=2, thickness_scaling = 1)
end
plot!(title = "mimetic="*string(mimetic)*", exact_jacobian="*string(exact_jacobian))
plot!(xlabel = "polydeg", ylabel = "|u_ex - u_disc|_inf")
plot!(ylims=(1e-15,1e-1))
plot!(xticks=([2, 4, 8, 16], ["2", "4", "8", "16"])) =#
58 changes: 52 additions & 6 deletions src/meshes/p4est_mesh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
An unstructured curved mesh based on trees that uses the C library `p4est`
to manage trees and mesh refinement.
"""
mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NNODES} <:
mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NDIMSP3, NNODES} <:
AbstractMesh{NDIMS}
p4est :: P # Either PointerWrapper{p4est_t} or PointerWrapper{p8est_t}
is_parallel :: IsParallel
Expand All @@ -26,10 +26,12 @@ mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NN
p4est_partition_allow_for_coarsening::Bool
mimetic::Bool
exact_jacobian::Bool
polydeg_parent_metrics::Int
tree_contravariant_vectors::Array{RealT, NDIMSP3} # [dimension, i, j, k, tree]

function P4estMesh{NDIMS}(p4est, tree_node_coordinates, nodes, boundary_names,
current_filename, unsaved_changes,
p4est_partition_allow_for_coarsening, mimetic = false, exact_jacobian = false) where {NDIMS}
p4est_partition_allow_for_coarsening, mimetic = false, exact_jacobian = false, polydeg_parent_metrics = false, tree_contravariant_vectors = Array{eltype(tree_node_coordinates), NDIMS + 3}(undef, 3, ntuple(_ -> 0, NDIMS)..., 1)) where {NDIMS}
if NDIMS == 2
@assert p4est isa Ptr{p4est_t}
elseif NDIMS == 3
Expand All @@ -51,7 +53,7 @@ mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NN
ghost_pw = PointerWrapper(ghost)

mesh = new{NDIMS, eltype(tree_node_coordinates), typeof(is_parallel),
typeof(p4est_pw), typeof(ghost_pw), NDIMS + 2, length(nodes)}(p4est_pw,
typeof(p4est_pw), typeof(ghost_pw), NDIMS + 2, NDIMS + 3, length(nodes)}(p4est_pw,
is_parallel,
ghost_pw,
tree_node_coordinates,
Expand All @@ -61,7 +63,9 @@ mutable struct P4estMesh{NDIMS, RealT <: Real, IsParallel, P, Ghost, NDIMSP2, NN
unsaved_changes,
p4est_partition_allow_for_coarsening,
mimetic,
exact_jacobian)
exact_jacobian,
polydeg_parent_metrics,
tree_contravariant_vectors)

# Destroy `p4est` structs when the mesh is garbage collected
finalizer(destroy_mesh, mesh)
Expand Down Expand Up @@ -172,7 +176,8 @@ function P4estMesh(trees_per_dimension; polydeg,
unsaved_changes = true,
p4est_partition_allow_for_coarsening = true,
mimetic = false,
exact_jacobian = false)
exact_jacobian = false,
polydeg_parent_metrics = 0)
@assert ((coordinates_min === nothing)===(coordinates_max === nothing)) "Either both or none of coordinates_min and coordinates_max must be specified"

@assert count(i -> i !== nothing,
Expand Down Expand Up @@ -209,6 +214,47 @@ function P4estMesh(trees_per_dimension; polydeg,
calc_tree_node_coordinates!(tree_node_coordinates, nodes, mapping,
trees_per_dimension)

tree_contravariant_vectors = Array{RealT, NDIMS + 3}(undef, NDIMS, NDIMS,
ntuple(_ -> polydeg_parent_metrics + 1,
NDIMS)...,
prod(trees_per_dimension))

if polydeg_parent_metrics > 0 # Only available for one tree
basis_parent_metrics = LobattoLegendreBasis(RealT, polydeg_parent_metrics)
nodes_parent_metrics = basis_parent_metrics.nodes

jacobian_matrix = zeros(3,3,ntuple(_ -> polydeg_parent_metrics+1,NDIMS)..., 1)
inverse_jacobian = zeros(ntuple(_ -> polydeg_parent_metrics+1,NDIMS)..., 1)
node_coordinates_comp = zeros(3, polydeg_parent_metrics+1)
node_coordinates_comp[1,:] = nodes_parent_metrics
node_coordinates_comp[2,:] = nodes_parent_metrics
node_coordinates_comp[3,:] = nodes_parent_metrics

if exact_jacobian
calc_jacobian_matrix_exact!(jacobian_matrix, 1, tree_node_coordinates, basis_parent_metrics, node_coordinates_comp)
else
# TODO: This makes sense only for polydeg_geo = polydeg_parent_metrics
calc_jacobian_matrix!(jacobian_matrix, 1, tree_node_coordinates, basis_parent_metrics)
end

if mimetic
calc_contravariant_vectors_mimetic!(tree_contravariant_vectors, 1, jacobian_matrix,
tree_node_coordinates, basis_parent_metrics, node_coordinates_comp)
else
# TODO: This makes sense only for polydeg_geo = polydeg_parent_metrics
calc_contravariant_vectors!(tree_contravariant_vectors, 1, jacobian_matrix,
tree_node_coordinates, basis_parent_metrics)
end

calc_inverse_jacobian!(inverse_jacobian, 1, jacobian_matrix, basis_parent_metrics)

#= @turbo for k in eachnode(basis_parent_metrics), j in eachnode(basis_parent_metrics), i in eachnode(basis_parent_metrics)
for r in 1:3, s in 1:3
tree_contravariant_vectors[s,r,i,j,k,1] *= inverse_jacobian[i,j,k,1]
end
end =#
end

# p4est_connectivity_new_brick has trees in Z-order, so use our own function for this
connectivity = connectivity_structured(trees_per_dimension..., periodicity)

Expand All @@ -221,7 +267,7 @@ function P4estMesh(trees_per_dimension; polydeg,

return P4estMesh{NDIMS}(p4est, tree_node_coordinates, nodes,
boundary_names, "", unsaved_changes,
p4est_partition_allow_for_coarsening, mimetic, exact_jacobian)
p4est_partition_allow_for_coarsening, mimetic, exact_jacobian, polydeg_parent_metrics, tree_contravariant_vectors)
end

# 2D version
Expand Down
62 changes: 52 additions & 10 deletions src/solvers/dgsem_p4est/containers_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ function init_elements!(elements, mesh::P4estMesh{3}, basis::LobattoLegendreBasi

for i in eachindex(quadrants)
element = offset + i
quad = quadrants[i]
quad_length = p4est_quadrant_len(quad.level) / p4est_root_len

if mesh.exact_jacobian || mesh.mimetic
quad = quadrants[i]
quad_length = p4est_quadrant_len(quad.level) / p4est_root_len
calc_node_coordinates_computational!(node_coordinates_comp, quad_length, p4est_root_len, quad, mesh, basis)
end

Expand All @@ -39,15 +39,19 @@ function init_elements!(elements, mesh::P4estMesh{3}, basis::LobattoLegendreBasi
calc_jacobian_matrix!(jacobian_matrix, element, node_coordinates, basis)
end

if mesh.mimetic
calc_contravariant_vectors_mimetic!(contravariant_vectors, element, jacobian_matrix,
node_coordinates, basis, node_coordinates_comp)
else
calc_contravariant_vectors!(contravariant_vectors, element, jacobian_matrix,
node_coordinates, basis)
end

calc_inverse_jacobian!(inverse_jacobian, element, jacobian_matrix, basis)

if mesh.polydeg_parent_metrics > 0
calc_contravariant_vectors_interpolate!(contravariant_vectors, element, quad, quad_length, tree, mesh, p4est_root_len, basis, inverse_jacobian)
else
if mesh.mimetic
calc_contravariant_vectors_mimetic!(contravariant_vectors, element, jacobian_matrix,
node_coordinates, basis, node_coordinates_comp)
else
calc_contravariant_vectors!(contravariant_vectors, element, jacobian_matrix,
node_coordinates, basis)
end
end
end
end

Expand Down Expand Up @@ -116,6 +120,44 @@ function calc_node_coordinates_computational!(node_coordinates_comp, quad_length
quad.z / p4est_root_len) .- 1
end

function calc_contravariant_vectors_interpolate!(contravariant_vectors, element, quad, quad_length, tree, mesh::P4estMesh{3}, p4est_root_len, basis, inverse_jacobian)
@unpack nodes = basis

basis_parent_metrics = LobattoLegendreBasis(eltype(contravariant_vectors), mesh.polydeg_parent_metrics)
nodes_parent_metrics = basis_parent_metrics.nodes

nodes_out_x = 2 * (quad_length * 1 / 2 * (nodes .+ 1) .+
quad.x / p4est_root_len) .- 1
nodes_out_y = 2 * (quad_length * 1 / 2 * (nodes .+ 1) .+
quad.y / p4est_root_len) .- 1
nodes_out_z = 2 * (quad_length * 1 / 2 * (nodes .+ 1) .+
quad.z / p4est_root_len) .- 1

matrix1 = polynomial_interpolation_matrix(nodes_parent_metrics, nodes_out_x)
matrix2 = polynomial_interpolation_matrix(nodes_parent_metrics, nodes_out_y)
matrix3 = polynomial_interpolation_matrix(nodes_parent_metrics, nodes_out_z)

multiply_dimensionwise!(view(contravariant_vectors, 1, :, :, :, :, element),
matrix1, matrix2, matrix3,
view(mesh.tree_contravariant_vectors, 1, :, :, :, :, tree))

multiply_dimensionwise!(view(contravariant_vectors, 2, :, :, :, :, element),
matrix1, matrix2, matrix3,
view(mesh.tree_contravariant_vectors, 2, :, :, :, :, tree))

multiply_dimensionwise!(view(contravariant_vectors, 3, :, :, :, :, element),
matrix1, matrix2, matrix3,
view(mesh.tree_contravariant_vectors, 3, :, :, :, :, tree))

#= @turbo for k in eachnode(basis), j in eachnode(basis), i in eachnode(basis)
for r in 1:3, s in 1:3
contravariant_vectors[s,r,i,j,k,element] /= inverse_jacobian[i,j,k,element]
end
end =#

contravariant_vectors[:,:,:,:,:,element] /= 2^(2 * quad.level)
end

# Initialize node_indices of interface container
@inline function init_interface_node_indices!(interfaces::P4estInterfaceContainer{3},
faces, orientation, interface_id)
Expand Down

0 comments on commit e652a26

Please sign in to comment.