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

P4 est enable mpi #7

Merged
merged 6 commits into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ julia> using p4est_wrapper
- Latests versions of julia `MPI` use artifacts to locally install a MPI distribution. You should take care with the compatibility (version/vendor/distribution) between the parallel `p4est` and `MPI` libraries. If you want julia `MPI` library to wrap your local MPI library, you must export `JULIA_MPI_BINARY="system"` before installing the package.
- Parallel `p4est` library can be manually installed in a custom path on your local machine. In order to succesfull describe your custom installation to be discovered by `p4est_wrapper`, you must export `P4EST_ROOT_DIR` environment variable pointing to the installation directory. If this environment variable is not available, and `julia >= 1.3`, `p4est_wrapper` will try to use [`P4est_jll` artifact](https://github.com/JuliaBinaryWrappers/P4est_jll.jl), but you should take into account that this artifact is not for parallel computations (MPI not enabled). Finally, in other case `p4est_wrapper` will try to find the `p4est` library in the usual linux user library directory (`/usr/lib`).

#### Basic OpenMPIMPI installation in debian based systems
#### Basic OpenMPI installation in debian based systems

`MPI` can be obtained from the default repositories of your Debian-based OS by means of `apt` tool.

Expand Down
7 changes: 7 additions & 0 deletions deps/build.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Libdl

P4EST_ARTIFACT = false
if VERSION < v"1.3"
DEFAULT_P4EST_ROOT_DIR = "/usr"
else
using P4est_jll
P4EST_ARTIFACT = true
DEFAULT_P4EST_ROOT_DIR = P4est_jll.artifact_dir
end

Expand All @@ -15,6 +17,9 @@ P4EST_INCLUDE_DIR = haskey(ENV,"P4EST_INCLUDE_DIR") ? ENV["P4EST_INCLUDE_DIR"]
P4EST_LIB_NAME = haskey(ENV,"P4EST_LIB_NAME") ? ENV["P4EST_LIB_NAME"] : "libp4est"
P4EST_LIB = haskey(ENV,"P4EST_LIB") ? ENV["P4EST_LIB"] : ""

DEFAULT_P4EST_ENABLE_MPI = !haskey(ENV,"P4EST_ROOT_DIR") && P4EST_ARTIFACT ? false : true
P4EST_ENABLE_MPI = haskey(ENV,"P4EST_ENABLE_MPI") ? Bool(ENV["P4EST_ENABLE_MPI"]) : DEFAULT_P4EST_ENABLE_MPI


# Check P4EST_DIR exists
if isdir(P4EST_DIR)
Expand Down Expand Up @@ -68,6 +73,7 @@ P4EST configuration:
- P4EST_LIB_DIR = $P4EST_LIB_DIR
- P4EST_INCLUDE_DIR = $P4EST_INCLUDE_DIR
- P4EST_LIB = $P4EST_LIB
- P4EST_ENABLE_MPI = $P4EST_ENABLE_MPI
"""

if !P4EST_FOUND
Expand All @@ -90,4 +96,5 @@ open(deps_jl,"w") do f
println(f, :(const P4EST_LIB_DIR = $P4EST_LIB_DIR))
println(f, :(const P4EST_INCLUDE_DIR = $P4EST_INCLUDE_DIR))
println(f, :(const P4EST_LIB = $P4EST_LIB))
println(f, :(const P4EST_ENABLE_MPI = $P4EST_ENABLE_MPI))
end
5 changes: 5 additions & 0 deletions gen/Project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
[deps]
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"

[compat]
Clang = "0.10.1"
julia = "1.0"

22 changes: 22 additions & 0 deletions src/api_fixes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,25 @@ function p4est_init(log_handler, log_threshold)
ccall((:p4est_init, p4est_lib), Cvoid, (sc_log_handler_t, Cint), log_handler, log_threshold)
end

################################################################
# Dereference functions
# Not part of P4est, but really usefull to access data from pointers
################################################################

PXEST_NAMED_STRUCTS = Union{p4est_quadrant, p4est_tree, p4est_inspect, p4est_connectivity, p4est, p4est_geometry,
p4est_ghost_t, p4est_ghost_exchange, p4est_iter_volume_info, p4est_iter_face_side,
p4est_iter_face_side, p4est_iter_corner_side, p4est_iter_corner_info, p4est_lnodes,
p4est_lnodes_rank, p4est_lnodes_buffer, p4est_search_local_t, p4est_vtk_context,
p6est_connectivity, p2est_quadrant, p6est_ghost, p8est_quadrant, p8est_tree, sc_array,
p8est_inspect, p8est_connectivity, p8est_connectivity, p8est_geometry, p8est_ghost_t,
p8est_ghost_exchange, p8est_iter_volume_info, p8est_iter_face_side, p8est_iter_face_info,
p8est_iter_edge_side, p8est_iter_edge_info, p8est_iter_corner_side, p8est_iter_corner_info,
p8est_lnodes, p8est_lnodes_rank, p8est_lnodes_buffer, p8est_search_local_t, p8est_vtk_context}

function Base.getindex(ptr::Ptr{T}) where {T<:PXEST_NAMED_STRUCTS}
unsafe_wrap(Array, ptr, 1)[]
end

function Base.getindex(ptr::Ptr{T}, i) where {T<:PXEST_NAMED_STRUCTS}
unsafe_wrap(Array, ptr, i)[i]
end
13 changes: 9 additions & 4 deletions src/common_fixes.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
################################################################
# Base fixed datatypes
################################################################
const FILE = Cvoid # File descriptor
const ssize_t = Cssize_t
const MPI_Comm = MPI.MPI_Comm
const MPI_File = MPI.MPI_File
const FILE = Cvoid # File descriptor
if P4EST_ENABLE_MPI
const MPI_Comm = MPI.MPI_Comm
else
const MPI_Comm = Cint
end
const MPI_Datatype = MPI.MPI_Datatype
const MPI_File = MPI.MPI_File
const sc_MPI_Comm = MPI_Comm
const ssize_t = Cssize_t

################################################################
# Non-wrapped but required data types
Expand Down
8 changes: 5 additions & 3 deletions test/example_1.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct point_t x::Cdouble; y::Cdouble; end
# Refine callback
function my_refine( ::Ptr{p4est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p4est_quadrant_t})
@assert which_tree == 0
q = unsafe_wrap(Array,quadrant,1)[1]
q = quadrant[]
((q.level == 0) || (q.level < 5 && p4est_quadrant_child_id(quadrant) == 1)) && return Cint(1)
return Cint(0)
end
Expand All @@ -38,12 +38,14 @@ const search_point_fn_c = @cfunction(search_point_fn, Cint, (Ptr{p4est_t}, p4est
# Main program
#############################################################################

mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)

# Create a connectivity structure for the unit square.
unitsquare_connectivity = p4est_connectivity_new_unitsquare()
@test unitsquare_connectivity != C_NULL

# Create a new forest
unitsquare_forest = p4est_new(MPI.COMM_WORLD, unitsquare_connectivity, 0, C_NULL, C_NULL)
unitsquare_forest = p4est_new(mpicomm, unitsquare_connectivity, 0, C_NULL, C_NULL)
@test unitsquare_forest != C_NULL

# Register callback function to decide for refinement.
Expand All @@ -54,7 +56,7 @@ ptr_to_points_sc_array = sc_array_new_count(sizeof(point_t), 2)
@test ptr_to_points_sc_array != C_NULL

# Check correct number of elements and its size in sc_array
points_sc_array = unsafe_wrap(Array, ptr_to_points_sc_array, 1)[1]
points_sc_array = ptr_to_points_sc_array[]
@test points_sc_array.elem_count == 2 && points_sc_array.elem_size == sizeof(point_t)

# Obtain reference to first point_t
Expand Down
25 changes: 12 additions & 13 deletions test/example_2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ end
# Refine callback
function my_refine( ::Ptr{p4est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p4est_quadrant_t})
@assert which_tree == 0
q = unsafe_wrap(Array,quadrant,1)[1]
q = quadrant[]
((q.level == 0) || (q.level < 2 && p4est_quadrant_child_id(quadrant) == 1)) && return Cint(1)
return Cint(0)
end
Expand All @@ -26,12 +26,14 @@ const my_refine_c = @cfunction(my_refine, Cint, (Ptr{p4est_t}, p4est_topidx_t, P
# Main program
#############################################################################

mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)

# Create a connectivity structure for the unit square.
unitsquare_connectivity = p4est_connectivity_new_unitsquare()
@assert Bool(p4est_connectivity_is_valid(unitsquare_connectivity))

# Create a new forest
unitsquare_forest = p4est_new(MPI.COMM_WORLD, unitsquare_connectivity, sizeof(p4est_quadrant_t), C_NULL, C_NULL)
unitsquare_forest = p4est_new(mpicomm, unitsquare_connectivity, sizeof(p4est_quadrant_t), C_NULL, C_NULL)
@test unitsquare_forest != C_NULL

# Register callback function to decide for refinement.
Expand All @@ -42,23 +44,20 @@ p4est_partition(unitsquare_forest, 0, C_NULL);

# Build the ghost layer.
ptr_to_p4est_ghost = p4est_ghost_new(unitsquare_forest, p4est_wrapper.P4EST_CONNECT_FULL)
p4est_ghost = unsafe_wrap(Array,ptr_to_p4est_ghost,1)[1]
p4est_ghost = ptr_to_p4est_ghost[]

# Obtain ghost quadrants
##p4est_quadrant_t * ptr_ghost_quadrants = (p4est_quadrant_t *) p4est_ghost->ghosts.array;
ptr_ghost_quadrants = Ptr{p4est_quadrant_t}(p4est_ghost.ghosts.array)
proc_offsets = unsafe_wrap(Array, p4est_ghost.proc_offsets, p4est_ghost.mpisize+1)
ghost_quadrants = unsafe_wrap(Array, ptr_ghost_quadrants, p4est_ghost.ghosts.elem_count)

let mpirank = MPI.Comm_rank(MPI.COMM_WORLD)
for i=1:p4est_ghost.mpisize
for j=proc_offsets[i]:proc_offsets[i+1]-1
quadrant = ghost_quadrants[j+1]
piggy3 = quadrant.p.piggy3
@test Bool(p4est_quadrant_is_valid(ptr_ghost_quadrants+(sizeof(p4est_quadrant_t)*j)))
p4est_quadrant_print(p4est_wrapper.SC_LP_INFO, ptr_ghost_quadrants+(sizeof(p4est_quadrant_t)*j))
print("(rank, local_num, which_tree) ($(mpirank),$(piggy3.local_num),$(piggy3.which_tree)) \n")
end
for i=1:p4est_ghost.mpisize
for j=proc_offsets[i]:proc_offsets[i+1]-1
quadrant = ptr_ghost_quadrants[j+1]
piggy3 = quadrant.p.piggy3
@test Bool(p4est_quadrant_is_valid(ptr_ghost_quadrants+(sizeof(p4est_quadrant_t)*j)))
p4est_quadrant_print(p4est_wrapper.SC_LP_INFO, ptr_ghost_quadrants+(sizeof(p4est_quadrant_t)*j))
print("(i, j, local_num, which_tree) ($(i),$(j),$(piggy3.local_num),$(piggy3.which_tree)) \n")
end
end

Expand Down
25 changes: 13 additions & 12 deletions test/example_3.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ function init_fn_callback_2d(forest_ptr::Ptr{p4est_t},
quadrant_ptr::Ptr{p4est_quadrant_t})
@assert which_tree == 0
# Extract a reference to the first (and uniquely allowed) tree
forest = unsafe_wrap(Array, forest_ptr, 1)[1]
tree = unsafe_wrap(Array, p4est_tree_array_index(forest.trees, 0), 1)[1]
quadrant = unsafe_wrap(Array, quadrant_ptr, 1)[1]
forest = forest_ptr[]
tree = p4est_tree_array_index(forest.trees, 0)[]
quadrant = quadrant_ptr[]
q = p4est_quadrant_array_index(tree.quadrants, current_quadrant_index)
@assert p4est_quadrant_compare(q,quadrant_ptr) == 0
user_data = unsafe_wrap(Array, Ptr{Cint}(forest.user_pointer), current_quadrant_index+1)[current_quadrant_index+1]
Expand All @@ -49,8 +49,8 @@ function refine_callback_2d(::Ptr{p4est_t},
which_tree::p4est_topidx_t,
quadrant_ptr::Ptr{p4est_quadrant_t})
@assert which_tree == 0
quadrant = unsafe_wrap(Array, quadrant_ptr, 1)[1]
return Cint(unsafe_wrap(Array, Ptr{Cint}(quadrant.p.user_data),1)[1] == refine_flag)
quadrant = quadrant_ptr[]
return Cint(unsafe_wrap(Array, Ptr{Cint}(quadrant.p.user_data),1)[] == refine_flag)
end

const refine_callback_2d_c = @cfunction(refine_callback_2d, Cint, (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}))
Expand All @@ -69,7 +69,7 @@ function refine_replace_callback_2d(forest_ptr::Ptr{p4est_t},
@assert num_incoming == p4est_wrapper.P4EST_CHILDREN
incoming = unsafe_wrap(Array, incoming_ptr, p4est_wrapper.P4EST_CHILDREN)
for quadrant_index = 1:p4est_wrapper.P4EST_CHILDREN
quadrant = unsafe_wrap(Array, incoming[quadrant_index], 1)[1]
quadrant = incoming[quadrant_index][]
if (num_calls % 2 == 0)
unsafe_store!(Ptr{Cint}(quadrant.p.user_data), nothing_flag, 1)
else
Expand All @@ -89,8 +89,8 @@ function coarsen_callback_2d(forest_ptr::Ptr{p4est_t},
coarsen = Cint(1)
quadrants = unsafe_wrap(Array, quadrants_ptr, p4est_wrapper.P4EST_CHILDREN)
for quadrant_index = 1:p4est_wrapper.P4EST_CHILDREN
quadrant = unsafe_wrap(Array, quadrants[quadrant_index], 1)[1]
coarsen = Cint(unsafe_wrap(Array, Ptr{Cint}(quadrant.p.user_data), 1)[1] == coarsen_flag)
quadrant = quadrants[quadrant_index][]
coarsen = Cint(unsafe_wrap(Array, Ptr{Cint}(quadrant.p.user_data), 1)[] == coarsen_flag)
if (!Bool(coarsen)) return coarsen end
end
return coarsen
Expand All @@ -101,8 +101,8 @@ const coarsen_callback_2d_c = @cfunction(coarsen_callback_2d, Cint, (Ptr{p4est_t
## Refine those cells with even identifier (0,2,4,6,8,...)
## Leave untouched cells with odd identifier (1,3,5,7,9,...)
function allocate_and_set_refinement_and_coarsening_flags(forest_ptr::Ptr{p4est_t})
forest = unsafe_wrap(Array, forest_ptr, 1)[1]
tree = unsafe_wrap(Array, p4est_tree_array_index(forest.trees, 0), 1)[1]
forest = forest_ptr[]
tree = p4est_tree_array_index(forest.trees, 0)[]
refinement_and_coarsening_flags = Ptr{Cint}(Libc.malloc(sizeof(Cint)*tree.quadrants.elem_count))
for i = 1:tree.quadrants.elem_count
if (i%2 == 0)
Expand All @@ -129,11 +129,12 @@ end
# Main program
#############################################################################

sc_init(MPI.COMM_WORLD, Cint(true), Cint(true), C_NULL, p4est_wrapper.SC_LP_DEFAULT)
mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)
sc_init(mpicomm, Cint(true), Cint(true), C_NULL, p4est_wrapper.SC_LP_DEFAULT)
p4est_init(C_NULL, p4est_wrapper.SC_LP_DEFAULT)

unitsquare_connectivity = p4est_connectivity_new_unitsquare()
unitsquare_forest = p4est_new(MPI.COMM_WORLD, unitsquare_connectivity, 0, C_NULL, C_NULL)
unitsquare_forest = p4est_new(mpicomm, unitsquare_connectivity, 0, C_NULL, C_NULL)

for i=1:7
perform_single_mesh_adaptation_step(unitsquare_forest,i)
Expand Down
4 changes: 3 additions & 1 deletion test/test_p4est_bindings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ end
# Definition of data structures and function callbacks
#############################################################################

mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)

# Dummy callback
dummy_callback( ::Ptr{p4est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p4est_quadrant_t}) = Cint(0)

Expand Down Expand Up @@ -44,7 +46,7 @@ for test_conn in [p4est_connectivity_new_periodic(),
end

# Create a new forest
unitsquare_forest = p4est_new(MPI.COMM_WORLD, unitsquare_connectivity, 0, C_NULL, C_NULL)
unitsquare_forest = p4est_new(mpicomm, unitsquare_connectivity, 0, C_NULL, C_NULL)
@test unitsquare_forest != C_NULL

# Create/Destroy geometry
Expand Down
3 changes: 2 additions & 1 deletion test/test_p8est_bindings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ end
#############################################################################
# Definition of data structures and function callbacks
#############################################################################
mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)

# Dummy callback
dummy_callback( ::Ptr{p8est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p8est_quadrant_t}) = Cint(0)
Expand Down Expand Up @@ -43,7 +44,7 @@ for test_conn in [p8est_connectivity_new_periodic(),
end

# Create a new forest
unitcube_forest = p8est_new(MPI.COMM_WORLD, unitcube_connectivity, 0, C_NULL, C_NULL)
unitcube_forest = p8est_new(mpicomm, unitcube_connectivity, 0, C_NULL, C_NULL)
@test unitcube_forest != C_NULL

# Create/Destroy geometry
Expand Down
6 changes: 4 additions & 2 deletions test/test_sc_bindings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ if !MPI.Initialized()
MPI.Init()
end

mpicomm = p4est_wrapper.P4EST_ENABLE_MPI ? MPI.COMM_WORLD : Cint(0)

# SC library initialization
sc_init(MPI.COMM_WORLD, Cint(true), Cint(true), C_NULL, p4est_wrapper.SC_LP_DEFAULT)
@test sc_is_root() == (MPI.Comm_rank(MPI.COMM_WORLD) == 0 ? 1 : 0)
sc_init(mpicomm, Cint(true), Cint(true), C_NULL, p4est_wrapper.SC_LP_DEFAULT)
@test typeof(sc_is_root()) == Cint

# SC package related API
id = sc_package_register(C_NULL, p4est_wrapper.SC_LP_INFO, "p4est", "A forest of octrees")
Expand Down