Skip to content

Commit 08e9db4

Browse files
authored
Merge pull request #157 from fverdugo/gallery
Starting to add gallery of PSparseMatrices
2 parents 5c4b712 + 7fa9fb7 commit 08e9db4

File tree

9 files changed

+287
-0
lines changed

9 files changed

+287
-0
lines changed

docs/make.jl

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ makedocs(
3131
"reference/ptimer.md",
3232
"reference/advanced.md",
3333
"reference/helpers.md",
34+
"reference/gallery.md",
3435
],
3536
"refindex.md",
3637
],

docs/src/reference/gallery.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Gallery
2+
3+
## PSparseMatrix
4+
5+
```@docs
6+
laplacian_fdm
7+
laplacian_fem
8+
```

src/PartitionedArrays.jl

+4
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,8 @@ export toc!
167167
export statistics
168168
include("p_timer.jl")
169169

170+
export laplacian_fdm
171+
export laplacian_fem
172+
include("gallery.jl")
173+
170174
end # module

src/gallery.jl

+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
2+
"""
3+
laplacian_fdm(
4+
nodes_per_dir,
5+
parts_per_dir,
6+
parts;
7+
index_type = Int64,
8+
value_type = Float64)
9+
10+
Document me!
11+
"""
12+
function laplacian_fdm(
13+
nodes_per_dir,
14+
parts_per_dir,
15+
parts;
16+
index_type::Type{Ti} = Int64,
17+
value_type::Type{Tv} = Float64,
18+
) where {Ti,Tv}
19+
function neig_node(cartesian_node_i,d,i,cartesian_node_to_node)
20+
function is_boundary_node(node_1d,nodes_1d)
21+
!(node_1d in 1:nodes_1d)
22+
end
23+
D = length(nodes_per_dir)
24+
inc = ntuple(k->( k==d ? i : zero(i)),Val{D}())
25+
cartesian_node_j = CartesianIndex(Tuple(cartesian_node_i) .+ inc)
26+
boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir))
27+
T = eltype(cartesian_node_to_node)
28+
if boundary
29+
return zero(T)
30+
end
31+
node_j = cartesian_node_to_node[cartesian_node_j]
32+
node_j
33+
end
34+
function setup(nodes,::Type{index_type},::Type{value_type}) where {index_type,value_type}
35+
D = length(nodes_per_dir)
36+
α = value_type(prod(i->(i+1),nodes_per_dir))
37+
node_to_cartesian_node = CartesianIndices(nodes_per_dir)
38+
cartesian_node_to_node = LinearIndices(nodes_per_dir)
39+
first_cartesian_node = node_to_cartesian_node[first(nodes)]
40+
last_cartesian_node = node_to_cartesian_node[last(nodes)]
41+
ranges = map(:,Tuple(first_cartesian_node),Tuple(last_cartesian_node))
42+
cartesian_nodes = CartesianIndices(ranges)
43+
nnz = 0
44+
for cartesian_node_i in cartesian_nodes
45+
nnz+=1
46+
for d in 1:D
47+
for i in (-1,1)
48+
node_j = neig_node(cartesian_node_i,d,i,cartesian_node_to_node)
49+
if node_j == 0
50+
continue
51+
end
52+
nnz+=1
53+
end
54+
end
55+
end
56+
myI = zeros(index_type,nnz)
57+
myJ = zeros(index_type,nnz)
58+
myV = zeros(value_type,nnz)
59+
t = 0
60+
for cartesian_node_i in cartesian_nodes
61+
t += 1
62+
node_i = cartesian_node_to_node[cartesian_node_i]
63+
myI[t] = node_i
64+
myJ[t] = node_i
65+
myV[t] = α*2*D
66+
for d in 1:D
67+
for i in (-1,1)
68+
node_j = neig_node(cartesian_node_i,d,i,cartesian_node_to_node)
69+
if node_j == 0
70+
continue
71+
end
72+
t += 1
73+
myI[t] = node_i
74+
myJ[t] = node_j
75+
myV[t] = -α
76+
end
77+
end
78+
end
79+
myI,myJ,myV
80+
end
81+
node_partition = uniform_partition(parts,parts_per_dir,nodes_per_dir)
82+
I,J,V = map(node_partition) do nodes
83+
setup(nodes,Ti,Tv)
84+
end |> tuple_of_arrays
85+
I,J,V,node_partition,node_partition
86+
end
87+
88+
"""
89+
laplacian_fem(
90+
nodes_per_dir,
91+
parts_per_dir,
92+
parts;
93+
index_type = Int64,
94+
value_type = Float64)
95+
96+
Document me!
97+
"""
98+
function laplacian_fem(
99+
nodes_per_dir, # free (== interior) nodes
100+
parts_per_dir,
101+
parts;
102+
index_type::Type{Ti} = Int64,
103+
value_type::Type{Tv} = Float64,
104+
) where {Ti,Tv}
105+
106+
cells_per_dir = nodes_per_dir .+ 1
107+
108+
function is_boundary_node(node_1d,nodes_1d)
109+
!(node_1d in 1:nodes_1d)
110+
end
111+
function ref_matrix(cartesian_local_nodes,h_per_dir,::Type{value_type}) where value_type
112+
D = ndims(cartesian_local_nodes)
113+
gp_1d = value_type[-sqrt(3)/3,sqrt(3)/3]
114+
sf_1d = zeros(value_type,length(gp_1d),2)
115+
sf_1d[:,1] = 0.5 .* (1 .- gp_1d)
116+
sf_1d[:,2] = 0.5 .* (gp_1d .+ 1)
117+
sg_1d = zeros(value_type,length(gp_1d),2)
118+
sg_1d[:,1] .= - 0.5
119+
sg_1d[:,2] .= 0.5
120+
cartesian_points = CartesianIndices(ntuple(d->length(gp_1d),Val{D}()))
121+
cartesian_local_node_to_local_node = LinearIndices(cartesian_local_nodes)
122+
cartesian_point_to_point = LinearIndices(cartesian_points)
123+
n = 2^D
124+
sg = Matrix{NTuple{D,value_type}}(undef,n,length(gp_1d)^D)
125+
for cartesian_local_node in cartesian_local_nodes
126+
local_node = cartesian_local_node_to_local_node[cartesian_local_node]
127+
local_node_tuple = Tuple(cartesian_local_node)
128+
for cartesian_point in cartesian_points
129+
point = cartesian_point_to_point[cartesian_point]
130+
point_tuple = Tuple(cartesian_point)
131+
v = ntuple(Val{D}()) do d
132+
prod(1:D) do i
133+
if i == d
134+
(2/h_per_dir[d])*sg_1d[local_node_tuple[d],point_tuple[d]]
135+
else
136+
sf_1d[local_node_tuple[i],point_tuple[i]]
137+
end
138+
end
139+
end
140+
sg[local_node,point] = v
141+
end
142+
end
143+
Aref = zeros(value_type,n,n)
144+
dV = prod(h_per_dir)/(2^D)
145+
for i in 1:n
146+
for j in 1:n
147+
for k in 1:n
148+
Aref[i,j] += dV*dot(sg[k,i],sg[k,j])
149+
end
150+
end
151+
end
152+
Aref
153+
end
154+
function setup(cells,::Type{index_type},::Type{value_type}) where {index_type,value_type}
155+
D = length(nodes_per_dir)
156+
h_per_dir = map(i->1/(i+1),nodes_per_dir)
157+
ttt = ntuple(d->2,Val{D}())
158+
cartesian_local_nodes = CartesianIndices(ttt)
159+
Aref = ref_matrix(cartesian_local_nodes,h_per_dir,value_type)#ones(value_type,2^D,2^D)
160+
cell_to_cartesian_cell = CartesianIndices(cells_per_dir)
161+
first_cartesian_cell = cell_to_cartesian_cell[first(cells)]
162+
last_cartesian_cell = cell_to_cartesian_cell[last(cells)]
163+
ranges = map(:,Tuple(first_cartesian_cell),Tuple(last_cartesian_cell))
164+
cartesian_cells = CartesianIndices(ranges)
165+
offset = CartesianIndex(ttt)
166+
cartesian_local_node_to_local_node = LinearIndices(cartesian_local_nodes)
167+
cartesian_node_to_node = LinearIndices(nodes_per_dir)
168+
nnz = 0
169+
for cartesian_cell in cartesian_cells
170+
for cartesian_local_node_i in cartesian_local_nodes
171+
local_node_i = cartesian_local_node_to_local_node[cartesian_local_node_i]
172+
# This is ugly to support Julia 1.6 (idem below)
173+
cartesian_node_i = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_i) .- Tuple(offset))
174+
boundary = any(map(is_boundary_node,Tuple(cartesian_node_i),nodes_per_dir))
175+
if boundary
176+
continue
177+
end
178+
node_i = cartesian_node_to_node[cartesian_node_i]
179+
for cartesian_local_node_j in cartesian_local_nodes
180+
local_node_j = cartesian_local_node_to_local_node[cartesian_local_node_j]
181+
cartesian_node_j = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_j) .- Tuple(offset))
182+
boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir))
183+
if boundary
184+
continue
185+
end
186+
node_j = cartesian_node_to_node[cartesian_node_j]
187+
nnz += 1
188+
end
189+
end
190+
end
191+
myI = zeros(index_type,nnz)
192+
myJ = zeros(index_type,nnz)
193+
myV = zeros(value_type,nnz)
194+
k = 0
195+
for cartesian_cell in cartesian_cells
196+
for cartesian_local_node_i in cartesian_local_nodes
197+
local_node_i = cartesian_local_node_to_local_node[cartesian_local_node_i]
198+
cartesian_node_i = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_i) .- Tuple(offset))
199+
boundary = any(map(is_boundary_node,Tuple(cartesian_node_i),nodes_per_dir))
200+
if boundary
201+
continue
202+
end
203+
node_i = cartesian_node_to_node[cartesian_node_i]
204+
for cartesian_local_node_j in cartesian_local_nodes
205+
local_node_j = cartesian_local_node_to_local_node[cartesian_local_node_j]
206+
cartesian_node_j = CartesianIndex(Tuple(cartesian_cell) .+ Tuple(cartesian_local_node_j) .- Tuple(offset))
207+
boundary = any(map(is_boundary_node,Tuple(cartesian_node_j),nodes_per_dir))
208+
if boundary
209+
continue
210+
end
211+
node_j = cartesian_node_to_node[cartesian_node_j]
212+
k += 1
213+
myI[k] = node_i
214+
myJ[k] = node_j
215+
myV[k] = Aref[local_node_i,local_node_j]
216+
end
217+
end
218+
end
219+
myI,myJ,myV
220+
end
221+
node_partition = uniform_partition(parts,parts_per_dir,nodes_per_dir)
222+
cell_partition = uniform_partition(parts,parts_per_dir,cells_per_dir)
223+
I,J,V = map(cell_partition) do cells
224+
setup(cells,Ti,Tv)
225+
end |> tuple_of_arrays
226+
I,J,V,node_partition,node_partition
227+
end
228+
229+

test/debug_array/gallery_tests.jl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module GalleryTests
2+
3+
include("../gallery_tests.jl")
4+
5+
with_debug(gallery_tests)
6+
7+
end #module

test/debug_array/runtests.jl

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ using PartitionedArrays
1313

1414
@testset "p_sparse_matrix" begin include("p_sparse_matrix_tests.jl") end
1515

16+
@testset "gallery" begin include("gallery_tests.jl") end
17+
1618
@testset "p_timer" begin include("p_timer_tests.jl") end
1719

1820
@testset "fdm_example" begin include("fdm_example.jl") end

test/gallery_tests.jl

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
using PartitionedArrays
3+
using Test
4+
5+
function gallery_tests(distribute)
6+
gallery_tests(distribute,(4,))
7+
gallery_tests(distribute,(2,2))
8+
gallery_tests(distribute,(2,1,2))
9+
end
10+
11+
function gallery_tests(distribute,parts_per_dir)
12+
p = prod(parts_per_dir)
13+
ranks = distribute(LinearIndices((p,)))
14+
nodes_per_dir = map(i->2*i,parts_per_dir)
15+
args = laplacian_fdm(nodes_per_dir,parts_per_dir,ranks)
16+
A = psparse(args...) |> fetch |> centralize |> display
17+
A = psparse(args...;assembled=true) |> fetch
18+
args = laplacian_fem(nodes_per_dir,parts_per_dir,ranks)
19+
A = psparse(args...) |> fetch |> centralize |> display
20+
end
21+
22+

test/mpi_array/gallery_tests.jl

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module GalleryTests
2+
3+
using MPI
4+
5+
project = joinpath(@__DIR__,"..","..")
6+
code = quote
7+
include(joinpath($project,"test","gallery_tests.jl"))
8+
with_mpi(gallery_tests)
9+
end
10+
11+
run(`$(mpiexec()) -np 4 julia --project=$project -e $code `)
12+
13+
end # module

test/mpi_array/runtests.jl

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using PartitionedArrays
88
@testset "p_range_tests" begin include("p_range_tests.jl") end
99
@testset "p_vector_tests" begin include("p_vector_tests.jl") end
1010
@testset "p_sparse_matrix_tests" begin include("p_sparse_matrix_tests.jl") end
11+
@testset "gallery" begin include("gallery_tests.jl") end
1112
@testset "p_timer_tests" begin include("p_timer_tests.jl") end
1213
@testset "fdm_example" begin include("fdm_example.jl") end
1314
@testset "fem_example" begin include("fem_example.jl") end

0 commit comments

Comments
 (0)