-
-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathOrdinaryDiffEqCoreSparseArraysExt.jl
More file actions
49 lines (40 loc) · 1.31 KB
/
OrdinaryDiffEqCoreSparseArraysExt.jl
File metadata and controls
49 lines (40 loc) · 1.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module OrdinaryDiffEqCoreSparseArraysExt
using SparseArrays: SparseMatrixCSC
import OrdinaryDiffEqCore: _isdiag, find_algebraic_vars_eqs
# Efficient O(nnz) isdiag check for sparse matrices.
# Standard isdiag is O(n²) which is prohibitively slow for large sparse matrices.
"""
_isdiag(A::SparseMatrixCSC)
Check if a sparse matrix is diagonal in O(nnz) time by traversing the CSC structure directly.
Returns `true` if all non-zero elements are on the diagonal.
"""
function _isdiag(A::SparseMatrixCSC)
m, n = size(A)
m != n && return false
@inbounds for j in 1:n
for k in A.colptr[j]:(A.colptr[j + 1] - 1)
A.rowval[k] != j && return false
end
end
return true
end
"""
find_algebraic_vars_eqs(M::SparseMatrixCSC)
O(nnz) detection of algebraic variables (zero columns) and equations (zero rows).
"""
function find_algebraic_vars_eqs(M::SparseMatrixCSC)
n_cols = size(M, 2)
n_rows = size(M, 1)
algebraic_vars = fill(true, n_cols)
algebraic_eqs = fill(true, n_rows)
@inbounds for j in 1:n_cols
for idx in M.colptr[j]:(M.colptr[j + 1] - 1)
if !iszero(M.nzval[idx])
algebraic_vars[j] = false
algebraic_eqs[M.rowval[idx]] = false
end
end
end
return algebraic_vars, algebraic_eqs
end
end