diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83a49f5..c1e860e 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,3 +19,7 @@ repos: rev: v2.2.4 hooks: - id: codespell +- repo: https://github.com/fredrikekre/runic-pre-commit + rev: v1.0.0 + hooks: + - id: runic diff --git a/docs/make.jl b/docs/make.jl index c9d39b1..8dce434 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,22 +1,24 @@ using Documenter, ExtendableSparse, AlgebraicMultigrid, IncompleteLU, Sparspak, LinearAlgebra function mkdocs() - makedocs(; sitename = "ExtendableSparse.jl", - modules = [ExtendableSparse], - doctest = false, - warnonly = true, - clean = false, - authors = "J. Fuhrmann", - repo = "https://github.com/WIAS-PDELib/ExtendableSparse.jl", - pages = [ - "Home" => "index.md", - "example.md", - "extsparse.md", - "linearsolve.md", - "internal.md", - "iter.md", - "changes.md", - ]) + return makedocs(; + sitename = "ExtendableSparse.jl", + modules = [ExtendableSparse], + doctest = false, + warnonly = true, + clean = false, + authors = "J. Fuhrmann", + repo = "https://github.com/WIAS-PDELib/ExtendableSparse.jl", + pages = [ + "Home" => "index.md", + "example.md", + "extsparse.md", + "linearsolve.md", + "internal.md", + "iter.md", + "changes.md", + ] + ) end mkdocs() diff --git a/ext/ExtendableSparseAMGCLWrapExt.jl b/ext/ExtendableSparseAMGCLWrapExt.jl index f078a0e..aded655 100644 --- a/ext/ExtendableSparseAMGCLWrapExt.jl +++ b/ext/ExtendableSparseAMGCLWrapExt.jl @@ -12,11 +12,13 @@ mutable struct AMGCL_AMGPreconditioner <: AbstractPreconditioner factorization::AMGCLWrap.AMGPrecon kwargs function ExtendableSparse.AMGCL_AMGPreconditioner(; kwargs...) - Base.depwarn("AMGCL_AMGPreconditioner() is deprecated. Use LinearSolve with `precs=AMGCLWrap.AMGPreconBuilder()` instead.", - :AMGCL_AMGPreconditioner) + Base.depwarn( + "AMGCL_AMGPreconditioner() is deprecated. Use LinearSolve with `precs=AMGCLWrap.AMGPreconBuilder()` instead.", + :AMGCL_AMGPreconditioner + ) precon = new() precon.kwargs = kwargs - precon + return precon end end @@ -27,11 +29,11 @@ end function update!(precon::AMGCL_AMGPreconditioner) @inbounds flush!(precon.A) - precon.factorization = AMGCLWrap.AMGPrecon(precon.A;precon.kwargs...) + return precon.factorization = AMGCLWrap.AMGPrecon(precon.A; precon.kwargs...) end -allow_views(::AMGCL_AMGPreconditioner)=true -allow_views(::Type{AMGCL_AMGPreconditioner})=true +allow_views(::AMGCL_AMGPreconditioner) = true +allow_views(::Type{AMGCL_AMGPreconditioner}) = true ############################################################################# mutable struct AMGCL_RLXPreconditioner <: AbstractPreconditioner @@ -39,11 +41,13 @@ mutable struct AMGCL_RLXPreconditioner <: AbstractPreconditioner factorization::AMGCLWrap.RLXPrecon kwargs function ExtendableSparse.AMGCL_RLXPreconditioner(; kwargs...) - Base.depwarn("AMGCL_RLXPreconditioner() is deprecated. Use LinearSolve with `precs=AMGCLWrap.RLXPreconBuilder()` instead.", - :AMGCL_RLXPreconditioner) + Base.depwarn( + "AMGCL_RLXPreconditioner() is deprecated. Use LinearSolve with `precs=AMGCLWrap.RLXPreconBuilder()` instead.", + :AMGCL_RLXPreconditioner + ) precon = new() precon.kwargs = kwargs - precon + return precon end end @@ -54,12 +58,11 @@ end function update!(precon::AMGCL_RLXPreconditioner) @inbounds flush!(precon.A) - precon.factorization = AMGCLWrap.RLXPrecon(precon.A;precon.kwargs...) + return precon.factorization = AMGCLWrap.RLXPrecon(precon.A; precon.kwargs...) end -allow_views(::AMGCL_RLXPreconditioner)=true -allow_views(::Type{AMGCL_RLXPreconditioner})=true - +allow_views(::AMGCL_RLXPreconditioner) = true +allow_views(::Type{AMGCL_RLXPreconditioner}) = true end diff --git a/ext/ExtendableSparseAlgebraicMultigridExt.jl b/ext/ExtendableSparseAlgebraicMultigridExt.jl index 7abdbc2..2dffa6a 100644 --- a/ext/ExtendableSparseAlgebraicMultigridExt.jl +++ b/ext/ExtendableSparseAlgebraicMultigridExt.jl @@ -8,8 +8,8 @@ using LinearAlgebra: I import ExtendableSparse: SmoothedAggregationPreconBuilder import ExtendableSparse: RugeStubenPreconBuilder -(b::SmoothedAggregationPreconBuilder)(A::AbstractSparseMatrixCSC,p)= (aspreconditioner(smoothed_aggregation(SparseMatrixCSC(A), Val{b.blocksize}; b.kwargs...)),I) -(b::RugeStubenPreconBuilder)(A::AbstractSparseMatrixCSC,p)= (aspreconditioner(ruge_stuben(SparseMatrixCSC(A), Val{b.blocksize}; b.kwargs...)),I) +(b::SmoothedAggregationPreconBuilder)(A::AbstractSparseMatrixCSC, p) = (aspreconditioner(smoothed_aggregation(SparseMatrixCSC(A), Val{b.blocksize}; b.kwargs...)), I) +(b::RugeStubenPreconBuilder)(A::AbstractSparseMatrixCSC, p) = (aspreconditioner(ruge_stuben(SparseMatrixCSC(A), Val{b.blocksize}; b.kwargs...)), I) #### @@ -19,23 +19,23 @@ import ExtendableSparse: RugeStubenPreconBuilder import ExtendableSparse: @makefrommatrix, AbstractPreconditioner, update! ###################################################################################### -rswarned=false +rswarned = false mutable struct RS_AMGPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::AlgebraicMultigrid.Preconditioner kwargs blocksize - function ExtendableSparse.RS_AMGPreconditioner(blocksize=1; kwargs...) + function ExtendableSparse.RS_AMGPreconditioner(blocksize = 1; kwargs...) global rswarned if !rswarned @warn "RS_AMGPreconditioner is deprecated. Use LinearSolve with `precs=RugeStubenPreconBuilder()` instead" - rswarned=true + rswarned = true end precon = new() precon.kwargs = kwargs - precon.blocksize=blocksize - precon + precon.blocksize = blocksize + return precon end end @@ -46,30 +46,30 @@ end function update!(precon::RS_AMGPreconditioner) @inbounds flush!(precon.A) - precon.factorization = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(precon.A.cscmatrix,Val{precon.blocksize}; precon.kwargs...)) + return precon.factorization = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(precon.A.cscmatrix, Val{precon.blocksize}; precon.kwargs...)) end -allow_views(::RS_AMGPreconditioner)=true -allow_views(::Type{RS_AMGPreconditioner})=true +allow_views(::RS_AMGPreconditioner) = true +allow_views(::Type{RS_AMGPreconditioner}) = true ###################################################################################### -sawarned=false +sawarned = false mutable struct SA_AMGPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::AlgebraicMultigrid.Preconditioner kwargs blocksize - function ExtendableSparse.SA_AMGPreconditioner(blocksize=1; kwargs...) + function ExtendableSparse.SA_AMGPreconditioner(blocksize = 1; kwargs...) global sawarned if !sawarned @warn "SA_AMGPreconditioner is deprecated. Use LinearSolve with `precs=SmoothedAggregationPreconBuilder()` instead" - sawarned=true + sawarned = true end precon = new() precon.kwargs = kwargs - precon.blocksize=blocksize - precon + precon.blocksize = blocksize + return precon end end @@ -80,11 +80,11 @@ end function update!(precon::SA_AMGPreconditioner) @inbounds flush!(precon.A) - precon.factorization = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.smoothed_aggregation(precon.A.cscmatrix, Val{precon.blocksize}; precon.kwargs...)) + return precon.factorization = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.smoothed_aggregation(precon.A.cscmatrix, Val{precon.blocksize}; precon.kwargs...)) end -allow_views(::SA_AMGPreconditioner)=true -allow_views(::Type{SA_AMGPreconditioner})=true +allow_views(::SA_AMGPreconditioner) = true +allow_views(::Type{SA_AMGPreconditioner}) = true ###################################################################################### # deprecated diff --git a/ext/ExtendableSparseIncompleteLUExt.jl b/ext/ExtendableSparseIncompleteLUExt.jl index 2a1e7bc..1a406a4 100644 --- a/ext/ExtendableSparseIncompleteLUExt.jl +++ b/ext/ExtendableSparseIncompleteLUExt.jl @@ -1,19 +1,19 @@ module ExtendableSparseIncompleteLUExt using ExtendableSparse -using IncompleteLU +using IncompleteLU using LinearAlgebra: I using SparseArrays: AbstractSparseMatrixCSC, SparseMatrixCSC, getcolptr, rowvals, nonzeros import ExtendableSparse: ILUTPreconBuilder -(b::ILUTPreconBuilder)(A::AbstractSparseMatrixCSC,p)=(IncompleteLU.ilu(SparseMatrixCSC(A); τ = b.droptol),I) +(b::ILUTPreconBuilder)(A::AbstractSparseMatrixCSC, p) = (IncompleteLU.ilu(SparseMatrixCSC(A); τ = b.droptol), I) import ExtendableSparse: @makefrommatrix, AbstractPreconditioner, update! # Deprecated from here -warned=false +warned = false mutable struct ILUTPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::IncompleteLU.ILUFactorization @@ -22,11 +22,11 @@ mutable struct ILUTPreconditioner <: AbstractPreconditioner global warned if !warned @warn "ILUTPreconditioner is deprecated. Use LinearSolve with `precs=ILUTPreconBuilder()` instead" - warned=true + warned = true end p = new() p.droptol = droptol - p + return p end end @@ -38,7 +38,7 @@ end function update!(precon::ILUTPreconditioner) A = precon.A @inbounds flush!(A) - precon.factorization = IncompleteLU.ilu(A.cscmatrix; τ = precon.droptol) + return precon.factorization = IncompleteLU.ilu(A.cscmatrix; τ = precon.droptol) end end diff --git a/ext/ExtendableSparseLinearSolveExt.jl b/ext/ExtendableSparseLinearSolveExt.jl index 8743955..66a0efd 100644 --- a/ext/ExtendableSparseLinearSolveExt.jl +++ b/ext/ExtendableSparseLinearSolveExt.jl @@ -9,17 +9,17 @@ struct LinearSolvePrecon{T} cache::T end -function LinearSolvePrecon(A,method::LinearSolve.AbstractFactorization) +function LinearSolvePrecon(A, method::LinearSolve.AbstractFactorization) pr = LinearProblem(A, zeros(eltype(A), size(A, 1))) - LinearSolvePrecon(init(pr, method)) + return LinearSolvePrecon(init(pr, method)) end function LinearAlgebra.ldiv!(u, P::LinearSolvePrecon, b) P.cache.b = b sol = solve!(P.cache) - copyto!(u, sol.u) + return copyto!(u, sol.u) end -(b::LinearSolvePreconBuilder)(A::AbstractSparseMatrixCSC,p) = (LinearSolvePrecon(A,b.method), LinearAlgebra.I) +(b::LinearSolvePreconBuilder)(A::AbstractSparseMatrixCSC, p) = (LinearSolvePrecon(A, b.method), LinearAlgebra.I) end diff --git a/ext/ExtendableSparsePardisoExt.jl b/ext/ExtendableSparsePardisoExt.jl index 92532e0..8582cca 100644 --- a/ext/ExtendableSparsePardisoExt.jl +++ b/ext/ExtendableSparsePardisoExt.jl @@ -12,38 +12,37 @@ if Pardiso.PARDISO_LOADED[] A::Union{ExtendableSparseMatrix, Nothing} ps::Pardiso.PardisoSolver phash::UInt64 - iparm::Union{Vector{Int},Nothing} - dparm::Union{Vector{Float64},Nothing} - mtype::Union{Int,Nothing} + iparm::Union{Vector{Int}, Nothing} + dparm::Union{Vector{Float64}, Nothing} + mtype::Union{Int, Nothing} end - - function ExtendableSparse.PardisoLU(; iparm = nothing, dparm = nothing,mtype = nothing) - fact = PardisoLU(nothing, Pardiso.PardisoSolver(), 0,iparm,dparm,mtype) + + function ExtendableSparse.PardisoLU(; iparm = nothing, dparm = nothing, mtype = nothing) + return fact = PardisoLU(nothing, Pardiso.PardisoSolver(), 0, iparm, dparm, mtype) end end - + ############################################################################################# mutable struct MKLPardisoLU <: AbstractPardisoLU A::Union{ExtendableSparseMatrix, Nothing} ps::Pardiso.MKLPardisoSolver phash::UInt64 - iparm::Union{Vector{Int},Nothing} + iparm::Union{Vector{Int}, Nothing} dparm::Nothing - mtype::Union{Int,Nothing} + mtype::Union{Int, Nothing} end function ExtendableSparse.MKLPardisoLU(; iparm = nothing, mtype = nothing) - fact = MKLPardisoLU(nothing, Pardiso.MKLPardisoSolver(), 0,iparm,nothing,mtype) + return fact = MKLPardisoLU(nothing, Pardiso.MKLPardisoSolver(), 0, iparm, nothing, mtype) end - ########################################################################################## -function default_initialize!(Tv,fact::AbstractPardisoLU) - iparm=fact.iparm - dparm=fact.dparm - mtype=fact.mtype +function default_initialize!(Tv, fact::AbstractPardisoLU) + iparm = fact.iparm + dparm = fact.dparm + mtype = fact.mtype # if !isnothing(mtype) # my_mtype=mtype fix this! # else @@ -57,26 +56,26 @@ function default_initialize!(Tv,fact::AbstractPardisoLU) Pardiso.set_matrixtype!(fact.ps, my_mtype) if !isnothing(iparm) - for i = 1:min(length(iparm), length(fact.ps.iparm)) + for i in 1:min(length(iparm), length(fact.ps.iparm)) Pardiso.set_iparm!(fact.ps, i, iparm[i]) end end if !isnothing(dparm) - for i = 1:min(length(dparm), length(fact.ps.dparm)) + for i in 1:min(length(dparm), length(fact.ps.dparm)) Pardiso.set_dparm!(fact.ps, i, dparm[i]) end end - fact + return fact end function update!(lufact::AbstractPardisoLU) ps = lufact.ps flush!(lufact.A) Acsc = lufact.A.cscmatrix - Tv=eltype(Acsc) + Tv = eltype(Acsc) if lufact.phash != lufact.A.phash - default_initialize!(Tv,lufact) + default_initialize!(Tv, lufact) Pardiso.set_phase!(ps, Pardiso.RELEASE_ALL) Pardiso.pardiso(ps, Tv[], Acsc, Tv[]) Pardiso.set_phase!(ps, Pardiso.ANALYSIS_NUM_FACT) @@ -86,21 +85,23 @@ function update!(lufact::AbstractPardisoLU) end Pardiso.fix_iparm!(ps, :N) Pardiso.pardiso(ps, Tv[], Acsc, Tv[]) - lufact + return lufact end -function LinearAlgebra.ldiv!(u::AbstractVector, - lufact::AbstractPardisoLU, - v::AbstractVector) +function LinearAlgebra.ldiv!( + u::AbstractVector, + lufact::AbstractPardisoLU, + v::AbstractVector + ) ps = lufact.ps Acsc = lufact.A.cscmatrix Pardiso.set_phase!(ps, Pardiso.SOLVE_ITERATIVE_REFINE) Pardiso.pardiso(ps, u, Acsc, v) - u + return u end function LinearAlgebra.ldiv!(fact::AbstractPardisoLU, v::AbstractVector) - ldiv!(v, fact, copy(v)) + return ldiv!(v, fact, copy(v)) end @eval begin diff --git a/src/ExtendableSparse.jl b/src/ExtendableSparse.jl index e4a67c8..5d028b7 100644 --- a/src/ExtendableSparse.jl +++ b/src/ExtendableSparse.jl @@ -1,6 +1,6 @@ module ExtendableSparse -using DocStringExtensions: DocStringExtensions, SIGNATURES, TYPEDEF,TYPEDFIELDS +using DocStringExtensions: DocStringExtensions, SIGNATURES, TYPEDEF, TYPEDFIELDS using ILUZero: ILUZero, ldiv!, nnz using LinearAlgebra: LinearAlgebra, Diagonal, Hermitian, Symmetric, Tridiagonal, cholesky, cholesky!, convert, lu!, mul!, norm, transpose @@ -37,7 +37,7 @@ include("matrix/genericextendablesparsematrixcsc.jl") Aliased to [`ExtendableSparseMatrixCSC`](@ref) """ -const ExtendableSparseMatrix=ExtendableSparseMatrixCSC +const ExtendableSparseMatrix = ExtendableSparseMatrixCSC """ @@ -48,8 +48,8 @@ Multithreaded extendable sparse matrix (Experimental). Aliased to [`GenericMTExtendableSparseMatricCSC`](@ref) with [`SparseMatrixDILNKC`](@ref) scalar matrix parameter. """ -const MTExtendableSparseMatrixCSC{Tv,Ti}=GenericMTExtendableSparseMatrixCSC{SparseMatrixDILNKC{Tv,Ti},Tv,Ti} -MTExtendableSparseMatrixCSC(m,n,args...)=MTExtendableSparseMatrixCSC{Float64,Int64}(m,n,args...) +const MTExtendableSparseMatrixCSC{Tv, Ti} = GenericMTExtendableSparseMatrixCSC{SparseMatrixDILNKC{Tv, Ti}, Tv, Ti} +MTExtendableSparseMatrixCSC(m, n, args...) = MTExtendableSparseMatrixCSC{Float64, Int64}(m, n, args...) """ STExtendableSparseMatrixCSC @@ -59,12 +59,12 @@ Single threaded extendable sparse matrix (Experimental). Aliased to [`GenericExtendableSparseMatricCSC`](@ref) with [`SparseMatrixDILNKC`](@ref) scalar matrix parameter. """ -const STExtendableSparseMatrixCSC{Tv,Ti}=GenericExtendableSparseMatrixCSC{SparseMatrixDILNKC{Tv,Ti},Tv,Ti} -STExtendableSparseMatrixCSC(m,n,args...)=STExtendableSparseMatrixCSC{Float64,Int64}(m,n,args...) +const STExtendableSparseMatrixCSC{Tv, Ti} = GenericExtendableSparseMatrixCSC{SparseMatrixDILNKC{Tv, Ti}, Tv, Ti} +STExtendableSparseMatrixCSC(m, n, args...) = STExtendableSparseMatrixCSC{Float64, Int64}(m, n, args...) export ExtendableSparseMatrixCSC, MTExtendableSparseMatrixCSC, STExtendableSparseMatrixCSC, GenericMTExtendableSparseMatrixCSC -export SparseMatrixLNK, ExtendableSparseMatrix,flush!, nnz, updateindex!, rawupdateindex!, colptrs, sparse, reset!, nnznew +export SparseMatrixLNK, ExtendableSparseMatrix, flush!, nnz, updateindex!, rawupdateindex!, colptrs, sparse, reset!, nnznew export partitioning! export eliminate_dirichlet, eliminate_dirichlet!, mark_dirichlet @@ -98,7 +98,7 @@ export JacobiPreconditioner, PointBlockILUZeroPreconditioner, ParallelJacobiPreconditioner, ParallelILU0Preconditioner, - BlockPreconditioner,allow_views + BlockPreconditioner, allow_views export AbstractFactorization, LUFactorization, CholeskyFactorization, SparspakLU export issolver @@ -129,7 +129,7 @@ Create the [`AMGPreconditioner`](@ref) wrapping the Ruge-Stüben AMG preconditi Deprecated in favor of [`RS_AMGPreconditioner`](@ref) """ -function AMGPreconditioner end +function AMGPreconditioner end export AMGPreconditioner @deprecate AMGPreconditioner() RS_AMGPreconditioner() @@ -144,7 +144,7 @@ RS_AMGPreconditioner(matrix;kwargs...) Create the [`RS_AMGPreconditioner`](@ref) wrapping the Ruge-Stüben AMG preconditioner from [AlgebraicMultigrid.jl](https://github.com/JuliaLinearAlgebra/AlgebraicMultigrid.jl) For `kwargs` see there. """ -function RS_AMGPreconditioner end +function RS_AMGPreconditioner end export RS_AMGPreconditioner @@ -157,12 +157,10 @@ SA_AMGPreconditioner(matrix;kwargs...) Create the [`SA_AMGPreconditioner`](@ref) wrapping the smoothed aggregation AMG preconditioner from [AlgebraicMultigrid.jl](https://github.com/JuliaLinearAlgebra/AlgebraicMultigrid.jl) For `kwargs` see there. """ -function SA_AMGPreconditioner end +function SA_AMGPreconditioner end export SA_AMGPreconditioner - - """ ``` AMGCL_AMGPreconditioner(;kwargs...) @@ -188,8 +186,6 @@ function AMGCL_RLXPreconditioner end export AMGCL_RLXPreconditioner - - """ ``` PardisoLU(;iparm::Vector, diff --git a/src/compat.jl b/src/compat.jl index b14f960..ad847b3 100644 --- a/src/compat.jl +++ b/src/compat.jl @@ -2,7 +2,7 @@ # https://github.com/JuliaDiff/DifferentiationInterface.jl/blob/main/DifferentiationInterface/src/compat.jl # macro public(ex) - if VERSION >= v"1.11.0-DEV.469" + return if VERSION >= v"1.11.0-DEV.469" args = if ex isa Symbol (ex,) elseif Base.isexpr(ex, :tuple) diff --git a/src/experimental/Experimental.jl b/src/experimental/Experimental.jl index 4769e4c..9a3bb30 100644 --- a/src/experimental/Experimental.jl +++ b/src/experimental/Experimental.jl @@ -2,10 +2,10 @@ module Experimental using ExtendableSparse, SparseArrays using LinearAlgebra using SparseArrays: AbstractSparseMatrixCSC -import SparseArrays: nonzeros, getcolptr,nzrange +import SparseArrays: nonzeros, getcolptr, nzrange import ExtendableSparse: flush!, reset!, rawupdateindex!, findindex using ExtendableSparse: ColEntry, AbstractPreconditioner, @makefrommatrix, phash -using ExtendableSparse: AbstractExtendableSparseMatrixCSC, AbstractSparseMatrixExtension +using ExtendableSparse: AbstractExtendableSparseMatrixCSC, AbstractSparseMatrixExtension using DocStringExtensions using Metis using Base.Threads @@ -18,7 +18,7 @@ include(joinpath(@__DIR__, "ExtendableSparseMatrixParallel", "ilu_Al-Kurdi_Mitta include(joinpath(@__DIR__, "ExtendableSparseMatrixParallel", "pilu_Al-Kurdi_Mittal.jl")) #using .PILUAM -include(joinpath(@__DIR__, "ExtendableSparseMatrixParallel" ,"iluam.jl")) +include(joinpath(@__DIR__, "ExtendableSparseMatrixParallel", "iluam.jl")) include(joinpath(@__DIR__, "ExtendableSparseMatrixParallel", "piluam.jl")) @eval begin @@ -29,14 +29,13 @@ end function factorize!(p::PILUAMPreconditioner, A::ExtendableSparseMatrixParallel) p.A = A update!(p) - p + return p end - -export ExtendableSparseMatrixParallel, SuperSparseMatrixLNK -export addtoentry!, reset!, dummy_assembly!, preparatory_multi_ps_less_reverse, fr, addtoentry!, compare_matrices_light -export ILUAMPreconditioner, PILUAMPreconditioner -export reorderlinsys, nnz_noflush +export ExtendableSparseMatrixParallel, SuperSparseMatrixLNK +export addtoentry!, reset!, dummy_assembly!, preparatory_multi_ps_less_reverse, fr, addtoentry!, compare_matrices_light +export ILUAMPreconditioner, PILUAMPreconditioner +export reorderlinsys, nnz_noflush end diff --git a/src/experimental/ExtendableSparseMatrixParallel/ExtendableSparseParallel.jl b/src/experimental/ExtendableSparseMatrixParallel/ExtendableSparseParallel.jl index 08268ee..593f11d 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/ExtendableSparseParallel.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/ExtendableSparseParallel.jl @@ -16,45 +16,45 @@ mutable struct ExtendableSparseMatrixParallel{Tv, Ti <: Integer} <: AbstractSpar """ Number of Nodes per Threads """ - nnts::Vector{Ti} - + nnts::Vector{Ti} + """ sortednodesperthread[i,j] = local index of the j-th global column in the i-th LNK matrix (this is used e.g. when assembling the matrix) """ sortednodesperthread::Matrix{Ti} - + """ depth+1 x nn matrix, old_noderegions[i,j] = region in which node j is, in level i old refers to the fact that j is the 'old index' (i.e. grid index, not matrix index, see 'new_indices') """ old_noderegions::Matrix{Ti} - + """ cellsforpart[i] is a vector containing all cells in the i-th region cellsforpart has length nt*depth + 1 """ cellsforpart::Vector{Vector{Ti}} - + """ globalindices[i][j] = index in the global (ESMP & CSC) matrix of the j-th column of the i-th LNK matrix (this maps the local indices (in the LNKs) to the global indices (ESMP & CSC)) """ globalindices::Vector{Vector{Ti}} - + """ For some applications such as the parallel ILU preconditioner, a block form is necessary. Thus, the columns are reordered and the A[i,i] does not correspond to the i-th node of the grid, but A[new_indices[i], new_indices[i]] does """ new_indices::Vector{Ti} - + """ Reverse: rev_new_indices[new_indices[i]] = i, for all i """ rev_new_indices::Vector{Ti} - + """ starts[i] gives the first column of the i-th region, i.e. starts[1] = 1 starts has length nt*depth + 1 @@ -65,12 +65,12 @@ mutable struct ExtendableSparseMatrixParallel{Tv, Ti <: Integer} <: AbstractSpar cellparts[i] = region of the i-th cell """ cellparts::Vector{Ti} - + """ Number of threads """ nt::Ti - + """ How often is the separator partitioned? (if never: depth = 1) """ @@ -87,8 +87,8 @@ mutable struct ExtendableSparseMatrixParallel{Tv, Ti <: Integer} <: AbstractSpar Number of columns / number of nodes in grid (only works for square matrices) """ m::Ti - - + + end @@ -105,10 +105,10 @@ The matrix structure is made for parallel computations with `nt` threads. `block_struct=true` means, the matrix should be reordered two have a block structure, this is necessary for parallel ILU, for `false`, the matrix is not reordered """ function ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct = true) where {Tv, Ti <: Integer} - nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, depth = preparatory_multi_ps_less_reverse(mat_cell_node, nc, nn, nt, depth, Ti; block_struct) - csc = spzeros(Tv, Ti, nn, nn) - lnk = [SuperSparseMatrixLNK{Tv, Ti}(nn, nnts[tid]) for tid=1:nt] - ExtendableSparseMatrixParallel{Tv, Ti}(csc, lnk, nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, nt, depth, phash(csc), csc.n, csc.m) + nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, depth = preparatory_multi_ps_less_reverse(mat_cell_node, nc, nn, nt, depth, Ti; block_struct) + csc = spzeros(Tv, Ti, nn, nn) + lnk = [SuperSparseMatrixLNK{Tv, Ti}(nn, nnts[tid]) for tid in 1:nt] + return ExtendableSparseMatrixParallel{Tv, Ti}(csc, lnk, nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, nt, depth, phash(csc), csc.n, csc.m) end @@ -122,16 +122,16 @@ This function should be used, if the thread in which the entry appears is known If the thread is not known, use `addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, v; known_that_unknown=false)`, this function calculates `tid`. If you know that the entry is not yet known to the CSC structure, set `known_that_unknown=true`. """ -function addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, tid, v; known_that_unknown=false) where {Tv, Ti <: Integer} - if known_that_unknown - A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v - return - end - - if updatentryCSC2!(A.cscmatrix, i, j, v) - else - A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v - end +function addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, tid, v; known_that_unknown = false) where {Tv, Ti <: Integer} + if known_that_unknown + A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v + return + end + + return if updatentryCSC2!(A.cscmatrix, i, j, v) + else + A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v + end end @@ -144,18 +144,18 @@ A[i,j] += v, using any partition. If the partition should be specified (for parallel use), use `function addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, tid, v; known_that_unknown=false) where {Tv, Ti <: Integer}`. """ -function addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, v; known_that_unknown=false) where {Tv, Ti <: Integer} - if known_that_unknown - level, tid = last_nz(A.old_noderegions[:, A.rev_new_indices[j]]) - A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v - return - end - - if updatentryCSC2!(A.cscmatrix, i, j, v) - else - _, tid = last_nz(A.old_noderegions[:, A.rev_new_indices[j]]) - A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v - end +function addtoentry!(A::ExtendableSparseMatrixParallel{Tv, Ti}, i, j, v; known_that_unknown = false) where {Tv, Ti <: Integer} + if known_that_unknown + level, tid = last_nz(A.old_noderegions[:, A.rev_new_indices[j]]) + A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v + return + end + + return if updatentryCSC2!(A.cscmatrix, i, j, v) + else + _, tid = last_nz(A.old_noderegions[:, A.rev_new_indices[j]]) + A.lnkmatrices[tid][i, A.sortednodesperthread[tid, j]] += v + end end #--------------------------------- @@ -167,20 +167,22 @@ $(SIGNATURES) Update element of the matrix with operation `op`. Use this method if the 'thread of the element' is not known, otherwise use `updateindex!(ext, op, v, i, j, tid)`. """ -function updateindex!(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - op, - v, - i, - j) where {Tv, Ti <: Integer} +function updateindex!( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + op, + v, + i, + j + ) where {Tv, Ti <: Integer} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) return else - level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) - updateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) + level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) + updateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) end - ext + return ext end """ @@ -190,20 +192,22 @@ $(SIGNATURES) Update element of the matrix with operation `op`. Use this method if the 'thread of the element' is known, otherwise use `updateindex!(ext, op, v, i, j)`. """ -function updateindex!(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - op, - v, - i, - j, - tid) where {Tv, Ti <: Integer} +function updateindex!( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + op, + v, + i, + j, + tid + ) where {Tv, Ti <: Integer} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) return else - updateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) + updateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) end - ext + return ext end """ @@ -213,19 +217,21 @@ $(SIGNATURES) Like [`updateindex!`](@ref) but without checking if v is zero. Use this method if the 'thread of the element' is not known. """ -function rawupdateindex!(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - op, - v, - i, - j) where {Tv, Ti <: Integer} +function rawupdateindex!( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + op, + v, + i, + j + ) where {Tv, Ti <: Integer} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) - rawupdateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) + rawupdateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) end - ext + return ext end """ @@ -235,19 +241,21 @@ $(SIGNATURES) Like [`updateindex!`](@ref) but without checking if v is zero. Use this method if the 'thread of the element' is known """ -function rawupdateindex!(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - op, - v, - i, - j, - tid) where {Tv, Ti <: Integer} +function rawupdateindex!( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + op, + v, + i, + j, + tid + ) where {Tv, Ti <: Integer} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else rawupdateindex!(ext.lnkmatrices[tid], op, v, i, ext.sortednodesperthread[tid, j]) end - ext + return ext end """ @@ -257,17 +265,19 @@ $(SIGNATURES) Find index in CSC matrix and return value, if it exists. Otherwise, return value from extension. """ -function Base.getindex(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - i::Integer, - j::Integer) where {Tv, Ti <: Integer} +function Base.getindex( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + i::Integer, + j::Integer + ) where {Tv, Ti <: Integer} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) if k > 0 return ext.cscmatrix.nzval[k] end - + level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) - ext.lnkmatrices[tid][i, ext.sortednodesperthread[tid, j]] - + return ext.lnkmatrices[tid][i, ext.sortednodesperthread[tid, j]] + end """ @@ -277,23 +287,24 @@ $(SIGNATURES) Find index in CSC matrix and set value if it exists. Otherwise, set index in extension if `v` is nonzero. """ -function Base.setindex!(ext::ExtendableSparseMatrixParallel{Tv, Ti}, - v::Union{Number,AbstractVecOrMat}, - i::Integer, - j::Integer) where {Tv, Ti} +function Base.setindex!( + ext::ExtendableSparseMatrixParallel{Tv, Ti}, + v::Union{Number, AbstractVecOrMat}, + i::Integer, + j::Integer + ) where {Tv, Ti} k = ExtendableSparse.findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = v else - level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) - #@info typeof(tid), typeof(j) - jj = ext.sortednodesperthread[tid, j] - ext.lnkmatrices[tid][i, jj] = v + level, tid = last_nz(ext.old_noderegions[:, ext.rev_new_indices[j]]) + #@info typeof(tid), typeof(j) + jj = ext.sortednodesperthread[tid, j] + ext.lnkmatrices[tid][i, jj] = v end end - #------------------------------------ """ @@ -302,8 +313,8 @@ $(SIGNATURES) Reset matrix, such that CSC and LNK have no non-zero entries. """ function reset!(A::ExtendableSparseMatrixParallel{Tv, Ti}) where {Tv, Ti <: Integer} - A.cscmatrix = spzeros(Tv, Ti, A.n, A.m) - A.lnkmatrices = [SuperSparseMatrixLNK{Tv, Ti}(A.n, A.nnts[tid]) for tid=1:A.nt] + A.cscmatrix = spzeros(Tv, Ti, A.n, A.m) + return A.lnkmatrices = [SuperSparseMatrixLNK{Tv, Ti}(A.n, A.nnts[tid]) for tid in 1:A.nt] end """ @@ -322,15 +333,15 @@ $(SIGNATURES) Compute number of non-zero elements, without flush. """ function nnz_noflush(ext::ExtendableSparseMatrixParallel) - return nnz(ext.cscmatrix), sum([ext.lnkmatrices[i].nnz for i=1:ext.nt]) + return nnz(ext.cscmatrix), sum([ext.lnkmatrices[i].nnz for i in 1:ext.nt]) end - + function matrixindextype(A::ExtendableSparseMatrixParallel{Tv, Ti}) where {Tv, Ti <: Integer} - Ti + return Ti end function matrixvaluetype(A::ExtendableSparseMatrixParallel{Tv, Ti}) where {Tv, Ti <: Integer} - Tv + return Tv end @@ -343,27 +354,29 @@ function Base.show(io::IO, ::MIME"text/plain", ext::ExtendableSparseMatrixParall #flush!(ext) xnnzCSC, xnnzLNK = nnz_noflush(ext) m, n = size(ext) - print(io, - m, - "×", - n, - " ", - typeof(ext), - " with ", - xnnzCSC, - " stored ", - xnnzCSC == 1 ? "entry" : "entries", - " in CSC and ", - xnnzLNK, - " stored ", - xnnzLNK == 1 ? "entry" : "entries", - " in LNK. CSC:") + print( + io, + m, + "×", + n, + " ", + typeof(ext), + " with ", + xnnzCSC, + " stored ", + xnnzCSC == 1 ? "entry" : "entries", + " in CSC and ", + xnnzLNK, + " stored ", + xnnzLNK == 1 ? "entry" : "entries", + " in LNK. CSC:" + ) if !haskey(io, :compact) io = IOContext(io, :compact => true) end - if !(m == 0 || n == 0 || xnnzCSC == 0) + return if !(m == 0 || n == 0 || xnnzCSC == 0) print(io, ":\n") Base.print_array(IOContext(io), ext.cscmatrix) end @@ -375,9 +388,9 @@ end Find out if CSC already has an nonzero entry at i,j without any allocations """ function entryexists2(CSC, i, j) #find out if CSC already has an nonzero entry at i,j - #vals = - #ids = CSC.colptr[j]:(CSC.colptr[j+1]-1) - i in view(CSC.rowval, CSC.colptr[j]:(CSC.colptr[j+1]-1)) + #vals = + #ids = CSC.colptr[j]:(CSC.colptr[j+1]-1) + return i in view(CSC.rowval, CSC.colptr[j]:(CSC.colptr[j + 1] - 1)) end """ @@ -386,27 +399,24 @@ $(SIGNATURES) Find out if i,j is non-zero entry in CSC, if yes, update entry with += v and return `true`, if not return `false` """ function updatentryCSC2!(CSC::SparseArrays.SparseMatrixCSC{Tv, Ti}, i::Integer, j::Integer, v) where {Tv, Ti <: Integer} - p1 = CSC.colptr[j] - p2 = CSC.colptr[j+1]-1 - - searchk = searchsortedfirst(view(CSC.rowval, p1:p2), i) + p1 - 1 - - if (searchk <= p2) && (CSC.rowval[searchk] == i) - CSC.nzval[searchk] += v - return true - else - return false - end -end + p1 = CSC.colptr[j] + p2 = CSC.colptr[j + 1] - 1 + searchk = searchsortedfirst(view(CSC.rowval, p1:p2), i) + p1 - 1 + if (searchk <= p2) && (CSC.rowval[searchk] == i) + CSC.nzval[searchk] += v + return true + else + return false + end +end Base.size(A::ExtendableSparseMatrixParallel) = (A.cscmatrix.m, A.cscmatrix.n) include("struct_flush.jl") - import LinearAlgebra.mul! """ @@ -415,12 +425,12 @@ $(SIGNATURES) This overwrites the mul! function for A::ExtendableSparseMatrixParallel """ -function LinearAlgebra.mul!(y::AbstractVector{Tv}, A::ExtendableSparseMatrixParallel{Tv, Ti}, x::AbstractVector{Tv}) where {Tv, Ti<:Integer} +function LinearAlgebra.mul!(y::AbstractVector{Tv}, A::ExtendableSparseMatrixParallel{Tv, Ti}, x::AbstractVector{Tv}) where {Tv, Ti <: Integer} #@info "my matvec" _, nnzLNK = nnz_noflush(A) @assert nnzLNK == 0 #mul!(y, A.cscmatrix, x) - matvec!(y, A, x) + return matvec!(y, A, x) end @@ -431,34 +441,33 @@ $(SIGNATURES) y <- A*x, where y and x are vectors and A is an ExtendableSparseMatrixParallel this computation is done in parallel, it has the same result as y = A.cscmatrix*x """ -function matvec!(y::AbstractVector{Tv}, A::ExtendableSparseMatrixParallel{Tv,Ti}, x::AbstractVector{Tv}) where {Tv, Ti<:Integer} +function matvec!(y::AbstractVector{Tv}, A::ExtendableSparseMatrixParallel{Tv, Ti}, x::AbstractVector{Tv}) where {Tv, Ti <: Integer} nt = A.nt depth = A.depth colptr = A.cscmatrix.colptr nzv = A.cscmatrix.nzval - rv = A.cscmatrix.rowval + rv = A.cscmatrix.rowval LinearAlgebra._rmul_or_fill!(y, 0.0) - - for level=1:depth - @threads for tid::Int64=1:nt - for col::Int64=A.start[(level-1)*nt+tid]:A.start[(level-1)*nt+tid+1]-1 - for row::Int64=colptr[col]:colptr[col+1]-1 # in nzrange(A, col) - y[rv[row]] += nzv[row]*x[col] + + for level in 1:depth + @threads for tid::Int64 in 1:nt + for col::Int64 in A.start[(level - 1) * nt + tid]:(A.start[(level - 1) * nt + tid + 1] - 1) + for row::Int64 in colptr[col]:(colptr[col + 1] - 1) # in nzrange(A, col) + y[rv[row]] += nzv[row] * x[col] end end end end - - @threads for tid=1:1 - for col::Int64=A.start[depth*nt+1]:A.start[depth*nt+2]-1 - for row::Int64=colptr[col]:colptr[col+1]-1 #nzrange(A, col) - y[rv[row]] += nzv[row]*x[col] + @threads for tid in 1:1 + for col::Int64 in A.start[depth * nt + 1]:(A.start[depth * nt + 2] - 1) + for row::Int64 in colptr[col]:(colptr[col + 1] - 1) #nzrange(A, col) + y[rv[row]] += nzv[row] * x[col] end end end - - y + + return y end diff --git a/src/experimental/ExtendableSparseMatrixParallel/ilu_Al-Kurdi_Mittal.jl b/src/experimental/ExtendableSparseMatrixParallel/ilu_Al-Kurdi_Mittal.jl index 6223d10..75c2341 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/ilu_Al-Kurdi_Mittal.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/ilu_Al-Kurdi_Mittal.jl @@ -1,199 +1,200 @@ #module ILUAM #using LinearAlgebra, SparseArrays -import LinearAlgebra.ldiv!, LinearAlgebra.\, SparseArrays.nnz +import LinearAlgebra.ldiv!, LinearAlgebra.\, SparseArrays.nnz #@info "ILUAM" -mutable struct ILUAMPrecon{T,N} +mutable struct ILUAMPrecon{T, N} - diag::AbstractVector + diag::AbstractVector nzval::AbstractVector - A::AbstractMatrix - + A::AbstractMatrix + end -function iluAM!(ILU::ILUAMPrecon{Tv,Ti}, A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <:Integer} - diag = ILU.diag - nzval = ILU.nzval +function iluAM!(ILU::ILUAMPrecon{Tv, Ti}, A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: Integer} + diag = ILU.diag + nzval = ILU.nzval + + nzval = copy(A.nzval) + diag = Vector{Ti}(undef, n) + ILU.A = A + colptr = A.colptr + rowval = A.rowval + n = A.n + point = zeros(Ti, n) + + for j in 1:n + for v in colptr[j]:(colptr[j + 1] - 1) + if rowval[v] == j + diag[j] = v + break + end + #elseif rowval[v] + end + end + + # compute L and U + for j in 1:n + for v in colptr[j]:(colptr[j + 1] - 1) ## start at colptr[j]+1 ?? + point[rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + #nzval[v] /= nzval[diag[i]] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end - nzval = copy(A.nzval) - diag = Vector{Ti}(undef, n) - ILU.A = A - colptr = A.colptr - rowval = A.rowval - n = A.n - point = zeros(Ti, n) - - for j=1:n - for v=colptr[j]:colptr[j+1]-1 - if rowval[v] == j - diag[j] = v - break - end - #elseif rowval[v] - end - end - - # compute L and U - for j=1:n - for v=colptr[j]:colptr[j+1]-1 ## start at colptr[j]+1 ?? - point[rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - #nzval[v] /= nzval[diag[i]] - for w=diag[i]+1:colptr[i+1]-1 - k = point[rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - - for v=colptr[j]:colptr[j+1]-1 - point[rowval[v]] = zero(Ti) - end - end + for v in colptr[j]:(colptr[j + 1] - 1) + point[rowval[v]] = zero(Ti) + end + end + + return end -function iluAM(A::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti <:Integer} - #@info "iluAM" - nzval = copy(A.nzval) - colptr = A.colptr - rowval = A.rowval - #nzval = ILU.nzval - n = A.n # number of columns - point = zeros(Ti, n) #Vector{Ti}(undef, n) - diag = Vector{Ti}(undef, n) - - # find diagonal entries - for j=1:n - for v=colptr[j]:colptr[j+1]-1 - if rowval[v] == j - diag[j] = v - break - end - #elseif rowval[v] - end - end +function iluAM(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: Integer} + #@info "iluAM" + nzval = copy(A.nzval) + colptr = A.colptr + rowval = A.rowval + #nzval = ILU.nzval + n = A.n # number of columns + point = zeros(Ti, n) #Vector{Ti}(undef, n) + diag = Vector{Ti}(undef, n) - #@info diag[1:20]' - #@info diag[end-20:end]' - - # compute L and U - for j=1:n - for v=colptr[j]:colptr[j+1]-1 ## start at colptr[j]+1 ?? - point[rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - #nzval[v] /= nzval[diag[i]] - for w=diag[i]+1:colptr[i+1]-1 - k = point[rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - - for v=colptr[j]:colptr[j+1]-1 - point[rowval[v]] = zero(Ti) - end - end - #nzval, diag - ILUAMPrecon{Tv,Ti}(diag, nzval, A) + # find diagonal entries + for j in 1:n + for v in colptr[j]:(colptr[j + 1] - 1) + if rowval[v] == j + diag[j] = v + break + end + #elseif rowval[v] + end + end + + #@info diag[1:20]' + #@info diag[end-20:end]' + + # compute L and U + for j in 1:n + for v in colptr[j]:(colptr[j + 1] - 1) ## start at colptr[j]+1 ?? + point[rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + #nzval[v] /= nzval[diag[i]] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end + + + for v in colptr[j]:(colptr[j + 1] - 1) + point[rowval[v]] = zero(Ti) + end + end + #nzval, diag + return ILUAMPrecon{Tv, Ti}(diag, nzval, A) end function forward_subst_old!(y, v, nzval, diag, A) - #@info "fso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" - n = A.n - colptr = A.colptr - rowval = A.rowval - - for i in eachindex(y) + #@info "fso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" + n = A.n + colptr = A.colptr + rowval = A.rowval + + for i in eachindex(y) y[i] = zero(Float64) end - #y .= 0 - @inbounds for j=1:n - y[j] += v[j] - for v=diag[j]+1:colptr[j+1]-1 - y[rowval[v]] -= nzval[v]*y[j] - end - end - y + #y .= 0 + @inbounds for j in 1:n + y[j] += v[j] + for v in (diag[j] + 1):(colptr[j + 1] - 1) + y[rowval[v]] -= nzval[v] * y[j] + end + end + return y end function backward_subst_old!(x, y, nzval, diag, A) - #@info "bso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" - n = A.n - colptr = A.colptr - rowval = A.rowval - @inbounds for j=n:-1:1 - x[j] = y[j] / nzval[diag[j]] - - for i=colptr[j]:diag[j]-1 - y[rowval[i]] -= nzval[i]*x[j] - end - - end - x + #@info "bso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" + n = A.n + colptr = A.colptr + rowval = A.rowval + @inbounds for j in n:-1:1 + x[j] = y[j] / nzval[diag[j]] + + for i in colptr[j]:(diag[j] - 1) + y[rowval[i]] -= nzval[i] * x[j] + end + + end + return x end function ldiv!(x, ILU::ILUAMPrecon, b) - #t = @elapsed begin - #@info "iluam ldiv 1" - nzval = ILU.nzval - diag = ILU.diag - A = ILU.A - y = copy(b) - #forward_subst!(y, b, ILU) - forward_subst_old!(y, b, nzval, diag, A) - backward_subst_old!(x, y, nzval, diag, A) - #@info "ILUAM:", b[1], y[1], x[1], maximum(abs.(b-A*x)), nnz(A) #, A[10,10] - #, b[1], x[1], y[1]#maximum(abs.(b)), maximum(abs.(x)) - #end - #println("$t") #@info t - x + #t = @elapsed begin + #@info "iluam ldiv 1" + nzval = ILU.nzval + diag = ILU.diag + A = ILU.A + y = copy(b) + #forward_subst!(y, b, ILU) + forward_subst_old!(y, b, nzval, diag, A) + backward_subst_old!(x, y, nzval, diag, A) + #@info "ILUAM:", b[1], y[1], x[1], maximum(abs.(b-A*x)), nnz(A) #, A[10,10] + #, b[1], x[1], y[1]#maximum(abs.(b)), maximum(abs.(x)) + #end + #println("$t") #@info t + return x end function ldiv!(ILU::ILUAMPrecon, b) - #@info "iluam ldiv 2" - nzval = ILU.nzval - diag = ILU.diag - A = ILU.A - y = copy(b) - #forward_subst!(y, b, ILU) - forward_subst_old!(y, b, nzval, diag, A) - backward_subst_old!(b, y, nzval, diag, A) - b + #@info "iluam ldiv 2" + nzval = ILU.nzval + diag = ILU.diag + A = ILU.A + y = copy(b) + #forward_subst!(y, b, ILU) + forward_subst_old!(y, b, nzval, diag, A) + backward_subst_old!(b, y, nzval, diag, A) + return b end -function \(ilu::ILUAMPrecon{T,N}, b) where {T,N<:Integer} +function \(ilu::ILUAMPrecon{T, N}, b) where {T, N <: Integer} x = copy(b) ldiv!(x, ilu, b) - x + return x end -function nnz(ilu::ILUAMPrecon{T,N}) where {T,N<:Integer} - length(ilu.nzval) +function nnz(ilu::ILUAMPrecon{T, N}) where {T, N <: Integer} + return length(ilu.nzval) end #= @@ -263,5 +264,4 @@ end =# - #end diff --git a/src/experimental/ExtendableSparseMatrixParallel/iluam.jl b/src/experimental/ExtendableSparseMatrixParallel/iluam.jl index 0e70f74..cbc05de 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/iluam.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/iluam.jl @@ -5,7 +5,7 @@ mutable struct ILUAMPreconditioner <: AbstractPreconditioner function ILUAMPreconditioner() p = new() p.phash = 0 - p + return p end end @@ -23,12 +23,12 @@ function update!(p::ILUAMPreconditioner) flush!(p.A) if p.A.phash != p.phash p.factorization = iluAM(p.A.cscmatrix) - p.phash=p.A.phash + p.phash = p.A.phash else iluam!(p.factorization, p.A.cscmatrix) end - p + return p end -allow_views(::ILUAMPreconditioner)=true -allow_views(::Type{ILUAMPreconditioner})=true +allow_views(::ILUAMPreconditioner) = true +allow_views(::Type{ILUAMPreconditioner}) = true diff --git a/src/experimental/ExtendableSparseMatrixParallel/pilu_Al-Kurdi_Mittal.jl b/src/experimental/ExtendableSparseMatrixParallel/pilu_Al-Kurdi_Mittal.jl index 157785f..3929ffd 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/pilu_Al-Kurdi_Mittal.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/pilu_Al-Kurdi_Mittal.jl @@ -2,160 +2,162 @@ #using Base.Threads #using LinearAlgebra, SparseArrays -import LinearAlgebra.ldiv!, LinearAlgebra.\, SparseArrays.nnz +import LinearAlgebra.ldiv!, LinearAlgebra.\, SparseArrays.nnz #@info "PILUAM" -mutable struct PILUAMPrecon{T,N} +mutable struct PILUAMPrecon{T, N} - diag::AbstractVector + diag::AbstractVector nzval::AbstractVector - A::AbstractMatrix - start::AbstractVector - nt::Integer - depth::Integer - + A::AbstractMatrix + start::AbstractVector + nt::Integer + depth::Integer + end function use_vector_par(n, nt, Ti) - point = [Vector{Ti}(undef, n) for tid=1:nt] - @threads for tid=1:nt - point[tid] = zeros(Ti, n) - end - point + point = [Vector{Ti}(undef, n) for tid in 1:nt] + @threads for tid in 1:nt + point[tid] = zeros(Ti, n) + end + return point end function compute_lu!(nzval, point, j0, j1, tid, rowval, colptr, diag, Ti) - for j=j0:j1-1 - for v=colptr[j]:colptr[j+1]-1 + for j in j0:(j1 - 1) + for v in colptr[j]:(colptr[j + 1] - 1) point[tid][rowval[v]] = v end - - for v=colptr[j]:diag[j]-1 + + for v in colptr[j]:(diag[j] - 1) i = rowval[v] - for w=diag[i]+1:colptr[i+1]-1 + for w in (diag[i] + 1):(colptr[i + 1] - 1) k = point[tid][rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] end end end - - for v=diag[j]+1:colptr[j+1]-1 + + for v in (diag[j] + 1):(colptr[j + 1] - 1) nzval[v] /= nzval[diag[j]] end - - for v=colptr[j]:colptr[j+1]-1 + + for v in colptr[j]:(colptr[j + 1] - 1) point[tid][rowval[v]] = zero(Ti) end end + return end -function piluAM!(ILU::PILUAMPrecon{Tv,Ti}, A::ExtendableSparseMatrixParallel{Tv,Ti}) where {Tv, Ti <:Integer} - #@info "piluAM!" - diag = ILU.diag - nzval = ILU.nzval - ILU.A = A - start = ILU.start - - ILU.nt = A.nt - nt = A.nt - - ILU.depth = A.depth - depth = A.depth - - - colptr = A.cscmatrix.colptr - rowval = A.cscmatrix.rowval - n = A.cscmatrix.n # number of columns - diag = Vector{Ti}(undef, n) - nzval = Vector{Tv}(undef, length(rowval)) #copy(A.nzval) - point = use_vector_par(n, A.nt, Int32) - - - @threads for tid=1:depth*nt+1 - for j=start[tid]:start[tid+1]-1 - for v=colptr[j]:colptr[j+1]-1 - nzval[v] = A.cscmatrix.nzval[v] - if rowval[v] == j - diag[j] = v - end - #elseif rowval[v] - end - end - end +function piluAM!(ILU::PILUAMPrecon{Tv, Ti}, A::ExtendableSparseMatrixParallel{Tv, Ti}) where {Tv, Ti <: Integer} + #@info "piluAM!" + diag = ILU.diag + nzval = ILU.nzval + ILU.A = A + start = ILU.start + + ILU.nt = A.nt + nt = A.nt + + ILU.depth = A.depth + depth = A.depth + + + colptr = A.cscmatrix.colptr + rowval = A.cscmatrix.rowval + n = A.cscmatrix.n # number of columns + diag = Vector{Ti}(undef, n) + nzval = Vector{Tv}(undef, length(rowval)) #copy(A.nzval) + point = use_vector_par(n, A.nt, Int32) - for level=1:depth - @threads for tid=1:nt - for j=start[(level-1)*nt+tid]:start[(level-1)*nt+tid+1]-1 - for v=colptr[j]:colptr[j+1]-1 - point[tid][rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - for w=diag[i]+1:colptr[i+1]-1 - k = point[tid][rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - for v=colptr[j]:colptr[j+1]-1 - point[tid][rowval[v]] = zero(Ti) - end - end - end - end - - #point = zeros(Ti, n) #Vector{Ti}(undef, n) - for j=start[depth*nt+1]:start[depth*nt+2]-1 - for v=colptr[j]:colptr[j+1]-1 - point[1][rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - for w=diag[i]+1:colptr[i+1]-1 - k = point[1][rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - for v=colptr[j]:colptr[j+1]-1 - point[1][rowval[v]] = zero(Ti) - end - end + @threads for tid in 1:(depth * nt + 1) + for j in start[tid]:(start[tid + 1] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + nzval[v] = A.cscmatrix.nzval[v] + if rowval[v] == j + diag[j] = v + end + #elseif rowval[v] + end + end + end + + for level in 1:depth + @threads for tid in 1:nt + for j in start[(level - 1) * nt + tid]:(start[(level - 1) * nt + tid + 1] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + point[tid][rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[tid][rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end + + for v in colptr[j]:(colptr[j + 1] - 1) + point[tid][rowval[v]] = zero(Ti) + end + end + end + end + + #point = zeros(Ti, n) #Vector{Ti}(undef, n) + for j in start[depth * nt + 1]:(start[depth * nt + 2] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + point[1][rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[1][rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end + + for v in colptr[j]:(colptr[j + 1] - 1) + point[1][rowval[v]] = zero(Ti) + end + end + + return end -function piluAM(A::ExtendableSparseMatrixParallel{Tv,Ti}) where {Tv, Ti <:Integer} - start = A.start - nt = A.nt - depth = A.depth - - colptr = A.cscmatrix.colptr - rowval = A.cscmatrix.rowval - nzval = Vector{Tv}(undef, length(rowval)) #copy(A.nzval) - n = A.cscmatrix.n # number of columns - diag = Vector{Ti}(undef, n) - point = use_vector_par(n, A.nt, Int32) - - # find diagonal entries - # - - #= +function piluAM(A::ExtendableSparseMatrixParallel{Tv, Ti}) where {Tv, Ti <: Integer} + start = A.start + nt = A.nt + depth = A.depth + + colptr = A.cscmatrix.colptr + rowval = A.cscmatrix.rowval + nzval = Vector{Tv}(undef, length(rowval)) #copy(A.nzval) + n = A.cscmatrix.n # number of columns + diag = Vector{Ti}(undef, n) + point = use_vector_par(n, A.nt, Int32) + + # find diagonal entries + # + + #= for j=1:n for v=colptr[j]:colptr[j+1]-1 nzval[v] = A.cscmatrix.nzval[v] @@ -169,183 +171,183 @@ function piluAM(A::ExtendableSparseMatrixParallel{Tv,Ti}) where {Tv, Ti <:Intege =# + @threads for tid in 1:(depth * nt + 1) + for j in start[tid]:(start[tid + 1] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + nzval[v] = A.cscmatrix.nzval[v] + if rowval[v] == j + diag[j] = v + end + #elseif rowval[v] + end + end + end - @threads for tid=1:depth*nt+1 - for j=start[tid]:start[tid+1]-1 - for v=colptr[j]:colptr[j+1]-1 - nzval[v] = A.cscmatrix.nzval[v] - if rowval[v] == j - diag[j] = v - end - #elseif rowval[v] - end - end - end + #@info diag[1:20]' + #@info diag[end-20:end]' - #@info diag[1:20]' - #@info diag[end-20:end]' - - for level=1:depth - @threads for tid=1:nt - for j=start[(level-1)*nt+tid]:start[(level-1)*nt+tid+1]-1 - for v=colptr[j]:colptr[j+1]-1 - point[tid][rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - for w=diag[i]+1:colptr[i+1]-1 - k = point[tid][rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - for v=colptr[j]:colptr[j+1]-1 - point[tid][rowval[v]] = zero(Ti) - end - end - end - end - - #point = zeros(Ti, n) #Vector{Ti}(undef, n) - for j=start[depth*nt+1]:start[depth*nt+2]-1 - for v=colptr[j]:colptr[j+1]-1 - point[1][rowval[v]] = v - end - - for v=colptr[j]:diag[j]-1 - i = rowval[v] - for w=diag[i]+1:colptr[i+1]-1 - k = point[1][rowval[w]] - if k>0 - nzval[k] -= nzval[v]*nzval[w] - end - end - end - - for v=diag[j]+1:colptr[j+1]-1 - nzval[v] /= nzval[diag[j]] - end - - for v=colptr[j]:colptr[j+1]-1 - point[1][rowval[v]] = zero(Ti) - end - end + for level in 1:depth + @threads for tid in 1:nt + for j in start[(level - 1) * nt + tid]:(start[(level - 1) * nt + tid + 1] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + point[tid][rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[tid][rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end + + for v in colptr[j]:(colptr[j + 1] - 1) + point[tid][rowval[v]] = zero(Ti) + end + end + end + end + + #point = zeros(Ti, n) #Vector{Ti}(undef, n) + for j in start[depth * nt + 1]:(start[depth * nt + 2] - 1) + for v in colptr[j]:(colptr[j + 1] - 1) + point[1][rowval[v]] = v + end + + for v in colptr[j]:(diag[j] - 1) + i = rowval[v] + for w in (diag[i] + 1):(colptr[i + 1] - 1) + k = point[1][rowval[w]] + if k > 0 + nzval[k] -= nzval[v] * nzval[w] + end + end + end + + for v in (diag[j] + 1):(colptr[j + 1] - 1) + nzval[v] /= nzval[diag[j]] + end + + for v in colptr[j]:(colptr[j + 1] - 1) + point[1][rowval[v]] = zero(Ti) + end + end - #nzval, diag - PILUAMPrecon{Tv,Ti}(diag, nzval, A.cscmatrix, start, nt, depth) + #nzval, diag + return PILUAMPrecon{Tv, Ti}(diag, nzval, A.cscmatrix, start, nt, depth) end function forward_subst_old!(y, v, nzval, diag, start, nt, depth, A) - #@info "pfso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" - #@info "fwo" - n = A.n - colptr = A.colptr - rowval = A.rowval - - y .= 0 - - for level=1:depth - @threads for tid=1:nt - @inbounds for j=start[(level-1)*nt+tid]:start[(level-1)*nt+tid+1]-1 - y[j] += v[j] - for v=diag[j]+1:colptr[j+1]-1 - y[rowval[v]] -= nzval[v]*y[j] - end - end - end - end - - @inbounds for j=start[depth*nt+1]:start[depth*nt+2]-1 - y[j] += v[j] - for v=diag[j]+1:colptr[j+1]-1 - y[rowval[v]] -= nzval[v]*y[j] - end - end - + #@info "pfso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" + #@info "fwo" + n = A.n + colptr = A.colptr + rowval = A.rowval + + y .= 0 + + for level in 1:depth + @threads for tid in 1:nt + @inbounds for j in start[(level - 1) * nt + tid]:(start[(level - 1) * nt + tid + 1] - 1) + y[j] += v[j] + for v in (diag[j] + 1):(colptr[j + 1] - 1) + y[rowval[v]] -= nzval[v] * y[j] + end + end + end + end + + return @inbounds for j in start[depth * nt + 1]:(start[depth * nt + 2] - 1) + y[j] += v[j] + for v in (diag[j] + 1):(colptr[j + 1] - 1) + y[rowval[v]] -= nzval[v] * y[j] + end + end + end function backward_subst_old!(x, y, nzval, diag, start, nt, depth, A) - #@info "pbso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" - - #@info "bwo" - n = A.n - colptr = A.colptr - rowval = A.rowval - #wrk = copy(y) - - - @inbounds for j=start[depth*nt+2]-1:-1:start[depth*nt+1] - x[j] = y[j] / nzval[diag[j]] - - for i=colptr[j]:diag[j]-1 - y[rowval[i]] -= nzval[i]*x[j] - end - - end - - for level=depth:-1:1 - @threads for tid=1:nt - @inbounds for j=start[(level-1)*nt+tid+1]-1:-1:start[(level-1)*nt+tid] - x[j] = y[j] / nzval[diag[j]] - for i=colptr[j]:diag[j]-1 - y[rowval[i]] -= nzval[i]*x[j] - end - end - end - end + #@info "pbso, $(sum(nzval)), $(sum(nzval.^2)), $(sum(diag)), $(A[1,1])" + + #@info "bwo" + n = A.n + colptr = A.colptr + rowval = A.rowval + #wrk = copy(y) + + + @inbounds for j in (start[depth * nt + 2] - 1):-1:start[depth * nt + 1] + x[j] = y[j] / nzval[diag[j]] + + for i in colptr[j]:(diag[j] - 1) + y[rowval[i]] -= nzval[i] * x[j] + end + + end + + for level in depth:-1:1 + @threads for tid in 1:nt + @inbounds for j in (start[(level - 1) * nt + tid + 1] - 1):-1:start[(level - 1) * nt + tid] + x[j] = y[j] / nzval[diag[j]] + for i in colptr[j]:(diag[j] - 1) + y[rowval[i]] -= nzval[i] * x[j] + end + end + end + end + return end function ldiv!(x, ILU::PILUAMPrecon, b) - #@info "piluam ldiv 1" - nzval = ILU.nzval - diag = ILU.diag - A = ILU.A + #@info "piluam ldiv 1" + nzval = ILU.nzval + diag = ILU.diag + A = ILU.A start = ILU.start - nt = ILU.nt + nt = ILU.nt depth = ILU.depth - y = copy(b) - #forward_subst!(y, b, ILU) - forward_subst_old!(y, b, nzval, diag, start, nt, depth, A) - backward_subst_old!(x, y, nzval, diag, start, nt, depth, A) - #@info "PILUAM:", b[1], y[1], x[1], maximum(abs.(b-A*x)), nnz(A) #, A[10,10] - #@info "PILUAM:", maximum(abs.(b-A*x)), b[1], x[1], maximum(abs.(b)), maximum(abs.(x)) - x + y = copy(b) + #forward_subst!(y, b, ILU) + forward_subst_old!(y, b, nzval, diag, start, nt, depth, A) + backward_subst_old!(x, y, nzval, diag, start, nt, depth, A) + #@info "PILUAM:", b[1], y[1], x[1], maximum(abs.(b-A*x)), nnz(A) #, A[10,10] + #@info "PILUAM:", maximum(abs.(b-A*x)), b[1], x[1], maximum(abs.(b)), maximum(abs.(x)) + return x end function ldiv!(ILU::PILUAMPrecon, b) - #@info "piluam ldiv 2" - nzval = ILU.nzval - diag = ILU.diag - A = ILU.A + #@info "piluam ldiv 2" + nzval = ILU.nzval + diag = ILU.diag + A = ILU.A start = ILU.start - nt = ILU.nt + nt = ILU.nt depth = ILU.depth - y = copy(b) - #forward_subst!(y, b, ILU) - forward_subst_old!(y, b, nzval, diag, start, nt, depth, A) - backward_subst_old!(b, y, nzval, diag, start, nt, depth, A) - b + y = copy(b) + #forward_subst!(y, b, ILU) + forward_subst_old!(y, b, nzval, diag, start, nt, depth, A) + backward_subst_old!(b, y, nzval, diag, start, nt, depth, A) + return b end -function \(ilu::PILUAMPrecon{T,N}, b) where {T,N<:Integer} +function \(ilu::PILUAMPrecon{T, N}, b) where {T, N <: Integer} x = copy(b) ldiv!(x, ilu, b) - x + return x end -function nnz(ilu::PILUAMPrecon{T,N}) where {T,N<:Integer} - length(ilu.nzval) +function nnz(ilu::PILUAMPrecon{T, N}) where {T, N <: Integer} + return length(ilu.nzval) end #end diff --git a/src/experimental/ExtendableSparseMatrixParallel/piluam.jl b/src/experimental/ExtendableSparseMatrixParallel/piluam.jl index 1fe37ce..9b5ce76 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/piluam.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/piluam.jl @@ -5,7 +5,7 @@ mutable struct PILUAMPreconditioner <: AbstractPreconditioner function PILUAMPreconditioner() p = new() p.phash = 0 - p + return p end end @@ -24,12 +24,12 @@ function update!(p::PILUAMPreconditioner) flush!(p.A) if p.A.phash != p.phash p.factorization = piluAM(p.A) - p.phash=p.A.phash + p.phash = p.A.phash else piluAM!(p.factorization, p.A) end - p + return p end -allow_views(::PILUAMPreconditioner)=true -allow_views(::Type{PILUAMPreconditioner})=true +allow_views(::PILUAMPreconditioner) = true +allow_views(::Type{PILUAMPreconditioner}) = true diff --git a/src/experimental/ExtendableSparseMatrixParallel/preparatory.jl b/src/experimental/ExtendableSparseMatrixParallel/preparatory.jl index 52e30af..1e9cc60 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/preparatory.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/preparatory.jl @@ -8,51 +8,52 @@ To assemble the system matrix parallelly, things such as `cellsforpart` (= which This should be somewhere else, longterm """ -function preparatory_multi_ps_less_reverse(mat_cell_node, nc, nn, nt, depth, Ti; - sequential=false, assembly=:cellwise, - minsize_sepa=10, do_print=false, check_partition=false, ne=0, ce=[], mat_edge_node=[], block_struct=true) - #grid = getgrid(nm; x0, x1) - adepth = 0 - if sequential - (allcells, start, cellparts, adepth) = grid_to_graph_cellwise_nogrid!(mat_cell_node, nc, nn, nt, depth; minsize_sepa, do_print)#) - else - (allcells, start, cellparts, adepth) = grid_to_graph_cellwise_par_nogrid!(mat_cell_node, nc, nn, nt, depth; minsize_sepa, do_print) - end +function preparatory_multi_ps_less_reverse( + mat_cell_node, nc, nn, nt, depth, Ti; + sequential = false, assembly = :cellwise, + minsize_sepa = 10, do_print = false, check_partition = false, ne = 0, ce = [], mat_edge_node = [], block_struct = true + ) + #grid = getgrid(nm; x0, x1) + adepth = 0 + if sequential + (allcells, start, cellparts, adepth) = grid_to_graph_cellwise_nogrid!(mat_cell_node, nc, nn, nt, depth; minsize_sepa, do_print) #) + else + (allcells, start, cellparts, adepth) = grid_to_graph_cellwise_par_nogrid!(mat_cell_node, nc, nn, nt, depth; minsize_sepa, do_print) + end - if (adepth != depth) && do_print - @info "The requested depth of partitioning is too high. The depth is set to $adepth." - end - depth = adepth - - if assembly == :cellwise - cfp = bettercellsforpart(cellparts, depth*nt+1) + if (adepth != depth) && do_print + @info "The requested depth of partitioning is too high. The depth is set to $adepth." + end + depth = adepth - else - edgeparts = edgewise_partition_from_cellwise_partition(nc, ne, ce, cellparts) - cfp = bettercellsforpart(edgeparts, depth*nt+1) - end + if assembly == :cellwise + cfp = bettercellsforpart(cellparts, depth * nt + 1) - - if check_partition - if assembly == :cellwise - validate_partition(nn, mat_cell_node, cellparts, start, allcells, nt, depth, assembly) - else - validate_partition(nn, mat_edge_node, cellparts, start, allcells, nt, depth, assembly) - end - end + else + edgeparts = edgewise_partition_from_cellwise_partition(nc, ne, ce, cellparts) + cfp = bettercellsforpart(edgeparts, depth * nt + 1) + end - #@info length.(cfp) - #@info minimum(cellparts), maximum(cellparts), nt, depth - (nnts, s, onr, gi, ni, rni, starts) = get_nnnts_and_sortednodesperthread_and_noderegs_from_cellregs_ps_less_reverse_nopush( - cellparts, allcells, start, nn, Ti, nt, depth; block_struct - ) - + if check_partition + if assembly == :cellwise + validate_partition(nn, mat_cell_node, cellparts, start, allcells, nt, depth, assembly) + else + validate_partition(nn, mat_edge_node, cellparts, start, allcells, nt, depth, assembly) + end + end - return nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, adepth -end + #@info length.(cfp) + #@info minimum(cellparts), maximum(cellparts), nt, depth + + (nnts, s, onr, gi, ni, rni, starts) = get_nnnts_and_sortednodesperthread_and_noderegs_from_cellregs_ps_less_reverse_nopush( + cellparts, allcells, start, nn, Ti, nt, depth; block_struct + ) + return nnts, s, onr, cfp, gi, ni, rni, starts, cellparts, adepth +end + """ `function get_nnnts_and_sortednodesperthread_and_noderegs_from_cellregs_ps_less_reverse_nopush(cellregs, allcells, start, nn, Ti, nt)` @@ -67,106 +68,103 @@ Furthermore, `nnts` (number of nodes of the threads) is computed, which contain `block_struct=true` means, the matrix should be reordered two have a block structure, this is necessary for parallel ILU, for `false`, the matrix is not reordered """ function get_nnnts_and_sortednodesperthread_and_noderegs_from_cellregs_ps_less_reverse_nopush(cellregs, allcells, start, nn, Ti, nt, depth; block_struct = true) - - #num_matrices = maximum(cellregs) - #depth = Int(floor((num_matrices-1)/nt)) - - #loop over each node, get the cellregion of the cell (the one not in the separator) write the position of that node inside the cellregions sorted ranking into a long vector - #nnts = [zeros(Ti, nt+1) for i=1:depth+1] - nnts = zeros(Ti, nt) - #noderegs_max_tmp = 0 - old_noderegions = zeros(Ti, (depth+1, nn)) - - # Count nodes per thread: - tmp = zeros(depth+1) - for j=1:nn - cells = @view allcells[start[j]:start[j+1]-1] - sortedcellregs = unique(sort(cellregs[cells])) - #tmp = [] - tmpctr = 1 - for cr in sortedcellregs - crmod = (cr-1)%nt+1 - level = Int(ceil(cr/nt)) - #nnts[crmod] += 1 - old_noderegions[level,j] = crmod - if !(crmod in tmp[1:tmpctr-1]) - nnts[crmod] += 1 - #sortednodesperthread[crmod,j] = nnts[crmod] #nnts[i][cr] - #push!(tmp, crmod) - if tmpctr > depth+1 - @info "Cellregs: ", sortedcellregs - @info "Levels : ", Int.(ceil.(sortedcellregs/nt)) - @info "PartsMod: ", ((sortedcellregs.-1).%nt).+1 - end - tmp[tmpctr] = crmod - tmpctr += 1 - end - end - end - - # Reorder inidices to receive a block structure: - # Taking the original matrix [a_ij] and mapping each i and j to new_indices[i] and new_indices[j], gives a block structure - # the reverse is also defined rev_new_indices[new_indices[k]] = k - # From now on we will only use this new ordering - counter_for_reorder = zeros(Ti, depth*nt+1) - for j=1:nn - level, reg = last_nz(old_noderegions[:, j]) - counter_for_reorder[(level-1)*nt + reg] += 1 #(reg-1)*depth + level] += 1 - end - - starts = vcat([0], cumsum(counter_for_reorder)) - counter_for_reorder2 = zeros(Ti, depth*nt+1) - new_indices = Vector{Ti}(undef, nn) - rev_new_indices = Vector{Ti}(undef, nn) - origin = Vector{Ti}(undef, nn) - for j=1:nn - level, reg = last_nz(old_noderegions[:, j]) - counter_for_reorder2[(level-1)*nt + reg] += 1 - origin[j] = reg - new_indices[j] = starts[(level-1)*nt + reg]+counter_for_reorder2[(level-1)*nt + reg] - rev_new_indices[new_indices[j]] = j - end - starts .+= 1 - - if !block_struct - new_indices = collect(1:nn) - rev_new_indices = collect(1:nn) - starts = [] - end - # Build sortednodesperthread and globalindices array: - # They are inverses of each other: globalindices[tid][sortednodeperthread[tid][j]] = j - # Note that j has to be a `new index` - - sortednodesperthread = zeros(Ti, (nt, nn)) #vvcons(Ti, nnts) - globalindices = vvcons(Ti, nnts) - gictrs = zeros(Ti, nt) - - for nj=1:nn - oj = rev_new_indices[nj] - cells = @view allcells[start[oj]:start[oj+1]-1] - sortedcellregs = unique(sort(cellregs[cells])) - #tmp = [] - tmpctr = 1 - for cr in sortedcellregs - crmod = (cr-1)%nt+1 - #level = Int(ceil(cr/nt)) - if !(crmod in tmp[1:tmpctr-1]) - gictrs[crmod] += 1 # , level] += 1 - sortednodesperthread[crmod,nj] = gictrs[crmod] - globalindices[crmod][gictrs[crmod]] = nj - #push!(tmp, crmod) - tmp[tmpctr] = crmod - tmpctr += 1 - end - end - end - - nnts, sortednodesperthread, old_noderegions, globalindices, new_indices, rev_new_indices, starts -end + #num_matrices = maximum(cellregs) + #depth = Int(floor((num_matrices-1)/nt)) + + #loop over each node, get the cellregion of the cell (the one not in the separator) write the position of that node inside the cellregions sorted ranking into a long vector + #nnts = [zeros(Ti, nt+1) for i=1:depth+1] + nnts = zeros(Ti, nt) + #noderegs_max_tmp = 0 + old_noderegions = zeros(Ti, (depth + 1, nn)) + + # Count nodes per thread: + tmp = zeros(depth + 1) + for j in 1:nn + cells = @view allcells[start[j]:(start[j + 1] - 1)] + sortedcellregs = unique(sort(cellregs[cells])) + #tmp = [] + tmpctr = 1 + for cr in sortedcellregs + crmod = (cr - 1) % nt + 1 + level = Int(ceil(cr / nt)) + #nnts[crmod] += 1 + old_noderegions[level, j] = crmod + if !(crmod in tmp[1:(tmpctr - 1)]) + nnts[crmod] += 1 + #sortednodesperthread[crmod,j] = nnts[crmod] #nnts[i][cr] + #push!(tmp, crmod) + if tmpctr > depth + 1 + @info "Cellregs: ", sortedcellregs + @info "Levels : ", Int.(ceil.(sortedcellregs / nt)) + @info "PartsMod: ", ((sortedcellregs .- 1) .% nt) .+ 1 + end + tmp[tmpctr] = crmod + tmpctr += 1 + end + end + end + + # Reorder inidices to receive a block structure: + # Taking the original matrix [a_ij] and mapping each i and j to new_indices[i] and new_indices[j], gives a block structure + # the reverse is also defined rev_new_indices[new_indices[k]] = k + # From now on we will only use this new ordering + counter_for_reorder = zeros(Ti, depth * nt + 1) + for j in 1:nn + level, reg = last_nz(old_noderegions[:, j]) + counter_for_reorder[(level - 1) * nt + reg] += 1 #(reg-1)*depth + level] += 1 + end + starts = vcat([0], cumsum(counter_for_reorder)) + counter_for_reorder2 = zeros(Ti, depth * nt + 1) + new_indices = Vector{Ti}(undef, nn) + rev_new_indices = Vector{Ti}(undef, nn) + origin = Vector{Ti}(undef, nn) + for j in 1:nn + level, reg = last_nz(old_noderegions[:, j]) + counter_for_reorder2[(level - 1) * nt + reg] += 1 + origin[j] = reg + new_indices[j] = starts[(level - 1) * nt + reg] + counter_for_reorder2[(level - 1) * nt + reg] + rev_new_indices[new_indices[j]] = j + end + starts .+= 1 + + if !block_struct + new_indices = collect(1:nn) + rev_new_indices = collect(1:nn) + starts = [] + end + # Build sortednodesperthread and globalindices array: + # They are inverses of each other: globalindices[tid][sortednodeperthread[tid][j]] = j + # Note that j has to be a `new index` + + sortednodesperthread = zeros(Ti, (nt, nn)) #vvcons(Ti, nnts) + globalindices = vvcons(Ti, nnts) + gictrs = zeros(Ti, nt) + + for nj in 1:nn + oj = rev_new_indices[nj] + cells = @view allcells[start[oj]:(start[oj + 1] - 1)] + sortedcellregs = unique(sort(cellregs[cells])) + #tmp = [] + tmpctr = 1 + for cr in sortedcellregs + crmod = (cr - 1) % nt + 1 + #level = Int(ceil(cr/nt)) + if !(crmod in tmp[1:(tmpctr - 1)]) + gictrs[crmod] += 1 # , level] += 1 + sortednodesperthread[crmod, nj] = gictrs[crmod] + globalindices[crmod][gictrs[crmod]] = nj + #push!(tmp, crmod) + tmp[tmpctr] = crmod + tmpctr += 1 + end + end + end + return nnts, sortednodesperthread, old_noderegions, globalindices, new_indices, rev_new_indices, starts +end """ @@ -181,56 +179,55 @@ This function partitions the separator, which is done if `depth`>1 (see `grid_to `preparatory_multi_ps` is the number of separator-cells. """ function separate!(cellregs, ACSC, nt, level0, ctr_sepanodes, ri, gi, do_print) - # current number of cells treated + # current number of cells treated nc2 = size(ACSC, 1) - indptr = collect(1:nc2+1) - indices = zeros(Int64, nc2) - rowval = zeros(Int64, nc2) + indptr = collect(1:(nc2 + 1)) + indices = zeros(Int64, nc2) + rowval = zeros(Int64, nc2) - indptrT = collect(1:ctr_sepanodes+1) - indicesT = zeros(Int64, ctr_sepanodes) - rowvalT = zeros(Int64, ctr_sepanodes) + indptrT = collect(1:(ctr_sepanodes + 1)) + indicesT = zeros(Int64, ctr_sepanodes) + rowvalT = zeros(Int64, ctr_sepanodes) - for i=1:ctr_sepanodes - j = ri[i] + for i in 1:ctr_sepanodes + j = ri[i] indices[j] = i - indicesT[i] = j - rowval[j] = 1 - rowvalT[i] = 1 - end + indicesT[i] = j + rowval[j] = 1 + rowvalT[i] = 1 + end - - R = SparseMatrixCSC(ctr_sepanodes, nc2, indptr, indices, rowval) - RT = SparseMatrixCSC(nc2, ctr_sepanodes, indptrT, indicesT, rowvalT) - # current adjacency matrix, taken as a part of the given one ACSC - RART = dropzeros(R)*ACSC*dropzeros(RT) - - cellregs2 = Metis.partition(RART, nt) - - - for i=1:ctr_sepanodes - if cellregs[gi[i]] < level0*nt+1 + R = SparseMatrixCSC(ctr_sepanodes, nc2, indptr, indices, rowval) + RT = SparseMatrixCSC(nc2, ctr_sepanodes, indptrT, indicesT, rowvalT) + # current adjacency matrix, taken as a part of the given one ACSC + RART = dropzeros(R) * ACSC * dropzeros(RT) + + cellregs2 = Metis.partition(RART, nt) + + + for i in 1:ctr_sepanodes + if cellregs[gi[i]] < level0 * nt + 1 @warn "cell treated in this iteration was not a separator-cell last iteration" end - cellregs[gi[i]] = level0*nt + cellregs2[i] + cellregs[gi[i]] = level0 * nt + cellregs2[i] end - # how many cells are in the separator of the new partition (which is only computed on the separator of the old partition) + # how many cells are in the separator of the new partition (which is only computed on the separator of the old partition) new_ctr_sepanodes = 0 ri2 = Vector{Int64}(undef, ctr_sepanodes) gi2 = Vector{Int64}(undef, ctr_sepanodes) - - for tid=1:nt - for i=1:ctr_sepanodes + + for tid in 1:nt + for i in 1:ctr_sepanodes if cellregs2[i] == tid - neighbors = RART.rowval[RART.colptr[i]:(RART.colptr[i+1]-1)] + neighbors = RART.rowval[RART.colptr[i]:(RART.colptr[i + 1] - 1)] rows = gi[vcat(neighbors, [i])] - #counts how many different regions (besides) the separator are adjacent to the current cell - x = how_many_different_below(cellregs[rows], (level0+1)*nt+1) + #counts how many different regions (besides) the separator are adjacent to the current cell + x = how_many_different_below(cellregs[rows], (level0 + 1) * nt + 1) if x > 1 - cellregs[gi[i]] = (level0+1)*nt+1 + cellregs[gi[i]] = (level0 + 1) * nt + 1 new_ctr_sepanodes += 1 gi2[new_ctr_sepanodes] = gi[i] ri2[new_ctr_sepanodes] = i @@ -244,14 +241,13 @@ function separate!(cellregs, ACSC, nt, level0, ctr_sepanodes, ri, gi, do_print) gi2 = gi2[1:new_ctr_sepanodes] if do_print - @info "At level $(level0+1), we found $new_ctr_sepanodes cells that have to be treated in the next iteration!" + @info "At level $(level0 + 1), we found $new_ctr_sepanodes cells that have to be treated in the next iteration!" end - RART, new_ctr_sepanodes, ri2, gi2 + return RART, new_ctr_sepanodes, ri2, gi2 end - """ `function grid_to_graph_ps_multi_nogrid!(nc, nn, mat_cell_node, nt, depth)` @@ -261,75 +257,75 @@ Here, `mat_cell_node[k,i]` is the i-th node in the k-th cell. `nt` is the number of threads. `depth` is the number of partition layers, for depth=1, there are nt parts and 1 separator, for depth=2, the separator is partitioned again, leading to 2*nt+1 submatrices... """ -function grid_to_graph_cellwise_nogrid!(nc, nn, mat_cell_node, nt, depth; minsize_sepa=10, do_print=false) - A = SparseMatrixLNK{Int64, Int64}(nc, nc) - number_cells_per_node = zeros(Int64, nn) - for j=1:nc - for node_id in mat_cell_node[:,j] - number_cells_per_node[node_id] += 1 - end - end - allcells = zeros(Int64, sum(number_cells_per_node)) - start = ones(Int64, nn+1) - start[2:end] += cumsum(number_cells_per_node) - number_cells_per_node .= 0 - for j=1:nc - for node_id in mat_cell_node[:,j] - allcells[start[node_id] + number_cells_per_node[node_id]] = j - number_cells_per_node[node_id] += 1 - end - end +function grid_to_graph_cellwise_nogrid!(nc, nn, mat_cell_node, nt, depth; minsize_sepa = 10, do_print = false) + A = SparseMatrixLNK{Int64, Int64}(nc, nc) + number_cells_per_node = zeros(Int64, nn) + for j in 1:nc + for node_id in mat_cell_node[:, j] + number_cells_per_node[node_id] += 1 + end + end + allcells = zeros(Int64, sum(number_cells_per_node)) + start = ones(Int64, nn + 1) + start[2:end] += cumsum(number_cells_per_node) + number_cells_per_node .= 0 + for j in 1:nc + for node_id in mat_cell_node[:, j] + allcells[start[node_id] + number_cells_per_node[node_id]] = j + number_cells_per_node[node_id] += 1 + end + end - for j=1:nn - cells = @view allcells[start[j]:start[j+1]-1] - for (i,id1) in enumerate(cells) - for id2 in cells[i+1:end] - A[id1,id2] = 1 - A[id2,id1] = 1 - end - end - end + for j in 1:nn + cells = @view allcells[start[j]:(start[j + 1] - 1)] + for (i, id1) in enumerate(cells) + for id2 in cells[(i + 1):end] + A[id1, id2] = 1 + A[id2, id1] = 1 + end + end + end - ACSC = SparseArrays.SparseMatrixCSC(A) - - partition = Metis.partition(ACSC, nt) - cellregs = copy(partition) - - sn = Vector{Int64}(undef, nc) - gi = Vector{Int64}(undef, nc) - ctr_sepanodes = 0 - - for tid=1:nt - for j=1:nc + ACSC = SparseArrays.SparseMatrixCSC(A) + + partition = Metis.partition(ACSC, nt) + cellregs = copy(partition) + + sn = Vector{Int64}(undef, nc) + gi = Vector{Int64}(undef, nc) + ctr_sepanodes = 0 + + for tid in 1:nt + for j in 1:nc if cellregs[j] == tid - rows = vcat(ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j+1]-1)], [j]) - if how_many_different_below(cellregs[rows], nt+1) > 1 - cellregs[j] = nt+1 #+ctr_sepanodes + rows = vcat(ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j + 1] - 1)], [j]) + if how_many_different_below(cellregs[rows], nt + 1) > 1 + cellregs[j] = nt + 1 #+ctr_sepanodes ctr_sepanodes += 1 sn[ctr_sepanodes] = j gi[ctr_sepanodes] = j end end end - end + end sn = sn[1:ctr_sepanodes] gi = gi[1:ctr_sepanodes] - + if do_print @info "At level $(1), we found $ctr_sepanodes cells that have to be treated in the next iteration!" end RART = copy(ACSC) actual_depth = 1 - for level=1:depth-1 - RART, ctr_sepanodes, sn, gi = separate!(cellregs, RART, nt, level, ctr_sepanodes, sn, gi, do_print) + for level in 1:(depth - 1) + RART, ctr_sepanodes, sn, gi = separate!(cellregs, RART, nt, level, ctr_sepanodes, sn, gi, do_print) actual_depth += 1 - if ctr_sepanodes < minsize_sepa - break - end - end - + if ctr_sepanodes < minsize_sepa + break + end + end + return allcells, start, cellregs, actual_depth end @@ -339,69 +335,69 @@ end Same result as `grid_to_graph_ps_multi_nogrid!`, but computed on multiple threads. """ -function grid_to_graph_cellwise_par_nogrid!(cn, nc, nn, nt, depth; minsize_sepa=10, do_print=false) - As = [ExtendableSparseMatrix{Int64, Int64}(nc, nc) for tid=1:nt] - number_cells_per_node = zeros(Int64, nn) - - - for j=1:nc - tmp = view(cn, :, j) - for node_id in tmp - number_cells_per_node[node_id] += 1 - end - end - - - allcells = zeros(Int64, sum(number_cells_per_node)) - start = ones(Int64, nn+1) - start[2:end] += cumsum(number_cells_per_node) - number_cells_per_node .= 0 - - for j=1:nc - tmp = view(cn, :, j) - for node_id in tmp - allcells[start[node_id] + number_cells_per_node[node_id]] = j - number_cells_per_node[node_id] += 1 - end - end +function grid_to_graph_cellwise_par_nogrid!(cn, nc, nn, nt, depth; minsize_sepa = 10, do_print = false) + As = [ExtendableSparseMatrix{Int64, Int64}(nc, nc) for tid in 1:nt] + number_cells_per_node = zeros(Int64, nn) - node_range = get_starts(nn, nt) - Threads.@threads for tid=1:nt - for j in node_range[tid]:node_range[tid+1]-1 - cells = @view allcells[start[j]:start[j+1]-1] - l = length(cells) - for (i,id1) in enumerate(cells) - ce = view(cells, i+1:l) - for id2 in ce - As[tid][id1,id2] = 1 - As[tid][id2,id1] = 1 - end - end - end - ExtendableSparse.flush!(As[tid]) - end - - ACSC = add_all_par!(As).cscmatrix - - cellregs = Metis.partition(ACSC, nt) - - sn = [Vector{Int64}(undef, Int(ceil(nc/nt))) for tid=1:nt] - ctr_sepanodess = zeros(Int64, nt) - - @threads for tid=1:nt - for j=1:nc + + for j in 1:nc + tmp = view(cn, :, j) + for node_id in tmp + number_cells_per_node[node_id] += 1 + end + end + + + allcells = zeros(Int64, sum(number_cells_per_node)) + start = ones(Int64, nn + 1) + start[2:end] += cumsum(number_cells_per_node) + number_cells_per_node .= 0 + + for j in 1:nc + tmp = view(cn, :, j) + for node_id in tmp + allcells[start[node_id] + number_cells_per_node[node_id]] = j + number_cells_per_node[node_id] += 1 + end + end + + node_range = get_starts(nn, nt) + Threads.@threads for tid in 1:nt + for j in node_range[tid]:(node_range[tid + 1] - 1) + cells = @view allcells[start[j]:(start[j + 1] - 1)] + l = length(cells) + for (i, id1) in enumerate(cells) + ce = view(cells, (i + 1):l) + for id2 in ce + As[tid][id1, id2] = 1 + As[tid][id2, id1] = 1 + end + end + end + ExtendableSparse.flush!(As[tid]) + end + + ACSC = add_all_par!(As).cscmatrix + + cellregs = Metis.partition(ACSC, nt) + + sn = [Vector{Int64}(undef, Int(ceil(nc / nt))) for tid in 1:nt] + ctr_sepanodess = zeros(Int64, nt) + + @threads for tid in 1:nt + for j in 1:nc if cellregs[j] == tid - rows = vcat(ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j+1]-1)], [j]) - if how_many_different_below(cellregs[rows], nt+1) > 1 - cellregs[j] = nt+1 #+ctr_sepanodes + rows = vcat(ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j + 1] - 1)], [j]) + if how_many_different_below(cellregs[rows], nt + 1) > 1 + cellregs[j] = nt + 1 #+ctr_sepanodes ctr_sepanodess[tid] += 1 sn[tid][ctr_sepanodess[tid]] = j end end end - end + end - for tid=1:nt + for tid in 1:nt sn[tid] = sn[tid][1:ctr_sepanodess[tid]] end ctr_sepanodes = sum(ctr_sepanodess) @@ -414,14 +410,14 @@ function grid_to_graph_cellwise_par_nogrid!(cn, nc, nn, nt, depth; minsize_sepa= RART = ACSC actual_depth = 1 - for level=1:depth-1 - RART, ctr_sepanodes, sn, gi = separate!(cellregs, RART, nt, level, ctr_sepanodes, sn, gi, do_print) + for level in 1:(depth - 1) + RART, ctr_sepanodes, sn, gi = separate!(cellregs, RART, nt, level, ctr_sepanodes, sn, gi, do_print) actual_depth += 1 - if ctr_sepanodes < minsize_sepa - break - end - end - + if ctr_sepanodes < minsize_sepa + break + end + end + #grid[CellRegions] = cellregs #grid return allcells, start, cellregs, actual_depth @@ -671,19 +667,19 @@ end """ function edgewise_partition_from_cellwise_partition(nc, ne, ce, cellregs) - #ce = grid[CellEdges] - edgeregs = maximum(cellregs)*ones(Int64, ne) - - for icell=1:nc - tmp = cellregs[icell] - for iedge in ce[:,icell] - if tmp < edgeregs[iedge] - edgeregs[iedge] = tmp - end - end - end + #ce = grid[CellEdges] + edgeregs = maximum(cellregs) * ones(Int64, ne) + + for icell in 1:nc + tmp = cellregs[icell] + for iedge in ce[:, icell] + if tmp < edgeregs[iedge] + edgeregs[iedge] = tmp + end + end + end - edgeregs + return edgeregs end """ @@ -693,22 +689,22 @@ Add LNK matrices (stored in a vector) parallelly (tree structure). The result is stored in the first LNK matrix. """ function add_all_par!(As) - nt = length(As) - depth = Int(floor(log2(nt))) - endpoint = nt - for level=1:depth - - @threads for tid=1:2^(depth-level) - #@info "$level, $tid" - start = tid+2^(depth-level) - while start <= endpoint - As[tid] += As[start] - start += 2^(depth-level) - end - end - endpoint = 2^(depth-level) - end - As[1] + nt = length(As) + depth = Int(floor(log2(nt))) + endpoint = nt + for level in 1:depth + + @threads for tid in 1:(2^(depth - level)) + #@info "$level, $tid" + start = tid + 2^(depth - level) + while start <= endpoint + As[tid] += As[start] + start += 2^(depth - level) + end + end + endpoint = 2^(depth - level) + end + return As[1] end @@ -720,8 +716,8 @@ end The function creates a vector of zero vectors of type `Ti` of length `lengths[i]`. """ function vvcons(Ti, lengths) - x::Vector{Vector{Ti}} = [zeros(Ti, i) for i in lengths] - return x + x::Vector{Vector{Ti}} = [zeros(Ti, i) for i in lengths] + return x end @@ -735,157 +731,156 @@ The element v1 would be the list of cells that are in partition 1 etc. The function is basically a faster findall. """ function bettercellsforpart(xx, upper) - ctr = zeros(Int64, upper) - for x in xx - ctr[x] += 1 - end - cfp = vvcons(Int64, ctr) - ctr .= 1 - for (i,x) in enumerate(xx) - cfp[x][ctr[x]] = i - ctr[x] += 1 - end - cfp + ctr = zeros(Int64, upper) + for x in xx + ctr[x] += 1 + end + cfp = vvcons(Int64, ctr) + ctr .= 1 + for (i, x) in enumerate(xx) + cfp[x][ctr[x]] = i + ctr[x] += 1 + end + return cfp end - function get_starts(n, nt) - ret = ones(Int64, nt+1) - ret[end] = n+1 - for i=nt:-1:2 - ret[i] = ret[i+1] - Int(round(ret[i+1]/i)) #Int(round(n/nt))-1 - end - ret + ret = ones(Int64, nt + 1) + ret[end] = n + 1 + for i in nt:-1:2 + ret[i] = ret[i + 1] - Int(round(ret[i + 1] / i)) #Int(round(n/nt))-1 + end + return ret end function last_nz(x) - n = length(x) - for j=n:-1:1 - if x[j] != 0 - return (j, x[j]) - end - end + n = length(x) + for j in n:-1:1 + if x[j] != 0 + return (j, x[j]) + end + end + return end -function how_many_different_below(x0, y; u=0) +function how_many_different_below(x0, y; u = 0) x = copy(x0) z = unique(x) - t = findall(w->ww>u,z[t]) - length(t) + t = findall(w -> w < y, z) + t = findall(w -> w > u, z[t]) + return length(t) end - function lookat_grid_to_graph_ps_multi!(nm, nt, depth) - grid = getgrid(nm) - A = SparseMatrixLNK{Int64, Int64}(num_cells(grid), num_cells(grid)) - number_cells_per_node = zeros(Int64, num_nodes(grid)) - for j=1:num_cells(grid) - for node_id in grid[CellNodes][:,j] - number_cells_per_node[node_id] += 1 - end - end - allcells = zeros(Int64, sum(number_cells_per_node)) - start = ones(Int64, num_nodes(grid)+1) - start[2:end] += cumsum(number_cells_per_node) - number_cells_per_node .= 0 - for j=1:num_cells(grid) - for node_id in grid[CellNodes][:,j] - allcells[start[node_id] + number_cells_per_node[node_id]] = j - number_cells_per_node[node_id] += 1 - end - end + grid = getgrid(nm) + A = SparseMatrixLNK{Int64, Int64}(num_cells(grid), num_cells(grid)) + number_cells_per_node = zeros(Int64, num_nodes(grid)) + for j in 1:num_cells(grid) + for node_id in grid[CellNodes][:, j] + number_cells_per_node[node_id] += 1 + end + end + allcells = zeros(Int64, sum(number_cells_per_node)) + start = ones(Int64, num_nodes(grid) + 1) + start[2:end] += cumsum(number_cells_per_node) + number_cells_per_node .= 0 + for j in 1:num_cells(grid) + for node_id in grid[CellNodes][:, j] + allcells[start[node_id] + number_cells_per_node[node_id]] = j + number_cells_per_node[node_id] += 1 + end + end - for j=1:num_nodes(grid) - cells = @view allcells[start[j]:start[j+1]-1] - for (i,id1) in enumerate(cells) - for id2 in cells[i+1:end] - A[id1,id2] = 1 - A[id2,id1] = 1 - end - end - end + for j in 1:num_nodes(grid) + cells = @view allcells[start[j]:(start[j + 1] - 1)] + for (i, id1) in enumerate(cells) + for id2 in cells[(i + 1):end] + A[id1, id2] = 1 + A[id2, id1] = 1 + end + end + end + + ACSC = SparseArrays.SparseMatrixCSC(A) + + partition = Metis.partition(ACSC, nt) + cellregs = copy(partition) + + sn = [] + gi = [] + ctr_sepanodes = 0 + for j in 1:num_cells(grid) + rows = ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j + 1] - 1)] + if minimum(partition[rows]) != maximum(partition[rows]) + cellregs[j] = nt + 1 + ctr_sepanodes += 1 + push!(sn, j) + push!(gi, j) + end + end + RART = ACSC + #sn = 1:num_cells(grid) + #gi = 1:num_cells(grid) + for level in 1:(depth - 1) + RART, ctr_sepanodes, sn, gi = separate_careful!(cellregs, num_cells(grid), RART, nt, level, ctr_sepanodes, sn, gi) + if ctr_sepanodes == 0 + return RART + end + end - ACSC = SparseArrays.SparseMatrixCSC(A) - - partition = Metis.partition(ACSC, nt) - cellregs = copy(partition) - - sn = [] - gi = [] - ctr_sepanodes = 0 - for j=1:num_cells(grid) - rows = ACSC.rowval[ACSC.colptr[j]:(ACSC.colptr[j+1]-1)] - if minimum(partition[rows]) != maximum(partition[rows]) - cellregs[j] = nt+1 - ctr_sepanodes += 1 - push!(sn, j) - push!(gi, j) - end - end - RART = ACSC - #sn = 1:num_cells(grid) - #gi = 1:num_cells(grid) - for level=1:depth-1 - RART, ctr_sepanodes, sn, gi = separate_careful!(cellregs, num_cells(grid), RART, nt, level, ctr_sepanodes, sn, gi) - if ctr_sepanodes == 0 - return RART - end - end - - #return allcells, start, cellregs - RART + #return allcells, start, cellregs + return RART end function adjacencies(grid) - A = SparseMatrixLNK{Int64, Int64}(num_cells(grid), num_cells(grid)) - number_cells_per_node = zeros(Int64, num_nodes(grid)) - for j=1:num_cells(grid) - for node_id in grid[CellNodes][:,j] - number_cells_per_node[node_id] += 1 - end - end - allcells = zeros(Int64, sum(number_cells_per_node)) - start = ones(Int64, num_nodes(grid)+1) - start[2:end] += cumsum(number_cells_per_node) - number_cells_per_node .= 0 - for j=1:num_cells(grid) - for node_id in grid[CellNodes][:,j] - allcells[start[node_id] + number_cells_per_node[node_id]] = j - number_cells_per_node[node_id] += 1 - end - end + A = SparseMatrixLNK{Int64, Int64}(num_cells(grid), num_cells(grid)) + number_cells_per_node = zeros(Int64, num_nodes(grid)) + for j in 1:num_cells(grid) + for node_id in grid[CellNodes][:, j] + number_cells_per_node[node_id] += 1 + end + end + allcells = zeros(Int64, sum(number_cells_per_node)) + start = ones(Int64, num_nodes(grid) + 1) + start[2:end] += cumsum(number_cells_per_node) + number_cells_per_node .= 0 + for j in 1:num_cells(grid) + for node_id in grid[CellNodes][:, j] + allcells[start[node_id] + number_cells_per_node[node_id]] = j + number_cells_per_node[node_id] += 1 + end + end - for j=1:num_nodes(grid) - cells = @view allcells[start[j]:start[j+1]-1] - for (i,id1) in enumerate(cells) - for id2 in cells[i+1:end] - A[id1,id2] = 1 - A[id2,id1] = 1 - end - end - end + for j in 1:num_nodes(grid) + cells = @view allcells[start[j]:(start[j + 1] - 1)] + for (i, id1) in enumerate(cells) + for id2 in cells[(i + 1):end] + A[id1, id2] = 1 + A[id2, id1] = 1 + end + end + end - allcells, start, SparseArrays.SparseMatrixCSC(A) + return allcells, start, SparseArrays.SparseMatrixCSC(A) end function check_adjacencies(nm) - grid = getgrid(nm) - allcells, start, A = adjacencies(grid) + grid = getgrid(nm) + allcells, start, A = adjacencies(grid) - i = 1 - cells1 = sort(vcat([i], A.rowval[A.colptr[i]:(A.colptr[i+1]-1)])) #adjacent cells - nodes2 = grid[CellNodes][:,i] - cells2 = sort(unique(vcat([allcells[start[j]:start[j+1]-1] for j in nodes2]...))) + i = 1 + cells1 = sort(vcat([i], A.rowval[A.colptr[i]:(A.colptr[i + 1] - 1)])) #adjacent cells + nodes2 = grid[CellNodes][:, i] + cells2 = sort(unique(vcat([allcells[start[j]:(start[j + 1] - 1)] for j in nodes2]...))) - @info cells1 - @info cells2 - @info maximum(abs.(cells1-cells2)) + @info cells1 + @info cells2 + return @info maximum(abs.(cells1 - cells2)) end @@ -906,36 +901,36 @@ end =# function validate_partition(nn, mat, cellregs, start, allcells, nt, depth, assemblytype) - violation_ctr = 0 + violation_ctr = 0 - if assemblytype == :cellwise - key = CellNodes - else - key = EdgeNodes - end + if assemblytype == :cellwise + key = CellNodes + else + key = EdgeNodes + end - for j=1:nn - cells = @view allcells[start[j]:start[j+1]-1] - sortedcellregs = unique(sort(cellregs[cells])) - levels = Int.(ceil.(sortedcellregs/nt)) - - for i=1:depth+1 - ids_lev = findall(x->x==i, levels) - if length(ids_lev) > 1 - violation_ctr += 1 - - if violation_ctr == 1 - @info "Node Id : $j (we only show one violation)" - @info "Cellregs: $sortedcellregs" - @info "Levels : $levels" - - loc = findall(x->x==4, Int.(ceil.(cellregs[allcells[start[j]:start[j+1]-1]]/nt))) - cells_at_level4 = allcells[loc.+(start[j]-1)] - @info cells_at_level4, cellregs[cells_at_level4] - @info mat[:,cells_at_level4[1]], mat[:,cells_at_level4[2]] - end - end - end - end - @info "We found $violation_ctr violation(s)" + for j in 1:nn + cells = @view allcells[start[j]:(start[j + 1] - 1)] + sortedcellregs = unique(sort(cellregs[cells])) + levels = Int.(ceil.(sortedcellregs / nt)) + + for i in 1:(depth + 1) + ids_lev = findall(x -> x == i, levels) + if length(ids_lev) > 1 + violation_ctr += 1 + + if violation_ctr == 1 + @info "Node Id : $j (we only show one violation)" + @info "Cellregs: $sortedcellregs" + @info "Levels : $levels" + + loc = findall(x -> x == 4, Int.(ceil.(cellregs[allcells[start[j]:(start[j + 1] - 1)]] / nt))) + cells_at_level4 = allcells[loc .+ (start[j] - 1)] + @info cells_at_level4, cellregs[cells_at_level4] + @info mat[:, cells_at_level4[1]], mat[:, cells_at_level4[2]] + end + end + end + end + return @info "We found $violation_ctr violation(s)" end diff --git a/src/experimental/ExtendableSparseMatrixParallel/struct_flush.jl b/src/experimental/ExtendableSparseMatrixParallel/struct_flush.jl index 8a34dab..73a7955 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/struct_flush.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/struct_flush.jl @@ -1,266 +1,265 @@ -function flush!(A::ExtendableSparseMatrixParallel; do_dense=false, keep_zeros=true) - _, nnzLNK = nnz_noflush(A) - - if nnzLNK == 0 - return - end - - if !do_dense - A.cscmatrix = A.cscmatrix+sparse_flush!(A; keep_zeros) - - else - if keep_zeros - A.cscmatrix = dense_flush_keepzeros!(A.lnkmatrices, A.old_noderegions, A.sortednodesperthread, A.nt, A.rev_new_indices) - else - A.cscmatrix = dense_flush_removezeros!(A.lnkmatrices, A.old_noderegions, A.sortednodesperthread, A.nt, A.rev_new_indices) - end - end - A.phash = phash(A.cscmatrix) - A.lnkmatrices = [SuperSparseMatrixLNK{matrixvaluetype(A), matrixindextype(A)}(A.n, A.nnts[tid]) for tid=1:A.nt] +function flush!(A::ExtendableSparseMatrixParallel; do_dense = false, keep_zeros = true) + _, nnzLNK = nnz_noflush(A) + + if nnzLNK == 0 + return + end + + if !do_dense + A.cscmatrix = A.cscmatrix + sparse_flush!(A; keep_zeros) + + else + if keep_zeros + A.cscmatrix = dense_flush_keepzeros!(A.lnkmatrices, A.old_noderegions, A.sortednodesperthread, A.nt, A.rev_new_indices) + else + A.cscmatrix = dense_flush_removezeros!(A.lnkmatrices, A.old_noderegions, A.sortednodesperthread, A.nt, A.rev_new_indices) + end + end + A.phash = phash(A.cscmatrix) + return A.lnkmatrices = [SuperSparseMatrixLNK{matrixvaluetype(A), matrixindextype(A)}(A.n, A.nnts[tid]) for tid in 1:A.nt] end """ `CSC_RLNK_plusequals_less3_reordered_super!` from `plusequals.jl` """ -function sparse_flush!(A::ExtendableSparseMatrixParallel; keep_zeros=true) +function sparse_flush!(A::ExtendableSparseMatrixParallel; keep_zeros = true) - #dropzeros!( - plus_remap(A.lnkmatrices, A.cscmatrix, A.globalindices; keep_zeros) - #) - -end + #dropzeros!( + return plus_remap(A.lnkmatrices, A.cscmatrix, A.globalindices; keep_zeros) + #) +end """ `CSC_RLNK_si_oc_ps_dz_less_reordered` from `conversion.jl` """ function dense_flush_keepzeros!( - As::Vector{SuperSparseMatrixLNK{Tv, Ti}}, - onr, s, nt, rni - ) where {Tv, Ti <: Integer} - - nnz = sum([As[i].nnz for i=1:nt]) #you could also subtract the diagonal entries from shared columns, since those are definitely double - indptr = zeros(Ti, As[1].m+1) - indices = zeros(Ti, nnz) #sum(As.nnz)) - data = zeros(Float64, nnz) #sum(As.nnz)) - ctr = 1 - eqctr = 0 - tmp = zeros(Ti, size(onr)[1]) - - #@warn [As[i].nnz for i=1:nt], [As[i].n for i=1:nt], [As[i].m for i=1:nt] - #@info maximum.([As[i].colptr for i=1:nt]) - - for nj=1:As[1].m - indptr[nj] = ctr - oj = rni[nj] - regionctr = 1 - jc = 0 - nrr = view(onr, :, oj) - tmp .= 0 - for region in nrr #nrr #[:,j] - regmod = region #(region-1)%nt+1 - if (region > 0) & !(region in tmp) - k = s[regmod, nj] - if regionctr == 1 - while k>0 - if As[regmod].rowval[k] != 0 - if ctr > nnz - @info "ctr > nnz, $nj, $oj" - end - indices[ctr] = As[regmod].rowval[k] - data[ctr] = As[regmod].nzval[k] - - for jcc=1:jc - if indices[ctr-jcc] > indices[ctr-jcc+1] - tmp_i = indices[ctr-jcc+1] - tmp_d = data[ctr-jcc+1] - indices[ctr-jcc+1] = indices[ctr-jcc] - data[ctr-jcc+1] = data[ctr-jcc] - - indices[ctr-jcc] = tmp_i - data[ctr-jcc] = tmp_d - else - break - end - end - - ctr += 1 - jc += 1 - end - k = As[regmod].colptr[k] - end - else - while k>0 - if As[regmod].rowval[k] != 0 - indices[ctr] = As[regmod].rowval[k] - data[ctr] = As[regmod].nzval[k] - - for jcc=1:jc - if indices[ctr-jcc] > indices[ctr-jcc+1] - tmp_i = indices[ctr-jcc+1] - tmp_d = data[ctr-jcc+1] - indices[ctr-jcc+1] = indices[ctr-jcc] - data[ctr-jcc+1] = data[ctr-jcc] - - indices[ctr-jcc] = tmp_i - data[ctr-jcc] = tmp_d - elseif indices[ctr-jcc] == indices[ctr-jcc+1] - data[ctr-jcc] += data[ctr-jcc+1] - eqctr += 1 - - for jccc=1:jcc - indices[ctr-jcc+jccc] = indices[ctr-jcc+jccc+1] - data[ctr-jcc+jccc] = data[ctr-jcc+jccc+1] - end - - ctr -= 1 - jc -= 1 - - break - else - break - end - end - - ctr += 1 - jc += 1 - end - k = As[regmod].colptr[k] - end - - end - tmp[regionctr] = region - regionctr += 1 - - end - - end - - end - - #@warn ctr/nnz - - indptr[end] = ctr - resize!(indices, ctr-1) - resize!(data, ctr-1) - - - SparseArrays.SparseMatrixCSC( - As[1].m, As[1].m, indptr, indices, data - ) - + As::Vector{SuperSparseMatrixLNK{Tv, Ti}}, + onr, s, nt, rni + ) where {Tv, Ti <: Integer} + + nnz = sum([As[i].nnz for i in 1:nt]) #you could also subtract the diagonal entries from shared columns, since those are definitely double + indptr = zeros(Ti, As[1].m + 1) + indices = zeros(Ti, nnz) #sum(As.nnz)) + data = zeros(Float64, nnz) #sum(As.nnz)) + ctr = 1 + eqctr = 0 + tmp = zeros(Ti, size(onr)[1]) + + #@warn [As[i].nnz for i=1:nt], [As[i].n for i=1:nt], [As[i].m for i=1:nt] + #@info maximum.([As[i].colptr for i=1:nt]) + + for nj in 1:As[1].m + indptr[nj] = ctr + oj = rni[nj] + regionctr = 1 + jc = 0 + nrr = view(onr, :, oj) + tmp .= 0 + for region in nrr #nrr #[:,j] + regmod = region #(region-1)%nt+1 + if (region > 0) & !(region in tmp) + k = s[regmod, nj] + if regionctr == 1 + while k > 0 + if As[regmod].rowval[k] != 0 + if ctr > nnz + @info "ctr > nnz, $nj, $oj" + end + indices[ctr] = As[regmod].rowval[k] + data[ctr] = As[regmod].nzval[k] + + for jcc in 1:jc + if indices[ctr - jcc] > indices[ctr - jcc + 1] + tmp_i = indices[ctr - jcc + 1] + tmp_d = data[ctr - jcc + 1] + indices[ctr - jcc + 1] = indices[ctr - jcc] + data[ctr - jcc + 1] = data[ctr - jcc] + + indices[ctr - jcc] = tmp_i + data[ctr - jcc] = tmp_d + else + break + end + end + + ctr += 1 + jc += 1 + end + k = As[regmod].colptr[k] + end + else + while k > 0 + if As[regmod].rowval[k] != 0 + indices[ctr] = As[regmod].rowval[k] + data[ctr] = As[regmod].nzval[k] + + for jcc in 1:jc + if indices[ctr - jcc] > indices[ctr - jcc + 1] + tmp_i = indices[ctr - jcc + 1] + tmp_d = data[ctr - jcc + 1] + indices[ctr - jcc + 1] = indices[ctr - jcc] + data[ctr - jcc + 1] = data[ctr - jcc] + + indices[ctr - jcc] = tmp_i + data[ctr - jcc] = tmp_d + elseif indices[ctr - jcc] == indices[ctr - jcc + 1] + data[ctr - jcc] += data[ctr - jcc + 1] + eqctr += 1 + + for jccc in 1:jcc + indices[ctr - jcc + jccc] = indices[ctr - jcc + jccc + 1] + data[ctr - jcc + jccc] = data[ctr - jcc + jccc + 1] + end + + ctr -= 1 + jc -= 1 + + break + else + break + end + end + + ctr += 1 + jc += 1 + end + k = As[regmod].colptr[k] + end + + end + tmp[regionctr] = region + regionctr += 1 + + end + + end + + end + + #@warn ctr/nnz + + indptr[end] = ctr + resize!(indices, ctr - 1) + resize!(data, ctr - 1) + + + return SparseArrays.SparseMatrixCSC( + As[1].m, As[1].m, indptr, indices, data + ) + end function dense_flush_removezeros!( - As::Vector{SuperSparseMatrixLNK{Tv, Ti}}, - onr, s, nt, rni - ) where {Tv, Ti <: Integer} - - nnz = sum([As[i].nnz for i=1:nt]) #you could also subtract the diagonal entries from shared columns, since those are definitely double - indptr = zeros(Ti, As[1].m+1) - indices = zeros(Ti, nnz) #sum(As.nnz)) - data = zeros(Float64, nnz) #sum(As.nnz)) - ctr = 1 - eqctr = 0 - tmp = zeros(Ti, size(onr)[1]) - - for nj=1:As[1].m - indptr[nj] = ctr - oj = rni[nj] - regionctr = 1 - jc = 0 - nrr = view(onr, :, oj) - tmp .= 0 - for region in nrr #nrr #[:,j] - regmod = region #(region-1)%nt+1 - if (region > 0) & !(region in tmp) - k = s[regmod, nj] - if regionctr == 1 - while k>0 - if As[regmod].nzval[k] != 0.0 - indices[ctr] = As[regmod].rowval[k] - data[ctr] = As[regmod].nzval[k] - - for jcc=1:jc - if indices[ctr-jcc] > indices[ctr-jcc+1] - tmp_i = indices[ctr-jcc+1] - tmp_d = data[ctr-jcc+1] - indices[ctr-jcc+1] = indices[ctr-jcc] - data[ctr-jcc+1] = data[ctr-jcc] - - indices[ctr-jcc] = tmp_i - data[ctr-jcc] = tmp_d - else - break - end - end - - ctr += 1 - jc += 1 - end - k = As[regmod].colptr[k] - end - else - while k>0 - if As[regmod].nzval[k] != 0.0 - indices[ctr] = As[regmod].rowval[k] - data[ctr] = As[regmod].nzval[k] - - for jcc=1:jc - if indices[ctr-jcc] > indices[ctr-jcc+1] - tmp_i = indices[ctr-jcc+1] - tmp_d = data[ctr-jcc+1] - indices[ctr-jcc+1] = indices[ctr-jcc] - data[ctr-jcc+1] = data[ctr-jcc] - - indices[ctr-jcc] = tmp_i - data[ctr-jcc] = tmp_d - elseif indices[ctr-jcc] == indices[ctr-jcc+1] - data[ctr-jcc] += data[ctr-jcc+1] - eqctr += 1 - - for jccc=1:jcc - indices[ctr-jcc+jccc] = indices[ctr-jcc+jccc+1] - data[ctr-jcc+jccc] = data[ctr-jcc+jccc+1] - end - - ctr -= 1 - jc -= 1 - - break - else - break - end - end - - ctr += 1 - jc += 1 - end - k = As[regmod].colptr[k] - end - - end - tmp[regionctr] = region - regionctr += 1 - - end - - end - - end - - #@warn ctr/nnz - - indptr[end] = ctr - resize!(indices, ctr-1) - resize!(data, ctr-1) - - - SparseArrays.SparseMatrixCSC( - As[1].m, As[1].m, indptr, indices, data - ) - + As::Vector{SuperSparseMatrixLNK{Tv, Ti}}, + onr, s, nt, rni + ) where {Tv, Ti <: Integer} + + nnz = sum([As[i].nnz for i in 1:nt]) #you could also subtract the diagonal entries from shared columns, since those are definitely double + indptr = zeros(Ti, As[1].m + 1) + indices = zeros(Ti, nnz) #sum(As.nnz)) + data = zeros(Float64, nnz) #sum(As.nnz)) + ctr = 1 + eqctr = 0 + tmp = zeros(Ti, size(onr)[1]) + + for nj in 1:As[1].m + indptr[nj] = ctr + oj = rni[nj] + regionctr = 1 + jc = 0 + nrr = view(onr, :, oj) + tmp .= 0 + for region in nrr #nrr #[:,j] + regmod = region #(region-1)%nt+1 + if (region > 0) & !(region in tmp) + k = s[regmod, nj] + if regionctr == 1 + while k > 0 + if As[regmod].nzval[k] != 0.0 + indices[ctr] = As[regmod].rowval[k] + data[ctr] = As[regmod].nzval[k] + + for jcc in 1:jc + if indices[ctr - jcc] > indices[ctr - jcc + 1] + tmp_i = indices[ctr - jcc + 1] + tmp_d = data[ctr - jcc + 1] + indices[ctr - jcc + 1] = indices[ctr - jcc] + data[ctr - jcc + 1] = data[ctr - jcc] + + indices[ctr - jcc] = tmp_i + data[ctr - jcc] = tmp_d + else + break + end + end + + ctr += 1 + jc += 1 + end + k = As[regmod].colptr[k] + end + else + while k > 0 + if As[regmod].nzval[k] != 0.0 + indices[ctr] = As[regmod].rowval[k] + data[ctr] = As[regmod].nzval[k] + + for jcc in 1:jc + if indices[ctr - jcc] > indices[ctr - jcc + 1] + tmp_i = indices[ctr - jcc + 1] + tmp_d = data[ctr - jcc + 1] + indices[ctr - jcc + 1] = indices[ctr - jcc] + data[ctr - jcc + 1] = data[ctr - jcc] + + indices[ctr - jcc] = tmp_i + data[ctr - jcc] = tmp_d + elseif indices[ctr - jcc] == indices[ctr - jcc + 1] + data[ctr - jcc] += data[ctr - jcc + 1] + eqctr += 1 + + for jccc in 1:jcc + indices[ctr - jcc + jccc] = indices[ctr - jcc + jccc + 1] + data[ctr - jcc + jccc] = data[ctr - jcc + jccc + 1] + end + + ctr -= 1 + jc -= 1 + + break + else + break + end + end + + ctr += 1 + jc += 1 + end + k = As[regmod].colptr[k] + end + + end + tmp[regionctr] = region + regionctr += 1 + + end + + end + + end + + #@warn ctr/nnz + + indptr[end] = ctr + resize!(indices, ctr - 1) + resize!(data, ctr - 1) + + + return SparseArrays.SparseMatrixCSC( + As[1].m, As[1].m, indptr, indices, data + ) + end diff --git a/src/experimental/ExtendableSparseMatrixParallel/supersparse.jl b/src/experimental/ExtendableSparseMatrixParallel/supersparse.jl index 1175c5e..5dc88f0 100644 --- a/src/experimental/ExtendableSparseMatrixParallel/supersparse.jl +++ b/src/experimental/ExtendableSparseMatrixParallel/supersparse.jl @@ -1,4 +1,3 @@ - mutable struct SuperSparseMatrixLNK{Tv, Ti <: Integer} <: AbstractSparseMatrix{Tv, Ti} """ Number of rows @@ -46,24 +45,24 @@ mutable struct SuperSparseMatrixLNK{Tv, Ti <: Integer} <: AbstractSparseMatrix{T Initial length is n, it grows with each new entry. """ nzval::Vector{Tv} - - """ - (Unsorted) list of all columns with non-zero entries - """ + + """ + (Unsorted) list of all columns with non-zero entries + """ collnk::Vector{Ti} - - # counts the number of columns in use + + # counts the number of columns in use colctr::Ti end function SparseArrays.SparseMatrixCSC(A::SuperSparseMatrixLNK{Tv, Ti})::SparseArrays.SparseMatrixCSC where {Tv, Ti <: Integer} - SparseArrays.SparseMatrixCSC(SparseMatrixLNK{Tv, Ti}(A.m, A.n, A.nnz, A.nentries, A.colptr, A.rowval, A.nzval)) + return SparseArrays.SparseMatrixCSC(SparseMatrixLNK{Tv, Ti}(A.m, A.n, A.nnz, A.nentries, A.colptr, A.rowval, A.nzval)) end function SuperSparseMatrixLNK{Tv, Ti}(m, n) where {Tv, Ti <: Integer} - SuperSparseMatrixLNK{Tv, Ti}(m, n, 0, n, zeros(Ti, n), zeros(Ti, n), zeros(Tv, n), zeros(Ti, n), 0) + return SuperSparseMatrixLNK{Tv, Ti}(m, n, 0, n, zeros(Ti, n), zeros(Ti, n), zeros(Tv, n), zeros(Ti, n), 0) end @@ -133,11 +132,11 @@ function Base.setindex!(lnk::SuperSparseMatrixLNK, v, i, j) # Set the first column entry if it was not yet set. if lnk.rowval[j] == 0 && !iszero(v) - lnk.colctr += 1 - lnk.collnk[lnk.colctr] = j - lnk.rowval[j] = i - lnk.nzval[j] = v - lnk.nnz += 1 + lnk.colctr += 1 + lnk.collnk[lnk.colctr] = j + lnk.rowval[j] = i + lnk.nzval[j] = v + lnk.nnz += 1 return lnk end @@ -161,11 +160,11 @@ entry is created. function updateindex!(lnk::SuperSparseMatrixLNK{Tv, Ti}, op, v, i, j) where {Tv, Ti} # Set the first column entry if it was not yet set. if lnk.rowval[j] == 0 && !iszero(v) - lnk.colctr += 1 - lnk.collnk[lnk.colctr] = j - lnk.rowval[j] = i - lnk.nzval[j] = op(lnk.nzval[j], v) - lnk.nnz += 1 + lnk.colctr += 1 + lnk.collnk[lnk.colctr] = j + lnk.rowval[j] = i + lnk.nzval[j] = op(lnk.nzval[j], v) + lnk.nnz += 1 return lnk end k, k0 = findindex(lnk, i, j) @@ -177,17 +176,17 @@ function updateindex!(lnk::SuperSparseMatrixLNK{Tv, Ti}, op, v, i, j) where {Tv, k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end function rawupdateindex!(lnk::SuperSparseMatrixLNK{Tv, Ti}, op, v, i, j) where {Tv, Ti} # Set the first column entry if it was not yet set. if lnk.rowval[j] == 0 - lnk.colctr += 1 - lnk.collnk[lnk.colctr] = j - lnk.rowval[j] = i - lnk.nzval[j] = op(lnk.nzval[j], v) - lnk.nnz += 1 + lnk.colctr += 1 + lnk.collnk[lnk.colctr] = j + lnk.rowval[j] = i + lnk.nzval[j] = op(lnk.nzval[j], v) + lnk.nnz += 1 return lnk end k, k0 = findindex(lnk, i, j) @@ -199,7 +198,7 @@ function rawupdateindex!(lnk::SuperSparseMatrixLNK{Tv, Ti}, op, v, i, j) where { k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end #= @@ -213,189 +212,189 @@ Base.isless(x::ColEntry, y::ColEntry) = (x.rowval < y.rowval) =# function get_column!(col::Vector{ColEntry{Tv, Ti}}, lnk::SuperSparseMatrixLNK{Tv, Ti}, j::Ti)::Ti where {Tv, Ti <: Integer} - k = j - ctr = zero(Ti) - while k>0 - if abs(lnk.nzval[k]) > 0 - ctr += 1 - col[ctr] = ColEntry(lnk.rowval[k], lnk.nzval[k]) - end - k = lnk.colptr[k] - end - sort!(col, 1, ctr, Base.QuickSort, Base.Forward) - ctr + k = j + ctr = zero(Ti) + while k > 0 + if abs(lnk.nzval[k]) > 0 + ctr += 1 + col[ctr] = ColEntry(lnk.rowval[k], lnk.nzval[k]) + end + k = lnk.colptr[k] + end + sort!(col, 1, ctr, Base.QuickSort, Base.Forward) + return ctr end function remove_doubles!(col, coll) - #input_ctr = 1 - last = 1 - for j=2:coll - if col[j].rowval == col[last].rowval - col[last].nzval += col[j].nzval - else - last += 1 - if last != j - col[last] = col[j] - end - end - end - last + #input_ctr = 1 + last = 1 + for j in 2:coll + if col[j].rowval == col[last].rowval + col[last].nzval += col[j].nzval + else + last += 1 + if last != j + col[last] = col[j] + end + end + end + return last end function get_column_removezeros!(col::Vector{ColEntry{Tv, Ti}}, lnks::Vector{SuperSparseMatrixLNK{Tv, Ti}}, js, tids, length)::Ti where {Tv, Ti <: Integer} - ctr = zero(Ti) - for i=1:length - tid = tids[i] - k = js[i] - #for (tid,j) in zip(tids, js) #j0:j1 - #tid = tids[j] - #k = j - while k>0 - if abs(lnks[tid].nzval[k]) > 0 - ctr += 1 - col[ctr] = ColEntry(lnks[tid].rowval[k], lnks[tid].nzval[k]) - end - k = lnks[tid].colptr[k] - end - end - - sort!(col, 1, ctr, Base.QuickSort, Base.Forward) - ctr = remove_doubles!(col, ctr) - #print_col(col, ctr) - ctr + ctr = zero(Ti) + for i in 1:length + tid = tids[i] + k = js[i] + #for (tid,j) in zip(tids, js) #j0:j1 + #tid = tids[j] + #k = j + while k > 0 + if abs(lnks[tid].nzval[k]) > 0 + ctr += 1 + col[ctr] = ColEntry(lnks[tid].rowval[k], lnks[tid].nzval[k]) + end + k = lnks[tid].colptr[k] + end + end + + sort!(col, 1, ctr, Base.QuickSort, Base.Forward) + ctr = remove_doubles!(col, ctr) + #print_col(col, ctr) + return ctr end function get_column_keepzeros!(col::Vector{ColEntry{Tv, Ti}}, lnks::Vector{SuperSparseMatrixLNK{Tv, Ti}}, js, tids, length)::Ti where {Tv, Ti <: Integer} - ctr = zero(Ti) - for i=1:length - tid = tids[i] - k = js[i] - #for (tid,j) in zip(tids, js) #j0:j1 - #tid = tids[j] - #k = j - while k>0 - #if abs(lnks[tid].nzval[k]) > 0 - ctr += 1 - col[ctr] = ColEntry(lnks[tid].rowval[k], lnks[tid].nzval[k]) - #end - k = lnks[tid].colptr[k] - end - end - - sort!(col, 1, ctr, Base.QuickSort, Base.Forward) - ctr = remove_doubles!(col, ctr) - #print_col(col, ctr) - ctr + ctr = zero(Ti) + for i in 1:length + tid = tids[i] + k = js[i] + #for (tid,j) in zip(tids, js) #j0:j1 + #tid = tids[j] + #k = j + while k > 0 + #if abs(lnks[tid].nzval[k]) > 0 + ctr += 1 + col[ctr] = ColEntry(lnks[tid].rowval[k], lnks[tid].nzval[k]) + #end + k = lnks[tid].colptr[k] + end + end + + sort!(col, 1, ctr, Base.QuickSort, Base.Forward) + ctr = remove_doubles!(col, ctr) + #print_col(col, ctr) + return ctr end function merge_into!(rowval::Vector{Ti}, nzval::Vector{Tv}, C::SparseArrays.SparseMatrixCSC{Tv, Ti}, col::Vector{ColEntry{Tv, Ti}}, J::Ti, coll::Ti, ptr1::Ti) where {Tv, Ti <: Integer} - j_min = 1 - numshifts = 0 - j_last = 0 - last_row = 0 - - #@warn "MERGING $J" - - #rowval0 = copy(C.rowval[C.colptr[J]:C.colptr[J+1]-1]) - #endptr = C.colptr[J+1] - - for (di,i) in enumerate(C.colptr[J]:C.colptr[J+1]-1) - for j=j_min:coll - #if col[j].rowval == last_row - # #@info "!! col j rowval == last row" - #end - if col[j].rowval < C.rowval[i] #ptr1+di+numshifts] #i+numshifts] - if col[j].rowval == last_row - #@info "$(ptr1+di+numshifts) : backwards EQUALITY: " - nzval[ptr1+di+numshifts] += col[j].nzval - else - #@info "$(ptr1+di+numshifts) : Insert from col: j=$j" - #shift_e!(C.rowval, C.nzval, 1, i+numshifts, C.colptr[end]-1) - rowval[ptr1+di+numshifts] = col[j].rowval - nzval[ptr1+di+numshifts] = col[j].nzval - numshifts += 1 - #endptr += 1 - end - j_last = j - elseif col[j].rowval > C.rowval[i] #if col[j].rowval - #@info "$(ptr1+di+numshifts) : Insert from C: i=$i" - rowval[ptr1+di+numshifts] = C.rowval[i] - nzval[ptr1+di+numshifts] = C.nzval[i] - j_min = j - break - else - #@info "$(ptr1+di+numshifts) : normal EQUALITY: i=$i, j=$j" - rowval[ptr1+di+numshifts] = C.rowval[i] - nzval[ptr1+di+numshifts] = C.nzval[i]+col[j].nzval - #numshifts += 1 - j_min = j+1 - j_last = j - - if j == coll - #@info "$(ptr1+di+numshifts+1) → $(ptr1+numshifts+(C.colptr[J+1]-C.colptr[J]))" - rowval[ptr1+di+numshifts+1:ptr1+numshifts+(C.colptr[J+1]-C.colptr[J])] = view(C.rowval, i+1:C.colptr[J+1]-1) #C.rowval[i:C.colptr[J+1]-1] - nzval[ptr1+di+numshifts+1:ptr1+numshifts+(C.colptr[J+1]-C.colptr[J])] = view(C.nzval, i+1:C.colptr[J+1]-1) #C.nzval[i:C.colptr[J+1]-1] - - #@info "FINISH" - return numshifts - end - - break - end - - if j == coll - #@info "$(ptr1+di+numshifts) → $(ptr1+numshifts+(C.colptr[J+1]-C.colptr[J]))" - rowval[ptr1+di+numshifts:ptr1+numshifts+(C.colptr[J+1]-C.colptr[J])] = view(C.rowval, i:C.colptr[J+1]-1) #C.rowval[i:C.colptr[J+1]-1] - nzval[ptr1+di+numshifts:ptr1+numshifts+(C.colptr[J+1]-C.colptr[J])] = view(C.nzval, i:C.colptr[J+1]-1) #C.nzval[i:C.colptr[J+1]-1] - - #@info "FINISH" - return numshifts - end - - last_row = col[j].rowval - end - end - endptr = ptr1 + numshifts + (C.colptr[J+1]-C.colptr[J]) - last_row = 0 - numshifts_old = numshifts - numshifts = 0 - #start_ptr = endptr - 1 #C.colptr[J+1]-1 - if j_last > 0 - last_row = col[j_last].rowval - end - - if j_last != coll - for j=j_last+1:coll - if col[j].rowval != last_row - numshifts += 1 - #shift_e!(C.rowval, C.nzval, 1, start_ptr+numshifts, C.colptr[end]-1) - #for k=start_ptr+numshifts: - #@info "$(endptr+numshifts) : after..." - rowval[endptr+numshifts] = col[j].rowval - nzval[endptr+numshifts] = col[j].nzval - last_row = rowval[endptr+numshifts] - #colptr[J+1:end] .+= 1 - else - nzval[endptr+numshifts] += col[j].nzval - end - end - end - - return numshifts + numshifts_old + j_min = 1 + numshifts = 0 + j_last = 0 + last_row = 0 + + #@warn "MERGING $J" + + #rowval0 = copy(C.rowval[C.colptr[J]:C.colptr[J+1]-1]) + #endptr = C.colptr[J+1] + + for (di, i) in enumerate(C.colptr[J]:(C.colptr[J + 1] - 1)) + for j in j_min:coll + #if col[j].rowval == last_row + # #@info "!! col j rowval == last row" + #end + if col[j].rowval < C.rowval[i] #ptr1+di+numshifts] #i+numshifts] + if col[j].rowval == last_row + #@info "$(ptr1+di+numshifts) : backwards EQUALITY: " + nzval[ptr1 + di + numshifts] += col[j].nzval + else + #@info "$(ptr1+di+numshifts) : Insert from col: j=$j" + #shift_e!(C.rowval, C.nzval, 1, i+numshifts, C.colptr[end]-1) + rowval[ptr1 + di + numshifts] = col[j].rowval + nzval[ptr1 + di + numshifts] = col[j].nzval + numshifts += 1 + #endptr += 1 + end + j_last = j + elseif col[j].rowval > C.rowval[i] #if col[j].rowval + #@info "$(ptr1+di+numshifts) : Insert from C: i=$i" + rowval[ptr1 + di + numshifts] = C.rowval[i] + nzval[ptr1 + di + numshifts] = C.nzval[i] + j_min = j + break + else + #@info "$(ptr1+di+numshifts) : normal EQUALITY: i=$i, j=$j" + rowval[ptr1 + di + numshifts] = C.rowval[i] + nzval[ptr1 + di + numshifts] = C.nzval[i] + col[j].nzval + #numshifts += 1 + j_min = j + 1 + j_last = j + + if j == coll + #@info "$(ptr1+di+numshifts+1) → $(ptr1+numshifts+(C.colptr[J+1]-C.colptr[J]))" + rowval[(ptr1 + di + numshifts + 1):(ptr1 + numshifts + (C.colptr[J + 1] - C.colptr[J]))] = view(C.rowval, (i + 1):(C.colptr[J + 1] - 1)) #C.rowval[i:C.colptr[J+1]-1] + nzval[(ptr1 + di + numshifts + 1):(ptr1 + numshifts + (C.colptr[J + 1] - C.colptr[J]))] = view(C.nzval, (i + 1):(C.colptr[J + 1] - 1)) #C.nzval[i:C.colptr[J+1]-1] + + #@info "FINISH" + return numshifts + end + + break + end + + if j == coll + #@info "$(ptr1+di+numshifts) → $(ptr1+numshifts+(C.colptr[J+1]-C.colptr[J]))" + rowval[(ptr1 + di + numshifts):(ptr1 + numshifts + (C.colptr[J + 1] - C.colptr[J]))] = view(C.rowval, i:(C.colptr[J + 1] - 1)) #C.rowval[i:C.colptr[J+1]-1] + nzval[(ptr1 + di + numshifts):(ptr1 + numshifts + (C.colptr[J + 1] - C.colptr[J]))] = view(C.nzval, i:(C.colptr[J + 1] - 1)) #C.nzval[i:C.colptr[J+1]-1] + + #@info "FINISH" + return numshifts + end + + last_row = col[j].rowval + end + end + endptr = ptr1 + numshifts + (C.colptr[J + 1] - C.colptr[J]) + last_row = 0 + numshifts_old = numshifts + numshifts = 0 + #start_ptr = endptr - 1 #C.colptr[J+1]-1 + if j_last > 0 + last_row = col[j_last].rowval + end + + if j_last != coll + for j in (j_last + 1):coll + if col[j].rowval != last_row + numshifts += 1 + #shift_e!(C.rowval, C.nzval, 1, start_ptr+numshifts, C.colptr[end]-1) + #for k=start_ptr+numshifts: + #@info "$(endptr+numshifts) : after..." + rowval[endptr + numshifts] = col[j].rowval + nzval[endptr + numshifts] = col[j].nzval + last_row = rowval[endptr + numshifts] + #colptr[J+1:end] .+= 1 + else + nzval[endptr + numshifts] += col[j].nzval + end + end + end + + return numshifts + numshifts_old end function print_col(col, coll) - v = zeros((2, coll)) - for j=1:coll - v[1,j] = col[j].rowval - v[2,j] = col[j].nzval - end - @info v + v = zeros((2, coll)) + for j in 1:coll + v[1, j] = col[j].rowval + v[2, j] = col[j].nzval + end + return @info v end @@ -405,110 +404,109 @@ $(SIGNATURES) Add the matrices `lnks` of type SuperSparseMatrixLNK onto the SparseMatrixCSC `csc`. `gi[i]` maps the indices in `lnks[i]` to the indices of `csc`. """ -function plus_remap(lnks::Vector{SuperSparseMatrixLNK{Tv, Ti}}, csc::SparseArrays.SparseMatrixCSC, gi::Vector{Vector{Ti}}; keep_zeros=true) where {Tv, Ti <: Integer} - nt = length(lnks) +function plus_remap(lnks::Vector{SuperSparseMatrixLNK{Tv, Ti}}, csc::SparseArrays.SparseMatrixCSC, gi::Vector{Vector{Ti}}; keep_zeros = true) where {Tv, Ti <: Integer} + nt = length(lnks) - if keep_zeros - get_col! = get_column_keepzeros! - else - get_col! = get_column_removezeros! - end - lnkscols = vcat([lnks[i].collnk[1:lnks[i].colctr] for i=1:nt]...) - supersparsecolumns = vcat([gi[i][lnks[i].collnk[1:lnks[i].colctr]] for i=1:nt]...) - num_cols = sum([lnks[i].colctr for i=1:nt]) - tids = Vector{Ti}(undef, num_cols) - ctr = 0 - for i=1:nt - for j=1:lnks[i].colctr - ctr += 1 - tids[ctr] = i - end - end + if keep_zeros + get_col! = get_column_keepzeros! + else + get_col! = get_column_removezeros! + end + lnkscols = vcat([lnks[i].collnk[1:lnks[i].colctr] for i in 1:nt]...) + supersparsecolumns = vcat([gi[i][lnks[i].collnk[1:lnks[i].colctr]] for i in 1:nt]...) + num_cols = sum([lnks[i].colctr for i in 1:nt]) + tids = Vector{Ti}(undef, num_cols) + ctr = 0 + for i in 1:nt + for j in 1:lnks[i].colctr + ctr += 1 + tids[ctr] = i + end + end - sortedcolumnids = sortperm(supersparsecolumns) - sortedcolumns = supersparsecolumns[sortedcolumnids] - sortedcolumns = vcat(sortedcolumns, [Ti(csc.n+1)]) - - coll = sum([lnks[i].nnz for i=1:nt]) - nnz_sum = length(csc.rowval) + coll - colptr = Vector{Ti}(undef, csc.n+1) - rowval = Vector{Ti}(undef, nnz_sum) - nzval = Vector{Tv}(undef, nnz_sum) - colptr[1] = one(Ti) - - if csc.m < coll - coll = csc.m - end - - col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i=1:coll] - numshifts = 0 - - colptr[1:sortedcolumns[1]] = view(csc.colptr, 1:sortedcolumns[1]) - rowval[1:csc.colptr[sortedcolumns[1]]-1] = view(csc.rowval, 1:csc.colptr[sortedcolumns[1]]-1) - nzval[1:csc.colptr[sortedcolumns[1]]-1] = view(csc.nzval, 1:csc.colptr[sortedcolumns[1]]-1) - - J = 1 - i0 = 0 - #lj_last = [] - #tid_last = [] - lj_last = Vector{Ti}(undef, nt) - tid_last = Vector{Ti}(undef, nt) - ctr_last = 1 - gj_last = 0 - for J=1:length(sortedcolumns)-1 - gj_now = sortedcolumns[J] - gj_next = sortedcolumns[J+1] - - lj_last[ctr_last] = lnkscols[sortedcolumnids[J]] - tid_last[ctr_last] = tids[sortedcolumnids[J]] - - if gj_now != gj_next - #@info typeof(lnks) - # do stuff from gj_last to gj_now / from last_lj to J - #@info lj_last, tid_last - coll = get_col!(col, lnks, lj_last, tid_last, ctr_last) - - nns = merge_into!(rowval, nzval, csc, col, gj_now, coll, colptr[gj_now]-one(Ti)) - numshifts += nns - - - colptr[gj_now+1:sortedcolumns[J+1]] = csc.colptr[gj_now+1:sortedcolumns[J+1]].+(-csc.colptr[gj_now]+colptr[gj_now] + nns) - - rowval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = view(csc.rowval, csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1) - nzval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = view(csc.nzval, csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1) - - #rowval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = csc.rowval[csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1] - #nzval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = csc.nzval[csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1] - - - #for k=csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1 - # k2 = k+(-csc.colptr[gj_now]+colptr[gj_now] + nns) - # rowval[k2] = csc.rowval[k] - # nzval[k2] = csc.nzval[k] - #end - - gj_last = gj_now - ctr_last = 0 #tids[sortedcolumnids[J]]] - end - - ctr_last += 1 - - - end - - - resize!(rowval, length(csc.rowval)+numshifts) - resize!(nzval, length(csc.rowval)+numshifts) - - - SparseArrays.SparseMatrixCSC(csc.m, csc.n, colptr, rowval, nzval) - + sortedcolumnids = sortperm(supersparsecolumns) + sortedcolumns = supersparsecolumns[sortedcolumnids] + sortedcolumns = vcat(sortedcolumns, [Ti(csc.n + 1)]) - #for ... - # take many columns together if necessary in `get_column` - #end + coll = sum([lnks[i].nnz for i in 1:nt]) + nnz_sum = length(csc.rowval) + coll + colptr = Vector{Ti}(undef, csc.n + 1) + rowval = Vector{Ti}(undef, nnz_sum) + nzval = Vector{Tv}(undef, nnz_sum) + colptr[1] = one(Ti) + + if csc.m < coll + coll = csc.m + end + col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i in 1:coll] + numshifts = 0 + + colptr[1:sortedcolumns[1]] = view(csc.colptr, 1:sortedcolumns[1]) + rowval[1:(csc.colptr[sortedcolumns[1]] - 1)] = view(csc.rowval, 1:(csc.colptr[sortedcolumns[1]] - 1)) + nzval[1:(csc.colptr[sortedcolumns[1]] - 1)] = view(csc.nzval, 1:(csc.colptr[sortedcolumns[1]] - 1)) + + J = 1 + i0 = 0 + #lj_last = [] + #tid_last = [] + lj_last = Vector{Ti}(undef, nt) + tid_last = Vector{Ti}(undef, nt) + ctr_last = 1 + gj_last = 0 + for J in 1:(length(sortedcolumns) - 1) + gj_now = sortedcolumns[J] + gj_next = sortedcolumns[J + 1] + + lj_last[ctr_last] = lnkscols[sortedcolumnids[J]] + tid_last[ctr_last] = tids[sortedcolumnids[J]] + + if gj_now != gj_next + #@info typeof(lnks) + # do stuff from gj_last to gj_now / from last_lj to J + #@info lj_last, tid_last + coll = get_col!(col, lnks, lj_last, tid_last, ctr_last) + + nns = merge_into!(rowval, nzval, csc, col, gj_now, coll, colptr[gj_now] - one(Ti)) + numshifts += nns + + + colptr[(gj_now + 1):sortedcolumns[J + 1]] = csc.colptr[(gj_now + 1):sortedcolumns[J + 1]] .+ (-csc.colptr[gj_now] + colptr[gj_now] + nns) + + rowval[colptr[gj_now + 1]:(colptr[sortedcolumns[J + 1]] - 1)] = view(csc.rowval, csc.colptr[gj_now + 1]:(csc.colptr[sortedcolumns[J + 1]] - 1)) + nzval[colptr[gj_now + 1]:(colptr[sortedcolumns[J + 1]] - 1)] = view(csc.nzval, csc.colptr[gj_now + 1]:(csc.colptr[sortedcolumns[J + 1]] - 1)) + + #rowval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = csc.rowval[csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1] + #nzval[colptr[gj_now+1]:colptr[sortedcolumns[J+1]]-1] = csc.nzval[csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1] + + + #for k=csc.colptr[gj_now+1]:csc.colptr[sortedcolumns[J+1]]-1 + # k2 = k+(-csc.colptr[gj_now]+colptr[gj_now] + nns) + # rowval[k2] = csc.rowval[k] + # nzval[k2] = csc.nzval[k] + #end + + gj_last = gj_now + ctr_last = 0 #tids[sortedcolumnids[J]]] + end + + ctr_last += 1 + + + end + + + resize!(rowval, length(csc.rowval) + numshifts) + resize!(nzval, length(csc.rowval) + numshifts) + + + return SparseArrays.SparseMatrixCSC(csc.m, csc.n, colptr, rowval, nzval) + + + #for ... + # take many columns together if necessary in `get_column` + #end end @@ -522,71 +520,71 @@ Add the SuperSparseMatrixLNK `lnk` onto the SparseMatrixCSC `csc`. """ function plus_remap(lnk::SuperSparseMatrixLNK{Tv, Ti}, csc::SparseArrays.SparseMatrixCSC, gi::Vector{Ti}) where {Tv, Ti <: Integer} - #@info lnk.collnk[1:lnk.colctr] - - - supersparsecolumns = gi[lnk.collnk[1:lnk.colctr]] - sortedcolumnids = sortperm(supersparsecolumns) - sortedcolumns = supersparsecolumns[sortedcolumnids] - #sortedcolumns = vcat([1], sortedcolumns) - #@info typeof(supersparsecolumns), typeof(sortedcolumns) - - sortedcolumns = vcat(sortedcolumns, [Ti(csc.n+1)]) - - #@info typeof(supersparsecolumns), typeof(sortedcolumns) - - - #@info supersparsecolumns - #@info sortedcolumns - #@info lnk.collnk[1:length(sortedcolumns)-1] - #@info lnk.collnk[sortedcolumnids[1:length(sortedcolumns)-1]] - - col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i=1:csc.m] - - #@info sortedcolumnids - - nnz_sum = length(csc.rowval) + lnk.nnz - colptr = Vector{Ti}(undef, csc.n+1) - rowval = Vector{Ti}(undef, nnz_sum) - nzval = Vector{Tv}(undef, nnz_sum) - colptr[1] = one(Ti) - - #first part: columns between 1 and first column of lnk - - colptr[1:sortedcolumns[1]] = view(csc.colptr, 1:sortedcolumns[1]) - rowval[1:csc.colptr[sortedcolumns[1]]-1] = view(csc.rowval, 1:csc.colptr[sortedcolumns[1]]-1) - nzval[1:csc.colptr[sortedcolumns[1]]-1] = view(csc.nzval, 1:csc.colptr[sortedcolumns[1]]-1) - - numshifts = 0 - - for J=1:length(sortedcolumns)-1 - i = sortedcolumns[J] - - coll = get_column!(col, lnk, lnk.collnk[sortedcolumnids[J]] ) - #@info typeof(i), typeof(coll), typeof(colptr), typeof(colptr[i]), typeof(colptr[i]-1) - nns = merge_into!(rowval, nzval, csc, col, i, coll, colptr[i]-one(Ti)) - numshifts += nns - - - colptr[i+1:sortedcolumns[J+1]] = csc.colptr[i+1:sortedcolumns[J+1]].+(-csc.colptr[i]+colptr[i] + nns) - rowval[colptr[i+1]:colptr[sortedcolumns[J+1]]-1] = view(csc.rowval, csc.colptr[i+1]:csc.colptr[sortedcolumns[J+1]]-1) - nzval[colptr[i+1]:colptr[sortedcolumns[J+1]]-1] = view(csc.nzval, csc.colptr[i+1]:csc.colptr[sortedcolumns[J+1]]-1) - - #= + #@info lnk.collnk[1:lnk.colctr] + + + supersparsecolumns = gi[lnk.collnk[1:lnk.colctr]] + sortedcolumnids = sortperm(supersparsecolumns) + sortedcolumns = supersparsecolumns[sortedcolumnids] + #sortedcolumns = vcat([1], sortedcolumns) + #@info typeof(supersparsecolumns), typeof(sortedcolumns) + + sortedcolumns = vcat(sortedcolumns, [Ti(csc.n + 1)]) + + #@info typeof(supersparsecolumns), typeof(sortedcolumns) + + + #@info supersparsecolumns + #@info sortedcolumns + #@info lnk.collnk[1:length(sortedcolumns)-1] + #@info lnk.collnk[sortedcolumnids[1:length(sortedcolumns)-1]] + + col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i in 1:csc.m] + + #@info sortedcolumnids + + nnz_sum = length(csc.rowval) + lnk.nnz + colptr = Vector{Ti}(undef, csc.n + 1) + rowval = Vector{Ti}(undef, nnz_sum) + nzval = Vector{Tv}(undef, nnz_sum) + colptr[1] = one(Ti) + + #first part: columns between 1 and first column of lnk + + colptr[1:sortedcolumns[1]] = view(csc.colptr, 1:sortedcolumns[1]) + rowval[1:(csc.colptr[sortedcolumns[1]] - 1)] = view(csc.rowval, 1:(csc.colptr[sortedcolumns[1]] - 1)) + nzval[1:(csc.colptr[sortedcolumns[1]] - 1)] = view(csc.nzval, 1:(csc.colptr[sortedcolumns[1]] - 1)) + + numshifts = 0 + + for J in 1:(length(sortedcolumns) - 1) + i = sortedcolumns[J] + + coll = get_column!(col, lnk, lnk.collnk[sortedcolumnids[J]]) + #@info typeof(i), typeof(coll), typeof(colptr), typeof(colptr[i]), typeof(colptr[i]-1) + nns = merge_into!(rowval, nzval, csc, col, i, coll, colptr[i] - one(Ti)) + numshifts += nns + + + colptr[(i + 1):sortedcolumns[J + 1]] = csc.colptr[(i + 1):sortedcolumns[J + 1]] .+ (-csc.colptr[i] + colptr[i] + nns) + rowval[colptr[i + 1]:(colptr[sortedcolumns[J + 1]] - 1)] = view(csc.rowval, csc.colptr[i + 1]:(csc.colptr[sortedcolumns[J + 1]] - 1)) + nzval[colptr[i + 1]:(colptr[sortedcolumns[J + 1]] - 1)] = view(csc.nzval, csc.colptr[i + 1]:(csc.colptr[sortedcolumns[J + 1]] - 1)) + + #= for k=csc.colptr[i+1]:csc.colptr[sortedcolumns[J+1]]-1 k2 = k+(-csc.colptr[i]+colptr[i] + nns) rowval[k2] = csc.rowval[k] nzval[k2] = csc.nzval[k] end =# - end - - - resize!(rowval, length(csc.rowval)+numshifts) - resize!(nzval, length(csc.rowval)+numshifts) - - - SparseArrays.SparseMatrixCSC(csc.m, csc.n, colptr, rowval, nzval) + end + + + resize!(rowval, length(csc.rowval) + numshifts) + resize!(nzval, length(csc.rowval) + numshifts) + + + return SparseArrays.SparseMatrixCSC(csc.m, csc.n, colptr, rowval, nzval) end @@ -779,9 +777,9 @@ end """ function mean(x) - sum(x)/length(x) + return sum(x) / length(x) end function form(x) - [minimum(x), mean(x), maximum(x)] + return [minimum(x), mean(x), maximum(x)] end diff --git a/src/factorizations/blockpreconditioner.jl b/src/factorizations/blockpreconditioner.jl index e9bc1f8..3b5fbf2 100644 --- a/src/factorizations/blockpreconditioner.jl +++ b/src/factorizations/blockpreconditioner.jl @@ -2,19 +2,18 @@ mutable struct BlockPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization phash::UInt64 - partitioning::Union{Nothing,Vector{AbstractVector}} + partitioning::Union{Nothing, Vector{AbstractVector}} facts::Vector - function BlockPreconditioner(;partitioning=nothing, factorization=ExtendableSparse.LUFactorization) + function BlockPreconditioner(; partitioning = nothing, factorization = ExtendableSparse.LUFactorization) p = new() p.phash = 0 - p.partitioning=partitioning - p.factorization=factorization - p + p.partitioning = partitioning + p.factorization = factorization + return p end end - """ BlockPreconditioner(;partitioning, factorization=LUFactorization) @@ -32,72 +31,70 @@ Factorizations on matrix partitions within a block preconditioner may or may not E.g. the umfpack factorization cannot work with views, while ILUZeroPreconditioner can. Implementing a method for `allow_views` returning `false` resp. `true` allows to dispatch to the proper case. """ -allow_views(::Any)=false +allow_views(::Any) = false function update!(precon::BlockPreconditioner) flush!(precon.A) - nall=sum(length,precon.partitioning) - n=size(precon.A,1) - if nall!=n - @warn "sum(length,partitioning)=$(nall) but n=$(n)" + nall = sum(length, precon.partitioning) + n = size(precon.A, 1) + if nall != n + @warn "sum(length,partitioning)=$(nall) but n=$(n)" end if isnothing(precon.partitioning) - partitioning=[1:n] + partitioning = [1:n] end - np=length(precon.partitioning) - precon.facts=Vector{Any}(undef,np) - Threads.@threads for ipart=1:np - factorization=deepcopy(precon.factorization) - AP=precon.A[precon.partitioning[ipart],precon.partitioning[ipart]] - FP=factorization(AP) - precon.facts[ipart]=FP + np = length(precon.partitioning) + precon.facts = Vector{Any}(undef, np) + return Threads.@threads for ipart in 1:np + factorization = deepcopy(precon.factorization) + AP = precon.A[precon.partitioning[ipart], precon.partitioning[ipart]] + FP = factorization(AP) + precon.facts[ipart] = FP end end - - -function LinearAlgebra.ldiv!(p::BlockPreconditioner,v) - partitioning=p.partitioning - facts=p.facts - np=length(partitioning) +function LinearAlgebra.ldiv!(p::BlockPreconditioner, v) + partitioning = p.partitioning + facts = p.facts + np = length(partitioning) if allow_views(p.factorization) - Threads.@threads for ipart=1:np - ldiv!(facts[ipart],view(v,partitioning[ipart])) + Threads.@threads for ipart in 1:np + ldiv!(facts[ipart], view(v, partitioning[ipart])) end else - Threads.@threads for ipart=1:np - vv=v[partitioning[ipart]] - ldiv!(facts[ipart],vv) - view(v,partitioning[ipart]).=vv + Threads.@threads for ipart in 1:np + vv = v[partitioning[ipart]] + ldiv!(facts[ipart], vv) + view(v, partitioning[ipart]) .= vv end end - v + return v end -function LinearAlgebra.ldiv!(u,p::BlockPreconditioner,v) - partitioning=p.partitioning - facts=p.facts - np=length(partitioning) - if allow_views(p.factorization) - Threads.@threads for ipart=1:np - ldiv!(view(u,partitioning[ipart]),facts[ipart],view(v,partitioning[ipart])) +function LinearAlgebra.ldiv!(u, p::BlockPreconditioner, v) + partitioning = p.partitioning + facts = p.facts + np = length(partitioning) + if allow_views(p.factorization) + Threads.@threads for ipart in 1:np + ldiv!(view(u, partitioning[ipart]), facts[ipart], view(v, partitioning[ipart])) end else - Threads.@threads for ipart=1:np - uu=u[partitioning[ipart]] - ldiv!(uu,facts[ipart],v[partitioning[ipart]]) - view(u,partitioning[ipart]).=uu + Threads.@threads for ipart in 1:np + uu = u[partitioning[ipart]] + ldiv!(uu, facts[ipart], v[partitioning[ipart]]) + view(u, partitioning[ipart]) .= uu end end - u + return u end -Base.eltype(p::BlockPreconditioner)=eltype(p.facts[1]) +Base.eltype(p::BlockPreconditioner) = eltype(p.facts[1]) """ @@ -113,15 +110,15 @@ from partition of unknowns. - `precs(A,p)` shall return a left precondioner for a matrix block. """ Base.@kwdef mutable struct BlockPreconBuilder - precs=UMFPACKPreconBuilder() - partitioning= A -> [1:size(A,1)] + precs = UMFPACKPreconBuilder() + partitioning = A -> [1:size(A, 1)] end -function (blockprecs::BlockPreconBuilder)(A,p) - (;precs, partitioning)=blockprecs - factorization= A->precs(A,p)[1] - bp=BlockPreconditioner(A;partitioning=partitioning(A), factorization) - (bp,LinearAlgebra.I) +function (blockprecs::BlockPreconBuilder)(A, p) + (; precs, partitioning) = blockprecs + factorization = A -> precs(A, p)[1] + bp = BlockPreconditioner(A; partitioning = partitioning(A), factorization) + return (bp, LinearAlgebra.I) end """ diff --git a/src/factorizations/cholmod_cholesky.jl b/src/factorizations/cholmod_cholesky.jl index 66228b4..3efa90b 100644 --- a/src/factorizations/cholmod_cholesky.jl +++ b/src/factorizations/cholmod_cholesky.jl @@ -5,7 +5,7 @@ mutable struct CholeskyFactorization <: AbstractLUFactorization A64::Any end -cholwarned=false +cholwarned = false """ CholeskyFactorization(;valuetype=Float64, indextype=Int64) CholeskyFactorization(matrix) @@ -16,9 +16,9 @@ function CholeskyFactorization() global cholwarned if !cholwarned @warn "ExtendableSparse.CholeskyFactorization is deprecated. Use LinearSolve.CholeskyFactorization` instead" - cholwarned=true + cholwarned = true end - CholeskyFactorization(nothing, nothing, 0, nothing) + return CholeskyFactorization(nothing, nothing, 0, nothing) end function update!(cholfact::CholeskyFactorization) @@ -32,7 +32,7 @@ function update!(cholfact::CholeskyFactorization) cholfact.A64.data.nzval .= A.cscmatrix.nzval cholfact.fact = cholesky!(cholfact.fact, cholfact.A64) end - cholfact + return cholfact end LinearAlgebra.ldiv!(fact::CholeskyFactorization, v) = fact.fact \ v diff --git a/src/factorizations/factorizations.jl b/src/factorizations/factorizations.jl index c9809d3..a692fc1 100644 --- a/src/factorizations/factorizations.jl +++ b/src/factorizations/factorizations.jl @@ -52,7 +52,6 @@ issolver(::AbstractLUFactorization) = true issolver(::AbstractPreconditioner) = false - """" @makefrommatrix(fact) @@ -65,10 +64,10 @@ For an AbstractFactorization `MyFact`, provide methods macro makefrommatrix(fact) return quote function $(esc(fact))(A::ExtendableSparseMatrix; kwargs...) - factorize!($(esc(fact))(;kwargs...), A) + return factorize!($(esc(fact))(; kwargs...), A) end function $(esc(fact))(A::SparseMatrixCSC; kwargs...) - $(esc(fact))(ExtendableSparseMatrix(A); kwargs...) + return $(esc(fact))(ExtendableSparseMatrix(A); kwargs...) end end end @@ -104,9 +103,9 @@ This method is aware of pattern changes. function factorize!(p::AbstractFactorization, A::ExtendableSparseMatrix) p.A = A update!(p) - p + return p end -factorize!(p::AbstractFactorization, A::SparseMatrixCSC)=factorize!(p,ExtendableSparseMatrix(A)) +factorize!(p::AbstractFactorization, A::SparseMatrixCSC) = factorize!(p, ExtendableSparseMatrix(A)) """ @@ -120,7 +119,7 @@ This method is aware of pattern changes. If `nothing` is passed as first parameter, [`factorize!`](@ref) is called. """ function LinearAlgebra.lu!(lufact::AbstractFactorization, A::ExtendableSparseMatrix) - factorize!(lufact, A) + return factorize!(lufact, A) end """ @@ -136,11 +135,11 @@ function lu end if USE_GPL_LIBS function LinearAlgebra.lu(A::ExtendableSparseMatrix) - factorize!(LUFactorization(), A) + return factorize!(LUFactorization(), A) end else function LinearAlgebra.lu(A::ExtendableSparseMatrix) - factorize!(SparspakLU(), A) + return factorize!(SparspakLU(), A) end end # USE_GPL_LIBS @@ -151,8 +150,8 @@ end # USE_GPL_LIBS Solve LU factorization problem. """ -function Base.:\(lufact::AbstractLUFactorization,v) - ldiv!(similar(v), lufact, v) +function Base.:\(lufact::AbstractLUFactorization, v) + return ldiv!(similar(v), lufact, v) end """ @@ -175,8 +174,6 @@ LinearAlgebra.ldiv!(u, fact::AbstractFactorization, v) = ldiv!(u, fact.factoriza LinearAlgebra.ldiv!(fact::AbstractFactorization, v) = ldiv!(fact.factorization, v) - - if USE_GPL_LIBS #requires SuiteSparse which is not available in non-GPL builds include("umfpack_lu.jl") diff --git a/src/factorizations/ilu0.jl b/src/factorizations/ilu0.jl index 12ce979..8ca3bfb 100644 --- a/src/factorizations/ilu0.jl +++ b/src/factorizations/ilu0.jl @@ -1,21 +1,21 @@ -mutable struct _ILU0Preconditioner{Tv,Ti} - cscmatrix::SparseMatrixCSC{Tv,Ti} +mutable struct _ILU0Preconditioner{Tv, Ti} + cscmatrix::SparseMatrixCSC{Tv, Ti} xdiag::Vector{Tv} idiag::Vector{Ti} end -function ilu0(cscmatrix::SparseMatrixCSC{Tv,Ti}) where{Tv,Ti} +function ilu0(cscmatrix::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} colptr = cscmatrix.colptr rowval = cscmatrix.rowval nzval = cscmatrix.nzval n = cscmatrix.n - + # Find main diagonal index and # copy main diagonal values - idiag=Vector{Ti}(undef,n) - @inbounds for j = 1:n - @inbounds for k = colptr[j]:(colptr[j + 1] - 1) + idiag = Vector{Ti}(undef, n) + @inbounds for j in 1:n + @inbounds for k in colptr[j]:(colptr[j + 1] - 1) i = rowval[k] if i == j idiag[j] = k @@ -23,13 +23,13 @@ function ilu0(cscmatrix::SparseMatrixCSC{Tv,Ti}) where{Tv,Ti} end end end - - xdiag=Vector{Tv}(undef,n) - @inbounds for j = 1:n + + xdiag = Vector{Tv}(undef, n) + @inbounds for j in 1:n xdiag[j] = one(Tv) / nzval[idiag[j]] - @inbounds for k = (idiag[j] + 1):(colptr[j + 1] - 1) + @inbounds for k in (idiag[j] + 1):(colptr[j + 1] - 1) i = rowval[k] - for l = colptr[i]:(colptr[i + 1] - 1) + for l in colptr[i]:(colptr[i + 1] - 1) if rowval[l] == j xdiag[i] -= nzval[l] * xdiag[j] * nzval[k] break @@ -37,22 +37,22 @@ function ilu0(cscmatrix::SparseMatrixCSC{Tv,Ti}) where{Tv,Ti} end end end - _ILU0Preconditioner(cscmatrix,xdiag,idiag) + return _ILU0Preconditioner(cscmatrix, xdiag, idiag) end -function ilu0!(p::_ILU0Preconditioner{Tv,Ti},cscmatrix::SparseMatrixCSC{Tv,Ti}) where{Tv,Ti} +function ilu0!(p::_ILU0Preconditioner{Tv, Ti}, cscmatrix::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} colptr = cscmatrix.colptr rowval = cscmatrix.rowval nzval = cscmatrix.nzval n = cscmatrix.n - idiag=p.idiag - xdiag=p.xdiag - - @inbounds for j = 1:n + idiag = p.idiag + xdiag = p.xdiag + + @inbounds for j in 1:n xdiag[j] = one(Tv) / nzval[idiag[j]] - @inbounds for k = (idiag[j] + 1):(colptr[j + 1] - 1) + @inbounds for k in (idiag[j] + 1):(colptr[j + 1] - 1) i = rowval[k] - for l = colptr[i]:(colptr[i + 1] - 1) + for l in colptr[i]:(colptr[i + 1] - 1) if rowval[l] == j xdiag[i] -= nzval[l] * xdiag[j] * nzval[k] break @@ -60,53 +60,52 @@ function ilu0!(p::_ILU0Preconditioner{Tv,Ti},cscmatrix::SparseMatrixCSC{Tv,Ti}) end end end - p.cscmatrix=cscmatrix - p + p.cscmatrix = cscmatrix + return p end -function LinearAlgebra.ldiv!(u,p::_ILU0Preconditioner{Tv,Ti},v) where {Tv,Ti} +function LinearAlgebra.ldiv!(u, p::_ILU0Preconditioner{Tv, Ti}, v) where {Tv, Ti} colptr = p.cscmatrix.colptr rowval = p.cscmatrix.rowval nzval = p.cscmatrix.nzval n = p.cscmatrix.n idiag = p.idiag xdiag = p.xdiag - - for j = 1:n + + for j in 1:n u[j] = xdiag[j] * v[j] end - - for j = n:-1:1 - for k = (idiag[j] + 1):(colptr[j + 1] - 1) + + for j in n:-1:1 + for k in (idiag[j] + 1):(colptr[j + 1] - 1) i = rowval[k] u[i] -= xdiag[i] * nzval[k] * u[j] end end - - for j = 1:n - for k = colptr[j]:(idiag[j] - 1) + + for j in 1:n + for k in colptr[j]:(idiag[j] - 1) i = rowval[k] u[i] -= xdiag[i] * nzval[k] * u[j] end end - u + return u end -function LinearAlgebra.ldiv!(p::_ILU0Preconditioner{Tv,Ti},v) where {Tv,Ti} - ldiv!(copy(v),p,v) +function LinearAlgebra.ldiv!(p::_ILU0Preconditioner{Tv, Ti}, v) where {Tv, Ti} + return ldiv!(copy(v), p, v) end - mutable struct ILU0Preconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::_ILU0Preconditioner phash::UInt64 - function ILU0Preconditioner() + function ILU0Preconditioner() p = new() p.phash = 0 - p + return p end end @@ -122,18 +121,17 @@ slower convergende than [`ILUZeroPreconditioner`](@ref). function ILU0Preconditioner end - function update!(p::ILU0Preconditioner) flush!(p.A) - Tv=eltype(p.A) - if p.A.phash!=p.phash - p.factorization=ilu0(p.A.cscmatrix) - p.phash=p.A.phash + Tv = eltype(p.A) + if p.A.phash != p.phash + p.factorization = ilu0(p.A.cscmatrix) + p.phash = p.A.phash else - ilu0!(p.factorization,p.A.cscmatrix) + ilu0!(p.factorization, p.A.cscmatrix) end - p + return p end -allow_views(::ILU0Preconditioner)=true -allow_views(::Type{ILU0Preconditioner})=true +allow_views(::ILU0Preconditioner) = true +allow_views(::Type{ILU0Preconditioner}) = true diff --git a/src/factorizations/iluzero.jl b/src/factorizations/iluzero.jl index af9bc12..4d8b038 100644 --- a/src/factorizations/iluzero.jl +++ b/src/factorizations/iluzero.jl @@ -1,4 +1,4 @@ -iluzerowarned=false +iluzerowarned = false mutable struct ILUZeroPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::ILUZero.ILU0Precon @@ -7,11 +7,11 @@ mutable struct ILUZeroPreconditioner <: AbstractPreconditioner global iluzerowarned if !iluzerowarned @warn "ILUZeroPreconditioner is deprecated. Use LinearSolve with `precs=ILUZeroPreconBuilder()` instead" - iluzerowarned=true + iluzerowarned = true end p = new() p.phash = 0 - p + return p end end @@ -29,34 +29,33 @@ function update!(p::ILUZeroPreconditioner) flush!(p.A) if p.A.phash != p.phash p.factorization = ILUZero.ilu0(p.A.cscmatrix) - p.phash=p.A.phash + p.phash = p.A.phash else ILUZero.ilu0!(p.factorization, p.A.cscmatrix) end - p + return p end -allow_views(::ILUZeroPreconditioner)=true -allow_views(::Type{ILUZeroPreconditioner})=true +allow_views(::ILUZeroPreconditioner) = true +allow_views(::Type{ILUZeroPreconditioner}) = true - -biluzerowarned=false +biluzerowarned = false mutable struct PointBlockILUZeroPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix factorization::ILUZero.ILU0Precon phash::UInt64 blocksize::Int - function PointBlockILUZeroPreconditioner(;blocksize=1) + function PointBlockILUZeroPreconditioner(; blocksize = 1) global biluzerowarned if !biluzerowarned @warn "PointBlockILUZeroPreconditioner is deprecated. Use LinearSolve with `precs=ILUZeroPreconBuilder(; blocksize=$(blocksize))` instead" - biluzerowarned=true + biluzerowarned = true end p = new() p.phash = 0 - p.blocksize=blocksize - p + p.blocksize = blocksize + return p end end @@ -72,27 +71,28 @@ function PointBlockILUZeroPreconditioner end function update!(p::PointBlockILUZeroPreconditioner) flush!(p.A) - Ab=pointblock(p.A.cscmatrix,p.blocksize) + Ab = pointblock(p.A.cscmatrix, p.blocksize) if p.A.phash != p.phash - p.factorization = ILUZero.ilu0(Ab, SVector{p.blocksize,eltype(p.A)}) - p.phash=p.A.phash + p.factorization = ILUZero.ilu0(Ab, SVector{p.blocksize, eltype(p.A)}) + p.phash = p.A.phash else ILUZero.ilu0!(p.factorization, Ab) end - p + return p end -function LinearAlgebra.ldiv!(p::PointBlockILUZeroPreconditioner,v) - vv=reinterpret(SVector{p.blocksize,eltype(v)},v) - LinearAlgebra.ldiv!(vv,p.factorization,vv) - v -end +function LinearAlgebra.ldiv!(p::PointBlockILUZeroPreconditioner, v) + vv = reinterpret(SVector{p.blocksize, eltype(v)}, v) + LinearAlgebra.ldiv!(vv, p.factorization, vv) + return v +end -function LinearAlgebra.ldiv!(u,p::PointBlockILUZeroPreconditioner,v) - LinearAlgebra.ldiv!(reinterpret(SVector{p.blocksize,eltype(u)},u), - p.factorization, - reinterpret(SVector{p.blocksize,eltype(v)},v) - ) - u +function LinearAlgebra.ldiv!(u, p::PointBlockILUZeroPreconditioner, v) + LinearAlgebra.ldiv!( + reinterpret(SVector{p.blocksize, eltype(u)}, u), + p.factorization, + reinterpret(SVector{p.blocksize, eltype(v)}, v) + ) + return u end diff --git a/src/factorizations/jacobi.jl b/src/factorizations/jacobi.jl index fc144c2..36b1be2 100644 --- a/src/factorizations/jacobi.jl +++ b/src/factorizations/jacobi.jl @@ -2,43 +2,44 @@ mutable struct _JacobiPreconditioner{Tv} invdiag::Vector{Tv} end -function jacobi(A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} +function jacobi(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} invdiag = Array{Tv, 1}(undef, A.n) n = A.n - @inbounds for i = 1:n + @inbounds for i in 1:n invdiag[i] = one(Tv) / A[i, i] end - _JacobiPreconditioner(invdiag) + return _JacobiPreconditioner(invdiag) end -function jacobi!(p::_JacobiPreconditioner{Tv},A::SparseMatrixCSC{Tv,Ti})where {Tv,Ti} +function jacobi!(p::_JacobiPreconditioner{Tv}, A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} n = A.n - @inbounds for i = 1:n + @inbounds for i in 1:n p.invdiag[i] = one(Tv) / A[i, i] end - p + return p end mutable struct JacobiPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix - factorization::Union{_JacobiPreconditioner,Nothing} + factorization::Union{_JacobiPreconditioner, Nothing} phash::UInt64 function JacobiPreconditioner() p = new() - p.factorization=nothing - p.phash=0 - p + p.factorization = nothing + p.phash = 0 + return p end end -function LinearAlgebra.ldiv!(u,p::_JacobiPreconditioner,v) - n=length(p.invdiag) - for i = 1:n +function LinearAlgebra.ldiv!(u, p::_JacobiPreconditioner, v) + n = length(p.invdiag) + for i in 1:n @inbounds u[i] = p.invdiag[i] * v[i] end + return end - LinearAlgebra.ldiv!(p::_JacobiPreconditioner,v)=ldiv!(v,p,v) +LinearAlgebra.ldiv!(p::_JacobiPreconditioner, v) = ldiv!(v, p, v) """ @@ -53,15 +54,15 @@ function JacobiPreconditioner end function update!(p::JacobiPreconditioner) flush!(p.A) - Tv=eltype(p.A) - if p.A.phash!=p.phash || isnothing(p.factorization) - p.factorization=jacobi(p.A.cscmatrix) - p.phash=p.A.phash + Tv = eltype(p.A) + if p.A.phash != p.phash || isnothing(p.factorization) + p.factorization = jacobi(p.A.cscmatrix) + p.phash = p.A.phash else - jacobi!(p.factorization,p.A.cscmatrix) + jacobi!(p.factorization, p.A.cscmatrix) end - p + return p end -allow_views(::JacobiPreconditioner)=true -allow_views(::Type{JacobiPreconditioner})=true +allow_views(::JacobiPreconditioner) = true +allow_views(::Type{JacobiPreconditioner}) = true diff --git a/src/factorizations/parallel_ilu0.jl b/src/factorizations/parallel_ilu0.jl index d4e8b91..eac1609 100644 --- a/src/factorizations/parallel_ilu0.jl +++ b/src/factorizations/parallel_ilu0.jl @@ -1,5 +1,5 @@ -mutable struct _ParallelILU0Preconditioner{Tv,Ti} - A::SparseMatrixCSC{Tv,Ti} +mutable struct _ParallelILU0Preconditioner{Tv, Ti} + A::SparseMatrixCSC{Tv, Ti} xdiag::Vector{Tv} idiag::Vector{Ti} coloring::Vector{Vector{Ti}} @@ -7,22 +7,22 @@ mutable struct _ParallelILU0Preconditioner{Tv,Ti} coloring_index_reverse::Vector{Vector{Ti}} end -function pilu0(A0::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} +function pilu0(A0::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} coloring = graphcol(A0) coloring_index, coloring_index_reverse = coloringindex(coloring) A = ExtendableSparseMatrix(reordermatrix(A0, coloring)).cscmatrix colptr = A.colptr rowval = A.rowval - nzval = A.nzval + nzval = A.nzval n = A.n - xdiag=Vector{Tv}(undef,n) - idiag=Vector{Ti}(undef,n) + xdiag = Vector{Tv}(undef, n) + idiag = Vector{Ti}(undef, n) # Find main diagonal index and # copy main diagonal values - @inbounds for j = 1:n - @inbounds for k = colptr[j]:(colptr[j + 1] - 1) + @inbounds for j in 1:n + @inbounds for k in colptr[j]:(colptr[j + 1] - 1) i = rowval[k] if i == j idiag[j] = k @@ -30,12 +30,12 @@ function pilu0(A0::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} end end end - - @inbounds for j = 1:n + + @inbounds for j in 1:n xdiag[j] = one(Tv) / nzval[idiag[j]] - @inbounds for k = (idiag[j] + 1):(colptr[j + 1] - 1) + @inbounds for k in (idiag[j] + 1):(colptr[j + 1] - 1) i = rowval[k] - for l = colptr[i]:(colptr[i + 1] - 1) + for l in colptr[i]:(colptr[i + 1] - 1) if rowval[l] == j xdiag[i] -= nzval[l] * xdiag[j] * nzval[k] break @@ -43,12 +43,14 @@ function pilu0(A0::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} end end end - _ParallelILU0Preconditioner(A,xdiag,idiag, coloring, coloring_index,coloring_index_reverse) + return _ParallelILU0Preconditioner(A, xdiag, idiag, coloring, coloring_index, coloring_index_reverse) end -function LinearAlgebra.ldiv!(u::AbstractVector, - precon::_ParallelILU0Preconditioner{Tv,Ti}, - v::AbstractVector) where {Tv,Ti} +function LinearAlgebra.ldiv!( + u::AbstractVector, + precon::_ParallelILU0Preconditioner{Tv, Ti}, + v::AbstractVector + ) where {Tv, Ti} A = precon.A colptr = A.colptr rowval = A.rowval @@ -60,14 +62,14 @@ function LinearAlgebra.ldiv!(u::AbstractVector, coloring = precon.coloring coloring_index = precon.coloring_index coloring_index_reverse = precon.coloring_index_reverse - - Threads.@threads for j = 1:n + + Threads.@threads for j in 1:n u[j] = xdiag[j] * v[j] end for indset in coloring_index_reverse Threads.@threads for j in indset - for k = (idiag[j] + 1):(colptr[j + 1] - 1) + for k in (idiag[j] + 1):(colptr[j + 1] - 1) i = rowval[k] u[i] -= xdiag[i] * nzval[k] * u[j] end @@ -75,36 +77,39 @@ function LinearAlgebra.ldiv!(u::AbstractVector, end for indset in coloring_index Threads.@threads for j in indset - for k = colptr[j]:(idiag[j] - 1) + for k in colptr[j]:(idiag[j] - 1) i = rowval[k] u[i] -= xdiag[i] * nzval[k] * u[j] end end end + return end -function LinearAlgebra.ldiv!(precon::_ParallelILU0Preconditioner{Tv,Ti}, - v::AbstractVector) where {Tv,Ti} - ldiv!(v, precon, v) +function LinearAlgebra.ldiv!( + precon::_ParallelILU0Preconditioner{Tv, Ti}, + v::AbstractVector + ) where {Tv, Ti} + return ldiv!(v, precon, v) end # Returns an independent set of the graph of a matrix # Reference: https://research.nvidia.com/sites/default/files/pubs/2015-05_Parallel-Graph-Coloring/nvr-2015-001.pdf -function indset(A::SparseMatrixCSC{Tv,Ti}, W::StridedVector) where {Tv, Ti} +function indset(A::SparseMatrixCSC{Tv, Ti}, W::StridedVector) where {Tv, Ti} # Random numbers for all vertices lenW = length(W) # r = sample(1:lenW, lenW, replace = false) r = rand(lenW) - @inbounds for i = 1:lenW + @inbounds for i in 1:lenW if W[i] == 0 r[i] = 0 end end # Empty independent set S = zeros(Int, lenW) - # Get independent set by comparing random number of vertex with the random + # Get independent set by comparing random number of vertex with the random # numbers of all neighbor vertices - @inbounds Threads.@threads for i = 1:lenW + @inbounds Threads.@threads for i in 1:lenW if W[i] != 0 j = A.rowval[A.colptr[i]:(A.colptr[i + 1] - 1)] if all(x -> x == 1, r[i] .>= r[j]) @@ -118,7 +123,7 @@ end # Returns coloring of the graph of a matrix # Reference: https://research.nvidia.com/sites/default/files/pubs/2015-05_Parallel-Graph-Coloring/nvr-2015-001.pdf -function graphcol(A::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} +function graphcol(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} # Empty list for coloring C = Vector{Ti}[] # Array of vertices @@ -138,37 +143,41 @@ function graphcol(A::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} end # Reorders a sparse matrix with provided coloring -function reordermatrix(A::SparseMatrixCSC{Tv, Ti}, - coloring) where {Tv, Ti} +function reordermatrix( + A::SparseMatrixCSC{Tv, Ti}, + coloring + ) where {Tv, Ti} c = collect(Iterators.flatten(coloring)) return A[c, :][:, c] end # Reorders a linear system with provided coloring -function reorderlinsys(A::SparseMatrixCSC{Tv, Ti}, - b::Vector{Tv} , - coloring) where {Tv, Ti} +function reorderlinsys( + A::SparseMatrixCSC{Tv, Ti}, + b::Vector{Tv}, + coloring + ) where {Tv, Ti} c = collect(Iterators.flatten(coloring)) return A[c, :][:, c], b[c] end -# Returns an array with the same structure of the input coloring and ordered -# entries 1:length(coloring) and an array with the structure of -# reverse(coloring) and ordered entries length(coloring):-1:1 +# Returns an array with the same structure of the input coloring and ordered +# entries 1:length(coloring) and an array with the structure of +# reverse(coloring) and ordered entries length(coloring):-1:1 function coloringindex(coloring) # First array c = deepcopy(coloring) cnt = 1 - @inbounds for i = 1:length(c) - @inbounds for j = 1:length(c[i]) + @inbounds for i in 1:length(c) + @inbounds for j in 1:length(c[i]) c[i][j] = cnt cnt += 1 end end # Second array cc = deepcopy(reverse(coloring)) - @inbounds for i = 1:length(cc) - @inbounds for j = 1:length(cc[i]) + @inbounds for i in 1:length(cc) + @inbounds for j in 1:length(cc[i]) cnt -= 1 cc[i][j] = cnt end @@ -178,18 +187,16 @@ function coloringindex(coloring) end - - ################################################################# mutable struct ParallelILU0Preconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix phash::UInt64 - factorization:: _ParallelILU0Preconditioner + factorization::_ParallelILU0Preconditioner function ParallelILU0Preconditioner() p = new() p.phash = 0 - p + return p end end @@ -206,12 +213,12 @@ function ParallelILU0Preconditioner end function update!(p::ParallelILU0Preconditioner) flush!(p.A) - Tv=eltype(p.A) - if p.A.phash!=p.phash - p.factorization=pilu0(p.A.cscmatrix) - p.phash=p.A.phash + Tv = eltype(p.A) + if p.A.phash != p.phash + p.factorization = pilu0(p.A.cscmatrix) + p.phash = p.A.phash else - pilu0!(p.factorization,p.A.cscmatrix) + pilu0!(p.factorization, p.A.cscmatrix) end - p + return p end diff --git a/src/factorizations/parallel_jacobi.jl b/src/factorizations/parallel_jacobi.jl index ad03ef2..68f444a 100644 --- a/src/factorizations/parallel_jacobi.jl +++ b/src/factorizations/parallel_jacobi.jl @@ -2,43 +2,44 @@ mutable struct _ParallelJacobiPreconditioner{Tv} invdiag::Vector{Tv} end -function pjacobi(A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} +function pjacobi(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} invdiag = Array{Tv, 1}(undef, A.n) n = A.n - Threads.@threads for i = 1:n + Threads.@threads for i in 1:n invdiag[i] = one(Tv) / A[i, i] end - _ParallelJacobiPreconditioner(invdiag) + return _ParallelJacobiPreconditioner(invdiag) end -function pjacobi!(p::_ParallelJacobiPreconditioner{Tv},A::SparseMatrixCSC{Tv,Ti})where {Tv,Ti} +function pjacobi!(p::_ParallelJacobiPreconditioner{Tv}, A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} n = A.n - Threads.@threads for i = 1:n + Threads.@threads for i in 1:n p.invdiag[i] = one(Tv) / A[i, i] end - p + return p end -function LinearAlgebra.ldiv!(u,p::_ParallelJacobiPreconditioner,v) - n=length(p.invdiag) - for i = 1:n +function LinearAlgebra.ldiv!(u, p::_ParallelJacobiPreconditioner, v) + n = length(p.invdiag) + for i in 1:n @inbounds u[i] = p.invdiag[i] * v[i] end + return end -LinearAlgebra.ldiv!(p::_ParallelJacobiPreconditioner,v)=ldiv!(v,p,v) +LinearAlgebra.ldiv!(p::_ParallelJacobiPreconditioner, v) = ldiv!(v, p, v) mutable struct ParallelJacobiPreconditioner <: AbstractPreconditioner A::ExtendableSparseMatrix - factorization::Union{_ParallelJacobiPreconditioner,Nothing} + factorization::Union{_ParallelJacobiPreconditioner, Nothing} phash::UInt64 function ParallelJacobiPreconditioner() p = new() p.factorization = nothing - p.phash=0 - p + p.phash = 0 + return p end end @@ -54,15 +55,15 @@ function ParallelJacobiPreconditioner end function update!(p::ParallelJacobiPreconditioner) flush!(p.A) - Tv=eltype(p.A) - if p.A.phash!=p.phash || isnothing(p.factorization) - p.factorization=pjacobi(p.A.cscmatrix) - p.phash=p.A.phash + Tv = eltype(p.A) + if p.A.phash != p.phash || isnothing(p.factorization) + p.factorization = pjacobi(p.A.cscmatrix) + p.phash = p.A.phash else - pjacobi!(p.factorization,p.A.cscmatrix) + pjacobi!(p.factorization, p.A.cscmatrix) end - p + return p end -allow_views(::ParallelJacobiPreconditioner)=true -allow_views(::Type{ParallelJacobiPreconditioner})=true +allow_views(::ParallelJacobiPreconditioner) = true +allow_views(::Type{ParallelJacobiPreconditioner}) = true diff --git a/src/factorizations/simple_iteration.jl b/src/factorizations/simple_iteration.jl index 36f3cc3..1516012 100644 --- a/src/factorizations/simple_iteration.jl +++ b/src/factorizations/simple_iteration.jl @@ -12,25 +12,27 @@ simple!(u,A,b; Simple iteration scheme ``u_{i+1}= u_i - P^{-1} (A u_i -b)`` with similar API as the methods in IterativeSolvers.jl. """ -function simple!(u, - A, - b; - abstol::Real = zero(real(eltype(b))), - reltol::Real = sqrt(eps(real(eltype(b)))), - log = false, - maxiter = 100, - Pl = nothing) +function simple!( + u, + A, + b; + abstol::Real = zero(real(eltype(b))), + reltol::Real = sqrt(eps(real(eltype(b)))), + log = false, + maxiter = 100, + Pl = nothing + ) res = A * u - b # initial residual upd = similar(res) r0 = norm(res) # residual norm history = [r0] # initialize history recording - for i = 1:maxiter + for i in 1:maxiter ldiv!(upd, Pl, res) u .-= upd # solve preconditioning system and update solution mul!(res, A, u) # calculate residual res .-= b r = norm(res) # residual norm - push!(history, r) # record in history + push!(history, r) # record in history if (r / r0) < reltol || r < abstol # check for tolerance break end diff --git a/src/factorizations/sparspak.jl b/src/factorizations/sparspak.jl index 5dfc4a1..6f99bda 100644 --- a/src/factorizations/sparspak.jl +++ b/src/factorizations/sparspak.jl @@ -1,4 +1,3 @@ - mutable struct SparspakLU <: AbstractLUFactorization A::Union{ExtendableSparseMatrix, Nothing} factorization::Union{Sparspak.SparseSolver.SparseSolver, Nothing} @@ -6,7 +5,7 @@ mutable struct SparspakLU <: AbstractLUFactorization end function SparspakLU() - fact = SparspakLU(nothing, nothing, 0) + return fact = SparspakLU(nothing, nothing, 0) end """ @@ -21,7 +20,7 @@ function SparspakLU end function update!(lufact::SparspakLU) flush!(lufact.A) - if lufact.A.phash != lufact.phash + return if lufact.A.phash != lufact.phash lufact.factorization = sparspaklu(lufact.A.cscmatrix) else sparspaklu!(lufact.factorization, lufact.A.cscmatrix) diff --git a/src/factorizations/umfpack_lu.jl b/src/factorizations/umfpack_lu.jl index 31dae29..3e0bc18 100644 --- a/src/factorizations/umfpack_lu.jl +++ b/src/factorizations/umfpack_lu.jl @@ -4,7 +4,7 @@ mutable struct LUFactorization <: AbstractLUFactorization phash::UInt64 end -LUFactorization() = LUFactorization(nothing,nothing,0) +LUFactorization() = LUFactorization(nothing, nothing, 0) """ ``` LUFactorization() @@ -23,5 +23,5 @@ function update!(lufact::LUFactorization) else lufact.factorization = lu!(lufact.factorization, lufact.A.cscmatrix) end - lufact + return lufact end diff --git a/src/matrix/abstractextendablesparsematrixcsc.jl b/src/matrix/abstractextendablesparsematrixcsc.jl index 491ebfb..c88770b 100644 --- a/src/matrix/abstractextendablesparsematrixcsc.jl +++ b/src/matrix/abstractextendablesparsematrixcsc.jl @@ -7,24 +7,23 @@ rawupdateindex! reset!: empty all internals, just keep size """ -abstract type AbstractExtendableSparseMatrixCSC{Tv,Ti} <: AbstractSparseMatrixCSC{Tv,Ti} end +abstract type AbstractExtendableSparseMatrixCSC{Tv, Ti} <: AbstractSparseMatrixCSC{Tv, Ti} end """ $(SIGNATURES) [`flush!`](@ref) and return number of nonzeros in ext.cscmatrix. """ -SparseArrays.nnz(ext::AbstractExtendableSparseMatrixCSC)=nnz(sparse(ext)) +SparseArrays.nnz(ext::AbstractExtendableSparseMatrixCSC) = nnz(sparse(ext)) """ $(SIGNATURES) [`flush!`](@ref) and return nonzeros in ext.cscmatrix. """ -SparseArrays.nonzeros(ext::AbstractExtendableSparseMatrixCSC)=nonzeros(sparse(ext)) - -Base.size(ext::AbstractExtendableSparseMatrixCSC)=size(ext.cscmatrix) +SparseArrays.nonzeros(ext::AbstractExtendableSparseMatrixCSC) = nonzeros(sparse(ext)) +Base.size(ext::AbstractExtendableSparseMatrixCSC) = size(ext.cscmatrix) """ @@ -35,37 +34,36 @@ Return element type. Base.eltype(::AbstractExtendableSparseMatrixCSC{Tv, Ti}) where {Tv, Ti} = Tv - """ $(SIGNATURES) Create SparseMatrixCSC from ExtendableSparseMatrix """ -SparseArrays.SparseMatrixCSC(A::AbstractExtendableSparseMatrixCSC)=sparse(A) - - +SparseArrays.SparseMatrixCSC(A::AbstractExtendableSparseMatrixCSC) = sparse(A) function Base.show(io::IO, ::MIME"text/plain", ext::AbstractExtendableSparseMatrixCSC) - A=sparse(ext) + A = sparse(ext) xnnz = nnz(A) m, n = size(A) - print(io, - m, - "×", - n, - " ", - typeof(ext), - " with ", - xnnz, - " stored ", - xnnz == 1 ? "entry" : "entries") + print( + io, + m, + "×", + n, + " ", + typeof(ext), + " with ", + xnnz, + " stored ", + xnnz == 1 ? "entry" : "entries" + ) if !haskey(io, :compact) io = IOContext(io, :compact => true) end - if !(m == 0 || n == 0 || xnnz == 0) + return if !(m == 0 || n == 0 || xnnz == 0) print(io, ":\n") Base.print_array(IOContext(io), A) end @@ -77,7 +75,7 @@ $(SIGNATURES) [`flush!`](@ref) and return rowvals in ext.cscmatrix. """ -SparseArrays.rowvals(ext::AbstractExtendableSparseMatrixCSC)=rowvals(sparse(ext)) +SparseArrays.rowvals(ext::AbstractExtendableSparseMatrixCSC) = rowvals(sparse(ext)) """ @@ -85,19 +83,19 @@ $(SIGNATURES) [`flush!`](@ref) and return colptr of in ext.cscmatrix. """ -SparseArrays.getcolptr(ext::AbstractExtendableSparseMatrixCSC)=getcolptr(sparse(ext)) +SparseArrays.getcolptr(ext::AbstractExtendableSparseMatrixCSC) = getcolptr(sparse(ext)) + - """ $(SIGNATURES) [`flush!`](@ref) and return findnz(ext.cscmatrix). """ -SparseArrays.findnz(ext::AbstractExtendableSparseMatrixCSC)=findnz(sparse(ext)) +SparseArrays.findnz(ext::AbstractExtendableSparseMatrixCSC) = findnz(sparse(ext)) @static if VERSION >= v"1.7" - SparseArrays._checkbuffers(ext::AbstractExtendableSparseMatrixCSC)= SparseArrays._checkbuffers(sparse(ext)) + SparseArrays._checkbuffers(ext::AbstractExtendableSparseMatrixCSC) = SparseArrays._checkbuffers(sparse(ext)) end """ @@ -107,9 +105,11 @@ end are allowed in the Julia sysimage and the floating point type of the matrix is Float64 or Complex64. In that case, Julias standard `\` is called, which is realized via UMFPACK. """ -function LinearAlgebra.:\(ext::AbstractExtendableSparseMatrixCSC{Tv, Ti}, - b::AbstractVector) where {Tv, Ti} - SparspakLU(sparse(ext)) \ b +function LinearAlgebra.:\( + ext::AbstractExtendableSparseMatrixCSC{Tv, Ti}, + b::AbstractVector + ) where {Tv, Ti} + return SparspakLU(sparse(ext)) \ b end @@ -118,9 +118,11 @@ $(SIGNATURES) [`\\`](@ref) for Symmetric{ExtendableSparse} """ -function LinearAlgebra.:\(symm_ext::Symmetric{Tm, T}, - b::AbstractVector) where {Tm, Ti, T<:AbstractExtendableSparseMatrixCSC{Tm,Ti}} - Symmetric(sparse(symm_ext.data),Symbol(symm_ext.uplo)) \ b # no ldlt yet ... +function LinearAlgebra.:\( + symm_ext::Symmetric{Tm, T}, + b::AbstractVector + ) where {Tm, Ti, T <: AbstractExtendableSparseMatrixCSC{Tm, Ti}} + return Symmetric(sparse(symm_ext.data), Symbol(symm_ext.uplo)) \ b # no ldlt yet ... end """ @@ -128,37 +130,55 @@ $(SIGNATURES) [`\\`](@ref) for Hermitian{ExtendableSparse} """ -function LinearAlgebra.:\(symm_ext::Hermitian{Tm, T}, - b::AbstractVector) where {Tm, Ti, T<:AbstractExtendableSparseMatrixCSC{Tm,Ti}} - Hermitian(sparse(symm_ext.data),Symbol(symm_ext.uplo)) \ b # no ldlt yet ... +function LinearAlgebra.:\( + symm_ext::Hermitian{Tm, T}, + b::AbstractVector + ) where {Tm, Ti, T <: AbstractExtendableSparseMatrixCSC{Tm, Ti}} + return Hermitian(sparse(symm_ext.data), Symbol(symm_ext.uplo)) \ b # no ldlt yet ... end if USE_GPL_LIBS for (Tv) in (:Float64, :ComplexF64) - @eval begin function LinearAlgebra.:\(ext::AbstractExtendableSparseMatrixCSC{$Tv, Ti}, - B::AbstractVector) where {Ti} - sparse(ext) \ B - end end - - @eval begin function LinearAlgebra.:\(symm_ext::Symmetric{$Tv, - AbstractExtendableSparseMatrixCSC{ - $Tv, - Ti - }}, - B::AbstractVector) where {Ti} - symm_csc = Symmetric(sparse(symm_ext.data), Symbol(symm_ext.uplo)) - symm_csc \ B - end end - - @eval begin function LinearAlgebra.:\(symm_ext::Hermitian{$Tv, - AbstractExtendableSparseMatrixCSC{ - $Tv, - Ti - }}, - B::AbstractVector) where {Ti} - symm_csc = Hermitian(sparse(symm_ext.data), Symbol(symm_ext.uplo)) - symm_csc \ B - end end + @eval begin + function LinearAlgebra.:\( + ext::AbstractExtendableSparseMatrixCSC{$Tv, Ti}, + B::AbstractVector + ) where {Ti} + return sparse(ext) \ B + end + end + + @eval begin + function LinearAlgebra.:\( + symm_ext::Symmetric{ + $Tv, + AbstractExtendableSparseMatrixCSC{ + $Tv, + Ti, + }, + }, + B::AbstractVector + ) where {Ti} + symm_csc = Symmetric(sparse(symm_ext.data), Symbol(symm_ext.uplo)) + return symm_csc \ B + end + end + + @eval begin + function LinearAlgebra.:\( + symm_ext::Hermitian{ + $Tv, + AbstractExtendableSparseMatrixCSC{ + $Tv, + Ti, + }, + }, + B::AbstractVector + ) where {Ti} + symm_csc = Hermitian(sparse(symm_ext.data), Symbol(symm_ext.uplo)) + return symm_csc \ B + end + end end end # USE_GPL_LIBS @@ -168,7 +188,7 @@ $(SIGNATURES) [`flush!`](@ref) and ldiv with ext.cscmatrix """ function LinearAlgebra.ldiv!(r, ext::AbstractExtendableSparseMatrixCSC, x) - LinearAlgebra.ldiv!(r, sparse(ext), x) + return LinearAlgebra.ldiv!(r, sparse(ext), x) end """ @@ -177,7 +197,7 @@ $(SIGNATURES) [`flush!`](@ref) and multiply with ext.cscmatrix """ function LinearAlgebra.mul!(r, ext::AbstractExtendableSparseMatrixCSC, x) - LinearAlgebra.mul!(r, sparse(ext), x) + return LinearAlgebra.mul!(r, sparse(ext), x) end """ @@ -215,35 +235,31 @@ $(SIGNATURES) function LinearAlgebra.issymmetric(A::AbstractExtendableSparseMatrixCSC) return LinearAlgebra.issymmetric(sparse(A)) end - - - - -function Base.:+(A::T, B::T) where T<:AbstractExtendableSparseMatrixCSC - T(sparse(A) + sparse(B)) +function Base.:+(A::T, B::T) where {T <: AbstractExtendableSparseMatrixCSC} + return T(sparse(A) + sparse(B)) end -function Base.:-(A::T, B::T) where T<:AbstractExtendableSparseMatrixCSC - T(sparse(A) - sparse(B)) +function Base.:-(A::T, B::T) where {T <: AbstractExtendableSparseMatrixCSC} + return T(sparse(A) - sparse(B)) end -function Base.:*(A::T, B::T) where T<:AbstractExtendableSparseMatrixCSC - T(sparse(A) * sparse(B)) +function Base.:*(A::T, B::T) where {T <: AbstractExtendableSparseMatrixCSC} + return T(sparse(A) * sparse(B)) end """ $(SIGNATURES) """ -function Base.:*(d::Diagonal, ext::T)where T<:AbstractExtendableSparseMatrixCSC +function Base.:*(d::Diagonal, ext::T) where {T <: AbstractExtendableSparseMatrixCSC} return T(d * sparse(ext)) end """ $(SIGNATURES) """ -function Base.:*(ext::T, d::Diagonal) where T<:AbstractExtendableSparseMatrixCSC +function Base.:*(ext::T, d::Diagonal) where {T <: AbstractExtendableSparseMatrixCSC} return T(sparse(ext) * d) end @@ -280,20 +296,19 @@ end $(SIGNATURES) """ function SparseArrays.dropzeros!(ext::AbstractExtendableSparseMatrixCSC) - dropzeros!(sparse(ext)) + return dropzeros!(sparse(ext)) end - -function mark_dirichlet(A::AbstractExtendableSparseMatrixCSC;penalty=1.0e20) - mark_dirichlet(sparse(A);penalty) +function mark_dirichlet(A::AbstractExtendableSparseMatrixCSC; penalty = 1.0e20) + return mark_dirichlet(sparse(A); penalty) end -function eliminate_dirichlet(A::T,dirichlet) where T<:AbstractExtendableSparseMatrixCSC - T(eliminate_dirichlet(sparse(A),dirichlet)) +function eliminate_dirichlet(A::T, dirichlet) where {T <: AbstractExtendableSparseMatrixCSC} + return T(eliminate_dirichlet(sparse(A), dirichlet)) end -function eliminate_dirichlet!(A::AbstractExtendableSparseMatrixCSC,dirichlet) - eliminate_dirichlet!(sparse(A),dirichlet) - A +function eliminate_dirichlet!(A::AbstractExtendableSparseMatrixCSC, dirichlet) + eliminate_dirichlet!(sparse(A), dirichlet) + return A end diff --git a/src/matrix/abstractsparsematrixextension.jl b/src/matrix/abstractsparsematrixextension.jl index c206483..ca3b972 100644 --- a/src/matrix/abstractsparsematrixextension.jl +++ b/src/matrix/abstractsparsematrixextension.jl @@ -14,6 +14,6 @@ Subtypes T_ext must implement: task or partition id """ -abstract type AbstractSparseMatrixExtension{Tv, Ti} <: AbstractSparseMatrix{Tv,Ti} end +abstract type AbstractSparseMatrixExtension{Tv, Ti} <: AbstractSparseMatrix{Tv, Ti} end -Base.:+(ext::AbstractSparseMatrixExtension, csx) = sum([ext],csx) +Base.:+(ext::AbstractSparseMatrixExtension, csx) = sum([ext], csx) diff --git a/src/matrix/extendable.jl b/src/matrix/extendable.jl index e38ef9a..e1d3f5e 100644 --- a/src/matrix/extendable.jl +++ b/src/matrix/extendable.jl @@ -17,7 +17,7 @@ mutable struct ExtendableSparseMatrixCSC{Tv, Ti <: Integer} <: AbstractExtendabl Linked list structure holding data of extension """ lnkmatrix::Union{SparseMatrixLNK{Tv, Ti}, Nothing} - + """ Pattern hash """ @@ -37,18 +37,20 @@ Create empty ExtendableSparseMatrixCSC. This is equivalent to `spzeros(m,n)` for """ function ExtendableSparseMatrixCSC{Tv, Ti}(m, n) where {Tv, Ti <: Integer} - ExtendableSparseMatrixCSC{Tv, Ti}(spzeros(Tv, Ti, m, n), nothing, 0) + return ExtendableSparseMatrixCSC{Tv, Ti}(spzeros(Tv, Ti, m, n), nothing, 0) end -function ExtendableSparseMatrixCSC(valuetype::Type{Tv}, - indextype::Type{Ti}, - m, - n) where {Tv, Ti <: Integer} - ExtendableSparseMatrixCSC{Tv, Ti}(m, n) +function ExtendableSparseMatrixCSC( + valuetype::Type{Tv}, + indextype::Type{Ti}, + m, + n + ) where {Tv, Ti <: Integer} + return ExtendableSparseMatrixCSC{Tv, Ti}(m, n) end function ExtendableSparseMatrixCSC(valuetype::Type{Tv}, m, n) where {Tv} - ExtendableSparseMatrixCSC{Tv, Int}(m, n) + return ExtendableSparseMatrixCSC{Tv, Int}(m, n) end ExtendableSparseMatrixCSC(m, n) = ExtendableSparseMatrixCSC{Float64, Int}(m, n) @@ -59,11 +61,11 @@ $(SIGNATURES) Create ExtendableSparseMatrixCSC from SparseMatrixCSC """ function ExtendableSparseMatrixCSC(csc::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: Integer} - ExtendableSparseMatrixCSC{Tv, Ti}(csc, nothing, phash(csc)) + return ExtendableSparseMatrixCSC{Tv, Ti}(csc, nothing, phash(csc)) end -function ExtendableSparseMatrixCSC{Tv,Ti}(csc::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: Integer} - ExtendableSparseMatrixCSC{Tv, Ti}(csc, nothing, phash(csc)) +function ExtendableSparseMatrixCSC{Tv, Ti}(csc::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: Integer} + return ExtendableSparseMatrixCSC{Tv, Ti}(csc, nothing, phash(csc)) end """ @@ -92,15 +94,15 @@ Create ExtendableSparseMatrixCSC from triplet (COO) data. ExtendableSparseMatrixCSC(I, J, V::AbstractVector) = ExtendableSparseMatrixCSC(sparse(I, J, V)) function ExtendableSparseMatrixCSC(I, J, V::AbstractVector, m, n) - ExtendableSparseMatrixCSC(sparse(I, J, V, m, n)) + return ExtendableSparseMatrixCSC(sparse(I, J, V, m, n)) end function ExtendableSparseMatrixCSC(I, J, V::AbstractVector, combine::Function) - ExtendableSparseMatrixCSC(sparse(I, J, V, combine)) + return ExtendableSparseMatrixCSC(sparse(I, J, V, combine)) end function ExtendableSparseMatrixCSC(I, J, V::AbstractVector, m, n, combine::Function) - ExtendableSparseMatrixCSC(sparse(I, J, V, m, n, combine)) + return ExtendableSparseMatrixCSC(sparse(I, J, V, m, n, combine)) end # THese are probably too much... @@ -117,18 +119,17 @@ end # end - """ $(SIGNATURES) Create similar but empty extendableSparseMatrix """ function Base.similar(m::ExtendableSparseMatrixCSC{Tv, Ti}) where {Tv, Ti} - ExtendableSparseMatrixCSC{Tv, Ti}(size(m)...) + return ExtendableSparseMatrixCSC{Tv, Ti}(size(m)...) end function Base.similar(m::ExtendableSparseMatrixCSC{Tv, Ti}, ::Type{T}) where {Tv, Ti, T} - ExtendableSparseMatrixCSC{T, Ti}(size(m)...) + return ExtendableSparseMatrixCSC{T, Ti}(size(m)...) end """ @@ -156,11 +157,13 @@ A If `v` is zero, no new entry is created. """ -function updateindex!(ext::ExtendableSparseMatrixCSC{Tv, Ti}, - op, - v, - i, - j) where {Tv, Ti <: Integer} +function updateindex!( + ext::ExtendableSparseMatrixCSC{Tv, Ti}, + op, + v, + i, + j + ) where {Tv, Ti <: Integer} k = findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) @@ -170,7 +173,7 @@ function updateindex!(ext::ExtendableSparseMatrixCSC{Tv, Ti}, end updateindex!(ext.lnkmatrix, op, v, i, j) end - ext + return ext end """ @@ -178,22 +181,24 @@ $(SIGNATURES) Like [`updateindex!`](@ref) but without checking if v is zero. """ -function rawupdateindex!(ext::ExtendableSparseMatrixCSC{Tv, Ti}, - op, - v, - i, - j, - part=1) where {Tv, Ti <: Integer} +function rawupdateindex!( + ext::ExtendableSparseMatrixCSC{Tv, Ti}, + op, + v, + i, + j, + part = 1 + ) where {Tv, Ti <: Integer} k = findindex(ext.cscmatrix, i, j) if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else - if ext.lnkmatrix == nothing - ext.lnkmatrix = SparseMatrixLNK{Tv, Ti}(ext.cscmatrix.m, ext.cscmatrix.n) - end - rawupdateindex!(ext.lnkmatrix, op, v, i, j) + if ext.lnkmatrix == nothing + ext.lnkmatrix = SparseMatrixLNK{Tv, Ti}(ext.cscmatrix.m, ext.cscmatrix.n) + end + rawupdateindex!(ext.lnkmatrix, op, v, i, j) end - ext + return ext end """ @@ -202,12 +207,14 @@ $(SIGNATURES) Find index in CSC matrix and set value if it exists. Otherwise, set index in extension if `v` is nonzero. """ -function Base.setindex!(ext::ExtendableSparseMatrixCSC{Tv, Ti}, - v::Union{Number,AbstractVecOrMat}, - i::Integer, - j::Integer) where {Tv, Ti} +function Base.setindex!( + ext::ExtendableSparseMatrixCSC{Tv, Ti}, + v::Union{Number, AbstractVecOrMat}, + i::Integer, + j::Integer + ) where {Tv, Ti} k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = v else if ext.lnkmatrix == nothing @@ -223,22 +230,23 @@ $(SIGNATURES) Find index in CSC matrix and return value, if it exists. Otherwise, return value from extension. """ -function Base.getindex(ext::ExtendableSparseMatrixCSC{Tv, Ti}, - i::Integer, - j::Integer) where {Tv, Ti <: Integer} +function Base.getindex( + ext::ExtendableSparseMatrixCSC{Tv, Ti}, + i::Integer, + j::Integer + ) where {Tv, Ti <: Integer} k = findindex(ext.cscmatrix, i, j) if k > 0 return ext.cscmatrix.nzval[k] elseif ext.lnkmatrix == nothing return zero(Tv) else - v=zero(Tv) - v=ext.lnkmatrix[i, j] + v = zero(Tv) + v = ext.lnkmatrix[i, j] end end - """ $(SIGNATURES) @@ -257,7 +265,7 @@ end function SparseArrays.sparse(ext::ExtendableSparseMatrixCSC) flush!(ext) - ext.cscmatrix + return ext.cscmatrix end @@ -267,18 +275,17 @@ $(SIGNATURES) Reset ExtenableSparseMatrix into state similar to that after creation. """ function reset!(A::ExtendableSparseMatrixCSC) - A.cscmatrix=spzeros(size(A)...) - A.lnkmatrix=nothing + A.cscmatrix = spzeros(size(A)...) + return A.lnkmatrix = nothing end - """ $(SIGNATURES) """ function Base.copy(S::ExtendableSparseMatrixCSC) - if isnothing(S.lnkmatrix) - ExtendableSparseMatrixCSC(copy(S.cscmatrix), nothing,S.phash) + return if isnothing(S.lnkmatrix) + ExtendableSparseMatrixCSC(copy(S.cscmatrix), nothing, S.phash) else ExtendableSparseMatrixCSC(copy(S.cscmatrix), copy(S.lnkmatrix), S.phash) end @@ -289,30 +296,30 @@ end Create a pointblock matrix. """ -function pointblock(A0::ExtendableSparseMatrixCSC{Tv,Ti},blocksize) where {Tv,Ti} - A=SparseMatrixCSC(A0) - colptr=A.colptr - rowval=A.rowval - nzval=A.nzval - n=A.n - block=zeros(Tv,blocksize,blocksize) - nblock=n÷blocksize - b=SMatrix{blocksize,blocksize}(block) - Tb=typeof(b) - Ab=ExtendableSparseMatrixCSC{Tb,Ti}(nblock,nblock) - - - for i=1:n - for k=colptr[i]:colptr[i+1]-1 - j=rowval[k] - iblock=(i-1)÷blocksize+1 - jblock=(j-1)÷blocksize+1 - ii=(i-1)%blocksize+1 - jj=(j-1)%blocksize+1 - block[ii,jj]=nzval[k] - rawupdateindex!(Ab,+,SMatrix{blocksize,blocksize}(block),iblock,jblock) - block[ii,jj]=zero(Tv) - end +function pointblock(A0::ExtendableSparseMatrixCSC{Tv, Ti}, blocksize) where {Tv, Ti} + A = SparseMatrixCSC(A0) + colptr = A.colptr + rowval = A.rowval + nzval = A.nzval + n = A.n + block = zeros(Tv, blocksize, blocksize) + nblock = n ÷ blocksize + b = SMatrix{blocksize, blocksize}(block) + Tb = typeof(b) + Ab = ExtendableSparseMatrixCSC{Tb, Ti}(nblock, nblock) + + + for i in 1:n + for k in colptr[i]:(colptr[i + 1] - 1) + j = rowval[k] + iblock = (i - 1) ÷ blocksize + 1 + jblock = (j - 1) ÷ blocksize + 1 + ii = (i - 1) % blocksize + 1 + jj = (j - 1) % blocksize + 1 + block[ii, jj] = nzval[k] + rawupdateindex!(Ab, +, SMatrix{blocksize, blocksize}(block), iblock, jblock) + block[ii, jj] = zero(Tv) + end end - flush!(Ab) + return flush!(Ab) end diff --git a/src/matrix/genericextendablesparsematrixcsc.jl b/src/matrix/genericextendablesparsematrixcsc.jl index fe1465f..0c0f649 100644 --- a/src/matrix/genericextendablesparsematrixcsc.jl +++ b/src/matrix/genericextendablesparsematrixcsc.jl @@ -1,9 +1,9 @@ -mutable struct GenericExtendableSparseMatrixCSC{Tm<:AbstractSparseMatrixExtension, Tv, Ti <: Integer} <: AbstractExtendableSparseMatrixCSC{Tv, Ti} +mutable struct GenericExtendableSparseMatrixCSC{Tm <: AbstractSparseMatrixExtension, Tv, Ti <: Integer} <: AbstractExtendableSparseMatrixCSC{Tv, Ti} """ Final matrix data """ cscmatrix::SparseMatrixCSC{Tv, Ti} - + """ Matrix for new entries """ @@ -11,82 +11,91 @@ mutable struct GenericExtendableSparseMatrixCSC{Tm<:AbstractSparseMatrixExtensio end -function GenericExtendableSparseMatrixCSC{Tm, Tv, Ti}(m::Integer,n::Integer) where{Tm<:AbstractSparseMatrixExtension, Tv, Ti<:Integer} - GenericExtendableSparseMatrixCSC(spzeros(Tv, Ti, m, n), - Tm(m,n) - ) +function GenericExtendableSparseMatrixCSC{Tm, Tv, Ti}(m::Integer, n::Integer) where {Tm <: AbstractSparseMatrixExtension, Tv, Ti <: Integer} + return GenericExtendableSparseMatrixCSC( + spzeros(Tv, Ti, m, n), + Tm(m, n) + ) end -nnznew(ext::GenericExtendableSparseMatrixCSC)=nnz(ext.xmatrix) +nnznew(ext::GenericExtendableSparseMatrixCSC) = nnz(ext.xmatrix) -function reset!(ext::GenericExtendableSparseMatrixCSC{Tm,Tv,Ti}) where {Tm,Tv,Ti} - m,n=size(ext.cscmatrix) - ext.cscmatrix=spzeros(Tv, Ti, m, n) - ext.xmatrix=Tm(m,n) - ext +function reset!(ext::GenericExtendableSparseMatrixCSC{Tm, Tv, Ti}) where {Tm, Tv, Ti} + m, n = size(ext.cscmatrix) + ext.cscmatrix = spzeros(Tv, Ti, m, n) + ext.xmatrix = Tm(m, n) + return ext end -function flush!(ext::GenericExtendableSparseMatrixCSC{Tm,Tv,Ti}) where{Tm,Tv,Ti} - if nnz(ext.xmatrix)>0 - ext.cscmatrix=ext.xmatrix+ext.cscmatrix - ext.xmatrix=Tm(size(ext.cscmatrix)...) +function flush!(ext::GenericExtendableSparseMatrixCSC{Tm, Tv, Ti}) where {Tm, Tv, Ti} + if nnz(ext.xmatrix) > 0 + ext.cscmatrix = ext.xmatrix + ext.cscmatrix + ext.xmatrix = Tm(size(ext.cscmatrix)...) end - ext + return ext end - + function SparseArrays.sparse(ext::GenericExtendableSparseMatrixCSC) flush!(ext) - ext.cscmatrix + return ext.cscmatrix end -function Base.setindex!(ext::GenericExtendableSparseMatrixCSC, - v::Union{Number,AbstractVecOrMat}, - i::Integer, - j::Integer) +function Base.setindex!( + ext::GenericExtendableSparseMatrixCSC, + v::Union{Number, AbstractVecOrMat}, + i::Integer, + j::Integer + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = v else - setindex!(ext.xmatrix,v,i,j) + setindex!(ext.xmatrix, v, i, j) end end -function Base.getindex(ext::GenericExtendableSparseMatrixCSC, - i::Integer, - j::Integer) +function Base.getindex( + ext::GenericExtendableSparseMatrixCSC, + i::Integer, + j::Integer + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] else - getindex(ext.xmatrix,i,j) + getindex(ext.xmatrix, i, j) end end -function rawupdateindex!(ext::GenericExtendableSparseMatrixCSC, - op, - v, - i, - j) +function rawupdateindex!( + ext::GenericExtendableSparseMatrixCSC, + op, + v, + i, + j + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else - rawupdateindex!(ext.xmatrix,op,v,i,j) + rawupdateindex!(ext.xmatrix, op, v, i, j) end end -function updateindex!(ext::GenericExtendableSparseMatrixCSC, - op, - v, - i, - j) +function updateindex!( + ext::GenericExtendableSparseMatrixCSC, + op, + v, + i, + j + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else - updateindex!(ext.xmatrix,op,v,i,j) + updateindex!(ext.xmatrix, op, v, i, j) end end diff --git a/src/matrix/genericmtextendablesparsematrixcsc.jl b/src/matrix/genericmtextendablesparsematrixcsc.jl index 25e76d2..c2a39de 100644 --- a/src/matrix/genericmtextendablesparsematrixcsc.jl +++ b/src/matrix/genericmtextendablesparsematrixcsc.jl @@ -1,4 +1,4 @@ -mutable struct GenericMTExtendableSparseMatrixCSC{Tm<:AbstractSparseMatrixExtension, Tv, Ti <: Integer} <: AbstractExtendableSparseMatrixCSC{Tv, Ti} +mutable struct GenericMTExtendableSparseMatrixCSC{Tm <: AbstractSparseMatrixExtension, Tv, Ti <: Integer} <: AbstractExtendableSparseMatrixCSC{Tv, Ti} """ Final matrix data """ @@ -13,131 +13,138 @@ mutable struct GenericMTExtendableSparseMatrixCSC{Tm<:AbstractSparseMatrixExtens partnodes::Vector{Ti} end -function GenericMTExtendableSparseMatrixCSC{Tm, Tv, Ti}(n,m,p::Integer=1) where{Tm<:AbstractSparseMatrixExtension, Tv, Ti} - GenericMTExtendableSparseMatrixCSC(spzeros(Tv, Ti, m, n), - [Tm(m,n) for i=1:p], - Ti[1,2], - Ti[1,n+1], - ) +function GenericMTExtendableSparseMatrixCSC{Tm, Tv, Ti}(n, m, p::Integer = 1) where {Tm <: AbstractSparseMatrixExtension, Tv, Ti} + return GenericMTExtendableSparseMatrixCSC( + spzeros(Tv, Ti, m, n), + [Tm(m, n) for i in 1:p], + Ti[1, 2], + Ti[1, n + 1], + ) end -function partitioning!(ext::GenericMTExtendableSparseMatrixCSC{Tm,Tv,Ti}, colparts, partnodes) where {Tm, Tv, Ti} - ext.partnodes=partnodes - ext.colparts=colparts - ext +function partitioning!(ext::GenericMTExtendableSparseMatrixCSC{Tm, Tv, Ti}, colparts, partnodes) where {Tm, Tv, Ti} + ext.partnodes = partnodes + ext.colparts = colparts + return ext end -function reset!(ext::GenericMTExtendableSparseMatrixCSC{Tm,Tv,Ti},p::Integer) where {Tm,Tv,Ti} - m,n=size(ext.cscmatrix) - ext.cscmatrix=spzeros(Tv, Ti, m, n) - ext.xmatrices=[Tm(m,n) for i=1:p] - ext.colparts=Ti[1,2] - ext.partnodes=Ti[1,n+1] - ext +function reset!(ext::GenericMTExtendableSparseMatrixCSC{Tm, Tv, Ti}, p::Integer) where {Tm, Tv, Ti} + m, n = size(ext.cscmatrix) + ext.cscmatrix = spzeros(Tv, Ti, m, n) + ext.xmatrices = [Tm(m, n) for i in 1:p] + ext.colparts = Ti[1, 2] + ext.partnodes = Ti[1, n + 1] + return ext end function reset!(ext::GenericMTExtendableSparseMatrixCSC) - reset!(ext,length(ext.xmatrices)) + return reset!(ext, length(ext.xmatrices)) end -function flush!(ext::GenericMTExtendableSparseMatrixCSC{Tm,Tv,Ti}) where{Tm,Tv,Ti} - ext.cscmatrix=Base.sum(ext.xmatrices, ext.cscmatrix) - np=length(ext.xmatrices) - (m,n)=size(ext.cscmatrix) - ext.xmatrices=[Tm(m,n) for i=1:np] - ext +function flush!(ext::GenericMTExtendableSparseMatrixCSC{Tm, Tv, Ti}) where {Tm, Tv, Ti} + ext.cscmatrix = Base.sum(ext.xmatrices, ext.cscmatrix) + np = length(ext.xmatrices) + (m, n) = size(ext.cscmatrix) + ext.xmatrices = [Tm(m, n) for i in 1:np] + return ext end function SparseArrays.sparse(ext::GenericMTExtendableSparseMatrixCSC) flush!(ext) - ext.cscmatrix + return ext.cscmatrix end -function Base.setindex!(ext::GenericMTExtendableSparseMatrixCSC, - v::Union{Number,AbstractVecOrMat}, - i::Integer, - j::Integer) +function Base.setindex!( + ext::GenericMTExtendableSparseMatrixCSC, + v::Union{Number, AbstractVecOrMat}, + i::Integer, + j::Integer + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = v else error("use rawupdateindex! for new entries into GenericMTExtendableSparseMatrixCSC") end end -function Base.getindex(ext::GenericMTExtendableSparseMatrixCSC, - i::Integer, - j::Integer) +function Base.getindex( + ext::GenericMTExtendableSparseMatrixCSC, + i::Integer, + j::Integer + ) k = findindex(ext.cscmatrix, i, j) if k > 0 return ext.cscmatrix.nzval[k] - elseif sum(nnz,ext.xmatrices) == 0 + elseif sum(nnz, ext.xmatrices) == 0 return zero(eltype(ext.cscmatrix)) else error("flush! GenericMTExtendableSparseMatrixCSC before using getindex") end end -nnznew(ext::GenericMTExtendableSparseMatrixCSC)=sum(nnz,ext.xmatrices) +nnznew(ext::GenericMTExtendableSparseMatrixCSC) = sum(nnz, ext.xmatrices) -function rawupdateindex!(ext::GenericMTExtendableSparseMatrixCSC, - op, - v, - i, - j, - tid=1) +function rawupdateindex!( + ext::GenericMTExtendableSparseMatrixCSC, + op, + v, + i, + j, + tid = 1 + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else - rawupdateindex!(ext.xmatrices[tid],op,v,i,j) + rawupdateindex!(ext.xmatrices[tid], op, v, i, j) end end -function updateindex!(ext::GenericMTExtendableSparseMatrixCSC, - op, - v, - i, - j, - tid=1) +function updateindex!( + ext::GenericMTExtendableSparseMatrixCSC, + op, + v, + i, + j, + tid = 1 + ) k = findindex(ext.cscmatrix, i, j) - if k > 0 + return if k > 0 ext.cscmatrix.nzval[k] = op(ext.cscmatrix.nzval[k], v) else - updateindex!(ext.xmatrices[tid],op,v,i,j) + updateindex!(ext.xmatrices[tid], op, v, i, j) end end - - # Needed in 1.9 -function Base.:*(ext::GenericMTExtendableSparseMatrixCSC{Tm, TA} where Tm<:ExtendableSparse.AbstractSparseMatrixExtension, x::Union{StridedVector, BitVector}) where TA - mul!(similar(x),ext,x) +function Base.:*(ext::GenericMTExtendableSparseMatrixCSC{Tm, TA} where {Tm <: ExtendableSparse.AbstractSparseMatrixExtension}, x::Union{StridedVector, BitVector}) where {TA} + return mul!(similar(x), ext, x) end function LinearAlgebra.mul!(r, ext::GenericMTExtendableSparseMatrixCSC, x) flush!(ext) - A=ext.cscmatrix - colparts=ext.colparts - partnodes=ext.partnodes + A = ext.cscmatrix + colparts = ext.colparts + partnodes = ext.partnodes rows = SparseArrays.rowvals(A) vals = nonzeros(A) - r.=zero(eltype(ext)) - m,n=size(A) - for icol=1:length(colparts)-1 - Threads.@threads for ip in colparts[icol]:colparts[icol+1]-1 - @inbounds for inode in partnodes[ip]:partnodes[ip+1]-1 - @inbounds for i in nzrange(A,inode) - r[rows[i]]+=vals[i]*x[inode] + r .= zero(eltype(ext)) + m, n = size(A) + for icol in 1:(length(colparts) - 1) + Threads.@threads for ip in colparts[icol]:(colparts[icol + 1] - 1) + @inbounds for inode in partnodes[ip]:(partnodes[ip + 1] - 1) + @inbounds for i in nzrange(A, inode) + r[rows[i]] += vals[i] * x[inode] end end end end - r + return r end diff --git a/src/matrix/sparsematrixcsc.jl b/src/matrix/sparsematrixcsc.jl index 5754359..36dd7c2 100644 --- a/src/matrix/sparsematrixcsc.jl +++ b/src/matrix/sparsematrixcsc.jl @@ -55,7 +55,7 @@ function updateindex!(csc::SparseMatrixCSC{Tv, Ti}, op, v, i, j) where {Tv, Ti < else # insert new value csc[i, j] = op(zero(Tv), v) end - csc + return csc end """ @@ -81,12 +81,12 @@ Check if sparsity patterns of two SparseMatrixCSC objects are equal. This is generally faster than comparing hashes. """ function pattern_equal(a::SparseMatrixCSC, b::SparseMatrixCSC) - a.colptr == b.colptr && a.rowval == b.rowval + return a.colptr == b.colptr && a.rowval == b.rowval end -function pointblock(A::SparseMatrixCSC,blocksize) - SparseMatrixCSC(pointblock(ExtendableSparseMatrix(A),blocksize)) +function pointblock(A::SparseMatrixCSC, blocksize) + return SparseMatrixCSC(pointblock(ExtendableSparseMatrix(A), blocksize)) end """ @@ -94,20 +94,20 @@ end Return boolean vector marking Dirichlet nodes, known by `A[i,i]>=penalty` """ -function mark_dirichlet(A::SparseMatrixCSC; penalty=1.0e20) - colptr=A.colptr - rowval=A.rowval - nzval=A.nzval - n=A.n - dirichlet=zeros(Bool,n) - for i=1:n - for j=colptr[i]:colptr[i+1]-1 - if rowval[j]==i && nzval[j]>=penalty - dirichlet[i]=true +function mark_dirichlet(A::SparseMatrixCSC; penalty = 1.0e20) + colptr = A.colptr + rowval = A.rowval + nzval = A.nzval + n = A.n + dirichlet = zeros(Bool, n) + for i in 1:n + for j in colptr[i]:(colptr[i + 1] - 1) + if rowval[j] == i && nzval[j] >= penalty + dirichlet[i] = true end end end - dirichlet + return dirichlet end """ @@ -121,30 +121,30 @@ for a node `i` marked as Dirichlet. Returns A. """ -function eliminate_dirichlet!(A::SparseMatrixCSC,dirichlet) - colptr=A.colptr - rowval=A.rowval - nzval=A.nzval - n=A.n - for i=1:n +function eliminate_dirichlet!(A::SparseMatrixCSC, dirichlet) + colptr = A.colptr + rowval = A.rowval + nzval = A.nzval + n = A.n + for i in 1:n # set off-diagonal column indiced to zero if !iszero(dirichlet[i]) - for j=colptr[i]:colptr[i+1]-1 - if rowval[j]==i - nzval[j]=1 + for j in colptr[i]:(colptr[i + 1] - 1) + if rowval[j] == i + nzval[j] = 1 else - nzval[j]=0 + nzval[j] = 0 end end end # set off-diagonal row indices to zero - for j=colptr[i]:colptr[i+1]-1 - if rowval[j]!=i && !iszero(dirichlet[rowval[j]]) - nzval[j]=0 + for j in colptr[i]:(colptr[i + 1] - 1) + if rowval[j] != i && !iszero(dirichlet[rowval[j]]) + nzval[j] = 0 end end end - A + return A end """ @@ -159,7 +159,7 @@ for a node `i` marked as Dirichlet. Returns B. """ -function eliminate_dirichlet(A::SparseMatrixCSC,dirichlet) - B=SparseMatrixCSC(A.m,A.n,A.colptr,A.rowval,copy(A.nzval)) - eliminate_dirichlet!(B,dirichlet) +function eliminate_dirichlet(A::SparseMatrixCSC, dirichlet) + B = SparseMatrixCSC(A.m, A.n, A.colptr, A.rowval, copy(A.nzval)) + return eliminate_dirichlet!(B, dirichlet) end diff --git a/src/matrix/sparsematrixdict.jl b/src/matrix/sparsematrixdict.jl index c5ee469..744c1df 100644 --- a/src/matrix/sparsematrixdict.jl +++ b/src/matrix/sparsematrixdict.jl @@ -3,119 +3,119 @@ Sparse matrix where entries are organized as dictionary. """ -mutable struct SparseMatrixDict{Tv,Ti} <: AbstractSparseMatrixExtension{Tv,Ti} +mutable struct SparseMatrixDict{Tv, Ti} <: AbstractSparseMatrixExtension{Tv, Ti} m::Ti n::Ti - values::Dict{Pair{Ti,Ti}, Tv} - SparseMatrixDict{Tv,Ti}(m,n) where {Tv,Ti} = new(m,n,Dict{Pair{Ti,Ti}, Tv}()) + values::Dict{Pair{Ti, Ti}, Tv} + SparseMatrixDict{Tv, Ti}(m, n) where {Tv, Ti} = new(m, n, Dict{Pair{Ti, Ti}, Tv}()) end -function reset!(m::SparseMatrixDict{Tv,Ti}) where {Tv,Ti} - m.values=Dict{Pair{Ti,Ti}, Tv}() +function reset!(m::SparseMatrixDict{Tv, Ti}) where {Tv, Ti} + return m.values = Dict{Pair{Ti, Ti}, Tv}() end -function Base.setindex!(m::SparseMatrixDict,v,i,j) - m.values[Pair(i,j)]=v +function Base.setindex!(m::SparseMatrixDict, v, i, j) + return m.values[Pair(i, j)] = v end -function rawupdateindex!(m::SparseMatrixDict{Tv,Ti},op,v,i,j) where {Tv,Ti} - p=Pair(i,j) - m.values[p]=op(get(m.values, p, zero(Tv)),v) +function rawupdateindex!(m::SparseMatrixDict{Tv, Ti}, op, v, i, j) where {Tv, Ti} + p = Pair(i, j) + return m.values[p] = op(get(m.values, p, zero(Tv)), v) end -function Base.getindex(m::SparseMatrixDict{Tv},i,j) where Tv - get(m.values,Pair(i,j),zero(Tv)) +function Base.getindex(m::SparseMatrixDict{Tv}, i, j) where {Tv} + return get(m.values, Pair(i, j), zero(Tv)) end -Base.size(m::SparseMatrixDict)=(m.m,m.n) +Base.size(m::SparseMatrixDict) = (m.m, m.n) -SparseArrays.nnz(m::SparseMatrixDict)=length(m.values) +SparseArrays.nnz(m::SparseMatrixDict) = length(m.values) -function SparseArrays.sparse(mat::SparseMatrixDict{Tv,Ti}) where {Tv,Ti} - l=length(mat.values) - I=Vector{Ti}(undef,l) - J=Vector{Ti}(undef,l) - V=Vector{Tv}(undef,l) - i=1 - for (p,v) in mat.values - I[i]=first(p) - J[i]=last(p) - V[i]=v - i=i+1 +function SparseArrays.sparse(mat::SparseMatrixDict{Tv, Ti}) where {Tv, Ti} + l = length(mat.values) + I = Vector{Ti}(undef, l) + J = Vector{Ti}(undef, l) + V = Vector{Tv}(undef, l) + i = 1 + for (p, v) in mat.values + I[i] = first(p) + J[i] = last(p) + V[i] = v + i = i + 1 end - @static if VERSION>=v"1.10" - return SparseArrays.sparse!(I,J,V,size(mat)...,+) + @static if VERSION >= v"1.10" + return SparseArrays.sparse!(I, J, V, size(mat)..., +) else - return SparseArrays.sparse(I,J,V,size(mat)...,+) + return SparseArrays.sparse(I, J, V, size(mat)..., +) end end -function Base.:+(dictmatrix::SparseMatrixDict{Tv,Ti}, cscmatrix::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} - lnew=length(dictmatrix.values) - if lnew>0 - (;colptr,nzval,rowval,m,n)=cscmatrix - l=lnew+nnz(cscmatrix) - I=Vector{Ti}(undef,l) - J=Vector{Ti}(undef,l) - V=Vector{Tv}(undef,l) - i=1 - for icsc=1:length(colptr)-1 - for j=colptr[icsc]:colptr[icsc+1]-1 - I[i]=icsc - J[i]=rowval[j] - V[i]=nzval[j] - i=i+1 - end +function Base.:+(dictmatrix::SparseMatrixDict{Tv, Ti}, cscmatrix::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} + lnew = length(dictmatrix.values) + if lnew > 0 + (; colptr, nzval, rowval, m, n) = cscmatrix + l = lnew + nnz(cscmatrix) + I = Vector{Ti}(undef, l) + J = Vector{Ti}(undef, l) + V = Vector{Tv}(undef, l) + i = 1 + for icsc in 1:(length(colptr) - 1) + for j in colptr[icsc]:(colptr[icsc + 1] - 1) + I[i] = icsc + J[i] = rowval[j] + V[i] = nzval[j] + i = i + 1 + end end - - for (p,v) in dictmatrix.values - I[i]=first(p) - J[i]=last(p) - V[i]=v - i=i+1 + + for (p, v) in dictmatrix.values + I[i] = first(p) + J[i] = last(p) + V[i] = v + i = i + 1 end - @static if VERSION>=v"1.10" - return SparseArrays.sparse!(I,J,V,m,n,+) + @static if VERSION >= v"1.10" + return SparseArrays.sparse!(I, J, V, m, n, +) else - return SparseArrays.sparse(I,J,V,m,n,+) + return SparseArrays.sparse(I, J, V, m, n, +) end end - cscmatrix + return cscmatrix end -function Base.sum(dictmatrices::Vector{SparseMatrixDict{Tv,Ti}}, cscmatrix::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} - lnew=sum(m->length(m.values),dictmatrices) - if lnew>0 - (;colptr,nzval,rowval,m,n)=cscmatrix - l=lnew+nnz(cscmatrix) - I=Vector{Ti}(undef,l) - J=Vector{Ti}(undef,l) - V=Vector{Tv}(undef,l) - i=1 - - for icsc=1:length(colptr)-1 - for j=colptr[icsc]:colptr[icsc+1]-1 - I[i]=icsc - J[i]=rowval[j] - V[i]=nzval[j] - i=i+1 - end +function Base.sum(dictmatrices::Vector{SparseMatrixDict{Tv, Ti}}, cscmatrix::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} + lnew = sum(m -> length(m.values), dictmatrices) + if lnew > 0 + (; colptr, nzval, rowval, m, n) = cscmatrix + l = lnew + nnz(cscmatrix) + I = Vector{Ti}(undef, l) + J = Vector{Ti}(undef, l) + V = Vector{Tv}(undef, l) + i = 1 + + for icsc in 1:(length(colptr) - 1) + for j in colptr[icsc]:(colptr[icsc + 1] - 1) + I[i] = icsc + J[i] = rowval[j] + V[i] = nzval[j] + i = i + 1 + end end - - ip=1 + + ip = 1 for m in dictmatrices - for (p,v) in m.values - I[i]=first(p) - J[i]=last(p) - V[i]=v - i=i+1 + for (p, v) in m.values + I[i] = first(p) + J[i] = last(p) + V[i] = v + i = i + 1 end - ip=ip+1 + ip = ip + 1 end - @static if VERSION>=v"1.10" - return SparseArrays.sparse!(I,J,V,m,n,+) + @static if VERSION >= v"1.10" + return SparseArrays.sparse!(I, J, V, m, n, +) else - return SparseArrays.sparse(I,J,V,m,n,+) + return SparseArrays.sparse(I, J, V, m, n, +) end end return cscmatrix diff --git a/src/matrix/sparsematrixdilnkc.jl b/src/matrix/sparsematrixdilnkc.jl index 6c71ddc..a394bcc 100644 --- a/src/matrix/sparsematrixdilnkc.jl +++ b/src/matrix/sparsematrixdilnkc.jl @@ -6,10 +6,10 @@ column j is stored in a dictionary. """ mutable struct SparseMatrixDILNKC{Tv, Ti <: Integer} <: AbstractSparseMatrixExtension{Tv, Ti} """ - Number of rows - """ + Number of rows + """ m::Ti - + """ Number of columns """ @@ -38,7 +38,7 @@ mutable struct SparseMatrixDILNKC{Tv, Ti <: Integer} <: AbstractSparseMatrixExte """ Dictionary to store start indices of columns """ - colstart::Dict{Ti,Ti} + colstart::Dict{Ti, Ti} """ Row numbers. For each index it contains the zero (initial state) @@ -59,7 +59,7 @@ $(SIGNATURES) Constructor of empty matrix. """ function SparseMatrixDILNKC{Tv, Ti}(m, n) where {Tv, Ti <: Integer} - SparseMatrixDILNKC{Tv, Ti}(m, n, 0, 0, zeros(Ti,10), Dict{Ti,Ti}(), zeros(Ti,10), zeros(Ti,10)) + return SparseMatrixDILNKC{Tv, Ti}(m, n, 0, 0, zeros(Ti, 10), Dict{Ti, Ti}(), zeros(Ti, 10), zeros(Ti, 10)) end """ @@ -67,9 +67,11 @@ $(SIGNATURES) Constructor of empty matrix. """ -function SparseMatrixDILNKC(valuetype::Type{Tv}, indextype::Type{Ti}, m, - n) where {Tv, Ti <: Integer} - SparseMatrixDILNKC{Tv, Ti}(m, n) +function SparseMatrixDILNKC( + valuetype::Type{Tv}, indextype::Type{Ti}, m, + n + ) where {Tv, Ti <: Integer} + return SparseMatrixDILNKC{Tv, Ti}(m, n) end """ @@ -92,15 +94,17 @@ $(SIGNATURES) Constructor from SparseMatrixCSC. """ -function SparseMatrixDILNKC(csc::SparseArrays.SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: - Integer} +function SparseMatrixDILNKC(csc::SparseArrays.SparseMatrixCSC{Tv, Ti}) where { + Tv, Ti <: + Integer, + } lnk = SparseMatrixDILNKC{Tv, Ti}(csc.m, csc.n) - for j = 1:(csc.n) - for k = csc.colptr[j]:(csc.colptr[j + 1] - 1) + for j in 1:(csc.n) + for k in csc.colptr[j]:(csc.colptr[j + 1] - 1) lnk[csc.rowval[k], j] = csc.nzval[k] end end - lnk + return lnk end """ @@ -114,8 +118,8 @@ function findindex(lnk::SparseMatrixDILNKC, i, j) end k = get(lnk.colstart, j, 0) - if k==0 - return 0,0 + if k == 0 + return 0, 0 end k0 = k while k > 0 @@ -156,9 +160,9 @@ function addentry!(lnk::SparseMatrixDILNKC, i, j, k, k0) resize!(lnk.rowval, newsize) resize!(lnk.colptr, newsize) end - - if k0==0 - lnk.colstart[j]=lnk.nentries + + if k0 == 0 + lnk.colstart[j] = lnk.nentries end # Append entry if not found @@ -167,10 +171,10 @@ function addentry!(lnk::SparseMatrixDILNKC, i, j, k, k0) # Shift the end of the list lnk.colptr[lnk.nentries] = 0 - if k0>0 + if k0 > 0 lnk.colptr[k0] = lnk.nentries end - + # Update number of nonzero entries lnk.nnz += 1 return lnk.nentries @@ -215,7 +219,7 @@ function updateindex!(lnk::SparseMatrixDILNKC{Tv, Ti}, op, v, i, j) where {Tv, T k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end """ @@ -233,7 +237,7 @@ function rawupdateindex!(lnk::SparseMatrixDILNKC{Tv, Ti}, op, v, i, j) where {Tv k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end """ @@ -255,37 +259,39 @@ SparseArrays.nnz(lnk::SparseMatrixDILNKC) = lnk.nnz $(SIGNATURES) Add lnk and csc via interim COO (coordinate) format, i.e. arrays I,J,V. """ -function add_via_COO(lnk::SparseMatrixDILNKC{Tv, Ti}, - csc::SparseMatrixCSC)::SparseMatrixCSC where {Tv, Ti <: Integer} - (;colptr,nzval,rowval,m,n)=csc - l=nnz(lnk)+nnz(csc) - I=Vector{Ti}(undef,l) - J=Vector{Ti}(undef,l) - V=Vector{Tv}(undef,l) - i=1 - if nnz(csc)>0 - for icsc=1:length(colptr)-1 - for j=colptr[icsc]:colptr[icsc+1]-1 - I[i]=icsc - J[i]=rowval[j] - V[i]=nzval[j] - i=i+1 - end +function add_via_COO( + lnk::SparseMatrixDILNKC{Tv, Ti}, + csc::SparseMatrixCSC + )::SparseMatrixCSC where {Tv, Ti <: Integer} + (; colptr, nzval, rowval, m, n) = csc + l = nnz(lnk) + nnz(csc) + I = Vector{Ti}(undef, l) + J = Vector{Ti}(undef, l) + V = Vector{Tv}(undef, l) + i = 1 + if nnz(csc) > 0 + for icsc in 1:(length(colptr) - 1) + for j in colptr[icsc]:(colptr[icsc + 1] - 1) + I[i] = icsc + J[i] = rowval[j] + V[i] = nzval[j] + i = i + 1 + end end end - for (j,k) in lnk.colstart - while k>0 - I[i]=lnk.rowval[k] - J[i]=j - V[i]=lnk.nzval[k] - k=lnk.colptr[k] - i=i+1 + for (j, k) in lnk.colstart + while k > 0 + I[i] = lnk.rowval[k] + J[i] = j + V[i] = lnk.nzval[k] + k = lnk.colptr[k] + i = i + 1 end end - @static if VERSION>=v"1.10" - return SparseArrays.sparse!(I,J,V,m,n,+) + @static if VERSION >= v"1.10" + return SparseArrays.sparse!(I, J, V, m, n, +) else - return SparseArrays.sparse(I,J,V,m,n,+) + return SparseArrays.sparse(I, J, V, m, n, +) end end @@ -295,10 +301,12 @@ end Add lnk and csc without creation of intermediate data. (to be fixed) """ -function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, - csc::SparseMatrixCSC)::SparseMatrixCSC where {Tv, Ti <: Integer} - @assert(csc.m==lnk.m) - @assert(csc.n==lnk.n) +function add_directly( + lnk::SparseMatrixDILNKC{Tv, Ti}, + csc::SparseMatrixCSC + )::SparseMatrixCSC where {Tv, Ti <: Integer} + @assert(csc.m == lnk.m) + @assert(csc.n == lnk.n) # overallocate arrays in order to avoid # presumably slower push! @@ -309,7 +317,7 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, # Detect the maximum column length of lnk lnk_maxcol = 0 - for (j,k) in lnk.colstart + for (j, k) in lnk.colstart lcol = zero(Ti) while k > 0 lcol += 1 @@ -319,7 +327,7 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, end # pre-allocate column data - col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i = 1:lnk_maxcol] + col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i in 1:lnk_maxcol] inz = 1 # counts the nonzero entries in the new matrix @@ -328,7 +336,7 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, in_lnk_col(jlnk, l_lnk_col) = (jlnk <= l_lnk_col) # loop over all columns - for j = 1:(csc.n) + for j in 1:(csc.n) # Copy extension entries into col and sort them k = get(lnk.colstart, j, 0) l_lnk_col = 0 @@ -344,7 +352,7 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, # jointly sort lnk and csc entries into new matrix data # this could be replaced in a more transparent manner by joint sorting: # make a joint array for csc and lnk col, sort them. - # Will this be faster? + # Will this be faster? colptr[j] = inz jlnk = one(Ti) # counts the entries in col @@ -352,15 +360,17 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, while true if in_csc_col(jcsc, j) && - (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] < col[jlnk].rowval || - !in_lnk_col(jlnk, l_lnk_col)) + ( + in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] < col[jlnk].rowval || + !in_lnk_col(jlnk, l_lnk_col) + ) # Insert entries from csc into new structure rowval[inz] = csc.rowval[jcsc] nzval[inz] = csc.nzval[jcsc] jcsc += 1 inz += 1 elseif in_csc_col(jcsc, j) && - (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] == col[jlnk].rowval) + (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] == col[jlnk].rowval) # Add up entries from csc and lnk rowval[inz] = csc.rowval[jcsc] nzval[inz] = csc.nzval[jcsc] + col[jlnk].nzval @@ -381,67 +391,66 @@ function add_directly(lnk::SparseMatrixDILNKC{Tv, Ti}, colptr[csc.n + 1] = inz resize!(rowval, inz - 1) resize!(nzval, inz - 1) - SparseMatrixCSC{Tv, Ti}(csc.m, csc.n, colptr, rowval, nzval) + return SparseMatrixCSC{Tv, Ti}(csc.m, csc.n, colptr, rowval, nzval) end - """ $(SIGNATURES) Add SparseMatrixCSC matrix and [`SparseMatrixDILNKC`](@ref) lnk, returning a SparseMatrixCSC """ #Base.:+(lnk::SparseMatrixDILNKC, csc::SparseMatrixCSC) = add_directly(lnk, csc) -Base.:+(lnk::SparseMatrixDILNKC, csc::SparseMatrixCSC) = sum([lnk],csc) - -function Base.sum(lnkdictmatrices::Vector{SparseMatrixDILNKC{Tv,Ti}}, cscmatrix::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} - lnew=sum(nnz,lnkdictmatrices) - if lnew>0 - (;colptr,nzval,rowval,m,n)=cscmatrix - l=lnew+nnz(cscmatrix) - I=Vector{Ti}(undef,l) - J=Vector{Ti}(undef,l) - V=Vector{Tv}(undef,l) - i=1 - - for icsc=1:length(colptr)-1 - for j=colptr[icsc]:colptr[icsc+1]-1 - I[i]=rowval[j] - J[i]=icsc - V[i]=nzval[j] - i=i+1 - end +Base.:+(lnk::SparseMatrixDILNKC, csc::SparseMatrixCSC) = sum([lnk], csc) + +function Base.sum(lnkdictmatrices::Vector{SparseMatrixDILNKC{Tv, Ti}}, cscmatrix::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} + lnew = sum(nnz, lnkdictmatrices) + if lnew > 0 + (; colptr, nzval, rowval, m, n) = cscmatrix + l = lnew + nnz(cscmatrix) + I = Vector{Ti}(undef, l) + J = Vector{Ti}(undef, l) + V = Vector{Tv}(undef, l) + i = 1 + + for icsc in 1:(length(colptr) - 1) + for j in colptr[icsc]:(colptr[icsc + 1] - 1) + I[i] = rowval[j] + J[i] = icsc + V[i] = nzval[j] + i = i + 1 + end end for lnk in lnkdictmatrices - for (j,k) in lnk.colstart - while k>0 - I[i]=lnk.rowval[k] - J[i]=j - V[i]=lnk.nzval[k] - k=lnk.colptr[k] - i=i+1 + for (j, k) in lnk.colstart + while k > 0 + I[i] = lnk.rowval[k] + J[i] = j + V[i] = lnk.nzval[k] + k = lnk.colptr[k] + i = i + 1 end end end - @assert l==i-1 - @static if VERSION>=v"1.10" - return SparseArrays.sparse!(I,J,V,m,n,+) + @assert l == i - 1 + @static if VERSION >= v"1.10" + return SparseArrays.sparse!(I, J, V, m, n, +) else - return SparseArrays.sparse(I,J,V,m,n,+) + return SparseArrays.sparse(I, J, V, m, n, +) end end return cscmatrix end - -function reset!(m::SparseMatrixDILNKC{Tv,Ti}) where {Tv,Ti} - m.nnz=0 - m.nentries=0 - m.colptr=zeros(Ti,10) - m.colstart::Dict{Ti,Ti} - m.rowval=zeros(Ti,10) - m.nzval=zeros(Ti,10) - m + +function reset!(m::SparseMatrixDILNKC{Tv, Ti}) where {Tv, Ti} + m.nnz = 0 + m.nentries = 0 + m.colptr = zeros(Ti, 10) + m.colstart::Dict{Ti, Ti} + m.rowval = zeros(Ti, 10) + m.nzval = zeros(Ti, 10) + return m end @@ -453,20 +462,22 @@ Constructor from SparseMatrixDILNKC. """ function SparseArrays.SparseMatrixCSC(lnk::SparseMatrixDILNKC)::SparseMatrixCSC csc = spzeros(lnk.m, lnk.n) - lnk + csc + return lnk + csc end function SparseArrays.sparse(lnk::SparseMatrixDILNKC) - lnk + spzeros(lnk.m, lnk.n) + return lnk + spzeros(lnk.m, lnk.n) end function Base.copy(S::SparseMatrixDILNKC) - SparseMatrixDILNKC(size(S, 1), - size(S, 2), - S.nnz, - S.nentries, - copy(S.colptr), - copy(S.colstart), - copy(S.rowvals), - copy(S.nzval)) + return SparseMatrixDILNKC( + size(S, 1), + size(S, 2), + S.nnz, + S.nentries, + copy(S.colptr), + copy(S.colstart), + copy(S.rowvals), + copy(S.nzval) + ) end diff --git a/src/matrix/sparsematrixlnk.jl b/src/matrix/sparsematrixlnk.jl index 502e22b..76f5e0b 100644 --- a/src/matrix/sparsematrixlnk.jl +++ b/src/matrix/sparsematrixlnk.jl @@ -1,4 +1,3 @@ - """ $(TYPEDEF) @@ -73,7 +72,7 @@ $(SIGNATURES) Constructor of empty matrix. """ function SparseMatrixLNK{Tv, Ti}(m, n) where {Tv, Ti <: Integer} - SparseMatrixLNK{Tv, Ti}(m, n, 0, n, zeros(Ti, n), zeros(Ti, n), zeros(Tv, n)) + return SparseMatrixLNK{Tv, Ti}(m, n, 0, n, zeros(Ti, n), zeros(Ti, n), zeros(Tv, n)) end """ @@ -81,9 +80,11 @@ $(SIGNATURES) Constructor of empty matrix. """ -function SparseMatrixLNK(valuetype::Type{Tv}, indextype::Type{Ti}, m, - n) where {Tv, Ti <: Integer} - SparseMatrixLNK{Tv, Ti}(m, n) +function SparseMatrixLNK( + valuetype::Type{Tv}, indextype::Type{Ti}, m, + n + ) where {Tv, Ti <: Integer} + return SparseMatrixLNK{Tv, Ti}(m, n) end """ @@ -106,18 +107,20 @@ $(SIGNATURES) Constructor from SparseMatrixCSC. """ -function SparseMatrixLNK(csc::SparseArrays.SparseMatrixCSC{Tv, Ti}) where {Tv, Ti <: - Integer} +function SparseMatrixLNK(csc::SparseArrays.SparseMatrixCSC{Tv, Ti}) where { + Tv, Ti <: + Integer, + } lnk = SparseMatrixLNK{Tv, Ti}(csc.m, csc.n) - for j = 1:(csc.n) - for k = csc.colptr[j]:(csc.colptr[j + 1] - 1) + for j in 1:(csc.n) + for k in csc.colptr[j]:(csc.colptr[j + 1] - 1) lnk[csc.rowval[k], j] = csc.nzval[k] end end - lnk + return lnk end -function findindex(lnk::SparseMatrixLNK{Tv,Ti}, i, j) where {Tv,Ti} +function findindex(lnk::SparseMatrixLNK{Tv, Ti}, i, j) where {Tv, Ti} if !((1 <= i <= lnk.m) & (1 <= j <= lnk.n)) throw(BoundsError(lnk, (i, j))) end @@ -224,7 +227,7 @@ function updateindex!(lnk::SparseMatrixLNK{Tv, Ti}, op, v, i, j) where {Tv, Ti} k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end """ @@ -249,7 +252,7 @@ function rawupdateindex!(lnk::SparseMatrixLNK{Tv, Ti}, op, v, i, j) where {Tv, T k = addentry!(lnk, i, j, k, k0) lnk.nzval[k] = op(zero(Tv), v) end - lnk + return lnk end """ @@ -291,10 +294,12 @@ $(SIGNATURES) Add SparseMatrixCSC matrix and [`SparseMatrixLNK`](@ref) lnk, returning a SparseMatrixCSC """ -function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, - csc::SparseMatrixCSC)::SparseMatrixCSC where {Tv, Ti <: Integer} - @assert(csc.m==lnk.m) - @assert(csc.n==lnk.n) +function Base.:+( + lnk::SparseMatrixLNK{Tv, Ti}, + csc::SparseMatrixCSC + )::SparseMatrixCSC where {Tv, Ti <: Integer} + @assert(csc.m == lnk.m) + @assert(csc.n == lnk.n) # overallocate arrays in order to avoid # presumably slower push! @@ -305,7 +310,7 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, # Detect the maximum column length of lnk lnk_maxcol = 0 - for j = 1:(csc.n) + for j in 1:(csc.n) lcol = zero(Ti) k = j while k > 0 @@ -316,7 +321,7 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, end # pre-allocate column data - col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i = 1:lnk_maxcol] + col = [ColEntry{Tv, Ti}(0, zero(Tv)) for i in 1:lnk_maxcol] inz = 1 # counts the nonzero entries in the new matrix @@ -325,7 +330,7 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, in_lnk_col(jlnk, l_lnk_col) = (jlnk <= l_lnk_col) # loop over all columns - for j = 1:(csc.n) + for j in 1:(csc.n) # Copy extension entries into col and sort them k = j l_lnk_col = 0 @@ -341,7 +346,7 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, # jointly sort lnk and csc entries into new matrix data # this could be replaced in a more transparent manner by joint sorting: # make a joint array for csc and lnk col, sort them. - # Will this be faster? + # Will this be faster? colptr[j] = inz jlnk = one(Ti) # counts the entries in col @@ -349,15 +354,17 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, while true if in_csc_col(jcsc, j) && - (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] < col[jlnk].rowval || - !in_lnk_col(jlnk, l_lnk_col)) + ( + in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] < col[jlnk].rowval || + !in_lnk_col(jlnk, l_lnk_col) + ) # Insert entries from csc into new structure rowval[inz] = csc.rowval[jcsc] nzval[inz] = csc.nzval[jcsc] jcsc += 1 inz += 1 elseif in_csc_col(jcsc, j) && - (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] == col[jlnk].rowval) + (in_lnk_col(jlnk, l_lnk_col) && csc.rowval[jcsc] == col[jlnk].rowval) # Add up entries from csc and lnk rowval[inz] = csc.rowval[jcsc] nzval[inz] = csc.nzval[jcsc] + col[jlnk].nzval @@ -379,7 +386,7 @@ function Base.:+(lnk::SparseMatrixLNK{Tv, Ti}, # Julia 1.7 wants this correct resize!(rowval, inz - 1) resize!(nzval, inz - 1) - SparseMatrixCSC{Tv, Ti}(csc.m, csc.n, colptr, rowval, nzval) + return SparseMatrixCSC{Tv, Ti}(csc.m, csc.n, colptr, rowval, nzval) end Base.:+(csc::SparseMatrixCSC, lnk::SparseMatrixLNK) = lnk + csc @@ -392,7 +399,7 @@ Constructor from SparseMatrixLNK. """ function SparseArrays.SparseMatrixCSC(lnk::SparseMatrixLNK)::SparseMatrixCSC csc = spzeros(lnk.m, lnk.n) - lnk + csc + return lnk + csc end rowvals(S::SparseMatrixLNK) = getfield(S, :rowval) @@ -400,11 +407,13 @@ getcolptr(S::SparseMatrixLNK) = getfield(S, :colptr) nonzeros(S::SparseMatrixLNK) = getfield(S, :nzval) function Base.copy(S::SparseMatrixLNK) - SparseMatrixLNK(size(S, 1), - size(S, 2), - S.nnz, - S.nentries, - copy(getcolptr(S)), - copy(rowvals(S)), - copy(nonzeros(S))) + return SparseMatrixLNK( + size(S, 1), + size(S, 2), + S.nnz, + S.nentries, + copy(getcolptr(S)), + copy(rowvals(S)), + copy(nonzeros(S)) + ) end diff --git a/src/matrix/sprand.jl b/src/matrix/sprand.jl index 6e8cd93..2ff7d21 100644 --- a/src/matrix/sprand.jl +++ b/src/matrix/sprand.jl @@ -6,13 +6,13 @@ using incremental assembly. """ function sprand!(A::AbstractSparseMatrix{Tv, Ti}, xnnz::Int) where {Tv, Ti} m, n = size(A) - for i = 1:xnnz + for i in 1:xnnz i = rand((1:m)) j = rand((1:n)) a = 1.0 + rand(Tv) A[i, j] += a end - A + return A end """ @@ -29,9 +29,9 @@ function sprand_sdd!(A::AbstractSparseMatrix{Tv, Ti}; nnzrow = 4) where {Tv, Ti} @assert m == n nnzrow = min(n, nnzrow) bandwidth = convert(Int, ceil(sqrt(n))) - for i = 1:n + for i in 1:n aii = 0 - for k = 1:nnzrow + for k in 1:nnzrow jmin = max(1, i - bandwidth) jmax = min(n, i + bandwidth) j = rand((jmin:jmax)) @@ -43,7 +43,7 @@ function sprand_sdd!(A::AbstractSparseMatrix{Tv, Ti}; nnzrow = 4) where {Tv, Ti} end A[i, i] = aii + rand(Tv) # make it strictly diagonally dominant end - A + return A end """ @@ -55,12 +55,14 @@ with finite difference discretization data on a unit hypercube. See It is required that `size(A)==(N,N)` where `N=nx*ny*nz` """ -function fdrand!(A::T, - nx, - ny = 1, - nz = 1; - update = (A, v, i, j) -> A[i, j] += v, - rand = () -> rand(eltype(A))) where {T <: AbstractMatrix} +function fdrand!( + A::T, + nx, + ny = 1, + nz = 1; + update = (A, v, i, j) -> A[i, j] += v, + rand = () -> rand(eltype(A)) + ) where {T <: AbstractMatrix} sz = size(A) N = nx * ny * nz if sz[1] != N || sz[2] != N @@ -88,7 +90,7 @@ function fdrand!(A::T, update(A, -v, i, j) update(A, -v, j, i) update(A, v, i, i) - update(A, v, j, j) + return update(A, v, j, j) end hx = 1.0 / nx @@ -97,9 +99,9 @@ function fdrand!(A::T, nxy = nx * ny l = 1 - for k = 1:nz - for j = 1:ny - for i = 1:nx + for k in 1:nz + for j in 1:ny + for i in 1:nx if i < nx update_pair(A, rand() * hy * hz / hx, l, l + 1) end @@ -122,7 +124,7 @@ function fdrand!(A::T, end end end - _flush!(A) + return _flush!(A) end """ @@ -140,14 +142,14 @@ function fdrand_coo(T, nx, ny = 1, nz = 1; rand = () -> rand()) function update(v, i, j) push!(I, i) push!(J, j) - push!(V, v) + return push!(V, v) end function update_pair(v, i, j) update(-v, i, j) update(-v, j, i) update(v, i, i) - update(v, j, j) + return update(v, j, j) end hx = 1.0 / nx @@ -156,9 +158,9 @@ function fdrand_coo(T, nx, ny = 1, nz = 1; rand = () -> rand()) nxy = nx * ny l = 1 - for k = 1:nz - for j = 1:ny - for i = 1:nx + for k in 1:nz + for j in 1:ny + for i in 1:nx if i < nx update_pair(rand() * hy * hz / hx, l, l + 1) end @@ -181,7 +183,7 @@ function fdrand_coo(T, nx, ny = 1, nz = 1; rand = () -> rand()) end end end - sparse(I, J, V) + return sparse(I, J, V) end """ $(SIGNATURES) @@ -223,14 +225,16 @@ are random unless e.g. `rand=()->1` is passed as random number generator. Tested for Matrix, SparseMatrixCSC, ExtendableSparseMatrix, Tridiagonal, SparseMatrixLNK and `:COO` """ -function fdrand(::Type{T}, - nx, - ny = 1, - nz = 1; - matrixtype::Union{Type, Symbol} = SparseMatrixCSC, - update = (A, v, i, j) -> A[i, j] += v, - rand = () -> 0.1 + rand(), - symmetric = true) where {T} +function fdrand( + ::Type{T}, + nx, + ny = 1, + nz = 1; + matrixtype::Union{Type, Symbol} = SparseMatrixCSC, + update = (A, v, i, j) -> A[i, j] += v, + rand = () -> 0.1 + rand(), + symmetric = true + ) where {T} N = nx * ny * nz if matrixtype == :COO A = fdrand_coo(T, nx, ny, nz; rand = rand) @@ -248,26 +252,28 @@ function fdrand(::Type{T}, end A = fdrand!(A, nx, ny, nz; update = update, rand = rand) end - if symmetric + return if symmetric A else - Diagonal([rand() for i = 1:size(A, 1)]) * A + Diagonal([rand() for i in 1:size(A, 1)]) * A end end fdrand(nx, ny = 1, nz = 1; kwargs...) = fdrand(Float64, nx, ny, nz; kwargs...) ### for use with LinearSolve.jl -function solverbenchmark(T, - solver, - nx, - ny = 1, - nz = 1; - symmetric = false, - matrixtype = ExtendableSparseMatrix, - seconds = 0.5, - repeat = 1, - tol = sqrt(eps(Float64))) +function solverbenchmark( + T, + solver, + nx, + ny = 1, + nz = 1; + symmetric = false, + matrixtype = ExtendableSparseMatrix, + seconds = 0.5, + repeat = 1, + tol = sqrt(eps(Float64)) + ) A = fdrand(T, nx, ny, nz; symmetric, matrixtype) n = size(A, 1) x = rand(n) @@ -275,7 +281,7 @@ function solverbenchmark(T, u = solver(A, b) nrm = norm(u - x, 1) / n if nrm > tol - error("solution inaccurate: $((nx,ny,nz)), |u-exact|=$nrm") + error("solution inaccurate: $((nx, ny, nz)), |u-exact|=$nrm") end secs = 0.0 nsol = 0 @@ -286,26 +292,30 @@ function solverbenchmark(T, tmin = min(tmin, t) nsol += 1 end - tmin + return tmin end -function solverbenchmark(T, - solver; - dim = 1, - nsizes = 10, - sizes = [10 * 2^i for i = 1:nsizes], - symmetric = false, - matrixtype = ExtendableSparseMatrix, - seconds = 0.1, - tol = sqrt(eps(Float64))) +function solverbenchmark( + T, + solver; + dim = 1, + nsizes = 10, + sizes = [10 * 2^i for i in 1:nsizes], + symmetric = false, + matrixtype = ExtendableSparseMatrix, + seconds = 0.1, + tol = sqrt(eps(Float64)) + ) if dim == 1 ns = sizes elseif dim == 2 ns = [(Int(ceil(x^(1 / 2))), Int(ceil(x^(1 / 2)))) for x in sizes] elseif dim == 3 - ns = [(Int(ceil(x^(1 / 3))), Int(ceil(x^(1 / 3))), Int(ceil(x^(1 / 3)))) - for - x in sizes] + ns = [ + (Int(ceil(x^(1 / 3))), Int(ceil(x^(1 / 3))), Int(ceil(x^(1 / 3)))) + for + x in sizes + ] end times = zeros(0) sizes = zeros(Int, 0) @@ -314,5 +324,5 @@ function solverbenchmark(T, push!(times, t) push!(sizes, prod(s)) end - sizes, times + return sizes, times end diff --git a/src/preconbuilders.jl b/src/preconbuilders.jl index 9cd5782..965caaf 100644 --- a/src/preconbuilders.jl +++ b/src/preconbuilders.jl @@ -5,9 +5,9 @@ Return callable object constructing a formal left preconditioner from a sparse L as the `precs` parameter for a [`BlockPreconBuilder`](@ref) or iterative methods wrapped by LinearSolve.jl. """ Base.@kwdef struct LinearSolvePreconBuilder - method=UMFPACKFactorization() + method = UMFPACKFactorization() end -(::LinearSolvePreconBuilder)(A,p)= error("import LinearSolve in order to use LinearSolvePreconBuilder") +(::LinearSolvePreconBuilder)(A, p) = error("import LinearSolve in order to use LinearSolvePreconBuilder") """ @@ -17,7 +17,7 @@ Return callable object constructing a left Jacobi preconditioner to be passed as the `precs` parameter to iterative methods wrapped by LinearSolve.jl. """ struct JacobiPreconBuilder end -(::JacobiPreconBuilder)(A::AbstractSparseMatrixCSC,p)=(JacobiPreconditioner(SparseMatrixCSC(size(A)..., getcolptr(A), rowvals(A),nonzeros(A))),LinearAlgebra.I) +(::JacobiPreconBuilder)(A::AbstractSparseMatrixCSC, p) = (JacobiPreconditioner(SparseMatrixCSC(size(A)..., getcolptr(A), rowvals(A), nonzeros(A))), LinearAlgebra.I) """ @@ -30,25 +30,27 @@ Base.@kwdef mutable struct ILUZeroPreconBuilder blocksize::Int = 1 end -struct ILUBlockPrecon{N,NN,Tv,Ti} +struct ILUBlockPrecon{N, NN, Tv, Ti} ilu0::ILUZero.ILU0Precon{SMatrix{N, N, Tv, NN}, Ti, SVector{N, Tv}} end -function LinearAlgebra.ldiv!(Y::Vector{Tv}, - A::ILUBlockPrecon{N,NN,Tv,Ti}, - B::Vector{Tv}) where {N,NN,Tv,Ti} - BY=reinterpret(SVector{N,Tv},Y) - BB=reinterpret(SVector{N,Tv},B) - ldiv!(BY,A.ilu0,BB) - Y +function LinearAlgebra.ldiv!( + Y::Vector{Tv}, + A::ILUBlockPrecon{N, NN, Tv, Ti}, + B::Vector{Tv} + ) where {N, NN, Tv, Ti} + BY = reinterpret(SVector{N, Tv}, Y) + BB = reinterpret(SVector{N, Tv}, B) + ldiv!(BY, A.ilu0, BB) + return Y end -function (b::ILUZeroPreconBuilder)(A0,p) - A=SparseMatrixCSC(size(A0)..., getcolptr(A0), rowvals(A0),nonzeros(A0)) - if b.blocksize==1 - (ILUZero.ilu0(A),LinearAlgebra.I) +function (b::ILUZeroPreconBuilder)(A0, p) + A = SparseMatrixCSC(size(A0)..., getcolptr(A0), rowvals(A0), nonzeros(A0)) + return if b.blocksize == 1 + (ILUZero.ilu0(A), LinearAlgebra.I) else - (ILUBlockPrecon(ILUZero.ilu0(pointblock(A,b.blocksize),SVector{b.blocksize,eltype(A)})),LinearAlgebra.I) + (ILUBlockPrecon(ILUZero.ilu0(pointblock(A, b.blocksize), SVector{b.blocksize, eltype(A)})), LinearAlgebra.I) end end @@ -60,10 +62,9 @@ Return callable object constructing a left ILUT preconditioner using [IncompleteLU.jl](https://github.com/haampie/IncompleteLU.jl) """ Base.@kwdef struct ILUTPreconBuilder - droptol::Float64=0.1 + droptol::Float64 = 0.1 end -(::ILUTPreconBuilder)(A,p)= error("import IncompleteLU.jl in order to use ILUTBuilder") - +(::ILUTPreconBuilder)(A, p) = error("import IncompleteLU.jl in order to use ILUTBuilder") """ @@ -79,11 +80,11 @@ struct SmoothedAggregationPreconBuilder{Tk} kwargs::Tk end -function SmoothedAggregationPreconBuilder(;blocksize=1, kwargs...) - SmoothedAggregationPreconBuilder(blocksize,kwargs) +function SmoothedAggregationPreconBuilder(; blocksize = 1, kwargs...) + return SmoothedAggregationPreconBuilder(blocksize, kwargs) end -(::SmoothedAggregationPreconBuilder)(A,p)= error("import AlgebraicMultigrid in order to use SmoothedAggregationPreconBuilder") +(::SmoothedAggregationPreconBuilder)(A, p) = error("import AlgebraicMultigrid in order to use SmoothedAggregationPreconBuilder") """ RugeStubenPreconBuilder(;blocksize=1, kwargs...) @@ -98,8 +99,8 @@ struct RugeStubenPreconBuilder{Tk} kwargs::Tk end -function RugeStubenPreconBuilder(;blocksize=1, kwargs...) - SmoothedAggregationPreconBuilder(blocksize,kwargs) +function RugeStubenPreconBuilder(; blocksize = 1, kwargs...) + return SmoothedAggregationPreconBuilder(blocksize, kwargs) end -(::RugeStubenPreconBuilder)(A,p)= error("import AlgebraicMultigrid in order to use RugeStubenAMGBuilder") +(::RugeStubenPreconBuilder)(A, p) = error("import AlgebraicMultigrid in order to use RugeStubenAMGBuilder") diff --git a/test/ExperimentalParallel.jl b/test/ExperimentalParallel.jl index c19f490..5b4640b 100644 --- a/test/ExperimentalParallel.jl +++ b/test/ExperimentalParallel.jl @@ -1,6 +1,6 @@ module ExperimentalParallel -using ExtendableSparse,SparseArrays +using ExtendableSparse, SparseArrays using ExtendableSparse.Experimental using BenchmarkTools using OhMyThreads: @tasks @@ -18,36 +18,36 @@ of color i which can be assembled independently. The current algorithm creates `nt^2` partitions with `nt` colors. """ -function part2d(X,Y, nt) - nt=max(4,nt) - XP=collect(ChunkSplitters.chunks(1:length(X)-1,n=nt)) - YP=collect(ChunkSplitters.chunks(1:length(Y)-1,n=nt)) - partitions = [Tuple{StepRange{Int64}, StepRange{Int64}}[] for i = 1:nt] - ipart=1 - col=1 - for jp=1:nt - for ip=1:nt +function part2d(X, Y, nt) + nt = max(4, nt) + XP = collect(ChunkSplitters.chunks(1:(length(X) - 1), n = nt)) + YP = collect(ChunkSplitters.chunks(1:(length(Y) - 1), n = nt)) + partitions = [Tuple{StepRange{Int64}, StepRange{Int64}}[] for i in 1:nt] + ipart = 1 + col = 1 + for jp in 1:nt + for ip in 1:nt push!(partitions[col], (XP[ip], YP[jp])) - col=(col -1 +1 )%nt+1 + col = (col - 1 + 1) % nt + 1 end - col=(col -1 +2)%nt+1 + col = (col - 1 + 2) % nt + 1 end - partitions + return partitions end -function colpart2d(X,Y,nt) - Nx=length(X) - Ny=length(Y) - p=part2d(X,Y,nt) - pc=zeros(Int,sum(length,p)) - jp=1 - for icol=1:length(p) - for ip=1:length(p[icol]) - pc[jp]=icol - jp+=1 +function colpart2d(X, Y, nt) + Nx = length(X) + Ny = length(Y) + p = part2d(X, Y, nt) + pc = zeros(Int, sum(length, p)) + jp = 1 + for icol in 1:length(p) + for ip in 1:length(p[icol]) + pc[jp] = icol + jp += 1 end end - p,pc + return p, pc end @@ -57,28 +57,28 @@ end Show grid partitioned according to [`part2d`](@ref). Needs a makie variant and ColorSchemes to be passed as modules. """ -function showgrid(Makie, ColorSchemes, X,Y,nt) +function showgrid(Makie, ColorSchemes, X, Y, nt) f = Makie.Figure() ax = Makie.Axis(f[1, 1]; aspect = 1) - p=part2d(X,Y,nt) - ncol=length(p) - @show sum(length,p), ncol - colors=get(ColorSchemes.rainbow,collect(1:ncol)/ncol) - poly=Vector{Makie.Point2f}(undef,4) - for icol = 1:ncol + p = part2d(X, Y, nt) + ncol = length(p) + @show sum(length, p), ncol + colors = get(ColorSchemes.rainbow, collect(1:ncol) / ncol) + poly = Vector{Makie.Point2f}(undef, 4) + for icol in 1:ncol for (xp, yp) in p[icol] for j in yp for i in xp - poly[1]=Makie.Point2f(X[i], Y[j]) - poly[2]=Makie.Point2f(X[i + 1], Y[j]) - poly[3]=Makie.Point2f(X[i + 1], Y[j + 1]) - poly[4]=Makie.Point2f(X[i], Y[j + 1]) - Makie.poly!(copy(poly),color = colors[icol]) + poly[1] = Makie.Point2f(X[i], Y[j]) + poly[2] = Makie.Point2f(X[i + 1], Y[j]) + poly[3] = Makie.Point2f(X[i + 1], Y[j + 1]) + poly[4] = Makie.Point2f(X[i], Y[j + 1]) + Makie.poly!(copy(poly), color = colors[icol]) end end end end - f + return f end @@ -87,18 +87,18 @@ end Assemble edge for finite volume laplacian. Used by [`partassemble!`](@ref). """ -function assembleedge!(A,v,k,l) - rawupdateindex!(A,+,v,k,k) - rawupdateindex!(A,+,-v,k,l) - rawupdateindex!(A,+,-v,l,k) - rawupdateindex!(A,+,v,l,l) +function assembleedge!(A, v, k, l) + rawupdateindex!(A, +, v, k, k) + rawupdateindex!(A, +, -v, k, l) + rawupdateindex!(A, +, -v, l, k) + return rawupdateindex!(A, +, v, l, l) end -function assembleedge!(A,v,k,l,tid) - rawupdateindex!(A,+,v,k,k,tid) - rawupdateindex!(A,+,-v,k,l,tid) - rawupdateindex!(A,+,-v,l,k,tid) - rawupdateindex!(A,+,v,l,l,tid) +function assembleedge!(A, v, k, l, tid) + rawupdateindex!(A, +, v, k, k, tid) + rawupdateindex!(A, +, -v, k, l, tid) + rawupdateindex!(A, +, -v, l, k, tid) + return rawupdateindex!(A, +, v, l, l, tid) end """ @@ -106,42 +106,42 @@ Assemble finite volume Laplacian + diagnonal term on grid cell `i,j`. Used by [`partassemble!`](@ref). """ -function assemblecell!(A,lindexes,X,Y,i,j,d) - hx=X[i+1]-X[i] - hy=Y[j+1]-Y[j] - ij00=lindexes[i,j] - ij10=lindexes[i+1,j] - ij11=lindexes[i+1,j+1] - ij01=lindexes[i,j+1] - - assembleedge!(A,0.5*hx/hy,ij00,ij01) - assembleedge!(A,0.5*hx/hy,ij10,ij11) - assembleedge!(A,0.5*hy/hx,ij00,ij10) - assembleedge!(A,0.5*hy/hx,ij01,ij11) - v=0.25*hx*hy - rawupdateindex!(A,+,v*d,ij00,ij00) - rawupdateindex!(A,+,v*d,ij01,ij01) - rawupdateindex!(A,+,v*d,ij10,ij10) - rawupdateindex!(A,+,v*d,ij11,ij11) +function assemblecell!(A, lindexes, X, Y, i, j, d) + hx = X[i + 1] - X[i] + hy = Y[j + 1] - Y[j] + ij00 = lindexes[i, j] + ij10 = lindexes[i + 1, j] + ij11 = lindexes[i + 1, j + 1] + ij01 = lindexes[i, j + 1] + + assembleedge!(A, 0.5 * hx / hy, ij00, ij01) + assembleedge!(A, 0.5 * hx / hy, ij10, ij11) + assembleedge!(A, 0.5 * hy / hx, ij00, ij10) + assembleedge!(A, 0.5 * hy / hx, ij01, ij11) + v = 0.25 * hx * hy + rawupdateindex!(A, +, v * d, ij00, ij00) + rawupdateindex!(A, +, v * d, ij01, ij01) + rawupdateindex!(A, +, v * d, ij10, ij10) + return rawupdateindex!(A, +, v * d, ij11, ij11) end -function assemblecell!(A,lindexes,X,Y,i,j,d,tid) - hx=X[i+1]-X[i] - hy=Y[j+1]-Y[j] - ij00=lindexes[i,j] - ij10=lindexes[i+1,j] - ij11=lindexes[i+1,j+1] - ij01=lindexes[i,j+1] - - assembleedge!(A,0.5*hx/hy,ij00,ij01,tid) - assembleedge!(A,0.5*hx/hy,ij10,ij11,tid) - assembleedge!(A,0.5*hy/hx,ij00,ij10,tid) - assembleedge!(A,0.5*hy/hx,ij01,ij11,tid) - v=0.25*hx*hy - rawupdateindex!(A,+,v*d,ij00,ij00,tid) - rawupdateindex!(A,+,v*d,ij01,ij01,tid) - rawupdateindex!(A,+,v*d,ij10,ij10,tid) - rawupdateindex!(A,+,v*d,ij11,ij11,tid) +function assemblecell!(A, lindexes, X, Y, i, j, d, tid) + hx = X[i + 1] - X[i] + hy = Y[j + 1] - Y[j] + ij00 = lindexes[i, j] + ij10 = lindexes[i + 1, j] + ij11 = lindexes[i + 1, j + 1] + ij01 = lindexes[i, j + 1] + + assembleedge!(A, 0.5 * hx / hy, ij00, ij01, tid) + assembleedge!(A, 0.5 * hx / hy, ij10, ij11, tid) + assembleedge!(A, 0.5 * hy / hx, ij00, ij10, tid) + assembleedge!(A, 0.5 * hy / hx, ij01, ij11, tid) + v = 0.25 * hx * hy + rawupdateindex!(A, +, v * d, ij00, ij00, tid) + rawupdateindex!(A, +, v * d, ij01, ij01, tid) + rawupdateindex!(A, +, v * d, ij10, ij10, tid) + return rawupdateindex!(A, +, v * d, ij11, ij11, tid) end """ @@ -150,20 +150,22 @@ Assemble finite volume Laplacian + diagnonal term on grid cells in partition described by ranges xp,yp. Used by [`partassemble!`](@ref). """ -function assemblepartition!(A,lindexes,X,Y,xp,yp,d) +function assemblepartition!(A, lindexes, X, Y, xp, yp, d) for j in yp - for i in xp - assemblecell!(A,lindexes,X,Y,i,j,d) - end + for i in xp + assemblecell!(A, lindexes, X, Y, i, j, d) + end end + return end -function assemblepartition!(A,lindexes,X,Y,xp,yp,d,tid) +function assemblepartition!(A, lindexes, X, Y, xp, yp, d, tid) for j in yp - for i in xp - assemblecell!(A,lindexes,X,Y,i,j,d,tid) - end + for i in xp + assemblecell!(A, lindexes, X, Y, i, j, d, tid) + end end + return end """ @@ -174,59 +176,57 @@ Partitioned, cellwise, multithreaded assembly of finite difference matrix for `X` and `Y` partitioned for work with `nt` threads Does not work during structure setup. """ -function partassemble!(A,X,Y,nt=1;d=0.1) - Nx=length(X) - Ny=length(Y) - size(A,1)==Nx*Ny || error("incompatible size of A") - size(A,2)==Nx*Ny || error("incompatible size of A") - - lindexes=LinearIndices((1:Nx,1:Ny)) - if nt==1 - assemblepartition!(A,lindexes,X,Y,1:Nx-1,1:Nx-1,d) +function partassemble!(A, X, Y, nt = 1; d = 0.1) + Nx = length(X) + Ny = length(Y) + size(A, 1) == Nx * Ny || error("incompatible size of A") + size(A, 2) == Nx * Ny || error("incompatible size of A") + + lindexes = LinearIndices((1:Nx, 1:Ny)) + if nt == 1 + assemblepartition!(A, lindexes, X, Y, 1:(Nx - 1), 1:(Nx - 1), d) else - p=part2d(X,Y,nt) - for icol=1:length(p) - @tasks for (xp, yp) in p[icol] - assemblepartition!(A,lindexes,X,Y,xp,yp,d) - end + p = part2d(X, Y, nt) + for icol in 1:length(p) + @tasks for (xp, yp) in p[icol] + assemblepartition!(A, lindexes, X, Y, xp, yp, d) + end end end - flush!(A) + return flush!(A) end -function partassemble!(A::Union{MTExtendableSparseMatrixCSC},X,Y,nt=1;d=0.1, reset=true) - Nx=length(X) - Ny=length(Y) +function partassemble!(A::Union{MTExtendableSparseMatrixCSC}, X, Y, nt = 1; d = 0.1, reset = true) + Nx = length(X) + Ny = length(Y) - size(A,1)==Nx*Ny || error("incompatible size of A") - size(A,2)==Nx*Ny || error("incompatible size of A") + size(A, 1) == Nx * Ny || error("incompatible size of A") + size(A, 2) == Nx * Ny || error("incompatible size of A") - lindexes=LinearIndices((1:Nx,1:Ny)) - if nt==1 - reset!(A,1) - assemblepartition!(A,lindexes,X,Y,1:Nx-1,1:Nx-1,d,1) + lindexes = LinearIndices((1:Nx, 1:Ny)) + if nt == 1 + reset!(A, 1) + assemblepartition!(A, lindexes, X, Y, 1:(Nx - 1), 1:(Nx - 1), d, 1) else - p,pc=colpart2d(X,Y,nt) + p, pc = colpart2d(X, Y, nt) if reset - reset!(A,pc) + reset!(A, pc) end - jp0=0 - for icol=1:length(p) - npc=length(p[icol]) - @tasks for ip=1:npc - (xp, yp)=p[icol][ip] - assemblepartition!(A,lindexes,X,Y,xp,yp,d,jp0+ip) - end - jp0+=npc + jp0 = 0 + for icol in 1:length(p) + npc = length(p[icol]) + @tasks for ip in 1:npc + (xp, yp) = p[icol][ip] + assemblepartition!(A, lindexes, X, Y, xp, yp, d, jp0 + ip) + end + jp0 += npc end end - flush!(A) + return flush!(A) end - - """ `test_ESMP(n, nt; depth=1, Tv=Float64, Ti=Int64, k=10)` @@ -234,14 +234,14 @@ Measure and output times for build and update for a rectangle grid with `n * n` Calculations are done on `nt` threads (`nt` >= 1). Returns the assembled matrix. """ -function test_ESMP(n, nt; depth=1, Tv=Float64, Ti=Int64, k=10) +function test_ESMP(n, nt; depth = 1, Tv = Float64, Ti = Int64, k = 10) m = n - lindexes = LinearIndices((1:n,1:m)) + lindexes = LinearIndices((1:n, 1:m)) mat_cell_node, nc, nn = generate_rectangle_grid(lindexes, Ti) if nt > 1 - A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct=false) + A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct = false) else - A = ExtendableSparseMatrix{Tv, Ti}(n*m, n*m) + A = ExtendableSparseMatrix{Tv, Ti}(n * m, n * m) end X = collect(1:n) #LinRange(0,1,n) @@ -249,97 +249,96 @@ function test_ESMP(n, nt; depth=1, Tv=Float64, Ti=Int64, k=10) #Build times_build = zeros(k) - for i=1:k + for i in 1:k ExtendableSparse.reset!(A) - times_build[i] = @elapsed assemble_ESMP(A, n-1, m-1, mat_cell_node, X, Y; set_CSC_zero=false) + times_build[i] = @elapsed assemble_ESMP(A, n - 1, m - 1, mat_cell_node, X, Y; set_CSC_zero = false) end - #update times_update = zeros(k) - for i=1:k - times_update[i] = @elapsed assemble_ESMP(A, n-1, m-1, mat_cell_node, X, Y; set_CSC_zero=true) + for i in 1:k + times_update[i] = @elapsed assemble_ESMP(A, n - 1, m - 1, mat_cell_node, X, Y; set_CSC_zero = true) end @info "TIMES: MIN, AVG, MAX" info_minmax(times_build, "build ") info_minmax(times_update, "update") - - A + + return A end -function test_correctness_build(n, depth=1, Tv=Float64, Ti=Int64, allnp=[4,5,6,7,8,9,10]) +function test_correctness_build(n, depth = 1, Tv = Float64, Ti = Int64, allnp = [4, 5, 6, 7, 8, 9, 10]) m = n - lindexes = LinearIndices((1:n,1:m)) + lindexes = LinearIndices((1:n, 1:m)) X = collect(1:n) #LinRange(0,1,n) Y = collect(1:n) #LinRange(0,1,m) - + mat_cell_node, nc, nn = generate_rectangle_grid(lindexes, Ti) - - A0 = ExtendableSparseMatrix{Tv, Ti}(n*m, n*m) - assemble_ESMP(A0, n-1, m-1, mat_cell_node, X, Y; set_CSC_zero=false) + + A0 = ExtendableSparseMatrix{Tv, Ti}(n * m, n * m) + assemble_ESMP(A0, n - 1, m - 1, mat_cell_node, X, Y; set_CSC_zero = false) for nt in allnp - A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct=false) - assemble_ESMP(A, n-1, m-1, mat_cell_node, X, Y; set_CSC_zero=false) - @assert A.cscmatrix≈A0.cscmatrix + A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct = false) + assemble_ESMP(A, n - 1, m - 1, mat_cell_node, X, Y; set_CSC_zero = false) + @assert A.cscmatrix ≈ A0.cscmatrix end + return end -function speedup_build(n, depth=1, Tv=Float64, Ti=Int64, allnp=[4,5,6,7,8,9,10]) +function speedup_build(n, depth = 1, Tv = Float64, Ti = Int64, allnp = [4, 5, 6, 7, 8, 9, 10]) m = n - lindexes = LinearIndices((1:n,1:m)) + lindexes = LinearIndices((1:n, 1:m)) X = collect(1:n) #LinRange(0,1,n) Y = collect(1:n) #LinRange(0,1,m) mat_cell_node, nc, nn = generate_rectangle_grid(lindexes, Ti) - A0 = ExtendableSparseMatrix{Tv, Ti}(n*m, n*m) - t0=@belapsed assemble_ESMP($A0, $n-1, $m-1, $mat_cell_node, $X, $Y; set_CSC_zero=false) seconds=1 setup=(reset!($A0)) - - result=[] + A0 = ExtendableSparseMatrix{Tv, Ti}(n * m, n * m) + t0 = @belapsed assemble_ESMP($A0, $n - 1, $m - 1, $mat_cell_node, $X, $Y; set_CSC_zero = false) seconds = 1 setup = (reset!($A0)) + + result = [] for nt in allnp - A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct=false) - t=@belapsed assemble_ESMP($A, $n-1, $m-1, $mat_cell_node, $X, $Y; set_CSC_zero=false) setup=(ExtendableSparse.reset!($A)) seconds=1 - @assert A.cscmatrix≈A0.cscmatrix - push!(result,(nt,round(t0/t,digits=2))) + A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct = false) + t = @belapsed assemble_ESMP($A, $n - 1, $m - 1, $mat_cell_node, $X, $Y; set_CSC_zero = false) setup = (ExtendableSparse.reset!($A)) seconds = 1 + @assert A.cscmatrix ≈ A0.cscmatrix + push!(result, (nt, round(t0 / t, digits = 2))) end - result - + return result + end -function speedup_update(n, depth=1, Tv=Float64, Ti=Int64, allnp=[4,5,6,7,8,9,10]) +function speedup_update(n, depth = 1, Tv = Float64, Ti = Int64, allnp = [4, 5, 6, 7, 8, 9, 10]) m = n - lindexes = LinearIndices((1:n,1:m)) + lindexes = LinearIndices((1:n, 1:m)) X = collect(1:n) #LinRange(0,1,n) Y = collect(1:n) #LinRange(0,1,m) mat_cell_node, nc, nn = generate_rectangle_grid(lindexes, Ti) - A0 = ExtendableSparseMatrix{Tv, Ti}(n*m, n*m) - assemble_ESMP(A0, n-1, m-1, mat_cell_node, X, Y) - t0=@belapsed assemble_ESMP($A0, $n-1, $m-1, $mat_cell_node, $X, $Y; set_CSC_zero=false) seconds=1 setup=(nonzeros($A0.cscmatrix).=0) - + A0 = ExtendableSparseMatrix{Tv, Ti}(n * m, n * m) + assemble_ESMP(A0, n - 1, m - 1, mat_cell_node, X, Y) + t0 = @belapsed assemble_ESMP($A0, $n - 1, $m - 1, $mat_cell_node, $X, $Y; set_CSC_zero = false) seconds = 1 setup = (nonzeros($A0.cscmatrix) .= 0) - result=[] + result = [] for nt in allnp - A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct=false) - assemble_ESMP(A, n-1, m-1, mat_cell_node, X, Y; set_CSC_zero=false) - t=@belapsed assemble_ESMP($A, $n-1, $m-1, $mat_cell_node, $X, $Y; set_CSC_zero=false) setup=(nonzeros($A.cscmatrix).=0) seconds=1 - @assert A.cscmatrix≈A0.cscmatrix - push!(result,(nt,round(t0/t,digits=2))) + A = ExtendableSparseMatrixParallel{Tv, Ti}(mat_cell_node, nc, nn, nt, depth; block_struct = false) + assemble_ESMP(A, n - 1, m - 1, mat_cell_node, X, Y; set_CSC_zero = false) + t = @belapsed assemble_ESMP($A, $n - 1, $m - 1, $mat_cell_node, $X, $Y; set_CSC_zero = false) setup = (nonzeros($A.cscmatrix) .= 0) seconds = 1 + @assert A.cscmatrix ≈ A0.cscmatrix + push!(result, (nt, round(t0 / t, digits = 2))) end - result - + return result + end @@ -349,138 +348,137 @@ end Generate a rectangle grid (i.e. a CellNodes matrix) based on LinerIndices """ function generate_rectangle_grid(lindexes, Ti) - n,m = size(lindexes) - nn = n*m # num nodes - nc = (n-1)*(m-1) + n, m = size(lindexes) + nn = n * m # num nodes + nc = (n - 1) * (m - 1) #lindexes=LinearIndices((1:n,1:m)) mat_cell_node = zeros(Ti, 4, nc) # links oben, rechts oben, rechts unten, links unten cell_id = 1 - for ir in 1:n-1 - for jr in 1:m-1 - mat_cell_node[1,cell_id] = lindexes[ir,jr] - mat_cell_node[2,cell_id] = lindexes[ir,jr+1] - mat_cell_node[3,cell_id] = lindexes[ir+1,jr+1] - mat_cell_node[4,cell_id] = lindexes[ir+1,jr] + for ir in 1:(n - 1) + for jr in 1:(m - 1) + mat_cell_node[1, cell_id] = lindexes[ir, jr] + mat_cell_node[2, cell_id] = lindexes[ir, jr + 1] + mat_cell_node[3, cell_id] = lindexes[ir + 1, jr + 1] + mat_cell_node[4, cell_id] = lindexes[ir + 1, jr] cell_id += 1 end end - mat_cell_node, nc, nn + return mat_cell_node, nc, nn end -function info_minmax(x, name; digits=3) +function info_minmax(x, name; digits = 3) n = length(x) - @info name*" $(round(minimum(x),digits=digits)), $(round(sum(x)/n,digits=digits)), $(round(maximum(x),digits=digits))" + return @info name * " $(round(minimum(x), digits = digits)), $(round(sum(x) / n, digits = digits)), $(round(maximum(x), digits = digits))" end """ Assembly functions for ExtendableSparseMatrixParallel """ -function assemble_ESMP(A::ExtendableSparseMatrixParallel{Tv, Ti}, n, m, mat_cell_node, X, Y; d=0.1, set_CSC_zero=true) where {Tv, Ti <: Integer} +function assemble_ESMP(A::ExtendableSparseMatrixParallel{Tv, Ti}, n, m, mat_cell_node, X, Y; d = 0.1, set_CSC_zero = true) where {Tv, Ti <: Integer} if set_CSC_zero A.cscmatrix.nzval .= 0 end - for level=1:A.depth - @tasks for tid=1:A.nt - for cell in A.cellsforpart[(level-1)*A.nt+tid] + for level in 1:A.depth + @tasks for tid in 1:A.nt + for cell in A.cellsforpart[(level - 1) * A.nt + tid] assemblecell!(A, n, m, mat_cell_node, X, Y, d, cell, tid) end end end - for cell in A.cellsforpart[A.depth*A.nt+1] + for cell in A.cellsforpart[A.depth * A.nt + 1] assemblecell!(A, n, m, mat_cell_node, X, Y, d, cell, 1) end nnzCSC, nnzLNK = nnz_noflush(A) - if nnzCSC > 0 && nnzLNK > 0 - flush!(A; do_dense=false) + return if nnzCSC > 0 && nnzLNK > 0 + flush!(A; do_dense = false) #sparse flush elseif nnzCSC == 0 && nnzLNK > 0 - flush!(A; do_dense=true) + flush!(A; do_dense = true) #dense flush end end -function assembleedge!(A::ExtendableSparseMatrixParallel{Tv, Ti},v,k,l,tid) where {Tv, Ti <: Integer} +function assembleedge!(A::ExtendableSparseMatrixParallel{Tv, Ti}, v, k, l, tid) where {Tv, Ti <: Integer} addtoentry!(A, k, k, tid, +v) addtoentry!(A, k, l, tid, -v) addtoentry!(A, l, k, tid, -v) - addtoentry!(A, l, l, tid, +v) + return addtoentry!(A, l, l, tid, +v) end -function assemblecell!(A::ExtendableSparseMatrixParallel{Tv, Ti},n,m,mcn,X,Y,d,cell,tid) where {Tv, Ti <: Integer} - ij00=mcn[1,cell] - ij10=mcn[2,cell] - ij11=mcn[3,cell] - ij01=mcn[4,cell] - - ix = (cell-1)%n+1 - iy = Int64(ceil(cell/n)) - - hx=X[ix+1]-X[ix] - hy=Y[iy+1]-Y[iy] - - assembleedge!(A,0.5*hx/hy,ij00,ij01,tid) - assembleedge!(A,0.5*hx/hy,ij10,ij11,tid) - assembleedge!(A,0.5*hy/hx,ij00,ij10,tid) - assembleedge!(A,0.5*hy/hx,ij01,ij11,tid) - v=0.25*hx*hy - addtoentry!(A, ij00, ij00, tid, v*d) - addtoentry!(A, ij01, ij01, tid, v*d) - addtoentry!(A, ij10, ij10, tid, v*d) - addtoentry!(A, ij11, ij11, tid, v*d) +function assemblecell!(A::ExtendableSparseMatrixParallel{Tv, Ti}, n, m, mcn, X, Y, d, cell, tid) where {Tv, Ti <: Integer} + ij00 = mcn[1, cell] + ij10 = mcn[2, cell] + ij11 = mcn[3, cell] + ij01 = mcn[4, cell] + + ix = (cell - 1) % n + 1 + iy = Int64(ceil(cell / n)) + + hx = X[ix + 1] - X[ix] + hy = Y[iy + 1] - Y[iy] + + assembleedge!(A, 0.5 * hx / hy, ij00, ij01, tid) + assembleedge!(A, 0.5 * hx / hy, ij10, ij11, tid) + assembleedge!(A, 0.5 * hy / hx, ij00, ij10, tid) + assembleedge!(A, 0.5 * hy / hx, ij01, ij11, tid) + v = 0.25 * hx * hy + addtoentry!(A, ij00, ij00, tid, v * d) + addtoentry!(A, ij01, ij01, tid, v * d) + addtoentry!(A, ij10, ij10, tid, v * d) + return addtoentry!(A, ij11, ij11, tid, v * d) end - """ Assembly functions for ExtendableSparseMatrix """ -function assemble_ESMP(A::ExtendableSparseMatrix{Tv, Ti}, n, m, mat_cell_node, X, Y; d=0.1, set_CSC_zero=true) where {Tv, Ti <: Integer} +function assemble_ESMP(A::ExtendableSparseMatrix{Tv, Ti}, n, m, mat_cell_node, X, Y; d = 0.1, set_CSC_zero = true) where {Tv, Ti <: Integer} if set_CSC_zero A.cscmatrix.nzval .= 0 end - nc = size(mat_cell_node,2) - for cell=1:nc + nc = size(mat_cell_node, 2) + for cell in 1:nc assemblecell!(A, n, m, mat_cell_node, X, Y, d, cell) end - ExtendableSparse.flush!(A) + return ExtendableSparse.flush!(A) end -function assembleedge!(A::ExtendableSparseMatrix{Tv, Ti},v,k,l) where {Tv, Ti <: Integer} - A[k,k]+=v - A[k,l]-=v - A[l,k]-=v - A[l,l]+=v +function assembleedge!(A::ExtendableSparseMatrix{Tv, Ti}, v, k, l) where {Tv, Ti <: Integer} + A[k, k] += v + A[k, l] -= v + A[l, k] -= v + return A[l, l] += v end -function assemblecell!(A::ExtendableSparseMatrix{Tv, Ti},n,m,mcn,X,Y,d,cell) where {Tv, Ti <: Integer} - ij00=mcn[1,cell] - ij10=mcn[2,cell] - ij11=mcn[3,cell] - ij01=mcn[4,cell] - - ix = (cell-1)%n+1 - iy = Int64(ceil(cell/n)) - - hx=X[ix+1]-X[ix] - hy=Y[iy+1]-Y[iy] - - assembleedge!(A,0.5*hx/hy,ij00,ij01) - assembleedge!(A,0.5*hx/hy,ij10,ij11) - assembleedge!(A,0.5*hy/hx,ij00,ij10) - assembleedge!(A,0.5*hy/hx,ij01,ij11) - v=0.25*hx*hy - A[ij00,ij00]+=v*d - A[ij01,ij01]+=v*d - A[ij10,ij10]+=v*d - A[ij11,ij11]+=v*d +function assemblecell!(A::ExtendableSparseMatrix{Tv, Ti}, n, m, mcn, X, Y, d, cell) where {Tv, Ti <: Integer} + ij00 = mcn[1, cell] + ij10 = mcn[2, cell] + ij11 = mcn[3, cell] + ij01 = mcn[4, cell] + + ix = (cell - 1) % n + 1 + iy = Int64(ceil(cell / n)) + + hx = X[ix + 1] - X[ix] + hy = Y[iy + 1] - Y[iy] + + assembleedge!(A, 0.5 * hx / hy, ij00, ij01) + assembleedge!(A, 0.5 * hx / hy, ij10, ij11) + assembleedge!(A, 0.5 * hy / hx, ij00, ij10) + assembleedge!(A, 0.5 * hy / hx, ij01, ij11) + v = 0.25 * hx * hy + A[ij00, ij00] += v * d + A[ij01, ij01] += v * d + A[ij10, ij10] += v * d + return A[ij11, ij11] += v * d end end diff --git a/test/femtools.jl b/test/femtools.jl index 8c7e652..b0b49a9 100644 --- a/test/femtools.jl +++ b/test/femtools.jl @@ -1,17 +1,17 @@ using OhMyThreads: @tasks using RecursiveFactorization -function testgrid(N; dim=3) - X = range(0, 1; length=N^(1.0 / dim) |> ceil |> Int) - simplexgrid((X for i = 1:dim)...) +function testgrid(N; dim = 3) + X = range(0, 1; length = N^(1.0 / dim) |> ceil |> Int) + return simplexgrid((X for i in 1:dim)...) end function coordmatrix!(C, coord, cellnodes, k) - spacedim=size(coord,1) - celldim=size(cellnodes,1) - @inbounds for jj = 1:celldim + spacedim = size(coord, 1) + celldim = size(cellnodes, 1) + return @inbounds for jj in 1:celldim C[1, jj] = 1 - @inbounds for ii = 1:spacedim + @inbounds for ii in 1:spacedim C[ii + 1, jj] = coord[ii, cellnodes[jj, k]] end end @@ -20,21 +20,21 @@ end function gradient!(G, C, factdim, I, ipiv) clu = RecursiveFactorization.lu!(C, ipiv, Val(true), Val(false)) ldiv!(G, clu, I) - abs(det(clu)) / factdim + return abs(det(clu)) / factdim end function scalpro(G, dim, jl, il) s = 0.0 - @inbounds @simd for k = 1:dim + @inbounds @simd for k in 1:dim s += G[jl, k + 1] * G[il, k + 1] end return s end function stiffness!(S, dim, G) - @inbounds for il = 1:(dim + 1) + @inbounds for il in 1:(dim + 1) S[il, il] = scalpro(G, dim, il, il) - @inbounds for jl = (il + 1):(dim + 1) + @inbounds for jl in (il + 1):(dim + 1) S[il, jl] = scalpro(G, dim, jl, il) S[jl, il] = S[il, jl] end @@ -55,20 +55,20 @@ function testassemble!(A_h, grid) ipiv = zeros(Int, lnodes) I = Matrix(Diagonal(ones(lnodes))) ncells = size(cellnodes, 2) - for icell = 1:ncells + for icell in 1:ncells coordmatrix!(C, coord, cellnodes, icell) vol = gradient!(G, C, factdim, I, ipiv) stiffness!(S, dim, G) - for il = 1:lnodes + for il in 1:lnodes i = cellnodes[il, icell] rawupdateindex!(A_h, +, 0.1 * vol / (dim + 1), i, i) - for jl = 1:lnodes + for jl in 1:lnodes j = cellnodes[jl, icell] rawupdateindex!(A_h, +, vol * (S[il, jl]), i, j) end end end - flush!(A_h) + return flush!(A_h) end function testassemble_parallel!(A_h, grid) @@ -79,10 +79,10 @@ function testassemble_parallel!(A_h, grid) lnodes = dim + 1 npart = num_partitions(grid) factdim::Float64 = factorial(dim) - SS = [zeros(lnodes, lnodes) for i = 1:npart] # local stiffness matrix - CC = [zeros(lnodes, lnodes) for i = 1:npart] # local coordinate matrix - GG = [zeros(lnodes, lnodes) for i = 1:npart] # shape function gradients - IP = [zeros(Int, lnodes) for i = 1:npart] # shape function gradients + SS = [zeros(lnodes, lnodes) for i in 1:npart] # local stiffness matrix + CC = [zeros(lnodes, lnodes) for i in 1:npart] # local coordinate matrix + GG = [zeros(lnodes, lnodes) for i in 1:npart] # shape function gradients + IP = [zeros(Int, lnodes) for i in 1:npart] # shape function gradients I = Matrix(Diagonal(ones(lnodes))) ncells = size(cellnodes, 2) for color in pcolors(grid) @@ -95,10 +95,10 @@ function testassemble_parallel!(A_h, grid) coordmatrix!(C, coord, cellnodes, icell) vol = gradient!(G, C, factdim, I, ipiv) stiffness!(S, dim, G) - for il = 1:lnodes + for il in 1:lnodes i = cellnodes[il, icell] rawupdateindex!(A_h, +, 0.1 * vol / (dim + 1), i, i, part) - for jl = 1:lnodes + for jl in 1:lnodes j = cellnodes[jl, icell] rawupdateindex!(A_h, +, vol * (S[il, jl]), i, j, part) end @@ -106,5 +106,5 @@ function testassemble_parallel!(A_h, grid) end end end - flush!(A_h) + return flush!(A_h) end diff --git a/test/runtests.jl b/test/runtests.jl index 93bf1b7..d404fe2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -19,16 +19,16 @@ end include("test_parallel.jl") for Tm in [STExtendableSparseMatrixCSC, MTExtendableSparseMatrixCSC, ExtendableSparseMatrix] - for N in [10000,20000] - test_parallel.test_correctness_build_seq(N,Tm, dim=2) + for N in [10000, 20000] + test_parallel.test_correctness_build_seq(N, Tm, dim = 2) end end for Tm in [MTExtendableSparseMatrixCSC] - for N in [10000,20000] - test_parallel.test_correctness_update(N,Tm, dim=2) - test_parallel.test_correctness_build(N,Tm, dim=2) - test_parallel.test_correctness_mul(N,Tm,dim=2) + for N in [10000, 20000] + test_parallel.test_correctness_update(N, Tm, dim = 2) + test_parallel.test_correctness_build(N, Tm, dim = 2) + test_parallel.test_correctness_mul(N, Tm, dim = 2) end end end @@ -43,39 +43,71 @@ end # end -@testset "Constructors" begin include("test_constructors.jl") end +@testset "Constructors" begin + include("test_constructors.jl") +end -@testset "Copy-Methods" begin include("test_copymethods.jl") end +@testset "Copy-Methods" begin + include("test_copymethods.jl") +end -@testset "Updates" begin include("test_updates.jl") end +@testset "Updates" begin + include("test_updates.jl") +end -@testset "Assembly" begin include("test_assembly.jl") end +@testset "Assembly" begin + include("test_assembly.jl") +end -@testset "Construction timings" begin include("test_timings.jl") end +@testset "Construction timings" begin + include("test_timings.jl") +end -@testset "Operations" begin include("test_operations.jl") end +@testset "Operations" begin + include("test_operations.jl") +end -@testset "fdrand" begin include("test_fdrand.jl") end +@testset "fdrand" begin + include("test_fdrand.jl") +end -@testset "Backslash" begin include("test_backslash.jl") end +@testset "Backslash" begin + include("test_backslash.jl") +end -@testset "Dirichlet" begin include("test_dirichlet.jl") end +@testset "Dirichlet" begin + include("test_dirichlet.jl") +end -@testset "LinearSolve" begin include("test_linearsolve.jl") end +@testset "LinearSolve" begin + include("test_linearsolve.jl") +end -@testset "Preconditioners" begin include("test_preconditioners.jl") end +@testset "Preconditioners" begin + include("test_preconditioners.jl") +end -@testset "Symmetric" begin include("test_symmetric.jl") end +@testset "Symmetric" begin + include("test_symmetric.jl") +end -@testset "ExtendableSparse.LUFactorization" begin include("test_default_lu.jl") end +@testset "ExtendableSparse.LUFactorization" begin + include("test_default_lu.jl") +end -@testset "Sparspak" begin include("test_sparspak.jl") end +@testset "Sparspak" begin + include("test_sparspak.jl") +end if ExtendableSparse.USE_GPL_LIBS - @testset "Cholesky" begin include("test_default_cholesky.jl") end + @testset "Cholesky" begin + include("test_default_cholesky.jl") + end end -@testset "block" begin include("test_block.jl") end +@testset "block" begin + include("test_block.jl") +end #@testset "parilu0" begin include("test_parilu0.jl") end diff --git a/test/test_assembly.jl b/test/test_assembly.jl index 2331a7e..16cc9fb 100644 --- a/test/test_assembly.jl +++ b/test/test_assembly.jl @@ -7,8 +7,8 @@ function test(; m = 1000, n = 1000, xnnz = 5000, nsplice = 1) A = ExtendableSparseMatrix{Float64, Int64}(m, n) m, n = size(A) S = spzeros(m, n) - for isplice = 1:nsplice - for inz = 1:xnnz + for isplice in 1:nsplice + for inz in 1:xnnz i = rand((1:m)) j = rand((1:n)) a = 1.0 + rand() @@ -16,19 +16,19 @@ function test(; m = 1000, n = 1000, xnnz = 5000, nsplice = 1) A[i, j] += a end flush!(A) - for j = 1:n + for j in 1:n @assert(issorted(A.cscmatrix.rowval[A.cscmatrix.colptr[j]:(A.cscmatrix.colptr[j + 1] - 1)])) end - @assert(nnz(S)==nnz(A)) + @assert(nnz(S) == nnz(A)) (I, J, V) = findnz(S) - for inz = 1:nnz(S) - @assert(A[I[inz], J[inz]]==V[inz]) + for inz in 1:nnz(S) + @assert(A[I[inz], J[inz]] == V[inz]) end (I, J, V) = findnz(A) - for inz = 1:nnz(A) - @assert(S[I[inz], J[inz]]==V[inz]) + for inz in 1:nnz(A) + @assert(S[I[inz], J[inz]] == V[inz]) end end return true @@ -46,7 +46,7 @@ end @test test(m = 100, n = 200, xnnz = 500, nsplice = 2) @test test(m = 1000, n = 2000, xnnz = 5000, nsplice = 3) -for irun = 1:10 +for irun in 1:10 m = rand((1:10000)) n = rand((1:10000)) nnz = rand((1:10000)) diff --git a/test/test_backslash.jl b/test/test_backslash.jl index f878fbe..da9cda4 100644 --- a/test/test_backslash.jl +++ b/test/test_backslash.jl @@ -13,7 +13,7 @@ function test_bslash(T, k, l, m) A = fdrand(T, k, l, m; rand = () -> one(T), matrixtype = ExtendableSparseMatrix) x = ones(T, size(A, 1)) b = A * x - norm(f64.(A \ b - x)) + return norm(f64.(A \ b - x)) end function test_bslash(T) @@ -21,7 +21,7 @@ function test_bslash(T) atol = 10.0 * sqrt(f64(eps(T))) @test isapprox(test_bslash(T, 100, 1, 1), 0.0; atol) @test isapprox(test_bslash(T, 20, 20, 1), 0.0; atol) - @test isapprox(test_bslash(T, 10, 10, 10), 0.0; atol) + return @test isapprox(test_bslash(T, 10, 10, 10), 0.0; atol) end test_bslash(Float32) diff --git a/test/test_block.jl b/test/test_block.jl index 22cabc1..010971e 100644 --- a/test/test_block.jl +++ b/test/test_block.jl @@ -7,46 +7,46 @@ using LinearAlgebra using Sparspak using AMGCLWrap -ExtendableSparse.allow_views(::typeof(ilu0))=true - -function main(;n=100) - - A=fdrand(n,n) - partitioning=[1:2:n^2, 2:2:n^2] - sol0=ones(n^2) - b=A*ones(n^2); - sol=cg(A,b,Pl=ilu0(A)) - - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning)) - @test sol≈sol0 - - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=ilu0)) - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=ILUZeroPreconditioner)) - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=ILU0Preconditioner)) - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=JacobiPreconditioner)) - @test sol≈sol0 - - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=AMGPreconditioner)) - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=sparspaklu)) - @test sol≈sol0 - - sol=cg(A,b,Pl=BlockPreconditioner(A;partitioning, factorization=SparspakLU)) - @test sol≈sol0 +ExtendableSparse.allow_views(::typeof(ilu0)) = true + +function main(; n = 100) + + A = fdrand(n, n) + partitioning = [1:2:(n^2), 2:2:(n^2)] + sol0 = ones(n^2) + b = A * ones(n^2) + sol = cg(A, b, Pl = ilu0(A)) + + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning)) + @test sol ≈ sol0 + + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = ilu0)) + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = ILUZeroPreconditioner)) + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = ILU0Preconditioner)) + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = JacobiPreconditioner)) + @test sol ≈ sol0 + + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = AMGPreconditioner)) + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = sparspaklu)) + @test sol ≈ sol0 + + sol = cg(A, b, Pl = BlockPreconditioner(A; partitioning, factorization = SparspakLU)) + return @test sol ≈ sol0 end -main(n=100) +main(n = 100) end diff --git a/test/test_constructors.jl b/test/test_constructors.jl index 693309d..50e4fc1 100644 --- a/test/test_constructors.jl +++ b/test/test_constructors.jl @@ -8,26 +8,28 @@ using MultiFloats using ForwardDiff const Dual64 = ForwardDiff.Dual{Float64, Float64, 1} -function Random.rand(rng::AbstractRNG, - ::Random.SamplerType{ForwardDiff.Dual{T, V, N}}) where {T, V, N} - ForwardDiff.Dual{T, V, N}(rand(rng, T)) +function Random.rand( + rng::AbstractRNG, + ::Random.SamplerType{ForwardDiff.Dual{T, V, N}} + ) where {T, V, N} + return ForwardDiff.Dual{T, V, N}(rand(rng, T)) end function test_construct(T) m = ExtendableSparseMatrix(T, 10, 10) - eltype(m) == T + return eltype(m) == T end function test_sprand(T) m = ExtendableSparseMatrix(sprand(T, 10, 10, 0.1)) - eltype(m) == T + return eltype(m) == T end function test_transient_construction(; m = 10, n = 10, d = 0.1) csc = sprand(m, n, d) lnk = SparseMatrixLNK(csc) csc2 = SparseMatrixCSC(lnk) - csc2 == csc + return csc2 == csc end function test() @@ -43,7 +45,7 @@ function test() D = Diagonal(rand(10)) ED = ExtendableSparseMatrix(D) - @test all([D[i, i] == ED[i, i] for i = 1:10]) + @test all([D[i, i] == ED[i, i] for i in 1:10]) I = rand(1:10, 100) J = rand(1:10, 100) @@ -56,12 +58,13 @@ function test() @test test_sprand(Float64x2) @test test_sprand(Dual64) - for irun = 1:10 + for irun in 1:10 m = rand((1:1000)) n = rand((1:1000)) d = 0.3 * rand() @test test_transient_construction(m = m, n = n, d = d) end + return end test() end diff --git a/test/test_copymethods.jl b/test/test_copymethods.jl index baf100f..e131a76 100644 --- a/test/test_copymethods.jl +++ b/test/test_copymethods.jl @@ -7,9 +7,11 @@ using MultiFloats using ForwardDiff const Dual64 = ForwardDiff.Dual{Float64, Float64, 1} -function Random.rand(rng::AbstractRNG, - ::Random.SamplerType{ForwardDiff.Dual{T, V, N}}) where {T, V, N} - ForwardDiff.Dual{T, V, N}(rand(rng, T)) +function Random.rand( + rng::AbstractRNG, + ::Random.SamplerType{ForwardDiff.Dual{T, V, N}} + ) where {T, V, N} + return ForwardDiff.Dual{T, V, N}(rand(rng, T)) end function test(T) @@ -22,11 +24,11 @@ function test(T) if !(t1 / t0 < 10 && t0 / t2 < 10) @warn """timing test failed. -If this occurs just once or twice, it is probably due to CPU noise. -So we nevertheless count this as passing. -""" + If this occurs just once or twice, it is probably due to CPU noise. + So we nevertheless count this as passing. + """ end - true + return true end test(Float64) test(Float64x2) diff --git a/test/test_dirichlet.jl b/test/test_dirichlet.jl index 794a137..4da8e7c 100644 --- a/test/test_dirichlet.jl +++ b/test/test_dirichlet.jl @@ -5,26 +5,26 @@ using SparseArrays using LinearAlgebra function tdirichlet(A) - n=size(A,1) - for i=1:10:n - A[i,i]=1.0e30 + n = size(A, 1) + for i in 1:10:n + A[i, i] = 1.0e30 end - f=ones(n) - u=A\f - diri=mark_dirichlet(A) - fD=f.* (1 .-diri) - AD=eliminate_dirichlet(A,diri) - uD=AD\fD - norm(uD-u,Inf) < 1.0e-20 + f = ones(n) + u = A \ f + diri = mark_dirichlet(A) + fD = f .* (1 .- diri) + AD = eliminate_dirichlet(A, diri) + uD = AD \ fD + return norm(uD - u, Inf) < 1.0e-20 end @test tdirichlet(fdrand(1000; matrixtype = SparseMatrixCSC)) @test tdirichlet(fdrand(1000; matrixtype = ExtendableSparseMatrix)) -@test tdirichlet(fdrand(20,20; matrixtype = SparseMatrixCSC)) -@test tdirichlet(fdrand(20,20; matrixtype = ExtendableSparseMatrix)) +@test tdirichlet(fdrand(20, 20; matrixtype = SparseMatrixCSC)) +@test tdirichlet(fdrand(20, 20; matrixtype = ExtendableSparseMatrix)) -@test tdirichlet(fdrand(10,10,10, matrixtype = SparseMatrixCSC)) -@test tdirichlet(fdrand(10,10,10; matrixtype = ExtendableSparseMatrix)) +@test tdirichlet(fdrand(10, 10, 10, matrixtype = SparseMatrixCSC)) +@test tdirichlet(fdrand(10, 10, 10; matrixtype = ExtendableSparseMatrix)) end diff --git a/test/test_fdrand.jl b/test/test_fdrand.jl index be1ec51..6dc2a63 100644 --- a/test/test_fdrand.jl +++ b/test/test_fdrand.jl @@ -15,41 +15,47 @@ function test_fdrand0(T, k, l, m; symmetric = true) jacobi_iteration_matrix = I - inv(Diagonal(A)) * A ext = extrema(real(eigvals(Float64.(ForwardDiff.value.(Matrix(jacobi_iteration_matrix)))))) mininv = minimum(inv(Matrix(A))) - abs(ext[1]) < 1 && abs(ext[2]) < 1 && mininv > 0 + return abs(ext[1]) < 1 && abs(ext[2]) < 1 && mininv > 0 end ############################################## function test_fdrand_coo(T, k, l, m) Acsc = fdrand(T, k, l, m; rand = () -> 1, matrixtype = SparseMatrixCSC) Acoo = fdrand(T, k, l, m; rand = () -> 1, matrixtype = :COO) - Acsc ≈ Acoo + return Acsc ≈ Acoo end ############################################## function test_fdrand_update(T, k, l, m) - A1 = fdrand(T, - k, - l, - m; - rand = () -> 1, - matrixtype = ExtendableSparseMatrix, - update = (A, v, i, j) -> A[i, j] += v) - A2 = fdrand(T, - k, - l, - m; - rand = () -> 1, - matrixtype = ExtendableSparseMatrix, - update = (A, v, i, j) -> rawupdateindex!(A, +, v, i, j)) - A3 = fdrand(T, - k, - l, - m; - rand = () -> 1, - matrixtype = ExtendableSparseMatrix, - update = (A, v, i, j) -> updateindex!(A, +, v, i, j)) + A1 = fdrand( + T, + k, + l, + m; + rand = () -> 1, + matrixtype = ExtendableSparseMatrix, + update = (A, v, i, j) -> A[i, j] += v + ) + A2 = fdrand( + T, + k, + l, + m; + rand = () -> 1, + matrixtype = ExtendableSparseMatrix, + update = (A, v, i, j) -> rawupdateindex!(A, +, v, i, j) + ) + A3 = fdrand( + T, + k, + l, + m; + rand = () -> 1, + matrixtype = ExtendableSparseMatrix, + update = (A, v, i, j) -> updateindex!(A, +, v, i, j) + ) - A1 ≈ A2 && A1 ≈ A3 + return A1 ≈ A2 && A1 ≈ A3 end for T in [Float64, Dual64, Float64x2] diff --git a/test/test_linearsolve.jl b/test/test_linearsolve.jl index 57355be..536b9fe 100644 --- a/test/test_linearsolve.jl +++ b/test/test_linearsolve.jl @@ -18,11 +18,11 @@ const Dual64 = ForwardDiff.Dual{Float64, Float64, 1} function test_ls1(T, k, l, m; linsolver = SparspakFactorization()) A = fdrand(k, l, m; matrixtype = ExtendableSparseMatrix) - b = A*ones(k * l * m) + b = A * ones(k * l * m) x0 = A \ b p = LinearProblem(T.(A), T.(b)) - x1 = solve(p, linsolver, abstol=1.0e-12) - x0 ≈ x1 + x1 = solve(p, linsolver, abstol = 1.0e-12) + return x0 ≈ x1 end function test_ls2(T, k, l, m; linsolver = SparspakFactorization()) @@ -31,15 +31,15 @@ function test_ls2(T, k, l, m; linsolver = SparspakFactorization()) p = LinearProblem(A, b) x0 = solve(p, linsolver) cache = x0.cache - x0=copy(x0) - nonzeros(A).-=1.0e-4 - for i = 1:k*l*m + x0 = copy(x0) + nonzeros(A) .-= 1.0e-4 + for i in 1:(k * l * m) A[i, i] += 1.0e-4 end - reinit!(cache; A, reuse_precs=true) + reinit!(cache; A, reuse_precs = true) x1 = solve!(cache, linsolver) - all(x0 .< x1) + return all(x0 .< x1) end @@ -48,7 +48,7 @@ end @test test_ls1(T, 10, 10, 10, linsolver = SparspakFactorization()) @test test_ls1(T, 25, 40, 1, linsolver = SparspakFactorization()) @test test_ls1(T, 100, 1, 1, linsolver = SparspakFactorization()) - + @test test_ls2(T, 10, 10, 10, linsolver = SparspakFactorization()) @test test_ls2(T, 25, 40, 1, linsolver = SparspakFactorization()) @test test_ls2(T, 100, 1, 1, linsolver = SparspakFactorization()) @@ -56,48 +56,50 @@ end end -factorizations=[UMFPACKFactorization(), - SparspakFactorization(), - KLUFactorization(reuse_symbolic=false)] +factorizations = [ + UMFPACKFactorization(), + SparspakFactorization(), + KLUFactorization(reuse_symbolic = false), +] if !Sys.isapple() - push!(factorizations,MKLPardisoFactorize()) + push!(factorizations, MKLPardisoFactorize()) end @testset "Factorizations" begin - + for factorization in factorizations @test test_ls1(Float64, 10, 10, 10, linsolver = factorization) @test test_ls1(Float64, 25, 40, 1, linsolver = factorization) @test test_ls1(Float64, 100, 1, 1, linsolver = factorization) - + @test test_ls2(Float64, 10, 10, 10, linsolver = factorization) @test test_ls2(Float64, 25, 40, 1, linsolver = factorization) @test test_ls2(Float64, 100, 1, 1, linsolver = factorization) end end -allprecs=[ +allprecs = [ + AMGCLWrap.AMGPreconBuilder(), AMGCLWrap.AMGPreconBuilder(), - AMGCLWrap.AMGPreconBuilder(), - AMGCLWrap.RLXPreconBuilder(), - ExtendableSparse.ILUZeroPreconBuilder(), - ExtendableSparse.ILUZeroPreconBuilder(;blocksize=2), - ExtendableSparse.ILUTPreconBuilder(), - ExtendableSparse.JacobiPreconBuilder(), + AMGCLWrap.RLXPreconBuilder(), + ExtendableSparse.ILUZeroPreconBuilder(), + ExtendableSparse.ILUZeroPreconBuilder(; blocksize = 2), + ExtendableSparse.ILUTPreconBuilder(), + ExtendableSparse.JacobiPreconBuilder(), ExtendableSparse.SmoothedAggregationPreconBuilder(), - ExtendableSparse.RugeStubenPreconBuilder() -] + ExtendableSparse.RugeStubenPreconBuilder(), +] @testset "iterations" begin for precs in allprecs - iteration=KrylovJL_GMRES(precs;) - + iteration = KrylovJL_GMRES(precs) + @test test_ls1(Float64, 10, 10, 10, linsolver = iteration) @test test_ls1(Float64, 25, 40, 1, linsolver = iteration) @test test_ls1(Float64, 100, 1, 1, linsolver = iteration) - + @test test_ls2(Float64, 10, 10, 10, linsolver = iteration) @test test_ls2(Float64, 25, 40, 1, linsolver = iteration) @test test_ls2(Float64, 100, 1, 1, linsolver = iteration) @@ -105,20 +107,20 @@ allprecs=[ end -luprecs=[ExtendableSparse.LinearSolvePreconBuilder(factorization) for factorization in factorizations] +luprecs = [ExtendableSparse.LinearSolvePreconBuilder(factorization) for factorization in factorizations] @testset "block preconditioning" begin - n=100 - A=fdrand(n,n) - partitioning=A->[1:2:size(A,1), 2:2:size(A,1)] - sol0=ones(n^2) - b=A*ones(n^2); - + n = 100 + A = fdrand(n, n) + partitioning = A -> [1:2:size(A, 1), 2:2:size(A, 1)] + sol0 = ones(n^2) + b = A * ones(n^2) + for precs in vcat(allprecs, luprecs) - iteration=KrylovJL_CG(precs=BlockPreconBuilder(;precs, partitioning)) - p=LinearProblem(A,b) - sol=solve(p, KrylovJL_CG(;precs), abstol=1.0e-12) - @test isapprox(sol, sol0, atol=1e-6) + iteration = KrylovJL_CG(precs = BlockPreconBuilder(; precs, partitioning)) + p = LinearProblem(A, b) + sol = solve(p, KrylovJL_CG(; precs), abstol = 1.0e-12) + @test isapprox(sol, sol0, atol = 1.0e-6) end end diff --git a/test/test_lu.jl b/test/test_lu.jl index 56e6d48..33af985 100644 --- a/test/test_lu.jl +++ b/test/test_lu.jl @@ -8,7 +8,7 @@ function test_lu1(T, k, l, m; lufac = ExtendableSparse.LUFactorization()) A = fdrand(k, l, m; rand = () -> 1, matrixtype = ExtendableSparseMatrix) b = rand(k * l * m) x1 = A \ b - for i = 1:(k * l * m) + for i in 1:(k * l * m) A[i, i] += 1.0 end x2 = A \ b @@ -18,7 +18,7 @@ function test_lu1(T, k, l, m; lufac = ExtendableSparse.LUFactorization()) a1 = deepcopy(Aext.cscmatrix) x1ext = lufac \ T.(b) - for i = 1:(k * l * m) + for i in 1:(k * l * m) Aext[i, i] += 1.0 end update!(lufac) @@ -26,7 +26,7 @@ function test_lu1(T, k, l, m; lufac = ExtendableSparse.LUFactorization()) x2ext = lufac \ T.(b) atol = 100 * sqrt(f64(max(eps(T), eps(Float64)))) - isapprox(norm(x1 - f64.(x1ext)) / norm(x1), 0; atol) && + return isapprox(norm(x1 - f64.(x1ext)) / norm(x1), 0; atol) && isapprox(norm(x2 - f64.(x2ext)) / norm(x2), 0; atol) end @@ -35,11 +35,11 @@ function test_lu2(T, k, l, m; lufac = ExtendableSparse.LUFactorization()) b = rand(k * l * m) lu!(lufac, Aext) x1ext = lufac \ T.(b) - for i = 4:(k * l * m - 3) + for i in 4:(k * l * m - 3) Aext[i, i + 3] -= 1.0e-4 Aext[i - 3, i] -= 1.0e-4 end lufac = lu!(lufac, Aext) x2ext = lufac \ T.(b) - all(x1ext .< x2ext) + return all(x1ext .< x2ext) end diff --git a/test/test_mklpardiso.jl b/test/test_mklpardiso.jl index 2603605..86dacc7 100644 --- a/test/test_mklpardiso.jl +++ b/test/test_mklpardiso.jl @@ -6,7 +6,7 @@ using LinearAlgebra using Pardiso include("test_lu.jl") -Base.eps(ComplexF64)=eps(Float64) +Base.eps(ComplexF64) = eps(Float64) @test test_lu1(Float64, 10, 10, 10, lufac = MKLPardisoLU()) @test test_lu1(Float64, 25, 40, 1, lufac = MKLPardisoLU()) @@ -17,7 +17,6 @@ Base.eps(ComplexF64)=eps(Float64) @test test_lu1(ComplexF64, 1000, 1, 1, lufac = MKLPardisoLU()) - @test test_lu2(Float64, 10, 10, 10, lufac = MKLPardisoLU()) @test test_lu2(Float64, 25, 40, 1, lufac = MKLPardisoLU()) @test test_lu2(Float64, 1000, 1, 1, lufac = MKLPardisoLU()) diff --git a/test/test_operations.jl b/test/test_operations.jl index 1936800..7fb43dc 100644 --- a/test/test_operations.jl +++ b/test/test_operations.jl @@ -9,7 +9,7 @@ function test_addition(; m = 10, n = 10, d = 0.1) csc = sprand(m, n, d) lnk = SparseMatrixLNK(csc) csc2 = csc + lnk - csc2 == 2 * csc + return csc2 == 2 * csc end function test_invert(n) @@ -18,11 +18,11 @@ function test_invert(n) b = rand(n) x = A \ b Ax = A * x - b ≈ Ax + return b ≈ Ax end function test() - for irun = 1:10 + for irun in 1:10 m = rand((1:1000)) n = rand((1:1000)) d = 0.3 * rand() @@ -52,7 +52,7 @@ function test() D = Diagonal(rand(10)) @test isa(D * extA, ExtendableSparseMatrix) - @test isa(extA * D, ExtendableSparseMatrix) + return @test isa(extA * D, ExtendableSparseMatrix) end test() diff --git a/test/test_parallel.jl b/test/test_parallel.jl index c280a68..e80d358 100644 --- a/test/test_parallel.jl +++ b/test/test_parallel.jl @@ -15,51 +15,54 @@ using Test include("femtools.jl") -function test_correctness_build_seq(N, Tm::Type{<:AbstractSparseMatrix}; dim=3) +function test_correctness_build_seq(N, Tm::Type{<:AbstractSparseMatrix}; dim = 3) grid = testgrid(N; dim) nnodes = num_nodes(grid) - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) - A = Tm{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) + A = Tm{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) testassemble!(A, grid) - @test sparse(A0) ≈ sparse(A) + return @test sparse(A0) ≈ sparse(A) end -function speedup_build_seq(N, Tm::Type{<:AbstractSparseMatrix}; dim=3) +function speedup_build_seq(N, Tm::Type{<:AbstractSparseMatrix}; dim = 3) grid = testgrid(N; dim) nnodes = num_nodes(grid) - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) - A = Tm{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) + A = Tm{Float64, Int}(nnodes, nnodes) tbase = @belapsed testassemble!($A0, $grid) seconds = 1 setup = (reset!($A0)) tx = @belapsed testassemble!($A, $grid) seconds = 1 setup = (reset!($A)) - tbase / tx + return tbase / tx end -function test_correctness_update(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function test_correctness_update( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) - A = Tm{Float64,Int}(nnodes, nnodes, 1) + A = Tm{Float64, Int}(nnodes, nnodes, 1) # Assembele without partitioning # this gives the "base truth" to compare with testassemble_parallel!(A, grid) - # Save the nonzeros + # Save the nonzeros nz = sort(copy(nonzeros(A))) for np in allnp # Reset the nonzeros, keeping the structure intact nonzeros(A) .= 0 # Parallel assembly with np threads - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) reset!(A, np) @show num_partitions_per_color(pgrid) testassemble_parallel!(A, pgrid) @test sort(nonzeros(A)) ≈ nz end + return end """ @@ -68,94 +71,106 @@ end Test correctness of parallel assembly on NxN grid during build phase, assuming that no structure has been assembled. """ -function test_correctness_build(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function test_correctness_build( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) # Get the "ground truth" - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) nz = sort(copy(nonzeros(A0))) for np in allnp # Make a new matrix and assemble parallel. # this should result in the same nonzeros - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) A = Tm(nnodes, nnodes, num_partitions(pgrid)) @show num_partitions_per_color(pgrid) @test check_partitioning(pgrid) testassemble_parallel!(A, pgrid) @test sort(nonzeros(A)) ≈ nz end + return end -function test_correctness_mul(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function test_correctness_mul( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) # Get the "ground truth" - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) b = rand(nnodes) A0b = A0 * b for np in allnp - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) @test check_partitioning(pgrid) A = Tm(nnodes, nnodes, num_partitions(pgrid)) - partitioning!(A, pgrid[PColorPartitions], - pgrid[PartitionNodes]) + partitioning!( + A, pgrid[PColorPartitions], + pgrid[PartitionNodes] + ) testassemble_parallel!(A, pgrid) invp = invperm(pgrid[NodePermutation]) diff = norm(A0b[invp] - A * b[invp], Inf) @show diff @test diff < sqrt(eps()) end + return end -function speedup_update(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function speedup_update( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) # Get the "ground truth" - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) nz = copy(nonzeros(A0)) |> sort # Get the base timing - # During setup, set matrix entries to zero while keeping the structure + # During setup, set matrix entries to zero while keeping the structure t0 = @belapsed testassemble!($A0, $grid) seconds = 1 setup = (nonzeros($A0) .= 0) result = [] A = Tm(nnodes, nnodes, 1) for np in allnp # Get the parallel timing # During setup, set matrix entries to zero while keeping the structure - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) @show num_partitions_per_color(pgrid) reset!(A, num_partitions(pgrid)) testassemble_parallel!(A, pgrid) t = @belapsed testassemble_parallel!($A, $pgrid) seconds = 1 setup = (nonzeros($A) .= 0) @assert sort(nonzeros(A)) ≈ nz - push!(result, (np, round(t0 / t; digits=2))) + push!(result, (np, round(t0 / t; digits = 2))) end - result + return result end -function speedup_build(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function speedup_build( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) # Get the "ground truth" - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) nz = nonzeros(A0) reset!(A0) @@ -172,26 +187,32 @@ function speedup_build(N, for np in allnp # Get the parallel timing # During setup, reset matrix to empty state. - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) reset!(A, num_partitions(pgrid)) @show num_partitions_per_color(pgrid) - t = @belapsed testassemble_parallel!($A, $pgrid) seconds = 1 setup = (reset!($A, - num_partitions($pgrid))) + t = @belapsed testassemble_parallel!($A, $pgrid) seconds = 1 setup = ( + reset!( + $A, + num_partitions($pgrid) + ) + ) @assert sort(nonzeros(A)) ≈ nz - push!(result, (np, round(t0 / t; digits=2))) + push!(result, (np, round(t0 / t; digits = 2))) end - result + return result end -function speedup_mul(N, - Tm::Type{<:AbstractSparseMatrix}; - Tp::Type{<:AbstractPartitioningAlgorithm}=PlainMetisPartitioning, - allnp=[10, 15, 20], - dim=3) +function speedup_mul( + N, + Tm::Type{<:AbstractSparseMatrix}; + Tp::Type{<:AbstractPartitioningAlgorithm} = PlainMetisPartitioning, + allnp = [10, 15, 20], + dim = 3 + ) grid = testgrid(N; dim) nnodes = num_nodes(grid) # Get the "ground truth" - A0 = ExtendableSparseMatrix{Float64,Int}(nnodes, nnodes) + A0 = ExtendableSparseMatrix{Float64, Int}(nnodes, nnodes) testassemble!(A0, grid) b = rand(nnodes) t0 = @belapsed $A0 * $b seconds = 1 @@ -199,19 +220,21 @@ function speedup_mul(N, result = [] A = Tm(nnodes, nnodes, 1) for np in allnp - pgrid = partition(grid, Tp(; npart=np), nodes=true, keep_nodepermutation=true) + pgrid = partition(grid, Tp(; npart = np), nodes = true, keep_nodepermutation = true) @show num_partitions_per_color(pgrid) reset!(A, num_partitions(pgrid)) testassemble_parallel!(A, pgrid) flush!(A) - partitioning!(A, pgrid[PColorPartitions], - pgrid[PartitionNodes]) + partitioning!( + A, pgrid[PColorPartitions], + pgrid[PartitionNodes] + ) t = @belapsed $A * $b seconds = 1 invp = invperm(pgrid[NodePermutation]) @assert A0b[invp] ≈ A * b[invp] - push!(result, (np, round(t0 / t; digits=2))) + push!(result, (np, round(t0 / t; digits = 2))) end - result + return result end #= diff --git a/test/test_parilu0.jl b/test/test_parilu0.jl index 52ee51e..b6562e0 100644 --- a/test/test_parilu0.jl +++ b/test/test_parilu0.jl @@ -19,7 +19,7 @@ function test(n) @show sol_par @show hist_ser.iters @show hist_par.iters - sol_ser ≈ sol_par && hist_ser.iters == hist_par.iters + return sol_ser ≈ sol_par && hist_ser.iters == hist_par.iters end @test test(10) diff --git a/test/test_preconditioners.jl b/test/test_preconditioners.jl index 4bc8aeb..66bbf4f 100644 --- a/test/test_preconditioners.jl +++ b/test/test_preconditioners.jl @@ -16,7 +16,7 @@ function test_precon(Precon, k, l, m; maxiter = 10000, symmetric = true) r = hist[:resnorm] nr = length(r) tail = min(100, length(r) ÷ 2) - all(x -> x < 1, r[(end - tail):end] ./ r[(end - tail - 1):(end - 1)]), norm(it - exact) + return all(x -> x < 1, r[(end - tail):end] ./ r[(end - tail - 1):(end - 1)]), norm(it - exact) end function test_precon2(precon, k, l, m; maxiter = 10000, symmetric = true) @@ -29,37 +29,39 @@ function test_precon2(precon, k, l, m; maxiter = 10000, symmetric = true) r = hist[:resnorm] nr = length(r) tail = min(100, length(r) ÷ 2) - all(x -> x < 1, r[(end - tail):end] ./ r[(end - tail - 1):(end - 1)]), norm(it - exact) + return all(x -> x < 1, r[(end - tail):end] ./ r[(end - tail - 1):(end - 1)]), norm(it - exact) end -@test all(test_precon(ILU0Preconditioner, 20, 20, 20) .≤ (true, 4e-5)) -@test all(test_precon(ILUZeroPreconditioner, 20, 20, 20) .≤ (true, 4e-5)) -@test all(test_precon(JacobiPreconditioner, 20, 20, 20) .≤ (true, 3e-4)) -@test all(test_precon(ParallelJacobiPreconditioner, 20, 20, 20) .≤ (true, 3e-4)) -@test all(test_precon(ILUTPreconditioner, 20, 20, 20) .≤ (true, 5e-5)) -@test all(test_precon(RS_AMGPreconditioner, 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon(SA_AMGPreconditioner, 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon(AMGCL_AMGPreconditioner, 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon(AMGCL_RLXPreconditioner, 20, 20, 20) .≤ (true, 4e-5)) +@test all(test_precon(ILU0Preconditioner, 20, 20, 20) .≤ (true, 4.0e-5)) +@test all(test_precon(ILUZeroPreconditioner, 20, 20, 20) .≤ (true, 4.0e-5)) +@test all(test_precon(JacobiPreconditioner, 20, 20, 20) .≤ (true, 3.0e-4)) +@test all(test_precon(ParallelJacobiPreconditioner, 20, 20, 20) .≤ (true, 3.0e-4)) +@test all(test_precon(ILUTPreconditioner, 20, 20, 20) .≤ (true, 5.0e-5)) +@test all(test_precon(RS_AMGPreconditioner, 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon(SA_AMGPreconditioner, 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon(AMGCL_AMGPreconditioner, 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon(AMGCL_RLXPreconditioner, 20, 20, 20) .≤ (true, 4.0e-5)) -@test all(test_precon(ILU0Preconditioner, 20, 20, 20; symmetric = false) .≤ (true, 4e-5)) -@test all(test_precon(ILUZeroPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 4e-5)) -@test all(test_precon(JacobiPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 3e-4)) -@test all(test_precon(ParallelJacobiPreconditioner, 20, 20, 20; symmetric = false) .≤ - (true, 3e-4)) -@test all(test_precon(ILUTPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 5e-5)) +@test all(test_precon(ILU0Preconditioner, 20, 20, 20; symmetric = false) .≤ (true, 4.0e-5)) +@test all(test_precon(ILUZeroPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 4.0e-5)) +@test all(test_precon(JacobiPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 3.0e-4)) +@test all( + test_precon(ParallelJacobiPreconditioner, 20, 20, 20; symmetric = false) .≤ + (true, 3.0e-4) +) +@test all(test_precon(ILUTPreconditioner, 20, 20, 20; symmetric = false) .≤ (true, 5.0e-5)) #@test all(test_precon(AMGPreconditioner,20,20,20,symmetric=false).≤ (true, 1e-5)) #@test all(test_precon(AMGCL_AMGPreconditioner,20,20,20,symmetric=false).≤ (true, 1e-5)) #@test all(test_precon(AMGCL_RLXPreconditioner,20,20,20,symmetric=false).≤ (true, 5e-5)) -@test all(test_precon2(ILU0Preconditioner(), 20, 20, 20) .≤ (true, 4e-5)) -@test all(test_precon2(ILUZeroPreconditioner(), 20, 20, 20) .≤ (true, 4e-5)) -@test all(test_precon2(JacobiPreconditioner(), 20, 20, 20) .≤ (true, 3e-4)) -@test all(test_precon2(ParallelJacobiPreconditioner(), 20, 20, 20) .≤ (true, 3e-4)) -@test all(test_precon2(ILUTPreconditioner(), 20, 20, 20) .≤ (true, 5e-5)) -@test all(test_precon2(RS_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon2(SA_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon2(AMGCL_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1e-5)) -@test all(test_precon2(AMGCL_RLXPreconditioner(), 20, 20, 20) .≤ (true, 4e-5)) +@test all(test_precon2(ILU0Preconditioner(), 20, 20, 20) .≤ (true, 4.0e-5)) +@test all(test_precon2(ILUZeroPreconditioner(), 20, 20, 20) .≤ (true, 4.0e-5)) +@test all(test_precon2(JacobiPreconditioner(), 20, 20, 20) .≤ (true, 3.0e-4)) +@test all(test_precon2(ParallelJacobiPreconditioner(), 20, 20, 20) .≤ (true, 3.0e-4)) +@test all(test_precon2(ILUTPreconditioner(), 20, 20, 20) .≤ (true, 5.0e-5)) +@test all(test_precon2(RS_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon2(SA_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon2(AMGCL_AMGPreconditioner(), 20, 20, 20) .≤ (true, 1.0e-5)) +@test all(test_precon2(AMGCL_RLXPreconditioner(), 20, 20, 20) .≤ (true, 4.0e-5)) end diff --git a/test/test_sparspak.jl b/test/test_sparspak.jl index 331809a..f5a1c68 100644 --- a/test/test_sparspak.jl +++ b/test/test_sparspak.jl @@ -10,11 +10,11 @@ include("test_lu.jl") for T in [Float32, Float64, Float64x1, Float64x2, Dual64] println("$T:") @test test_lu1(T, 10, 10, 10, lufac = SparspakLU()) - @test test_lu1(T, 25, 40, 1, lufac = SparspakLU()) + @test test_lu1(T, 25, 40, 1, lufac = SparspakLU()) @test test_lu1(T, 1000, 1, 1, lufac = SparspakLU()) @test test_lu2(T, 10, 10, 10, lufac = SparspakLU()) - @test test_lu2(T, 25, 40, 1, lufac = SparspakLU()) + @test test_lu2(T, 25, 40, 1, lufac = SparspakLU()) @test test_lu2(T, 1000, 1, 1, lufac = SparspakLU()) end end diff --git a/test/test_symmetric.jl b/test/test_symmetric.jl index 4a1d3d6..686a32d 100644 --- a/test/test_symmetric.jl +++ b/test/test_symmetric.jl @@ -12,7 +12,7 @@ function test_symm(n, uplo) SA = Symmetric(A, uplo) Scsc = Symmetric(A.cscmatrix, uplo) - if ExtendableSparse.USE_GPL_LIBS + return if ExtendableSparse.USE_GPL_LIBS #requires SuiteSparse which is not available on non-GPL builds SA \ b ≈ Scsc \ b else @@ -29,7 +29,7 @@ function test_hermitian(n, uplo) b = rand(n) HA = Hermitian(A, uplo) Hcsc = Hermitian(A.cscmatrix, uplo) - if ExtendableSparse.USE_GPL_LIBS + return if ExtendableSparse.USE_GPL_LIBS #requires SuiteSparse which is not available on non-GPL builds HA \ b ≈ Hcsc \ b else diff --git a/test/test_timings.jl b/test/test_timings.jl index 066b489..7c5e89a 100644 --- a/test/test_timings.jl +++ b/test/test_timings.jl @@ -11,25 +11,27 @@ using Printf const Dual64 = ForwardDiff.Dual{Float64, Float64, 1} function test(T, k, l, m) - t1 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $SparseMatrixCSC) seconds=0.1 - t2 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $ExtendableSparseMatrix) seconds=0.1 - t3 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $SparseMatrixLNK) seconds=0.1 - @printf("%s (%d,%d,%d): CSC %.4f EXT %.4f LNK %.4f\n", - string(T), - k, - l, - m, - t1*1000, - t2*1000, - t3*1000) + t1 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $SparseMatrixCSC) seconds = 0.1 + t2 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $ExtendableSparseMatrix) seconds = 0.1 + t3 = @belapsed fdrand($T, $k, $l, $m, matrixtype = $SparseMatrixLNK) seconds = 0.1 + @printf( + "%s (%d,%d,%d): CSC %.4f EXT %.4f LNK %.4f\n", + string(T), + k, + l, + m, + t1 * 1000, + t2 * 1000, + t3 * 1000 + ) if !(t3 < t2 < t1) @warn """timing test failed for $T $k x $l x $m. -If this occurs just once or twice, it is probably due to CPU noise. -So we nevertheless count this as passing. -""" + If this occurs just once or twice, it is probably due to CPU noise. + So we nevertheless count this as passing. + """ end - true + return true end @test test(Float64, 1000, 1, 1) diff --git a/test/test_updates.jl b/test/test_updates.jl index 2a5f899..0077334 100644 --- a/test/test_updates.jl +++ b/test/test_updates.jl @@ -21,7 +21,7 @@ function test(T) rawupdateindex!(A, +, 0.1, 2, 3) @test nnz(A) == 3 dropzeros!(A) - @test nnz(A) == 3 + return @test nnz(A) == 3 end test(Float64)