Skip to content

Commit 41bc283

Browse files
authored
Merge branch 'master' into divconforming
2 parents f967141 + f982cb0 commit 41bc283

11 files changed

Lines changed: 104 additions & 119 deletions

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Fixed `is_slave == false` (comparison instead of assignment) in `DivConformingFESpaces`, and simplified the boundary-facet branch by removing the now-redundant `if/else`.
13+
- Fixed `BlockPMatrix{V}(::UndefInitializer, rows, cols)` constructor dropping the `cols` argument, causing a `MethodError` at runtime.
14+
- Fixed `local_views(::BlockPMatrix, rows, cols)` indexing 1D block-range vectors with a 2D `CartesianIndex`, causing `BoundsError` for any multi-field problem with ≥2 fields.
15+
- Fixed `mul!(y::BlockPVector, A::BlockPMatrix, x::BlockPVector, α, β)` computing `α*β*(A*x)` instead of `α*(A*x) + β*y`; the 3-arg `mul!` was also updated to correctly zero `y` before accumulating.
16+
- Replaced fragile closure side-effect in `DistributedVisualizationData.filebase` with `getany(map(...))` for correct and idiomatic behaviour in both debug and MPI modes.
1317

1418
## [0.4.11] - 2026-02-20
1519

src/Algebra.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ end
387387

388388
function local_views(a::BlockPMatrix,new_rows::BlockPRange,new_cols::BlockPRange)
389389
vals = map(CartesianIndices(blocksize(a))) do I
390-
local_views(blocks(a)[I],blocks(new_rows)[I],blocks(new_cols)[I])
390+
local_views(blocks(a)[I],blocks(new_rows)[I[1]],blocks(new_cols)[I[2]])
391391
end |> to_parray_of_arrays
392392
return map(mortar,vals)
393393
end

src/BlockPartitionedArrays.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ function BlockPMatrix{V}(::UndefInitializer,rows::BlockPRange,cols::BlockPRange)
9494
c = block_cols[I[2]]
9595
PSparseMatrix{V}(undef,partition(r),partition(c))
9696
end
97-
return BlockPMatrix(vals,rows)
97+
return BlockPMatrix(vals,rows,cols)
9898
end
9999

100100
# AbstractArray API
@@ -329,19 +329,23 @@ end
329329

330330
function LinearAlgebra.mul!(y::BlockPVector,A::BlockPMatrix,x::BlockPVector)
331331
o = one(eltype(A))
332-
mul!(y,A,x,o,o)
332+
z = zero(eltype(A))
333+
mul!(y,A,x,o,z)
333334
end
334335

335336
function LinearAlgebra.mul!(y::BlockPVector,A::BlockPMatrix,x::BlockPVector::Number::Number)
336337
yb, Ab, xb = blocks(y), blocks(A), blocks(x)
337-
z = zero(eltype(y))
338338
o = one(eltype(A))
339+
z = zero(eltype(y))
339340
for i in 1:blocksize(A,1)
340-
fill!(yb[i],z)
341+
if iszero(β)
342+
fill!(yb[i],z)
343+
else
344+
rmul!(yb[i],β)
345+
end
341346
for j in 1:blocksize(A,2)
342347
mul!(yb[i],Ab[i,j],xb[j],α,o)
343348
end
344-
rmul!(yb[i],β)
345349
end
346350
return y
347351
end

src/Visualization.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ function Base.getproperty(x::DistributedVisualizationData, sym::Symbol)
1010
if sym == :grid
1111
map(i->i.grid,x.visdata)
1212
elseif sym == :filebase
13-
r=nothing
14-
map(x.visdata) do visdata
15-
r = visdata.filebase
16-
end
17-
r
13+
getany(map(i->i.filebase,x.visdata))
1814
elseif sym == :celldata
1915
map(i->i.celldata,x.visdata)
2016
elseif sym == :nodaldata
Lines changed: 73 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,80 @@
1+
module BlockPartitionedArraysTests
2+
3+
using Test, LinearAlgebra, BlockArrays, SparseArrays
14

2-
using Test
35
using Gridap
4-
using PartitionedArrays
56
using GridapDistributed
6-
using BlockArrays
7-
using SparseArrays
8-
using LinearAlgebra
9-
7+
using PartitionedArrays
108
using GridapDistributed: BlockPArray, BlockPVector, BlockPMatrix, BlockPRange
119

12-
ranks = with_debug() do distribute
13-
distribute(LinearIndices((2,)))
10+
function main(distribute, parts)
11+
ranks = distribute(LinearIndices((prod(parts),)))
12+
13+
n_global = 4*prod(parts)
14+
indices = uniform_partition(ranks, n_global, true)
15+
16+
pr = PRange(indices)
17+
block_range = BlockPRange([pr, pr])
18+
19+
# BlockPRange API
20+
@test blocklength(block_range) == 2
21+
@test blocksize(block_range) == (2,)
22+
23+
# BlockPVector: constructor, fill!, similar, arithmetic
24+
v = BlockPVector{Vector{Float64}}(undef, block_range)
25+
fill!(v, 1.0)
26+
v2 = similar(v, block_range)
27+
fill!(v2, 2.0)
28+
29+
v2 = v .+ 1.0
30+
v2 = v .- 1.0
31+
v2 = v .* 2.0
32+
v2 = v ./ 2.0
33+
copy!(v2, v)
34+
35+
@test norm(v) sqrt(2*n_global)
36+
37+
# PartitionedArrays vector API
38+
consistent!(v) |> wait
39+
assemble!(v) |> wait
40+
partition(v)
41+
local_values(v)
42+
own_values(v)
43+
ghost_values(v)
44+
45+
# local_views on vector with and without new range
46+
local_views(v)
47+
local_views(v, block_range)
48+
49+
# BlockPMatrix: constructor (exercises BUG3 fix: cols must not be dropped)
50+
m = BlockPMatrix{SparseMatrixCSC{Float64,Int64}}(undef, block_range, block_range)
51+
@test blocksize(m) == (2,2)
52+
53+
m2 = similar(m, (block_range, block_range))
54+
@test blocksize(m2) == (2,2)
55+
56+
# PartitionedArrays matrix API
57+
assemble!(m) |> wait
58+
LinearAlgebra.fillstored!(m, 0.0)
59+
partition(m)
60+
own_ghost_values(m)
61+
ghost_own_values(m)
62+
63+
# local_views on matrix (exercises BUG5 fix: correct I[1]/I[2] indexing)
64+
local_views(m)
65+
local_views(m, block_range, block_range)
66+
67+
maximum(abs, v)
68+
minimum(abs, v)
69+
70+
# BUG4 fix: mul!(y,A,x,α,β) must compute α*(A*x) + β*y, not α*β*(A*x)
71+
# With A=0: y ← α*(0*x) + β*y_old = β*y_old
72+
fill!(v, 1.0)
73+
v4 = similar(v, block_range)
74+
fill!(v4, 3.0)
75+
LinearAlgebra.fillstored!(m, 0.0)
76+
mul!(v4, m, v, 2.0, 2.0) # y ← 2*(0*x) + 2*[3,...] = [6,...]
77+
@test norm(v4) 6.0 * sqrt(2*n_global)
1478
end
1579

16-
indices = map(ranks) do r
17-
if r == 1
18-
own_gids = [1,2,3,4,5]
19-
ghost_gids = [6,7]
20-
ghost_owners = [2,2]
21-
else
22-
own_gids = [6,7,8,9,10]
23-
ghost_gids = [5]
24-
ghost_owners = [1]
25-
end
26-
own_idx = OwnIndices(10,r,own_gids)
27-
ghost_idx = GhostIndices(10,ghost_gids,ghost_owners)
28-
OwnAndGhostIndices(own_idx,ghost_idx)
29-
end
30-
31-
block_range = BlockPRange([PRange(indices),PRange(indices)])
32-
33-
_v = PVector{OwnAndGhostVectors{Vector{Float64}}}(undef,indices)
34-
v = BlockPArray([_v,_v],(block_range,))
35-
fill!(v,1.0)
36-
37-
_m = map(CartesianIndices((2,2))) do I
38-
i,j = I[1],I[2]
39-
local_mats = map(ranks,indices) do r, ind
40-
n = local_length(ind)
41-
if i==j && r == 1
42-
SparseMatrixCSC(n,n,Int[1,3,5,7,9,10,11,13],Int[1,2,2,3,3,4,4,5,5,6,6,7],fill(1.0,12))
43-
elseif i==j && r == 2
44-
SparseMatrixCSC(n,n,Int[1,2,4,6,8,10,11],Int[1,1,2,2,3,3,4,4,5,6],fill(1.0,10))
45-
else
46-
SparseMatrixCSC(n,n,fill(Int(1),n+1),Int[],Float64.([]))
47-
end
48-
end
49-
PSparseMatrix(local_mats,indices,indices)
50-
end;
51-
m = BlockPArray(_m,(block_range,block_range))
52-
53-
x = similar(_v)
54-
mul!(x,_m[1,1],_v)
55-
56-
# BlockPRange
57-
58-
@test blocklength(block_range) == 2
59-
@test blocksize(block_range) == (2,)
60-
61-
# AbstractArray API
62-
63-
__v = similar(v,block_range)
64-
__m = similar(m,(block_range,block_range))
65-
fill!(__v,1.0)
66-
67-
__v = __v .+ 1.0
68-
__v = __v .- 1.0
69-
__v = __v .* 1.0
70-
__v = __v ./ 1.0
71-
72-
# PartitionedArrays API
73-
74-
consistent!(__v) |> wait
75-
t = assemble!(__v)
76-
assemble!(__m) |> wait
77-
fetch(t);
78-
79-
PartitionedArrays.to_trivial_partition(m)
80-
81-
partition(v)
82-
partition(m)
83-
local_values(v)
84-
own_values(v)
85-
ghost_values(v)
86-
own_ghost_values(m)
87-
ghost_own_values(m)
88-
89-
# LinearAlgebra API
90-
fill!(v,1.0)
91-
x = similar(v)
92-
mul!(x,m,v)
93-
consistent!(x) |> wait
94-
95-
@test dot(v,x) 36
96-
norm(v)
97-
copy!(x,v)
98-
99-
LinearAlgebra.fillstored!(__m,1.0)
100-
101-
__v = BlockPVector{Vector{Float64}}(undef,block_range)
102-
#__m = BlockPMatrix{SparseMatrixCSC{Float64,Int64}}(undef,block_range,block_range)
103-
104-
maximum(abs,v)
105-
minimum(abs,v)
106-
107-
# GridapDistributed API
108-
v_parts = local_views(v)
109-
m_parts = local_views(m)
110-
111-
v_parts = local_views(v,block_range)
112-
m_parts = local_views(m,block_range,block_range)
80+
end # module

test/BlockSparseMatrixAssemblersTests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function is_same_vector(x::BlockPVector,y::PVector,Ub,U)
2121
res = map(1:num_fields(Ub)) do i
2222
xi = restrict_to_field(Ub,x_fespace,i)
2323
yi = restrict_to_field(U,y_fespace,i)
24-
xi yi
24+
norm(xi - yi) < 1.0e-10
2525
end
2626
return all(res)
2727
end

test/TestApp/src/TestApp.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module TestApp
1818
include("../../AdaptivityMultiFieldTests.jl")
1919
include("../../PolytopalCoarseningTests.jl")
2020
include("../../BlockSparseMatrixAssemblersTests.jl")
21+
include("../../BlockPartitionedArraysTests.jl")
2122
include("../../VisualizationTests.jl")
2223
include("../../AutodiffTests.jl")
2324
include("../../ConstantFESpacesTests.jl")

test/mpi/runtests_np4_body.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function all_tests(distribute,parts)
5353
end
5454

5555
TestApp.BlockSparseMatrixAssemblersTests.main(distribute,parts)
56+
TestApp.BlockPartitionedArraysTests.main(distribute,parts)
5657
PArrays.toc!(t,"BlockSparseMatrixAssemblers")
5758

5859
if prod(parts) == 4
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
module BlockSparseMatrixAssemblersTestsSeq
22
using PartitionedArrays
33
include("../BlockSparseMatrixAssemblersTests.jl")
4+
include("../BlockPartitionedArraysTests.jl")
45

56
with_debug() do distribute
67
BlockSparseMatrixAssemblersTests.main(distribute,(2,2))
8+
BlockPartitionedArraysTests.main(distribute,(2,2))
79
end
810

911
with_debug() do distribute
1012
BlockSparseMatrixAssemblersTests.main(distribute,(2,1))
13+
BlockPartitionedArraysTests.main(distribute,(2,1))
1114
end
1215

1316
with_debug() do distribute
1417
BlockSparseMatrixAssemblersTests.main(distribute,(1,2))
18+
BlockPartitionedArraysTests.main(distribute,(1,2))
1519
end
1620

1721
end # module
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module VisualizationTestsSeq
2+
include("../VisualizationTests.jl")
3+
using PartitionedArrays
4+
with_debug() do distribute
5+
VisualizationTests.main(distribute,(2,2))
6+
end
7+
end

0 commit comments

Comments
 (0)