GithubHelp home page GithubHelp logo

julialinearalgebra / blockbandedmatrices.jl Goto Github PK

View Code? Open in Web Editor NEW
56.0 56.0 13.0 1021 KB

A Julia package for representing block-banded matrices and banded-block-banded matrices

Home Page: https://julialinearalgebra.github.io/BlockBandedMatrices.jl/

License: MIT License

Julia 100.00%

blockbandedmatrices.jl's People

Contributors

briochemc avatar dependabot[bot] avatar dkarrasch avatar dlfivefifty avatar github-actions[bot] avatar jagot avatar jishnub avatar juliatagbot avatar mdavezac avatar putianyi889 avatar ranocha avatar snowball13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blockbandedmatrices.jl's Issues

Inference issues due to changes in BandedMatrices.jl

The new CONTAINER type parameter in BandedMatrix has made some formerly-concrete fields now non-concrete. For example:

struct BlockBandedSizes
    block_sizes::BlockSizes{2}
    block_starts::BandedMatrix{Int} # gives index where the blocks start
    block_strides::Vector{Int} # gives stride to next block for J-th column
end

that BandedMatrix{Int} is now actually a BandedMatrix{Int, C} where C, which is causing some inference and performance issues when working with views.

We should either make CONTAINER also a type parameter of BlockBandedSizes or enforce a particular container type (presumably Matrix{T} as it was before). I'm not familiar enough with these packages yet to know which one to prefer. Any suggestions?

Yet another error in complex QR

I realized that QR/QL factorizations still don't work with complex matrices, since the example I provided yesterday did not have any off-diagonal blocks, and hence the apply_qr! function, that's only implemented for the real case at the moment, was never run. I have a fix, and just want to put together a decent test.

Precompilation failure in mybinder.org

Hi,
BlockBandedMatrices package fails to precompile in https://mybinder.org/ environment. @ChrisRackauckas helped to upstream the original issue JuliaDiff/SparseDiffTools.jl#69 .It can be reproduced by provisioning a simple mybinder notebook,
https://mybinder.org/v2/gh/davidanthoff/bindertest/master?filepath=src%2Fmain.ipynb
and running

using Pkg; Pkg.add("BlockBandedMatrices")
using BlockBandedMatrices

Failed to precompile BlockBandedMatrices [ffab5731-97b5-5995-9138-79e8c1846df0] to /srv/julia/pkg/compiled/v1.1/BlockBandedMatrices/0zTvf.ji.

Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] compilecache(::Base.PkgId, ::String) at ./loading.jl:1197
 [3] _require(::Base.PkgId) at ./loading.jl:960
 [4] require(::Base.PkgId) at ./loading.jl:858
 [5] require(::Module, ::Symbol) at ./loading.jl:853
 [6] top-level scope at In[1]:2

This issue is not present with my local Julia. So it seems to be related only to the environments provisioned with mybinder.
Also BlockBandedMatrices v0.4.6 precompiles without errors in mybinder

Stack-overflow in matrix–vector multiplication

As discussed in #15, #16:

using BlockBandedMatrices

function tryme(::Type{T},::Type{B}) where {T,B}
    rows = [5,3,5]
    M = sum(rows)
    A = BlockBandedMatrix(Zeros{T}(M,M), (rows,rows), (1,1))
    A.data .= 1:length(A.data)
    b=ones(B,size(A,1))
    A*b
end

tryme(Float64,Float64) # Fine
tryme(Float64,Int64) # Goodbye cruel world
tryme(Int64,Float64) # same
tryme(Int64,Int64) # same
tryme(Float64,ComplexF64) # same
tryme(ComplexF64,Float64) # same
tryme(ComplexF64,ComplexF64) # fine

All of the above works fine on v0.1.1

Banded block banded matrix with different bandwidths for the blocks

I have a banded block banded matrix where the blocks themselves can have different bandwidths. Specifically, the bandwidth within the blocks is dependent on which block-diagonal the block is in. e.g., the block at index k ∈ [-l, u] would have a bandwidth of (λ, μ) = (1 - k, 1 + k), so that a block on the subdiagonal k=-1 has a bandwidth of (2, 0), a block on the diagonal k=0 is tridiagonal, and a block on the superdiagonal k=1 has a bandwidth of (0, 2). Can this be represented using this package?

Incompatible with spy

using FillArrays, BlockBandedMatrices
l,u = 1,1          # block bandwidths
N = M = 2          # number of row/column blocks
cols = rows = 1:N  # block sizes
jac_bbm = BlockBandedMatrix(Ones(sum(rows),sum(cols)), (rows,cols), (l,u)) # creates a block-banded matrix with ones in the non-zero entries                        # creates a block-banded  identity matrix
using Plots
spy(jac_bbm,markersize=1,colorbar=false,color=:deep)
MethodError: no method matching findnz(::BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Tuple{Array{Int64,1},Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}})
Closest candidates are:
  findnz(!Matched::SparseMatrixCSC{Tv,Ti}) where {Tv, Ti} at C:\cygwin\home\Administrator\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.2\SparseArrays\src\sparsematrix.jl:1299
  findnz(!Matched::SparseVector{Tv,Ti}) where {Tv, Ti} at C:\cygwin\home\Administrator\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.2\SparseArrays\src\sparsevector.jl:738
macro expansion at recipes.jl:1064 [inlined]
apply_recipe(::Dict{Symbol,Any}, ::Type{Val{:spy}}, ::Array{Float64,1}, ::Array{Float64,1}, ::Surface{BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Tuple{Array{Int64,1},Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}}) at RecipesBase.jl:275
_process_seriesrecipe(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}) at pipeline.jl:408
_plot!(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}, ::Tuple{Plots.Spy}) at plot.jl:234
#plot#137(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:markersize, :colorbar, :color),Tuple{Int64,Bool,Symbol}}}, ::typeof(plot), ::Plots.Spy) at plot.jl:57
#plot at none:0 [inlined]
#spy#230 at RecipesBase.jl:350 [inlined]
(::getfield(Plots, Symbol("#kw##spy")))(::NamedTuple{(:markersize, :colorbar, :color),Tuple{Int64,Bool,Symbol}}, ::typeof(spy), ::BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Tuple{Array{Int64,1},Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}) at none:0
top-level scope at advanced_ode_example.jmd:328

Surprising denseness?

I just converted my code to use BlockBandedMatrices (the latest release) instead of my homegrown BlockMaps and noticed a substantial performance degradation. I found out that although my operators where block-banded, anytime I used them, they had become dense (due to multiplications by scalars, etc). In summary, these operations, for T::BlockBandedMatrix, yield dense matrices:

  • T/2
  • 2T (also 2 .* T)
  • T *= 2
  • T /= 2
  • T + I
  • copy(T)
  • similar(T)

All of the above work as I would expect for e.g. Tridiagonal matrices.

T ./= 2 does not become dense, neither does lmul!(2, T), but sometimes I would like to have a scaled copy of a matrix, without modifying the original one. Is this all by design?

Constructors from Kronecker Products?

Usually these types of matrices from from PDEs where they can be constructed from the Kronecker product of the actions along each dimension, like:

using SparseArrays
Iy = SparseMatrixCSC(I,N,N)
Ix = SparseMatrixCSC(I,N,N)
fJ = ones(3,3)
Dz = [1 0 0
      0 0 0
      0 0 0]
A = kron(Dz,Iy,sparse(Mx)) + kron(Dz,sparse(My),Ix) + kron(fJ,Iy,Ix)

Could there be a way like that last statement to directly form a BlockBandedMatrix or BandedBlockBandedMatrix?

Addition/broadcasting type unstable with mixed block range types

Allocations increase drastically with newer versions of BandedMatrices.jl, BlockbandedMatrices.jl, LazyArrays.jl and LazyBandedMatrices.jl

I do not know where the problem is.

$ julia-15 mwe.jl
20.566046 seconds (1.11 M allocations: 65.356 MiB, 0.16% gc time)

$ julia-16 mwe.jl
135.413411 seconds (1.11 G allocations: 95.863 GiB, 6.35% gc time, 3.05% compilation time)

$ julia-16 mwe.jl #(with package versions as in 1.5.3)
18.151103 seconds (2.76 M allocations: 143.134 MiB, 0.74% gc time, 18.48% compilation time)

OS: macOS Big Sur

Setup:
Julia 1.5.3
[aae01518] BandedMatrices v0.15.15
[ffab5731] BlockBandedMatrices v0.8.11
[5078a376] LazyArrays v0.16.16
[d7e5e226] LazyBandedMatrices v0.2.12
Julia 1.6.1
[aae01518] BandedMatrices v0.16.8
[ffab5731] BlockBandedMatrices v0.10.4
[5078a376] LazyArrays v0.21.3
[d7e5e226] LazyBandedMatrices v0.5.5

@code_warntype 1.5.3
Variables
#self#::Core.Compiler.Const(toeplitz, false)
n::Int64
vc::Array{Array{Int64,2},1}
vr::Array{Array{Int64,2},1}
s::Int64
u::Int64
l::Int64
Tn::BlockSkylineMatrix{Int64,Array{Int64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockArrays.BlockedUnitRange{Array{Int64,1}},BlockArrays.BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}
@_9::Union{Nothing, Tuple{Int64,Int64}}
@_10::Union{Nothing, Tuple{Int64,Int64}}
ii::Int64
jj::Int64

@code_warntype 1.6.1
Variables
#self#::Core.Const(toeplitz)
n::Int64
vc::Vector{Matrix{Int64}}
vr::Vector{Matrix{Int64}}
@_5::Union{Nothing, Tuple{Int64, Int64}}
@_6::Union{Nothing, Tuple{Int64, Int64}}
Tn::Any
l::Int64
u::Int64
s::Int64
ii::Int64
jj::Int64

@code_warntype 1.6.1 (with package versions as in 1.5.3)
Variables
#self#::Core.Const(toeplitz)
n::Int64
vc::Vector{Matrix{Int64}}
vr::Vector{Matrix{Int64}}
@_5::Union{Nothing, Tuple{Int64, Int64}}
@_6::Union{Nothing, Tuple{Int64, Int64}}
Tn::BlockBandedMatrix{Int64}
l::Int64
u::Int64
s::Int64
ii::Int64
jj::Int64

mwe.jl:

using LinearAlgebra
using BandedMatrices
using BlockBandedMatrices
using LazyArrays
using LazyBandedMatrices
function toeplitz(n :: Integer, vc :: Array{T,1}, vr :: Array{T,1}) where T
      s = size(vc[1],2)
      u = size(vr)[1] - 1
      l = size(vc)[1] - 1
      Tn = BlockBandedMatrix(convert.(eltype(T),Zeros(n*s,n*s)), s*ones(Int64,n),s*ones(Int64,n), (l,u))
      for ii = 1:length(vc)
        Tn = Tn + BandedBlockBandedMatrix(Kron(BandedMatrix(-ii+1=>ones(eltype(T),n-ii+1)),vc[ii]))
      end
      for jj = 2:length(vr)
        Tn = Tn + BandedBlockBandedMatrix(Kron(BandedMatrix( jj-1=>ones(eltype(T),n-jj+1)),vr[jj]))
      end
      return Tn
end
@time toeplitz(5000,[[ 1 2;3 4]], [[ 1 2;3 4], [9 10; 11 12]]);

Performance of `BandedBlockBandedMatrix` `Vector` Multiplication

I have a big BanedBlockBandedMatrix and need to multiply it with a vector. However it seems to be rather slow and require a lot of allocation. Here's a MWE

using BlockArrays: BlockRange
using ApproxFunOrthogonalPolynomials
using LinearAlgebra
using SparseArrays

using BenchmarkTools

# Making one of my Matrices
CC = Chebyshev(-1..1)         ⊗ Chebyshev(-1..1)
UC = Ultraspherical(1, -1..1) ⊗ Chebyshev(-1..1)
CU = Chebyshev(-1..1)         ⊗ Ultraspherical(1, -1..1)
UU = Ultraspherical(1, -1..1) ⊗ Ultraspherical(1, -1..1)

degree = 500

Du = Derivative(CC, [1,0])[BlockRange(1:degree), BlockRange(1:degree+1)]
UCtoC2 = Conversion(UC, UU)[BlockRange(1:degree), BlockRange(1:degree)]
DutoC2 = UCtoC2 * Du

# Benchmarks

@benchmark mul!(out, $DutoC2, v) setup=begin
    out = Vector{Float64}(undef, size(DutoC2, 1))
    v = rand(size(DutoC2, 2))
end
# 3.2 ms with 257.62 KiB allocated

@benchmark mul!(out, $(sparse(DutoC2)), v) setup=begin
    out = Vector{Float64}(undef, size(DutoC2, 1))
    v = rand(size(DutoC2, 2))
end
# For comparison: 1.5 ms with 0 bytes allocated

I wonder why the BandedBlockBandedMatrix multiplication allocates so much and why it's slower than using a sparse matrix. Any ideas?

Infinite dim. BandedBlockBandedMatrices interaction with Symmetric() broken?

Symmetric BandedBlockBandedMatrices (at least in the infinite case) don't seem to work correctly, by which I mean the object is constructed successfully but it behaves in unexpected ways.

Consider the following toy example (relevant for Zernike polynomial Jacobi matrices I'm implementing for MultivariateOPs.jl):

julia> using BlockArrays, BlockBandedMatrices, LinearAlgebra, InfiniteArrays, LazyArrays, InfiniteLinearAlgebra
julia> import Base: oneto
julia> import InfiniteLinearAlgebra: BlockBroadcastArray, BlockHcat
julia> k = mortar(Base.OneTo.(oneto(∞)))
ℵ₀-blocked ℵ₀-element BlockVector{Int64, BroadcastVector{Base.OneTo{Int64}, Type{Base.OneTo}, Tuple{InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}:
 11
 21
 2
 31
 2
 3
 41
 2
 
julia> n = mortar(Fill.(oneto(∞),oneto(∞)))
ℵ₀-blocked ℵ₀-element BlockVector{Int64, BroadcastVector{Fill{Int64, 1, Tuple{Base.OneTo{Int64}}}, Type{Fill}, Tuple{InfiniteArrays.OneToInf{Int64}, InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}:
 12
 23
 3
 34
 4
 4
 45
 5
 
julia> dat = BlockHcat(
               BlockBroadcastArray(hcat, float.(k) ,Zeros((axes(n,1),)), float.(n)),
               Zeros((axes(n,1),Base.OneTo(3))),
               Zeros((axes(n,1),Base.OneTo(3)))                 
               )
ℵ₀×3-blocked ℵ₀×9 BlockHcat{Float64, Tuple{BlockBroadcastArray{Float64, 2, typeof(hcat), Tuple{BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Base.OneTo{Int64}, Type{Base.OneTo}, Tuple{InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, Zeros{Float64, 1, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Fill{Int64, 1, Tuple{Base.OneTo{Int64}}}, Type{Fill}, Tuple{InfiniteArrays.OneToInf{Int64}, InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}}}, Zeros{Float64, 2, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}, Base.OneTo{Int64}}}, Zeros{Float64, 2, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}, Base.OneTo{Int64}}}}}:
 1.0  0.0  1.0                 
 ───────────────┼─────────────────┼───────────────
 1.0  0.0  2.0                 
 2.0  0.0  2.0                 
 ───────────────┼─────────────────┼───────────────
 1.0  0.0  3.0                 
 2.0  0.0  3.0                 
 3.0  0.0  3.0                 
 ───────────────┼─────────────────┼───────────────
 1.0  0.0  4.0                 
 2.0  0.0  4.0                 
 3.0  0.0  4.0                 
 4.0  0.0  4.0                 
 ───────────────┼─────────────────┼───────────────
 1.0  0.0  5.0                 
 2.0  0.0  5.0                 
                                       
julia># Generate a tridiagonal blocked tridiagonal matrix
julia> M = BlockBandedMatrices._BandedBlockBandedMatrix(dat', axes(k,1), (1,1), (1,1))
ℵ₀×ℵ₀-blocked ℵ₀×ℵ₀ BandedBlockBandedMatrix{Float64, LazyBandedMatrices.BlockVcat{Float64, 2, Tuple{Adjoint{Float64, BlockBroadcastArray{Float64, 2, typeof(hcat), Tuple{BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Base.OneTo{Int64}, Type{Base.OneTo}, Tuple{InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, Zeros{Float64, 1, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Fill{Int64, 1, Tuple{Base.OneTo{Int64}}}, Type{Fill}, Tuple{InfiniteArrays.OneToInf{Int64}, InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}:
 0.00.0  2.0                                         
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────    
 0.00.0  0.00.0  2.0                                         
 0.00.0  0.03.0  0.0  3.0                                 
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────     
  0.0  0.00.0  0.0   0.0  2.0                                 
  0.0  0.00.0  0.0  0.04.0  0.0  3.0                             
     0.0   0.0  0.0   4.0  0.0  4.0                     
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────    
      0.0  0.0   0.0  0.0       0.0  2.0                     
      0.0  0.0  0.00.0  0.0  0.0   5.0  0.0  3.0                 
         0.0  0.0   0.0  0.0  0.0   5.0  0.0  4.0             
             0.0       0.0  0.0       5.0  0.0  5.0     
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────     
              0.0  0.0       0.0  0.0           0.0  2.0    
              0.0  0.0  0.0   0.0  0.0  0.0       6.0  0.0     
                                                                                    
julia> # Symmetric version of the above matrix
julia> Ms = Symmetric(M)
ℵ₀×ℵ₀ Symmetric{Float64, BandedBlockBandedMatrix{Float64, LazyBandedMatrices.BlockVcat{Float64, 2, Tuple{Adjoint{Float64, BlockBroadcastArray{Float64, 2, typeof(hcat), Tuple{BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Base.OneTo{Int64}, Type{Base.OneTo}, Tuple{InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, Zeros{Float64, 1, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Fill{Int64, 1, Tuple{Base.OneTo{Int64}}}, Type{Fill}, Tuple{InfiniteArrays.OneToInf{Int64}, InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}} with indices 1:1:ℵ₀×1:1:ℵ₀:
 0.00.0  2.00.0  0.0  0.00.0  0.0  0.0  0.00.0  0.0  0.0  0.0  0.00.0  0.0
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────    
 0.00.0  0.00.0  2.0  0.00.0  0.0  0.0  0.00.0  0.0  0.0  0.0  0.00.0  0.0     
 2.00.0  0.03.0  0.0  3.00.0  0.0  0.0  0.00.0  0.0  0.0  0.0  0.00.0  0.0
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────     
 0.00.0  3.00.0  0.0  0.00.0  2.0  0.0  0.00.0  0.0  0.0  0.0  0.00.0  0.0     
 0.02.0  0.00.0  0.0  0.04.0  0.0  3.0  0.00.0  0.0  0.0  0.0  0.00.0  0.0     
 0.00.0  3.00.0  0.0  0.00.0  4.0  0.0  4.00.0  0.0  0.0  0.0  0.00.0  0.0
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────    
 0.00.0  0.00.0  4.0  0.00.0  0.0  0.0  0.00.0  2.0  0.0  0.0  0.00.0  0.0     
 0.00.0  0.02.0  0.0  4.00.0  0.0  0.0  0.05.0  0.0  3.0  0.0  0.00.0  0.0     
 0.00.0  0.00.0  3.0  0.00.0  0.0  0.0  0.00.0  5.0  0.0  4.0  0.00.0  0.0     
 0.00.0  0.00.0  0.0  4.00.0  0.0  0.0  0.00.0  0.0  5.0  0.0  5.00.0  0.0
 ─────┼────────────┼─────────────────┼──────────────────────┼───────────────────────────┼──────────     
 0.00.0  0.00.0  0.0  0.00.0  5.0  0.0  0.00.0  0.0  0.0  0.0  0.00.0  2.0    
 0.00.0  0.00.0  0.0  0.02.0  0.0  5.0  0.00.0  0.0  0.0  0.0  0.06.0  0.0     
                                                                                    

Ok so as I said it constructs the object, although it visually fills in zeros. The stored data field remains banded block banded so initially I thought I might get lucky and it would only be a visual bug, but...

Testing some basic multiplication with the above shows that Symmetric doesn't appear to work:

julia> M * [Ones(10); Zeros(∞)]  # This gives expected output
ℵ₀-blocked ℵ₀-element PseudoBlockVector{Float64, LazyArrays.CachedArray{Float64, 1, Vector{Float64}, Zeros{Float64, 1, Tuple{InfiniteArrays.OneToInf{Int64}}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}:
 2.0
 ───
 2.0
 6.0
 ───
 2.0
 7.0
 8.0
 ───
 0.0
 0.0
 0.0
 0.0
 ───
 0.0
 0.0
 ⋮

julia> Ms * [Ones(10); Zeros(∞)] # This never finishes...
ERROR: ┌ Error: Error trying to display an error.
└ @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.6.17/scripts/packages/VSCodeServer/src/eval.jl:321
^C
julia> ^C

Even more important is that calling blocks also does not work:

julia> # Getindex for blocks is also not functional:
julia> M[Block.(1:5), Block.(1:5)] # Works as expected
5×5-blocked 15×15 BandedBlockBandedMatrix{Float64, PseudoBlockMatrix{Float64, Matrix{Float64}, Tuple{BlockedUnitRange{StepRange{Int64, Int64}}, BlockedUnitRange{Vector{Int64}}}}, BlockedUnitRange{Vector{Int64}}}:
 0.00.0  2.0                                     
 ─────┼────────────┼─────────────────┼──────────────────────┼─────────────────────────
 0.00.0  0.00.0  2.0                                
 0.00.0  0.03.0  0.0  3.0                             
 ─────┼────────────┼─────────────────┼──────────────────────┼─────────────────────────
  0.0  0.00.0  0.0   0.0  2.0                        
  0.0  0.00.0  0.0  0.04.0  0.0  3.0                    
     0.0   0.0  0.0   4.0  0.0  4.0                 
 ─────┼────────────┼─────────────────┼──────────────────────┼─────────────────────────
      0.0  0.0   0.0  0.0       0.0  2.0            
      0.0  0.0  0.00.0  0.0  0.0   5.0  0.0  3.0        
         0.0  0.0   0.0  0.0  0.0   5.0  0.0  4.0    
             0.0       0.0  0.0       5.0  0.0  5.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.0
                         0.0           0.0  0.0

julia> Ms[Block.(1:5), Block.(1:5)] # Throws error
ERROR: MethodError: getindex(::Symmetric{Float64, BandedBlockBandedMatrix{Float64, LazyBandedMatrices.BlockVcat{Float64, 2, Tuple{Adjoint{Float64, BlockBroadcastArray{Float64, 2, typeof(hcat), Tuple{BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Base.OneTo{Int64}, Type{Base.OneTo}, Tuple{InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, Zeros{Float64, 1, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, BroadcastVector{Float64, typeof(float), Tuple{BlockVector{Int64, BroadcastVector{Fill{Int64, 1, Tuple{Base.OneTo{Int64}}}, Type{Fill}, Tuple{InfiniteArrays.OneToInf{Int64}, InfiniteArrays.OneToInf{Int64}}}, Tuple{BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, Zeros{Float64, 2, Tuple{Base.OneTo{Int64}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}}}, BlockedUnitRange{ArrayLayouts.RangeCumsum{Int64, InfiniteArrays.OneToInf{Int64}}}}}, ::BlockRange{1, Tuple{UnitRange{Int64}}}, ::BlockRange{1, Tuple{UnitRange{Int64}}}) is ambiguous. Candidates:
  getindex(A::AbstractMatrix, kr::BlockRange{1, R} where R<:Tuple{AbstractUnitRange{Int64}}, jr::BlockRange{1, R} where R<:Tuple{AbstractUnitRange{Int64}}) in BlockArrays at /home/timon/.julia/packages/BlockArrays/EpvQQ/src/abstractblockarray.jl:184
  getindex(A::Symmetric{<:Any, <:ArrayLayouts.LayoutMatrix}, kr::AbstractVector, jr::AbstractVector) in ArrayLayouts at /home/timon/.julia/packages/ArrayLayouts/aaoru/src/ArrayLayouts.jl:151
Possible fix, define
  getindex(::Symmetric{<:Any, <:ArrayLayouts.LayoutMatrix}, ::BlockRange{1, R} where R<:Tuple{AbstractUnitRange{Int64}}, ::BlockRange{1, R} where R<:Tuple{AbstractUnitRange{Int64}})
Stacktrace:
 [1] top-level scope
   @ ~/Documents/Projects/MultivariateOrthogonalPolynomials.jl/examples/diskhelmholtz.jl:293

I can in principle work around all of this for the Zernike application but I thought I'd still bring this up for future reference (or if we want this for Zernike since it would make everything substantially easier / more elegant).

Of course there is also a possibility that I'm doing something in an unintended way - in which case I'd be happy to learn what the correct way to call Symmetric on these objects would be.

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

QR factorization for complex matrices fails

When I try this

using BlockBandedMatrices

A=BlockBandedMatrix{Float64}(I, ([1,1],[1,1]), (0,0))
display(A)
@show qr(A)
B=BlockBandedMatrix{ComplexF64}(I, ([1,1],[1,1]), (0,0))
display(B)
@show qr(B)

I get this

2×2-blocked 2×2 BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}:
 1.0 
 ─────┼─────
  1.0
qr(A) = QR{Float64,BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}}([1.0 0.0; 0.0 1.0], [0.0, 0.0])
2×2-blocked 2×2 BlockSkylineMatrix{Complex{Float64},Array{Complex{Float64},1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}:
 1.0+0.0im    
 ───────────┼───────────
     1.0+0.0im
ERROR: LoadError: MethodError: no method matching _qrf!(::LazyArrays.ColumnMajor, ::LazyArrays.DenseColumnMajor, ::SubArray{Complex{Float64},2,BlockSkylineMatrix{Complex{Float64},Array{Complex{Float64},1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}},Tuple{BlockArrays.BlockSlice{BlockArrays.BlockRange{1,Tuple{UnitRange{Int64}}}},BlockArrays.BlockSlice{Block{1,Int64}}},false}, ::SubArray{Float64,1,BlockArrays.PseudoBlockArray{Float64,1,Array{Float64,1},BlockArrays.BlockSizes{1,Array{Int64,1}}},Tuple{BlockArrays.BlockSlice{Block{1,Int64}}},false})
Closest candidates are:
  _qrf!(::LazyArrays.AbstractColumnMajor, ::LazyArrays.AbstractStridedLayout, ::AbstractArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},2}, ::AbstractArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},1}) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} at /home/jagot/.julia/packages/BlockBandedMatrices/HOshO/src/blockskylineqr.jl:2
Stacktrace:
 [1] qrf!(::SubArray{Complex{Float64},2,BlockSkylineMatrix{Complex{Float64},Array{Complex{Float64},1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}},Tuple{BlockArrays.BlockSlice{BlockArrays.BlockRange{1,Tuple{UnitRange{Int64}}}},BlockArrays.BlockSlice{Block{1,Int64}}},false}, ::SubArray{Float64,1,BlockArrays.PseudoBlockArray{Float64,1,Array{Float64,1},BlockArrays.BlockSizes{1,Array{Int64,1}}},Tuple{BlockArrays.BlockSlice{Block{1,Int64}}},false}) at /home/jagot/.julia/packages/BlockBandedMatrices/HOshO/src/blockskylineqr.jl:1
 [2] qr!(::BlockSkylineMatrix{Complex{Float64},Array{Complex{Float64},1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}) at /home/jagot/.julia/packages/BlockBandedMatrices/HOshO/src/blockskylineqr.jl:24
 [3] qr(::BlockSkylineMatrix{Complex{Float64},Array{Complex{Float64},1},BlockBandedMatrices.BlockSkylineSizes{BlockArrays.BlockSizes{2,Array{Int64,1}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}) at /home/jagot/.julia/packages/BlockBandedMatrices/HOshO/src/blockskylineqr.jl:56

Performances of mul!(x, transpose(B), y)

Thanks for the great package! I am trying to use BandedBlockBandedMatrix as a Jacobian in NLsolve (following SciML/DifferentialEquations.jl#483). However the performances get worse than for a sparse matrix. I think this comes from this line in NLSolve. To give an example

using LinearAlgebra, SparseArrays, BlockBandedMatrices, BenchmarkTools
x = rand(10000)
y = rand(10000)
J = BandedBlockBandedMatrix(Ones(10000, 10000), (fill(100, 100), fill(100, 100)), (1, 1), (1, 1))
@btime mul!($x, transpose($J), $y)
# 2.528 s (1 allocation: 16 bytes)
sparseJ = sparse(J)
@btime mul!($x, transpose($sparseJ), $y)
#  60.817 μs (1 allocation: 16 bytes)

Is there a way to make this operation faster?

New type of BlockTridiagonalKron (or something)

Combination code and basic linear algebra question for @dlfivefifty and any other experts: We have a very particular structure for some of my sparse matrices, which is common enough in economics to be worth specializing types:

  • Take a sequence of Tridiagonal matrices of size MxM, L_1, ... L_N and a square (possibly dense) matrix Q of size NxN, which is an intensity matrix of a markov chain (i.e. q_ii = - sum(q_ij | j != i))
  • Then you can construct a sparse matrix with code like the following
L = blockdiag(L_1, L_2, ..., L_N) + kron(Q, sparse(I, M, M))
  • The structure of this is: a block matrix with tridiagonal matrices down the diagonal, and a bunch of constant coefficient diagonal matrices on all off-diagonal blocks. Lots of structure.

While I can represent this in a BlockBanded matrix, it is inefficient in space (since it has to have the same bandwidth for each block). More importantly, there is structure there that might be exploited to speed up linear solves.

So, with that in mind, what do you think about both the feasibility and payoff of creating a specialized matrix type of that form that can exploit the structure for fast linear solves?

This is where I am entirely ignorant... But looking at https://github.com/JuliaMatrices/BlockBandedMatrices.jl/blob/master/src/blockskylineqr.jl#L19 it seems like the QR decomposition can be done in blocks in some way? The QR for every block other than the diagonal is trivial. Is this both something feasible without too much specialized knowledge, and likely to pay off big for the speed of linear solves?

If you think it worthwhile, we could create this type and add it to this package.

BlockBandedMatrix should have extra entries so subblocks are banded

Ideally we'd have:

julia> B = BlockBandedMatrix{Float64}(undef, Fill(2,10), Fill(3, 10), (1, 2));

julia> MemoryLayout(view(B, getindex.(Block.(1:10), 1), getindex.(Block.(1:1), 2))) isa BandedColumns{StridedLayout}

To do this, we have several things to do:

  1. Support getindex.(Block.(1:10), 1). This will need a new type in BlockArrays.jl
  2. Split out BlockBandedMatrix from BlockSkylineMatrix (to simplify things)
  3. Special case when the block sizes are all the same size.

Way to invert matrix?

Is there a way to invert BandedBlockBandedMatrix? I'm getting the following error from:

A \ b


MethodError: no method matching lu!(::BlockBandedMatrices.BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}, ::Val{true}; check=true)
Closest candidates are:
  lu!(!Matched::Union{DenseArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},2}, ReinterpretArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},2,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray}, ReshapedArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},2,A,MI} where MI<:Tuple{Vararg{SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray}, SubArray{T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64},2,A,I,L} where L where I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, AbstractCartesianIndex},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}}, ::Union{Val{false}, Val{true}}; check) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/lu.jl:37
  lu!(!Matched::Union{Hermitian{T,S}, Symmetric{T,S}} where S where T, ::Union{Val{false}, Val{true}}; check) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/lu.jl:45
  lu!(!Matched::Union{DenseArray{T,2}, ReinterpretArray{T,2,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray}, ReshapedArray{T,2,A,MI} where MI<:Tuple{Vararg{SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray}, SubArray{T,2,A,I,L} where L where I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, AbstractCartesianIndex},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Tuple{AbstractUnitRange,Vararg{Any,N} where N} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}} where T, ::Union{Val{false}, Val{true}}; check) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/lu.jl:86
  ...

Stacktrace:
 [1] #lu#103(::Bool, ::Function, ::BlockBandedMatrices.BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}, ::Val{true}) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/lu.jl:142
 [2] lu(::BlockBandedMatrices.BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}, ::Val{true}) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/lu.jl:142 (repeats 2 times)
 [3] \(::BlockBandedMatrices.BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}, ::Array{Float64,1}) at /Users/osx/buildbot/slave/package_osx64/build/usr/share/julia/stdlib/v1.0/LinearAlgebra/src/generic.jl:870
 [4] solve!(::LinearSystem) at /Users/dan/code/NINT/src/methods/solve.jl:2
 [5] solve!(::LaplaceProblem) at /Users/dan/code/NINT/src/methods/solve.jl:6
 [6] #LaplaceProblem#8(::Base.Iterators.Pairs{Symbol,Real,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:r_min, :r_max, :reference_value),Tuple{Float64,Float64,Int64}}}, ::Type, ::Int64, ::Int64, ::Int64) at /Users/dan/code/NINT/src/structs/laplace_problem.jl:58
 [7] Type at ./none:0 [inlined]
 [8] (::getfield(Main, Symbol("##971#974")))(::Int64, ::Int64, ::String) at ./In[255]:2
 [9] map(::Function, ::Observable{Int64}, ::Observable{Int64}, ::Observable{Any}) at /Users/dan/.julia/packages/Observables/qCJWB/src/Observables.jl:174
 [10] top-level scope at /Users/dan/.julia/packages/InteractBase/3SqBl/src/manipulate.jl:21
 [11] top-level scope at In[255]:1

StackOverFlow Error

julia> A=BlockBandedMatrix(Zeros(1,1),[1],[1],(0,0))
1×1-blocked 1×1 BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockedUnitRange{Array{Int64,1}},BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}:
 0.0

julia> A[Block(1)]
ERROR: StackOverflowError:
Stacktrace:
 [1] view(::BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockedUnitRange{Array{Int64,1}},BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}, ::Block{1,Int64}) at C:\Users\pty\.julia\packages\BlockArrays\g01fJ\src\abstractblockarray.jl:129 (repeats 79984 times)

An error is expected, but not stack overflow maybe?

Adding diagonal matrix to BlockBandedMatrix/BlockSkylineMatrix yields dense BlockArray

I noticed that my performance went down when upgrading to the latest BlockBandedMatrices.jl and discovered this:

using BlockBandedMatrices
using LinearAlgebra

l,u = 2,1          # block bandwidths
N = M = 4          # number of row/column blocks
cols = rows = 1:N  # block sizes

A = BlockBandedMatrix(Zeros(sum(rows),sum(cols)), rows,cols, (l,u))
display(A)
V = Diagonal(ones(size(A,1)))
A+V

gives the result

4×4-blocked 10×10 BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockArrays.BlockedUnitRange{Array{Int64,1}},BlockArrays.BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}:
 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  │  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  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
  ⋅   │  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
4×4-blocked 10×10 BlockArrays.BlockArray{Float64,2}:
 1.0  │  0.0  0.0  │  0.0  0.0  0.0  │  0.0  0.0  0.0  0.0
 ─────┼────────────┼─────────────────┼────────────────────
 0.0  │  1.0  0.0  │  0.0  0.0  0.0  │  0.0  0.0  0.0  0.0
 0.0  │  0.0  1.0  │  0.0  0.0  0.0  │  0.0  0.0  0.0  0.0
 ─────┼────────────┼─────────────────┼────────────────────
 0.0  │  0.0  0.0  │  1.0  0.0  0.0  │  0.0  0.0  0.0  0.0
 0.0  │  0.0  0.0  │  0.0  1.0  0.0  │  0.0  0.0  0.0  0.0
 0.0  │  0.0  0.0  │  0.0  0.0  1.0  │  0.0  0.0  0.0  0.0
 ─────┼────────────┼─────────────────┼────────────────────
 0.0  │  0.0  0.0  │  0.0  0.0  0.0  │  1.0  0.0  0.0  0.0
 0.0  │  0.0  0.0  │  0.0  0.0  0.0  │  0.0  1.0  0.0  0.0
 0.0  │  0.0  0.0  │  0.0  0.0  0.0  │  0.0  0.0  1.0  0.0
 0.0  │  0.0  0.0  │  0.0  0.0  0.0  │  0.0  0.0  0.0  1.0

`setindex!()` performance

Hi! We're considering using the BlockBandedMatrix type in RigidBodyDynamics.jl to store a block-diagonal Jacobian matrix, but it looks like the current performance of setindex!() is a little too slow for our needs. More importantly, we're trying to write our in-place algorithms in a way that doesn't allocate at all, and the current implementation of setindex!() for BlockBandedMatrix allocates memory for a new view() at each call.

For example:

julia> using BlockBandedMatrices

julia> l,u = 0, 0          # block bandwidths
(0, 0)

julia> N = M = 4          # number of row/column blocks
4

julia> cols = rows = 1:N  # block sizes
1:4

julia> m = BlockBandedMatrix(eye(10, 10), (rows,cols), (l,u));

julia> using BenchmarkTools

julia> @btime $m[2, 2] = 5.0
  70.054 ns (2 allocations: 128 bytes)
5.0

as compared to 1.604 ns (0 allocations: 0 bytes) for a plain Matrix{Float64}.

Do you have any thoughts or plans on how to improve the performance? My current solution involves a different AbstractMatrix type which stores all of its block views at construction time, so looking up a block doesn't require allocating a new view. Could we do the same thing in BlockBandedMatrix?

Allow general backends in `BlockSkylineMatrix`

I have a need for non-Vector (in fact, infinite) backends in BlockSkylineMatrix so am planning to template out the storage, just as BandedBlockBandedMatrix and BlockArray allow general backends.

While I'm at it, there's a question whether we want to make the type signature more resemble the new BlockArray:

BlockArray{T, N, R <: AbstractArray{<:AbstractArray{T,N},N}, BS<:AbstractBlockSizes{N}}

That is, we have two options:

  1. BlockSkylineMatrix{T, R <: AbstractVector{T}, LL<:AbstractVector{Int}, UU<:AbstractVector{Int}}
  2. BlockSkylineMatrix{T, R <: AbstractVector{T}, BS<:AbstractBlockSizes{2}}

Option 2 is closer to the new BlockArray. @jagot Any reason to prefer Option 1?

view(A,Block(K,K))[band(0)] = ... syntax not working

Hello,
I have set up a BandedBlockBandedMatrix like this:

nx = ny = 11
Δx = 1/(nx-1);
Δy = 1/(ny-1); # 
rows = cols = 1:nx
l = u = λ = μ = 1
Ae = Aw = An = As = 1
Ap = -4
A = BandedBlockBandedMatrix(Zeros(sum(rows),sum(cols)), rows, cols, (l,u), (λ,μ))

When I try to fill in its bands using code like this:

Re = 100
#### Fill up the main diagonal block
for K in 2:nx-1
    view(A,Block(K,K))[band(0)] .= Ap.*Δt./(2*Re*Δx^2);
    view(A,Block(K,K))[band(-1)] .= Ae.*Δt./(2*Re*Δx^2);
    view(A,Block(K,K))[band(1)] .= Aw.*Δt./(2*Re*Δx^2);
end
#### Fill up off-diagonal blocks
for K = 2:ny-1
    view(A,Block(K,K+1))[band(0)] .= As.*Δt./(2*Re*Δx^2);
end
for K = 1:ny-2
    view(A,Block(K+1,K))[band(0)] .= An.*Δt./(2*Re*Δx^2);
end

I receive the error: UndefVarError: band not defined.

What is an alternative way of doing this?

Bugs in addition of BlockSkylineMatrices of varying bandwidths

I noticed the following:

julia> A = BlockSkylineMatrix{Float64}(undef, ([3,4,5],[3,4,5]), ([1,0,1],[0,1,0])); A.data .= rand(size(A.data)...);A
12×12 BlockSkylineMatrix{Float64,Array{Int64,1},Array{Int64,1}}:
 0.515874  0.435296   0.8036670.157059  0.0994608   0.578049   0.810365                                      
 0.240064  0.30819    0.1639810.833147  0.50423     0.765289   0.826576                                      
 0.629761  0.308399   0.9781920.981489  0.645819    0.0636914  0.178307                                      
 ───────────────────────────────┼──────────────────────────────────────────────┼────────────────────────────────────────────────────
 0.364572  0.372321   0.3559410.618376  0.798309    0.135298   0.692863                                      
 0.270431  0.0233375  0.7873320.967244  0.713229    0.860661   0.982289                                      
 0.668875  0.792493   0.3176770.372895  0.0349658   0.0198107  0.953447                                      
 0.460245  0.292726   0.2665550.349721  0.00627247  0.450215   0.0195057                                      
 ───────────────────────────────┼──────────────────────────────────────────────┼────────────────────────────────────────────────────
                                                   0.087982  0.680505   0.201285  0.214275   0.195476
                                                   0.143701  0.133647   0.938344  0.0487296  0.40534
                                                   0.890303  0.1469     0.079983  0.221671   0.832606
                                                   0.739889  0.0567633  0.302035  0.473111   0.952199
                                                   0.941039  0.332872   0.540892  0.0617018  0.178641

julia> A+A
12×12 BlockSkylineMatrix{Float64,Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}}}:
 1.03175   0.870593   1.607330.314117  0.198922   1.1561     1.62073                                     
 0.480129  0.616381   0.3279621.66629   1.00846    1.53058    1.65315                                     
 1.25952   0.616799   1.956381.96298   1.29164    0.127383   0.356613                                     
 ───────────────────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────
 0.729144  0.744643   0.7118821.23675   1.59662    0.270596   1.385730.0       0.0       0.0       0.0        0.0
 0.540863  0.0466751  1.574661.93449   1.42646    1.72132    1.964580.0       0.0       0.0       0.0        0.0
 1.33775   1.58499    0.6353540.74579   0.0699316  0.0396214  1.906890.0       0.0       0.0       0.0        0.0
 0.920489  0.585451   0.533110.699442  0.0125449  0.900431   0.03901150.0       0.0       0.0       0.0        0.0
 ───────────────────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────
                     0.0       0.0        0.0        0.00.175964  1.36101   0.40257   0.428549   0.390953
                     0.0       0.0        0.0        0.00.287403  0.267293  1.87669   0.0974592  0.81068
                     0.0       0.0        0.0        0.01.78061   0.2938    0.159966  0.443342   1.66521
                     0.0       0.0        0.0        0.01.47978   0.113527  0.604071  0.946223   1.9044
                     0.0       0.0        0.0        0.01.88208   0.665744  1.08178   0.123404   0.357281

julia> D = BandedBlockBandedMatrix{Float64}(undef, ([3,4,5],[3,4,5]), (0,0), (0,0)); D.data .= rand(size(D.data)...); D
12×12 BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}:
 0.809596                                                                            
          0.228581                                                                   
                   0.00918763                                                                
 ────────────────────────────────┼──────────────────────────────────────────┼───────────────────────────────────────────────────
                    0.125747                                                          
                            0.431363                                                 
                                     0.843291                                        
                                              0.226849                                     
 ────────────────────────────────┼──────────────────────────────────────────┼───────────────────────────────────────────────────
                                               0.921379                               
                                                       0.619485                      
                                                                0.755453             
                                                                         0.0732969   
                                                                                   0.711645

julia> A+D
ERROR: DimensionMismatch("")
Stacktrace:
 [1] _combined_blocksizes at /Users/jagot/.julia/dev/BlockBandedMatrices/src/broadcast.jl:243 [inlined]
 [2] copyto!(::BlockSkylineMatrix{Float64,Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}}}, ::Base.Broadcast.Broadcasted{BlockBandedMatrices.BlockBandedStyle,Tuple{Base.OneTo{Int64},Base.OneTo{Int64}},typeof(+),Tuple{BlockSkylineMatrix{Float64,Array{Int64,1},Array{Int64,1}},BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}}}) at /Users/jagot/.julia/dev/BlockBandedMatrices/src/broadcast.jl:276
 [3] materialize at ./broadcast.jl:773 [inlined]
 [4] broadcast(::typeof(+), ::BlockSkylineMatrix{Float64,Array{Int64,1},Array{Int64,1}}, ::BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}) at ./broadcast.jl:707
 [5] +(::BlockSkylineMatrix{Float64,Array{Int64,1},Array{Int64,1}}, ::BandedBlockBandedMatrix{Float64,BlockArrays.PseudoBlockArray{Float64,2,Array{Float64,2}}}) at ./arraymath.jl:39
 [6] top-level scope at none:0

If A isa BlockBandedMatrix, i.e. with constant block-bandwidth, A+A and A+D work as expected. I will try to investigate the cause.

No method for multiplying compatible BlockSkyLineMatrix and BandedMatrix

Matrix multiplication is apparently not currently defined for BlockSkyLineMatrix and BandedMatrix even when dimensions should be compatible (i.e m x n array times n x k array).

Not entirely sure if this belongs in BandedMatrices or BlockBandedMatrices but I tend towards the latter so I'll put this here for now.

Here's a simple snippet that reproduces the error:

using BandedMatrices, BlockBandedMatrices

# generate some simple arrays
function M1(N::Integer)
    M = BlockBandedMatrix(Zeros(sum(1:N),N), (1:N,Ones{Int}(N)), (0,0))
        for n=1:N
            for j=1:n
                view(M, Block(n,n))[j,1] = 1.
            end
        end
    return M
end
function M2(N::Integer)
    M=BandedMatrix{Float64}(undef, (N, N), (0,1))
    for n=1:N-1
        M[n,n]=1.
        M[n,n+1]=1.
    end
    M[N,N]=1.
    return M
end

# works as intended, 55x10 * 10x10 * 10x1 array gives 55x1 array
N = 10
M1(N)
M2(N)
testvec = Ones(N,1)
M1(N)*(M2(N)*testvec)

# doesn't work:
M1(N)*M2(N)*testvec
# because this doesn't work
M1(N)*M2(N)

# also doesn't work:
M2(sum(1:N))*M1(N)*testvec
#while this does:
M2(sum(1:N))*(M1(N)*testvec)

0.7

It seems like the examples in the README do not work with the 0.7 version of BlockBandedMatrices.
If this is expected, could you modify the doc with the new syntax?

Unable to assign entries through BlockIndex

julia> A=BlockBandedMatrix(zeros(7,9), [1,2,4], [3,2,4], (0,1))
3×3-blocked 7×9 BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockedUnitRange{Array{Int64,1}},BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}:
 0.0  0.0  0.00.0  0.0            
 ───────────────┼────────────┼────────────────────
          0.0  0.00.0  0.0  0.0  0.0
          0.0  0.00.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

julia> A[BlockIndex((1,1),(1,1))]=1
ERROR: BoundsError: attempt to access ()
  at index [1]
Stacktrace:
 [1] getindex(::Tuple, ::Int64) at .\tuple.jl:24
 [2] to_indices(::BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockedUnitRange{Array{Int64,1}},BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}, ::Tuple{}, ::Tuple{BlockIndex{1}}) at C:\Users\pty\.julia\packages\BlockArrays\g01fJ\src\views.jl:26 (repeats 2 times)
 [3] to_indices at C:\Users\pty\.julia\packages\BlockArrays\g01fJ\src\views.jl:35 [inlined]
 [4] to_indices at .\indices.jl:322 [inlined]
 [5] setindex!(::BlockSkylineMatrix{Float64,Array{Float64,1},BlockBandedMatrices.BlockSkylineSizes{Tuple{BlockedUnitRange{Array{Int64,1}},BlockedUnitRange{Array{Int64,1}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},Fill{Int64,1,Tuple{Base.OneTo{Int64}}},BandedMatrices.BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}},Array{Int64,1}}}, ::Int64, ::BlockIndex{2}) at .\abstractarray.jl:1153
 [6] top-level scope at none:1

This issue doesn't happen on BlockArray or PseudoBlockArray.

Can't Use on Linux

julia> using BlockBandedMatrices
[ Info: Precompiling BlockBandedMatrices [ffab5731-97b5-5995-9138-79e8c1846df0]
ERROR: LoadError: LoadError: TypeError: in BlockSizes, in VT, expected VT<:Tuple{Vararg{AbstractArray{Int64,1},N}}, got Type{Array{Int64,1}}
Stacktrace:
 [1] top-level scope at none:0
 [2] include at ./boot.jl:326 [inlined]
 [3] include_relative(::Module, ::String) at ./loading.jl:1038
 [4] include at ./sysimg.jl:29 [inlined]
 [5] include(::String) at /home/arnavsood/.julia/packages/BlockBandedMatrices/meBlM/src/BlockBandedMatrices.jl:2
 [6] top-level scope at none:0
 [7] include at ./boot.jl:326 [inlined]
 [8] include_relative(::Module, ::String) at ./loading.jl:1038
 [9] include(::Module, ::String) at ./sysimg.jl:29
 [10] top-level scope at none:2
 [11] eval at ./boot.jl:328 [inlined]
 [12] eval(::Expr) at ./client.jl:404
 [13] top-level scope at ./none:3
in expression starting at /home/arnavsood/.julia/packages/BlockBandedMatrices/meBlM/src/BlockSkylineMatrix.jl:63
in expression starting at /home/arnavsood/.julia/packages/BlockBandedMatrices/meBlM/src/BlockBandedMatrices.jl:52
ERROR: Failed to precompile BlockBandedMatrices [ffab5731-97b5-5995-9138-79e8c1846df0] to /home/arnavsood/.julia/compiled/v1.1/BlockBandedMatrices/0zTvf.ji.
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] compilecache(::Base.PkgId, ::String) at ./loading.jl:1197
 [3] _require(::Base.PkgId) at ./loading.jl:960
 [4] require(::Base.PkgId) at ./loading.jl:858
 [5] require(::Module, ::Symbol) at ./loading.jl:853

julia> versioninfo()
Julia Version 1.1.1
Commit 55e36cc308 (2019-05-16 04:10 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.