Skip to content

Commit ac69c40

Browse files
authored
Merge pull request #131 from fverdugo/allow_negative_indices
Allow negative indices
2 parents 8661e93 + 987e77b commit ac69c40

7 files changed

+129
-9
lines changed

CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [0.4.2] - unreleased
8+
## [0.4.3] - 2024-02-09
9+
10+
### Added
11+
12+
- Function `sparse_matrix`, which is is equivalent to `sparse`, but it allows one to pass negative indices (which will be ignored). Useful to handle boundary conditions.
13+
14+
## [0.4.2] - 2024-02-07
915

1016
### Added
1117

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PartitionedArrays"
22
uuid = "5a9dfac6-5c52-46f7-8278-5e2210713be9"
33
authors = ["Francesc Verdugo <[email protected]> and contributors"]
4-
version = "0.4.2"
4+
version = "0.4.3"
55

66
[deps]
77
CircularArrays = "7a955b69-7140-5f4e-a0ed-f168c5e2e749"

src/PartitionedArrays.jl

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export nziterator
2020
export nzindex
2121
export compresscoo
2222
export indextype
23+
export sparse_matrix
24+
export sparse_matrix!
2325
include("sparse_utils.jl")
2426

2527
export linear_indices

src/p_sparse_matrix.jl

+14-3
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ function psparse(f,row_partition,col_partition;assembled)
10431043
end
10441044

10451045
function psparse(I,J,V,rows,cols;kwargs...)
1046-
psparse(sparse,I,J,V,rows,cols;kwargs...)
1046+
psparse(sparse_matrix,I,J,V,rows,cols;kwargs...)
10471047
end
10481048

10491049
"""
@@ -1063,6 +1063,7 @@ function psparse(f,I,J,V,rows,cols;
10631063
restore_ids = true,
10641064
assembly_neighbors_options_rows = (;),
10651065
assembly_neighbors_options_cols = (;),
1066+
assembled_rows = nothing,
10661067
reuse=Val(false)
10671068
)
10681069

@@ -1126,6 +1127,9 @@ function psparse(f,I,J,V,rows,cols;
11261127
elseif subassembled
11271128
rows_sa = rows
11281129
cols_sa = cols
1130+
if assembled_rows == nothing
1131+
assembled_rows = map(remove_ghost,rows_sa)
1132+
end
11291133
if indices === :global
11301134
map(map_global_to_local!,I,rows_sa)
11311135
map(map_global_to_local!,J,cols_sa)
@@ -1145,7 +1149,7 @@ function psparse(f,I,J,V,rows,cols;
11451149
B,cacheB = A,nothing
11461150
end
11471151
if assemble
1148-
t = PartitionedArrays.assemble(B,rows;reuse=true,assembly_neighbors_options_cols)
1152+
t = PartitionedArrays.assemble(B,assembled_rows;reuse=true,assembly_neighbors_options_cols)
11491153
else
11501154
t = @async B,cacheB
11511155
end
@@ -1196,7 +1200,7 @@ function psparse!(C,V,cache)
11961200
rows_sa = partition(axes(A,1))
11971201
cols_sa = partition(axes(A,2))
11981202
values_sa = partition(A)
1199-
map(setcoofast!,values_sa,V,K)
1203+
map(sparse_matrix!,values_sa,V,K)
12001204
if split_format
12011205
split_format!(B,A,cacheB)
12021206
end
@@ -1905,6 +1909,7 @@ function psystem(I,J,V,I2,V2,rows,cols;
19051909
restore_ids = true,
19061910
assembly_neighbors_options_rows = (;),
19071911
assembly_neighbors_options_cols = (;),
1912+
assembled_rows = nothing,
19081913
reuse=Val(false)
19091914
)
19101915

@@ -1913,13 +1918,18 @@ function psystem(I,J,V,I2,V2,rows,cols;
19131918
# It can be optimized to exploit the fact
19141919
# that we want to generate a matrix and a vector
19151920

1921+
if assembled_rows === nothing && subassembled
1922+
assembled_rows = map(remove_ghost,rows)
1923+
end
1924+
19161925
t1 = psparse(I,J,V,rows,cols;
19171926
subassembled,
19181927
assembled,
19191928
assemble,
19201929
restore_ids,
19211930
assembly_neighbors_options_rows,
19221931
assembly_neighbors_options_cols,
1932+
assembled_rows,
19231933
reuse=true)
19241934

19251935
t2 = pvector(I2,V2,rows;
@@ -1928,6 +1938,7 @@ function psystem(I,J,V,I2,V2,rows,cols;
19281938
assemble,
19291939
restore_ids,
19301940
assembly_neighbors_options_rows,
1941+
assembled_rows,
19311942
reuse=true)
19321943

19331944
@async begin

src/p_vector.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ function pvector(f,I,V,rows;
579579
restore_ids = true,
580580
indices = :global,
581581
reuse=Val(false),
582+
assembled_rows = nothing,
582583
assembly_neighbors_options_rows = (;)
583584
)
584585

@@ -609,6 +610,9 @@ function pvector(f,I,V,rows;
609610
t = @async A, nothing
610611
end
611612
elseif subassembled
613+
if assembled_rows === nothing
614+
assembled_rows = map(remove_ghost,rows)
615+
end
612616
rows_sa = rows
613617
if indices === :global
614618
map(map_global_to_local!,I,rows_sa)
@@ -622,7 +626,7 @@ function pvector(f,I,V,rows;
622626
end
623627
A = PVector(values_sa,rows_sa)
624628
if assemble
625-
t = PartitionedArrays.assemble(A,rows;reuse=true)
629+
t = PartitionedArrays.assemble(A,assembled_rows;reuse=true)
626630
else
627631
t = @async A, nothing
628632
end

src/sparse_utils.jl

+64-3
Original file line numberDiff line numberDiff line change
@@ -333,21 +333,82 @@ Base.@propagate_inbounds Base.getindex(v::EltypeVector{T},i::Integer) where T =
333333
Base.@propagate_inbounds Base.setindex!(v::EltypeVector,w,i::Integer) = (v.parent[i] = w)
334334
Base.IndexStyle(::Type{<:EltypeVector{T,V}}) where {T,V} = IndexStyle(V)
335335

336+
# TODO deprecated
337+
function setcoofast!(A,V,K)
338+
sparse_matrix!(A,V,K)
339+
end
340+
341+
struct FilteredCooVector{F,A,B,C,T} <: AbstractVector{T}
342+
f::F
343+
I::A
344+
J::B
345+
V::C
346+
function FilteredCooVector(f::F,I::A,J::B,V::C) where {F,A,B,C}
347+
T = eltype(C)
348+
new{F,A,B,C,T}(f,I,J,V)
349+
end
350+
end
351+
Base.size(a::FilteredCooVector) = size(a.V)
352+
Base.IndexStyle(::Type{<:FilteredCooVector}) = IndexLinear()
353+
Base.@propagate_inbounds function Base.getindex(a::FilteredCooVector,k::Int)
354+
i = a.I[k]
355+
j = a.J[k]
356+
v = a.V[k]
357+
if i < 1 || j < 1
358+
return a.f(v)
359+
end
360+
v
361+
end
362+
363+
function sparse_matrix(I,J,V,m,n;kwargs...)
364+
sparse_matrix(sparse,I,J,V,m,n;kwargs...)
365+
end
366+
function sparse_matrix(f,I,J,V,m,n;reuse=Val(false),skip_out_of_bounds=true)
367+
if !skip_out_of_bounds
368+
I2 = I
369+
J2 = J
370+
V2 = V
371+
elseif m*n == 0
372+
Ti = eltype(I)
373+
Tv = eltype(V)
374+
I2 = Ti[]
375+
J2 = Ti[]
376+
V2 = Tv[]
377+
else
378+
I2 = FilteredCooVector(one,I,J,I)
379+
J2 = FilteredCooVector(one,I,J,J)
380+
V2 = FilteredCooVector(zero,I,J,V)
381+
end
382+
A = f(I2,J2,V2,m,n)
383+
if val_parameter(reuse)
384+
K = precompute_nzindex(A,I,J)
385+
return A,K
386+
end
387+
A
388+
end
389+
336390
function precompute_nzindex(A,I,J)
337391
K = zeros(Int32,length(I))
338392
for (p,(i,j)) in enumerate(zip(I,J))
393+
if i < 1 || j < 1
394+
continue
395+
end
339396
K[p] = nzindex(A,i,j)
340397
end
341398
K
342399
end
343400

344-
function setcoofast!(A,V,K)
345-
LinearAlgebra.fillstored!(A,0)
401+
function sparse_matrix!(A,V,K;reset=true)
402+
if reset
403+
LinearAlgebra.fillstored!(A,0)
404+
end
346405
A_nz = nonzeros(A)
347406
for (k,v) in zip(K,V)
407+
if k < 1
408+
continue
409+
end
348410
A_nz[k] += v
349411
end
350412
A
351413
end
352414

353-

test/sparse_utils_tests.jl

+36
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,42 @@ function test_mat(T)
5454
@test y A[rows,cols]*x
5555
@test C*x A[rows,cols]*x
5656

57+
I = Ti[1,2,5,4,1]
58+
J = Ti[3,6,1,1,3]
59+
V = Tv[4,5,3,2,5]
60+
m = 7
61+
n = 6
62+
A = sparse_matrix(I,J,V,m,n)
63+
A,Acache = sparse_matrix(I,J,V,m,n;reuse=true)
64+
sparse_matrix!(A,V,Acache)
65+
66+
I = Ti[-1]
67+
J = Ti[-1]
68+
V = Tv[-1]
69+
m = 7
70+
n = 6
71+
A = sparse_matrix(I,J,V,m,n)
72+
A,Acache = sparse_matrix(I,J,V,m,n;reuse=true)
73+
sparse_matrix!(A,V,Acache)
74+
75+
I = Ti[-1]
76+
J = Ti[-1]
77+
V = Tv[-1]
78+
m = 0
79+
n = 0
80+
A = sparse_matrix(I,J,V,m,n)
81+
A,Acache = sparse_matrix(I,J,V,m,n;reuse=true)
82+
sparse_matrix!(A,V,Acache)
83+
84+
I = Ti[]
85+
J = Ti[]
86+
V = Tv[]
87+
m = 0
88+
n = 0
89+
A = sparse_matrix(I,J,V,m,n)
90+
A,Acache = sparse_matrix(I,J,V,m,n;reuse=true)
91+
sparse_matrix!(A,V,Acache)
92+
5793
end
5894

5995
test_mat(SparseMatrixCSC{Float64,Int})

0 commit comments

Comments
 (0)