# BlockBandedMatrices.jl Documentation

## Creating block-banded and banded-block-banded matrices

`BlockBandedMatrices.BlockBandedMatrix`

— Type`BlockBandedMatrix`

A `BlockBandedMatrix`

is a subtype of `BlockMatrix`

of `BlockArrays.jl`

whose layout of non-zero blocks is banded.

`BlockBandedMatrices.BlockBandedMatrix`

— Method```
BlockBandedMatrix(A::Union{AbstractMatrix,UniformScaling},
rows::AbstractVector{Int}, cols::AbstractVector{Int},
(l,u)::NTuple{2,Int})
```

Return a `sum(rows) × sum(cols)`

`BlockBandedMatrix`

, with `rows`

by `cols`

blocks, with `(l,u)`

as the block-bandwidth. The structural non-zero entries are equal to the corresponding indices of `A`

.

**Examples**

```
julia> using LinearAlgebra, FillArrays
julia> l,u = 0,1; # block bandwidths
julia> nrowblk, ncolblk = 3, 3; # number of row/column blocks
julia> rows = 1:nrowblk; cols = 1:ncolblk; # block sizes
julia> BlockBandedMatrix(I, rows, cols, (l,u))
3×3-blocked 6×6 BlockBandedMatrix{Bool}:
1 │ 0 0 │ ⋅ ⋅ ⋅
───┼────────┼─────────
⋅ │ 1 0 │ 0 0 0
⋅ │ 0 1 │ 0 0 0
───┼────────┼─────────
⋅ │ ⋅ ⋅ │ 1 0 0
⋅ │ ⋅ ⋅ │ 0 1 0
⋅ │ ⋅ ⋅ │ 0 0 1
julia> BlockBandedMatrix(Ones(sum(rows),sum(cols)), rows, cols, (l,u))
3×3-blocked 6×6 BlockBandedMatrix{Float64}:
1.0 │ 1.0 1.0 │ ⋅ ⋅ ⋅
─────┼────────────┼───────────────
⋅ │ 1.0 1.0 │ 1.0 1.0 1.0
⋅ │ 1.0 1.0 │ 1.0 1.0 1.0
─────┼────────────┼───────────────
⋅ │ ⋅ ⋅ │ 1.0 1.0 1.0
⋅ │ ⋅ ⋅ │ 1.0 1.0 1.0
⋅ │ ⋅ ⋅ │ 1.0 1.0 1.0
```

`BlockBandedMatrices.BlockBandedMatrix`

— Method`BlockBandedMatrix(A::AbstractMatrix, (l,u)::NTuple{2,Int})`

Return a `BlockBandedMatrix`

with block-bandwidths `(l,u)`

, where the structural non-zero blocks correspond to those of `A`

.

Examples

```
julia> using BlockArrays
julia> B = BlockArray(ones(6,6), 1:3, 1:3);
julia> BlockBandedMatrix(B, (1,1))
3×3-blocked 6×6 BlockBandedMatrix{Float64}:
1.0 │ 1.0 1.0 │ ⋅ ⋅ ⋅
─────┼────────────┼───────────────
1.0 │ 1.0 1.0 │ 1.0 1.0 1.0
1.0 │ 1.0 1.0 │ 1.0 1.0 1.0
─────┼────────────┼───────────────
⋅ │ 1.0 1.0 │ 1.0 1.0 1.0
⋅ │ 1.0 1.0 │ 1.0 1.0 1.0
⋅ │ 1.0 1.0 │ 1.0 1.0 1.0
```

`BlockBandedMatrices.BlockBandedMatrix`

— Method```
BlockBandedMatrix{T}(undef, rows::AbstractVector{Int}, cols::AbstractVector{Int},
(l,u)::NTuple{2,Int})
```

Return an unitialized `sum(rows) × sum(cols)`

`BlockBandedMatrix`

having `eltype`

`T`

, with `rows`

by `cols`

blocks and `(l,u)`

as the block-bandwidth.

`BlockBandedMatrices.BandedBlockBandedMatrix`

— Type```
BandedBlockBandedMatrix(M::Union{UniformScaling,AbstractMatrix},
rows, cols, (l, u), (λ, μ))
```

Return a `sum(rows) × sum(cols)`

banded-block-banded matrix `A`

, with block-bandwidths `(l,u)`

and where `A[Block(K,J)]`

is a `BandedMatrix`

of size `rows[K]`

×`cols[J]`

with bandwidths `(λ,μ)`

. The structural non-zero elements of the returned matrix corresponds to those of `M`

.

**Examples**

```
julia> using LinearAlgebra, FillArrays
julia> BandedBlockBandedMatrix(I, [3,4,3], [3,4,3], (1,1), (1,1))
3×3-blocked 10×10 BandedBlockBandedMatrix{Bool, BlockArrays.PseudoBlockMatrix{Bool, Matrix{Bool}, Tuple{BlockArrays.BlockedUnitRange{Vector{Int64}}, BlockArrays.BlockedUnitRange{Vector{Int64}}}}, BlockArrays.BlockedUnitRange{Vector{Int64}}}:
1 0 ⋅ │ 0 0 ⋅ ⋅ │ ⋅ ⋅ ⋅
0 1 0 │ 0 0 0 ⋅ │ ⋅ ⋅ ⋅
⋅ 0 1 │ ⋅ 0 0 0 │ ⋅ ⋅ ⋅
─────────┼──────────────┼─────────
0 0 ⋅ │ 1 0 ⋅ ⋅ │ 0 0 ⋅
0 0 0 │ 0 1 0 ⋅ │ 0 0 0
⋅ 0 0 │ ⋅ 0 1 0 │ ⋅ 0 0
⋅ ⋅ 0 │ ⋅ ⋅ 0 1 │ ⋅ ⋅ 0
─────────┼──────────────┼─────────
⋅ ⋅ ⋅ │ 0 0 ⋅ ⋅ │ 1 0 ⋅
⋅ ⋅ ⋅ │ 0 0 0 ⋅ │ 0 1 0
⋅ ⋅ ⋅ │ ⋅ 0 0 0 │ ⋅ 0 1
julia> BandedBlockBandedMatrix(Ones{Int}(10,13), [3,4,3], [4,5,4], (1,1), (1,1))
3×3-blocked 10×13 BandedBlockBandedMatrix{Int64, BlockArrays.PseudoBlockMatrix{Int64, Matrix{Int64}, Tuple{BlockArrays.BlockedUnitRange{Vector{Int64}}, BlockArrays.BlockedUnitRange{Vector{Int64}}}}, BlockArrays.BlockedUnitRange{Vector{Int64}}}:
1 1 ⋅ ⋅ │ 1 1 ⋅ ⋅ ⋅ │ ⋅ ⋅ ⋅ ⋅
1 1 1 ⋅ │ 1 1 1 ⋅ ⋅ │ ⋅ ⋅ ⋅ ⋅
⋅ 1 1 1 │ ⋅ 1 1 1 ⋅ │ ⋅ ⋅ ⋅ ⋅
────────────┼─────────────────┼────────────
1 1 ⋅ ⋅ │ 1 1 ⋅ ⋅ ⋅ │ 1 1 ⋅ ⋅
1 1 1 ⋅ │ 1 1 1 ⋅ ⋅ │ 1 1 1 ⋅
⋅ 1 1 1 │ ⋅ 1 1 1 ⋅ │ ⋅ 1 1 1
⋅ ⋅ 1 1 │ ⋅ ⋅ 1 1 1 │ ⋅ ⋅ 1 1
────────────┼─────────────────┼────────────
⋅ ⋅ ⋅ ⋅ │ 1 1 ⋅ ⋅ ⋅ │ 1 1 ⋅ ⋅
⋅ ⋅ ⋅ ⋅ │ 1 1 1 ⋅ ⋅ │ 1 1 1 ⋅
⋅ ⋅ ⋅ ⋅ │ ⋅ 1 1 1 ⋅ │ ⋅ 1 1 1
```

`BlockBandedMatrices.BandedBlockBandedMatrix`

— Method`BandedBlockBandedMatrix{T}(undef, rows, cols, (l, u), (λ, μ))`

Return an unitialized `BandedBlockBandedMatrix`

having `eltype`

`T`

, with block-bandwidths `(l,u)`

and where `A[Block(K,J)]`

is a `BandedMatrix{T}`

of size `rows[K]×cols[J]`

with bandwidths `(λ,μ)`

.

## Accessing block-banded and banded-block-banded matrices

`BlockBandedMatrices.blockbandwidths`

— Function`blockbandwidths(A)`

Returns a tuple containing the upper and lower blockbandwidth of `A`

.

`BlockBandedMatrices.blockbandwidth`

— Function`blockbandwidth(A,i)`

Returns the lower blockbandwidth (`i==1`

) or the upper blockbandwidth (`i==2`

).

`BlockBandedMatrices.subblockbandwidths`

— Function`subblockbandwidths(A)`

returns the sub-block bandwidths of `A`

, where `A`

is a banded-block-banded matrix. In other words, `A[Block(K,J)]`

will return a `BandedMatrix`

with bandwidths given by `subblockbandwidths(A)`

.

`BlockBandedMatrices.subblockbandwidth`

— Function`subblockbandwidth(A, i)`

returns the sub-block lower (`i == 1`

) or upper (`i == 2`

) bandwidth of `A`

, where `A`

is a banded-block-banded matrix. In other words, `A[Block(K,J)]`

will return a `BandedMatrix`

with the returned lower/upper bandwidth.

## Implementation

A `BlockBandedMatrix`

stores the entries in a single vector, ordered by columns. For example, if `A`

is a `BlockBandedMatrix`

with block-bandwidths `(A.l,A.u) == (1,0)`

and the block sizes `fill(2, N)`

where `N = 3`

is the number of row and column blocks, then `A`

has zero structure

```
[ a_11 a_12 │ ⋅ ⋅
a_21 a_22 │ ⋅ ⋅
──────────┼──────────
a_31 a_32 │ a_33 a_34
a_41 a_42 │ a_43 a_44
──────────┼──────────
⋅ ⋅ │ a_53 a_54
⋅ ⋅ │ a_63 a_64 ]
```

and is stored in memory via `A.data`

as a single vector by columns, containing:

`[a_11,a_21,a_31,a_41,a_12,a_22,a_32,a_42,a_33,a_43,a_53,a_63,a_34,a_44,a_54,a_64]`

The reasoning behind this storage scheme as that each block still satisfies the strided matrix interface, but we can also use BLAS and LAPACK to, for example, upper-triangularize a block column all at once.

A `BandedBlockBandedMatrix`

stores the entries as a `PseudoBlockMatrix`

, with the number of row blocks equal to `A.l + A.u + 1`

, and the row block sizes are all `A.μ + A.λ + 1`

. The column block sizes of the storage is the same as the the column block sizes of the `BandedBlockBandedMatrix`

. This is a block-wise version of the storage of `BandedMatrix`

.

For example, if `A`

is a `BandedBlockBandedMatrix`

with block-bandwidths `(A.l,A.u) == (1,0)`

and subblock-bandwidths `(A.λ, A.μ) == (1,0)`

, and the block sizes `fill(2, N)`

where `N = 3`

is the number of row and column blocks, then `A`

has zero structure

```
[ a_11 ⋅ │ ⋅ ⋅
a_21 a_22 │ ⋅ ⋅
──────────┼──────────
a_31 ⋅ │ a_33 ⋅
a_41 a_42 │ a_43 a_44
──────────┼──────────
⋅ ⋅ │ a_53 ⋅
⋅ ⋅ │ a_63 a_64 ]
```

and is stored in memory via `A.data`

as a `PseudoBlockMatrix`

, which has block sizes 2 x 2, containing entries:

```
[a_11 a_22 │ a_33 a_44
a_21 × │ a_43 ×
──────────┼──────────
a_31 a_42 │ a_53 a_64
a_41 × │ a_63 × ]
```

where `×`

is an entry in memory that is not used.

The reasoning behind this storage scheme as that each block still satisfies the banded matrix interface.