@muladd begin
"""
init_p4est()
Initialize `p4est` by calling `p4est_init` and setting the log level to `SC_LP_ERROR`.
This function will check if `p4est` is already initialized
and if yes, do nothing, thus it is safe to call it multiple times.
"""
function init_p4est()
if P4est.preferences_set_correctly()
p4est_package_id = P4est.package_id()
if p4est_package_id >= 0
return nothing
end
p4est_init(C_NULL, SC_LP_ERROR)
else
@warn "Preferences for P4est.jl are not set correctly. Until fixed, using `P4estMesh` will result in a crash. " *
"See also https://trixi-framework.github.io/TrixiDocumentation/stable/parallelization/#parallel_system_MPI"
end
return nothing
end
const PointerOrWrapper = Union{Ptr{T}, PointerWrapper{T}} where {T}
function unsafe_wrap_sc(::Type{T}, sc_array_ptr::Ptr{sc_array}) where {T}
sc_array_obj = unsafe_load(sc_array_ptr)
return unsafe_wrap_sc(T, sc_array_obj)
end
function unsafe_wrap_sc(::Type{T}, sc_array_obj::sc_array) where {T}
elem_count = sc_array_obj.elem_count
array = sc_array_obj.array
return unsafe_wrap(Array, Ptr{T}(array), elem_count)
end
function unsafe_wrap_sc(::Type{T}, sc_array_pw::PointerWrapper{sc_array}) where {T}
elem_count = sc_array_pw.elem_count[]
array = sc_array_pw.array
return unsafe_wrap(Array, Ptr{T}(pointer(array)), elem_count)
end
function load_pointerwrapper_sc(::Type{T}, sc_array::PointerWrapper{sc_array},
i::Integer = 1) where {T}
return PointerWrapper(T, pointer(sc_array.array) + (i - 1) * sizeof(T))
end
function unsafe_load_sc(::Type{T}, sc_array::PointerWrapper{sc_array},
i::Integer = 1) where {T}
return unsafe_load(Ptr{T}(pointer(sc_array.array)), i)
end
function unsafe_store_sc!(sc_array::PointerWrapper{sc_array}, x::T,
i::Integer = 1) where {T}
return unsafe_store!(Ptr{T}(pointer(sc_array.array)), x, i)
end
function new_p4est(connectivity::PointerOrWrapper{p4est_connectivity_t},
initial_refinement_level)
comm = P4est.uses_mpi() ? mpi_comm() : 0
p4est_new_ext(comm,
connectivity,
0,
initial_refinement_level,
true,
2 * sizeof(Int),
C_NULL,
C_NULL)
end
function new_p4est(connectivity::PointerOrWrapper{p8est_connectivity_t},
initial_refinement_level)
comm = P4est.uses_mpi() ? mpi_comm() : 0
p8est_new_ext(comm, connectivity, 0, initial_refinement_level, true,
2 * sizeof(Int), C_NULL, C_NULL)
end
function save_p4est!(file, p4est::PointerOrWrapper{p4est_t})
p4est_save(file, p4est, false)
end
function save_p4est!(file, p8est::PointerOrWrapper{p8est_t})
p8est_save(file, p8est, false)
end
function load_p4est(file, ::Val{2})
conn_vec = Vector{Ptr{p4est_connectivity_t}}(undef, 1)
comm = P4est.uses_mpi() ? mpi_comm() : C_NULL
p4est = p4est_load_ext(file,
comm,
0,
0,
1,
0,
C_NULL,
pointer(conn_vec))
p4est_reset_data(p4est,
2 * sizeof(Int),
C_NULL,
C_NULL)
return p4est
end
function load_p4est(file, ::Val{3})
conn_vec = Vector{Ptr{p8est_connectivity_t}}(undef, 1)
comm = P4est.uses_mpi() ? mpi_comm() : C_NULL
p4est = p8est_load_ext(file, comm, 0, 0, 1, 0, C_NULL, pointer(conn_vec))
p8est_reset_data(p4est, 2 * sizeof(Int), C_NULL, C_NULL)
return p4est
end
read_inp_p4est(meshfile, ::Val{2}) = p4est_connectivity_read_inp(meshfile)
read_inp_p4est(meshfile, ::Val{3}) = p8est_connectivity_read_inp(meshfile)
function refine_p4est!(p4est::PointerOrWrapper{p4est_t}, recursive, refine_fn_c,
init_fn_c)
p4est_refine(p4est, recursive, refine_fn_c, init_fn_c)
end
function refine_p4est!(p8est::PointerOrWrapper{p8est_t}, recursive, refine_fn_c,
init_fn_c)
p8est_refine(p8est, recursive, refine_fn_c, init_fn_c)
end
function coarsen_p4est!(p4est::PointerOrWrapper{p4est_t}, recursive, coarsen_fn_c,
init_fn_c)
p4est_coarsen(p4est, recursive, coarsen_fn_c, init_fn_c)
end
function coarsen_p4est!(p8est::PointerOrWrapper{p8est_t}, recursive, coarsen_fn_c,
init_fn_c)
p8est_coarsen(p8est, recursive, coarsen_fn_c, init_fn_c)
end
function ghost_new_p4est(p4est::PointerOrWrapper{p4est_t})
p4est_ghost_new(p4est, P4est.P4EST_CONNECT_FACE)
end
function ghost_new_p4est(p8est::PointerOrWrapper{p8est_t})
p8est_ghost_new(p8est, P4est.P8EST_CONNECT_FULL)
end
function ghost_is_valid_p4est(p4est::PointerOrWrapper{p4est_t},
ghost_layer::Ptr{p4est_ghost_t})
return p4est_ghost_is_valid(p4est, ghost_layer)
end
function ghost_is_valid_p4est(p4est::PointerOrWrapper{p8est_t},
ghost_layer::Ptr{p8est_ghost_t})
return p8est_ghost_is_valid(p4est, ghost_layer)
end
function ghost_destroy_p4est(ghost_layer::PointerOrWrapper{p4est_ghost_t})
p4est_ghost_destroy(ghost_layer)
end
function ghost_destroy_p4est(ghost_layer::PointerOrWrapper{p8est_ghost_t})
p8est_ghost_destroy(ghost_layer)
end
function iterate_p4est(p4est::PointerOrWrapper{p4est_t}, user_data;
ghost_layer = C_NULL,
iter_volume_c = C_NULL, iter_face_c = C_NULL)
if user_data === C_NULL
user_data_ptr = user_data
elseif user_data isa AbstractArray
user_data_ptr = pointer(user_data)
else
user_data_ptr = pointer_from_objref(user_data)
end
GC.@preserve user_data begin
p4est_iterate(p4est,
ghost_layer,
user_data_ptr,
iter_volume_c,
iter_face_c,
C_NULL)
end
return nothing
end
function iterate_p4est(p8est::PointerOrWrapper{p8est_t}, user_data;
ghost_layer = C_NULL,
iter_volume_c = C_NULL, iter_face_c = C_NULL)
if user_data === C_NULL
user_data_ptr = user_data
elseif user_data isa AbstractArray
user_data_ptr = pointer(user_data)
else
user_data_ptr = pointer_from_objref(user_data)
end
GC.@preserve user_data begin
p8est_iterate(p8est,
ghost_layer,
user_data_ptr,
iter_volume_c,
iter_face_c,
C_NULL,
C_NULL)
end
return nothing
end
function load_pointerwrapper_side(info::PointerWrapper{p4est_iter_face_info_t},
i::Integer = 1)
return load_pointerwrapper_sc(p4est_iter_face_side_t, info.sides, i)
end
function load_pointerwrapper_side(info::PointerWrapper{p8est_iter_face_info_t},
i::Integer = 1)
return load_pointerwrapper_sc(p8est_iter_face_side_t, info.sides, i)
end
function load_pointerwrapper_tree(p4est::PointerWrapper{p4est_t}, i::Integer = 1)
return load_pointerwrapper_sc(p4est_tree_t, p4est.trees, i)
end
function load_pointerwrapper_tree(p8est::PointerWrapper{p8est_t}, i::Integer = 1)
return load_pointerwrapper_sc(p8est_tree_t, p8est.trees, i)
end
end