2015-11-12 08:15:55 +02:00
|
|
|
# This file is a part of JuliaFEM.
|
|
|
|
|
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
|
|
|
|
|
|
|
|
|
|
# Sparse utils to make assembly of local and global matrices easier.
|
|
|
|
|
# Unoptimized but should do all necessary stuff for at start.
|
|
|
|
|
|
2015-12-23 01:52:28 +02:00
|
|
|
type SparseMatrixCOO
|
2015-11-12 08:15:55 +02:00
|
|
|
I :: Vector{Int}
|
|
|
|
|
J :: Vector{Int}
|
|
|
|
|
V :: Vector{Float64}
|
|
|
|
|
end
|
|
|
|
|
|
2015-12-23 01:52:28 +02:00
|
|
|
typealias SparseMatrixIJV SparseMatrixCOO
|
2015-12-02 17:42:48 +02:00
|
|
|
|
2015-12-23 01:52:28 +02:00
|
|
|
function SparseMatrixCOO()
|
|
|
|
|
SparseMatrixCOO([], [], [])
|
2015-11-12 08:15:55 +02:00
|
|
|
end
|
|
|
|
|
|
2015-12-29 17:50:41 +02:00
|
|
|
function Base.convert(::Type{SparseMatrixCOO}, A::SparseMatrixCSC)
|
|
|
|
|
return SparseMatrixCOO(findnz(A)...)
|
|
|
|
|
end
|
|
|
|
|
|
2016-02-10 22:21:30 +02:00
|
|
|
function Base.convert(::Type{SparseMatrixCOO}, A::Matrix)
|
|
|
|
|
return SparseMatrixCOO(findnz(A)...)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Base.convert(::Type{SparseMatrixCOO}, A::Vector)
|
|
|
|
|
return SparseMatrixCOO(findnz(sparse(A))...)
|
|
|
|
|
end
|
|
|
|
|
|
2016-02-05 11:32:50 +02:00
|
|
|
""" Convert from COO format to CSC.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
tol
|
|
|
|
|
used to drop near zero values less than tol.
|
|
|
|
|
"""
|
|
|
|
|
function Base.sparse(A::SparseMatrixIJV, args...; tol=1.0e-12)
|
|
|
|
|
B = sparse(A.I, A.J, A.V, args...)
|
|
|
|
|
SparseMatrix.droptol!(B, tol)
|
|
|
|
|
return B
|
2015-11-12 21:54:46 +02:00
|
|
|
end
|
|
|
|
|
|
2015-11-12 08:15:55 +02:00
|
|
|
function Base.push!(A::SparseMatrixIJV, I::Int, J::Int, V::Float64)
|
|
|
|
|
push!(A.I, I)
|
|
|
|
|
push!(A.J, J)
|
|
|
|
|
push!(A.V, V)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Base.empty!(A::SparseMatrixIJV)
|
|
|
|
|
empty!(A.I)
|
|
|
|
|
empty!(A.J)
|
|
|
|
|
empty!(A.V)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Base.append!(A::SparseMatrixIJV, I::Vector{Int}, J::Vector{Int}, V::Vector{Float64})
|
|
|
|
|
append!(A.I, I)
|
|
|
|
|
append!(A.J, J)
|
|
|
|
|
append!(A.V, V)
|
|
|
|
|
end
|
|
|
|
|
|
2015-12-03 11:29:01 +02:00
|
|
|
function Base.append!(A::SparseMatrixIJV, B::SparseMatrixIJV)
|
|
|
|
|
append!(A.I, B.I)
|
|
|
|
|
append!(A.J, B.J)
|
|
|
|
|
append!(A.V, B.V)
|
|
|
|
|
end
|
|
|
|
|
|
2015-11-24 03:06:56 +02:00
|
|
|
function Base.isempty(A::SparseMatrixIJV)
|
|
|
|
|
return isempty(A.I) && isempty(A.J) && isempty(A.V)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Base.(:+)(A::SparseMatrixIJV, B::SparseMatrixIJV)
|
|
|
|
|
if isempty(A)
|
|
|
|
|
return B
|
|
|
|
|
end
|
|
|
|
|
if isempty(B)
|
|
|
|
|
return A
|
|
|
|
|
end
|
|
|
|
|
C = SparseMatrixIJV([A.I;B.I], [A.J;B.J], [A.V;B.V])
|
|
|
|
|
return C
|
|
|
|
|
end
|
|
|
|
|
|
2015-11-12 08:15:55 +02:00
|
|
|
function Base.full(A::SparseMatrixIJV, args...)
|
2015-11-18 01:19:04 +02:00
|
|
|
return full(sparse(A.I, A.J, A.V, args...))
|
2015-11-12 08:15:55 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
""" Add local element matrix to sparse matrix. This basically does:
|
|
|
|
|
|
|
|
|
|
>>> A[dofs1, dofs2] = A[dofs1, dofs2] + data
|
|
|
|
|
|
|
|
|
|
Example
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
>>> S = [3, 4]
|
|
|
|
|
>>> M = [6, 7, 8]
|
|
|
|
|
>>> data = Float64[5 6 7; 8 9 10]
|
|
|
|
|
>>> A = SparseMatrixIJV()
|
|
|
|
|
>>> add!(A, S, M, data)
|
|
|
|
|
>>> full(A)
|
|
|
|
|
4x8 Array{Float64,2}:
|
|
|
|
|
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
|
|
|
|
|
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
|
|
|
|
|
0.0 0.0 0.0 0.0 0.0 5.0 6.0 7.0
|
|
|
|
|
0.0 0.0 0.0 0.0 0.0 8.0 9.0 10.0
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
function add!(A::SparseMatrixIJV, dofs1::Vector{Int}, dofs2::Vector{Int}, data::Matrix{Float64})
|
|
|
|
|
n, m = size(data)
|
2015-12-23 01:52:28 +02:00
|
|
|
for j=1:m
|
|
|
|
|
for i=1:n
|
2015-12-04 07:27:40 +02:00
|
|
|
push!(A.I, dofs1[i])
|
|
|
|
|
push!(A.J, dofs2[j])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
# append!(A.I, repeat(dofs1, outer=[m]))
|
|
|
|
|
# append!(A.J, repeat(dofs2, inner=[n]))
|
2015-11-12 08:15:55 +02:00
|
|
|
append!(A.V, vec(data))
|
|
|
|
|
end
|
|
|
|
|
|
2015-12-30 17:24:01 +02:00
|
|
|
""" Add new data to COO Sparse vector. """
|
2015-12-31 08:37:47 +02:00
|
|
|
function add!(A::SparseMatrixCOO, dofs::Vector{Int}, data::Array{Float64}, dim::Int=1)
|
2015-12-30 17:24:01 +02:00
|
|
|
if length(dofs) != length(data)
|
|
|
|
|
info("dofs = $dofs")
|
|
|
|
|
info("data = $(vec(data))")
|
|
|
|
|
error("when adding to sparse vector dimension mismatch!")
|
|
|
|
|
end
|
2015-11-12 21:54:46 +02:00
|
|
|
append!(A.I, dofs)
|
2015-12-31 08:37:47 +02:00
|
|
|
append!(A.J, dim*ones(Int, length(dofs)))
|
2015-11-12 21:54:46 +02:00
|
|
|
append!(A.V, vec(data))
|
|
|
|
|
end
|
|
|
|
|
|
2016-02-05 11:32:50 +02:00
|
|
|
""" Combine (I,J,V) values is possible. """
|
2015-12-02 17:42:48 +02:00
|
|
|
function optimize!(A::SparseMatrixIJV)
|
|
|
|
|
I, J, V = findnz(sparse(A))
|
|
|
|
|
A = SparseMatrixCOO(I, J, V)
|
|
|
|
|
gc()
|
|
|
|
|
end
|
2016-02-05 11:32:50 +02:00
|
|
|
|
|
|
|
|
""" Find all nonzero rows from sparse matrix.
|
|
|
|
|
|
|
|
|
|
Returns
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
|
|
Ordered list of row indices.
|
|
|
|
|
"""
|
2016-02-05 12:27:36 +02:00
|
|
|
function get_nonzero_rows(A::SparseMatrixCSC)
|
2016-02-05 11:32:50 +02:00
|
|
|
# FIXME: This is probably a very inefficient way to do this.
|
|
|
|
|
return sort(unique(rowvals(A)))
|
|
|
|
|
end
|
|
|
|
|
|