diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index b65795c..39d6a26 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-20T08:40:37","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-26T12:11:18","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/changes/index.html b/dev/changes/index.html index 1da66dd..746b3d2 100644 --- a/dev/changes/index.html +++ b/dev/changes/index.html @@ -1,2 +1,2 @@ -Changes · ExtendableSparse.jl

Changes

v1.5, July 17, 2024

  • Multithreading

v1.4, Jan 25, 2024

  • Dirichlet elimination

v1.3, Jan 16, 2024

  • AMGCLWrap extension, renamed AMGPreconditioner to RS_AMGPreconditioner
  • muted Pardiso

v1.2, August 5, 2023

  • Introduced 1.9 extensions for Pardiso, AlgebraicMultigrid, IncompleteLU

v1.1, May 3, 2023

  • AbstractFactorization and subtypes are now without element and index type information. They wrap more concretely typed info. This shall allow to construct a preconditioner without knowing matrix and element type.
  • First steps to block preconditioning
  • src directory restructured

v1.0.1, Jan 22, 2023

  • support of AbstractSparseMatrixCSC interface
  • replace SparseArrays.sparse by SparseArrays.SparseMatrixCSC

v0.9.6, Jan 22, 2023

  • support for LinearSolve.jl

v0.9.1 ... v0.9.5, Jan 5, 2023

  • update interface with Sparspak
  • Addition, multiplication etc. for ExtendableSparse
  • ILUZero.jl as dependency for ILUZeroPreconditioner
  • fix ILU0Preconditioner backsubstitution for unsymmetric matrices
  • Add LinearAlgebra.lu etc. for ExtendableSparse

v0.9, Sept 28, 2022

  • \ support for general number types and non-GPL system images based on Sparspak.jl 0.3.0

v0.8, Sept 1, 2022

  • Remove LinearSolve compatibility in favor of (future) interfacing via AbstractSparseMatrixCSC
  • Add Sparspak LU factorization
  • Add handling of GPL free sysimage build

v0.7, August 19, 2022

  • Require Julia 1.6
  • first steps to compatibility with LinearSolve.jl

v0.6, April 20, 2021

  • use type parameters to describe factorizations

v0.5, April 10, 2021

  • Introduce lu/lu! , factorize/factorize!, unifying LU factorizations and preconditioners
  • Interface packages: Pardiso, AlgebraicMultigrid, IncompleteLU via Requires.jl

v0.4, March 2021

  • Fix handling of Symmetrix matrices
  • rawupdateindex does not check for entering zeros
  • Compare with COO method
  • Benchmarks in documentation

v0.3.7, March 20, 2021

  • Added parallel jacobi preconditioner (thanks, @jkr)
  • Fixes ldiv
  • Added simple iterative solver
  • Documentation update
  • Tests for precondioners, fdrand

v0.3.0, April 10, 2020

  • Don't create new entry if the value to be assigned is zero, making things consistent with SparseMatrixCSC and ForwardDiff as suggested by @MaximilianJHuber

v0.2.5, Jan 26, 2020

  • fixed allocations in Base.+
  • added updateindex! method
  • provide fdrand and fdrand! matrix constructors
  • automatic benchmarks in examples

v0.2.4, Jan 19, 2020

  • Allow preconditioner creation directly from CSC Matrix
  • Rename AbstractPreconditioner to AbstractExtendablePreconditioner

v0.2.3, Jan 15, 2020

  • Started to introduce preconditioners (undocumented)

v0.2.3, Jan 8, 2020

  • added norm, cond, opnorm methods
  • resize! instead of push! when adding entries should trigger less allocation operations

v0.2.2. Dec 23, 2019

  • What used to be _splice is now + and allows now real addition (resulting in a CSC matrix)
  • Added constructors of LNK matrix from CSC matrix and vice versa
  • reorganized tests

v0.2.1 Dec 22, 2019

  • Tried to track down the source from which I learned the linked list based struct in order to document this. Ended up with SPARSEKIT of Y.Saad, however I believe this already was in SPARSEPAK by Chu,George,Liu.
  • Internal rename of SparseMatrixExtension to SparseMatrixLNK.

v0.2 Dec 21, 2019

  • more interface methods delegating to csc, in particular mul! and ldiv!
  • lazy creation of extendable part: don't create idle memory
  • nicer constructors

V0.1, July 2019

  • Initial release
+Changes · ExtendableSparse.jl

Changes

v1.5, July 17, 2024

  • Multithreading

v1.4, Jan 25, 2024

  • Dirichlet elimination

v1.3, Jan 16, 2024

  • AMGCLWrap extension, renamed AMGPreconditioner to RS_AMGPreconditioner
  • muted Pardiso

v1.2, August 5, 2023

  • Introduced 1.9 extensions for Pardiso, AlgebraicMultigrid, IncompleteLU

v1.1, May 3, 2023

  • AbstractFactorization and subtypes are now without element and index type information. They wrap more concretely typed info. This shall allow to construct a preconditioner without knowing matrix and element type.
  • First steps to block preconditioning
  • src directory restructured

v1.0.1, Jan 22, 2023

  • support of AbstractSparseMatrixCSC interface
  • replace SparseArrays.sparse by SparseArrays.SparseMatrixCSC

v0.9.6, Jan 22, 2023

  • support for LinearSolve.jl

v0.9.1 ... v0.9.5, Jan 5, 2023

  • update interface with Sparspak
  • Addition, multiplication etc. for ExtendableSparse
  • ILUZero.jl as dependency for ILUZeroPreconditioner
  • fix ILU0Preconditioner backsubstitution for unsymmetric matrices
  • Add LinearAlgebra.lu etc. for ExtendableSparse

v0.9, Sept 28, 2022

  • \ support for general number types and non-GPL system images based on Sparspak.jl 0.3.0

v0.8, Sept 1, 2022

  • Remove LinearSolve compatibility in favor of (future) interfacing via AbstractSparseMatrixCSC
  • Add Sparspak LU factorization
  • Add handling of GPL free sysimage build

v0.7, August 19, 2022

  • Require Julia 1.6
  • first steps to compatibility with LinearSolve.jl

v0.6, April 20, 2021

  • use type parameters to describe factorizations

v0.5, April 10, 2021

  • Introduce lu/lu! , factorize/factorize!, unifying LU factorizations and preconditioners
  • Interface packages: Pardiso, AlgebraicMultigrid, IncompleteLU via Requires.jl

v0.4, March 2021

  • Fix handling of Symmetrix matrices
  • rawupdateindex does not check for entering zeros
  • Compare with COO method
  • Benchmarks in documentation

v0.3.7, March 20, 2021

  • Added parallel jacobi preconditioner (thanks, @jkr)
  • Fixes ldiv
  • Added simple iterative solver
  • Documentation update
  • Tests for precondioners, fdrand

v0.3.0, April 10, 2020

  • Don't create new entry if the value to be assigned is zero, making things consistent with SparseMatrixCSC and ForwardDiff as suggested by @MaximilianJHuber

v0.2.5, Jan 26, 2020

  • fixed allocations in Base.+
  • added updateindex! method
  • provide fdrand and fdrand! matrix constructors
  • automatic benchmarks in examples

v0.2.4, Jan 19, 2020

  • Allow preconditioner creation directly from CSC Matrix
  • Rename AbstractPreconditioner to AbstractExtendablePreconditioner

v0.2.3, Jan 15, 2020

  • Started to introduce preconditioners (undocumented)

v0.2.3, Jan 8, 2020

  • added norm, cond, opnorm methods
  • resize! instead of push! when adding entries should trigger less allocation operations

v0.2.2. Dec 23, 2019

  • What used to be _splice is now + and allows now real addition (resulting in a CSC matrix)
  • Added constructors of LNK matrix from CSC matrix and vice versa
  • reorganized tests

v0.2.1 Dec 22, 2019

  • Tried to track down the source from which I learned the linked list based struct in order to document this. Ended up with SPARSEKIT of Y.Saad, however I believe this already was in SPARSEPAK by Chu,George,Liu.
  • Internal rename of SparseMatrixExtension to SparseMatrixLNK.

v0.2 Dec 21, 2019

  • more interface methods delegating to csc, in particular mul! and ldiv!
  • lazy creation of extendable part: don't create idle memory
  • nicer constructors

V0.1, July 2019

  • Initial release
diff --git a/dev/example/index.html b/dev/example/index.html index 312996d..2875b05 100644 --- a/dev/example/index.html +++ b/dev/example/index.html @@ -10,11 +10,11 @@ end;
assemble (generic function with 1 method)

Measure the time (in seconds) for assembling a SparseMatrixCSC:

t_csc = @belapsed begin
     A = spzeros(10_000, 10_000)
     assemble(A)
-end
0.018308223

An ExtendableSparseMatrix can be used as a drop-in replacement. However, before any other use, this needs an internal structure rebuild which is invoked by the flush! method.

t_ext = @belapsed begin
+end
0.018289501

An ExtendableSparseMatrix can be used as a drop-in replacement. However, before any other use, this needs an internal structure rebuild which is invoked by the flush! method.

t_ext = @belapsed begin
     A = ExtendableSparseMatrix(10_000, 10_000)
     assemble(A)
     flush!(A)
-end
0.001306216

All specialized methods of linear algebra functions (e.g. \) for ExtendableSparseMatrix call flush! before proceeding.

The overall time gain from using ExtendableSparse is:

t_ext / t_csc
0.07134586464235225

The reason for this situation is that the SparseMatrixCSC struct just contains the data for storing the matrix in the compressed column format. Inserting a new entry in this storage scheme is connected with serious bookkeeping and shifts of large portions of array content.

Julia provides the sparse method which uses an intermediate storage of the data in two index arrays and a value array, the so called coordinate (or COO) format:

function assemble_coo(n)
+end
0.00131108

All specialized methods of linear algebra functions (e.g. \) for ExtendableSparseMatrix call flush! before proceeding.

The overall time gain from using ExtendableSparse is:

t_ext / t_csc
0.07168484257717037

The reason for this situation is that the SparseMatrixCSC struct just contains the data for storing the matrix in the compressed column format. Inserting a new entry in this storage scheme is connected with serious bookkeeping and shifts of large portions of array content.

Julia provides the sparse method which uses an intermediate storage of the data in two index arrays and a value array, the so called coordinate (or COO) format:

function assemble_coo(n)
     I = zeros(Int64, 0)
     J = zeros(Int64, 0)
     V = zeros(0)
@@ -32,9 +32,9 @@
     sparse(I, J, V)
 end;
 
-t_coo = @belapsed assemble_coo(10_000)
0.000685107

While more convenient to use, the assembly based on ExtendableSparseMatrix is only slightly slower:

t_ext / t_coo
1.906586854316187

Below one finds a more elaborate discussion for a quasi-3D problem.

Matrix creation benchmark

The method fdrand creates a matrix similar to the discretization matrix of a Poisson equation on a d-dimensional cube. The approach is similar to that of a typical finite element code: calculate a local stiffness matrix and assemble it into the global one.

Benchmark for ExtendableSparseMatrix

The code uses the index access API for the creation of the matrix, inserting elements via A[i,j]+=v, using an intermediate linked list structure which upon return is flushed into a SparseMatrixCSC structure.

@belapsed fdrand(30, 30, 30, matrixtype = ExtendableSparseMatrix)
0.010217307

Benchmark for SparseMatrixCSC

Here, for comparison we use a SparseMatrixCSC created with spzeros and insert entries via A[i,j]+=v.

@belapsed fdrand(30, 30, 30, matrixtype = SparseMatrixCSC)
0.37125781

Benchmark for intermediate coordinate format

A SparseMatrixCSC is created by accumulating data into arrays I,J,A and calling sparse(I,J,A)

@belapsed fdrand(30, 30, 30, matrixtype = :COO)
0.008418744

This is nearly on par with matrix creation via ExtendableSparseMatrix, but the later can be made faster:

Benchmark for ExtendableSparseMatrix with updateindex

Here, we use a ExtendableSparseMatrix created withspzerosand insert entries viaupdateindex(A,+,v,i,j)`, see the discussion below.

@belapsed fdrand(30, 30, 30,
+t_coo = @belapsed assemble_coo(10_000)
0.000672296

While more convenient to use, the assembly based on ExtendableSparseMatrix is only slightly slower:

t_ext / t_coo
1.950152908837774

Below one finds a more elaborate discussion for a quasi-3D problem.

Matrix creation benchmark

The method fdrand creates a matrix similar to the discretization matrix of a Poisson equation on a d-dimensional cube. The approach is similar to that of a typical finite element code: calculate a local stiffness matrix and assemble it into the global one.

Benchmark for ExtendableSparseMatrix

The code uses the index access API for the creation of the matrix, inserting elements via A[i,j]+=v, using an intermediate linked list structure which upon return is flushed into a SparseMatrixCSC structure.

@belapsed fdrand(30, 30, 30, matrixtype = ExtendableSparseMatrix)
0.010101841

Benchmark for SparseMatrixCSC

Here, for comparison we use a SparseMatrixCSC created with spzeros and insert entries via A[i,j]+=v.

@belapsed fdrand(30, 30, 30, matrixtype = SparseMatrixCSC)
0.370833059

Benchmark for intermediate coordinate format

A SparseMatrixCSC is created by accumulating data into arrays I,J,A and calling sparse(I,J,A)

@belapsed fdrand(30, 30, 30, matrixtype = :COO)
0.008413393

This is nearly on par with matrix creation via ExtendableSparseMatrix, but the later can be made faster:

Benchmark for ExtendableSparseMatrix with updateindex

Here, we use a ExtendableSparseMatrix created withspzerosand insert entries viaupdateindex(A,+,v,i,j)`, see the discussion below.

@belapsed fdrand(30, 30, 30,
                  matrixtype = ExtendableSparseMatrix,
-                 update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.007962634

Matrix update benchmark

For repeated calculations on the same sparsity structure (e.g. for time dependent problems or Newton iterations) it is convenient to skip all but the first creation steps and to just replace the values in the matrix after setting the elements of the nzval vector to zero. Typically in finite element and finite volume methods this step updates matrix entries (most of them several times) by adding values. In this case, the current indexing interface of Julia requires to access the matrix twice:

A = spzeros(3, 3)
+                 update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.007736853

Matrix update benchmark

For repeated calculations on the same sparsity structure (e.g. for time dependent problems or Newton iterations) it is convenient to skip all but the first creation steps and to just replace the values in the matrix after setting the elements of the nzval vector to zero. Typically in finite element and finite volume methods this step updates matrix entries (most of them several times) by adding values. In this case, the current indexing interface of Julia requires to access the matrix twice:

A = spzeros(3, 3)
 Meta.@lower A[1, 2] += 3
:($(Expr(:thunk, CodeInfo(
     @ none within `top-level scope`
 1 ─ %1 = +
@@ -44,10 +44,10 @@
 └──      return %3
 ))))

For sparse matrices this requires to perform the index search in the structure twice. The packages provides the method updateindex! for both SparseMatrixCSC and for ExtendableSparse which allows to update a matrix element with just one index search.

Benchmark for SparseMatrixCSC

A = fdrand(30, 30, 30; matrixtype = SparseMatrixCSC)
 @belapsed fdrand!(A, 30, 30, 30,
-                  update = (A, v, i, j) -> A[i, j] += v)
0.005268095
A = fdrand(30, 30, 30; matrixtype = SparseMatrixCSC)
+                  update = (A, v, i, j) -> A[i, j] += v)
0.005293948
A = fdrand(30, 30, 30; matrixtype = SparseMatrixCSC)
 @belapsed fdrand!(A, 30, 30, 30,
-                  update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.002008005

Benchmark for ExtendableSparseMatrix

A = fdrand(30, 30, 30; matrixtype = ExtendableSparseMatrix)
+                  update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.001967188

Benchmark for ExtendableSparseMatrix

A = fdrand(30, 30, 30; matrixtype = ExtendableSparseMatrix)
 @belapsed fdrand!(A, 30, 30, 30,
-                  update = (A, v, i, j) -> A[i, j] += v)
0.004688143
A = fdrand(30, 30, 30; matrixtype = ExtendableSparseMatrix)
+                  update = (A, v, i, j) -> A[i, j] += v)
0.004670713
A = fdrand(30, 30, 30; matrixtype = ExtendableSparseMatrix)
 @belapsed fdrand!(A, 30, 30, 30,
-                  update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.002521364

Note that the update process for ExtendableSparse may be slightly slower than for SparseMatrixCSC due to the overhead which comes from checking the presence of new entries.

+ update = (A, v, i, j) -> updateindex!(A, +, v, i, j))
0.002529408

Note that the update process for ExtendableSparse may be slightly slower than for SparseMatrixCSC due to the overhead which comes from checking the presence of new entries.

diff --git a/dev/extsparse/index.html b/dev/extsparse/index.html index 6f0f7d7..8a1e49c 100644 --- a/dev/extsparse/index.html +++ b/dev/extsparse/index.html @@ -27,4 +27,4 @@ a\nabla u\cdot \vec n + b u &=g && \text{on}\; \partial\Omega \end{align*}\]

The matrix is irreducibly diagonally dominant, has positive main diagonal entries and nonpositive off-diagonal entries, hence it has the M-Property. Therefore, its inverse will be a dense matrix with positive entries, and the spectral radius of the Jacobi iteration matrix $ho(I-D(A)^{-1}A)<1$ .

Moreover, in the symmetric case, it is positive definite.

Parameters+ default values:

Parameter + default valeDescription
nxNumber of unknowns in x direction
nyNumber of unknowns in y direction
nzNumber of unknowns in z direction
matrixtype = SparseMatrixCSCMatrix type
update = (A,v,i,j)-> A[i,j]+=vElement update function
rand =()-> rand()Random number generator
symmetric=trueWhether to create symmetric matrix or not

The sparsity structure is fixed to an orthogonal grid, resulting in a 3, 5 or 7 diagonal matrix depending on dimension. The entries are random unless e.g. rand=()->1 is passed as random number generator. Tested for Matrix, SparseMatrixCSC, ExtendableSparseMatrix, Tridiagonal, SparseMatrixLNK and :COO

source
ExtendableSparse.sprand!Method
sprand!(A, xnnz)
 

Fill empty sparse matrix A with random nonzero elements from interval [1,2] using incremental assembly.

source
ExtendableSparse.sprand_sdd!Method
sprand_sdd!(A; nnzrow)
-

Fill sparse matrix with random entries such that it becomes strictly diagonally dominant and thus invertible and has a fixed number nnzrow (default: 4) of nonzeros in its rows. The matrix bandwidth is bounded by sqrt(n) in order to resemble a typical matrix of a 2D piecewise linear FEM discretization.

source
+

Fill sparse matrix with random entries such that it becomes strictly diagonally dominant and thus invertible and has a fixed number nnzrow (default: 4) of nonzeros in its rows. The matrix bandwidth is bounded by sqrt(n) in order to resemble a typical matrix of a 2D piecewise linear FEM discretization.

source diff --git a/dev/index.html b/dev/index.html index c257929..c39b875 100644 --- a/dev/index.html +++ b/dev/index.html @@ -18,4 +18,4 @@ jac=DiffResults.jacobian(dresult) h=jac\x

However, without a priori information on sparsity, ForwardDiff calls element insertion for the full range of n^2 indices, leading to a O(n^2) scaling behavior due to the nevertheless necessary search operations, see this discourse thread.

updateindex!

In addition, the package provides a method updateindex!(A,op,v,i,j) for both SparseMatrixCSC and for ExtendableSparse which allows to update a matrix element with one index search instead of two. It allows to replace e.g. A[i,j]+=v by updateindex!(A,+,v,i,j). The former operation is lowered to

%1 = Base.getindex(A, 1, 2)
 %2 = %1 + 3
-Base.setindex!(A, %2, 1, 2)

triggering two index searches, one for getindex! and another one for setindex!.

See Julia issue #15630 for a discussion on this.

Factorizations and Preconditioners

The package provides a common API for factorizations and preconditioners supporting series of solutions of similar problem as they occur during nonlinear and transient solves. For details, see the corresponding documentation.

With the advent of LinearSolve.jl, this functionality probably will be reduced to some core cases.

Interfaces to other packages

The package directly provides interfaces to other sparse matrix solvers and preconditioners. Dependencies on these packages are handled via Requires.jl. Currently, support includes:

For a similar approach, see Preconditioners.jl

Alternatives

You may also evaluate alternatives to this package:

Index

+Base.setindex!(A, %2, 1, 2)

triggering two index searches, one for getindex! and another one for setindex!.

See Julia issue #15630 for a discussion on this.

Factorizations and Preconditioners

The package provides a common API for factorizations and preconditioners supporting series of solutions of similar problem as they occur during nonlinear and transient solves. For details, see the corresponding documentation.

With the advent of LinearSolve.jl, this functionality probably will be reduced to some core cases.

Interfaces to other packages

The package directly provides interfaces to other sparse matrix solvers and preconditioners. Dependencies on these packages are handled via Requires.jl. Currently, support includes:

For a similar approach, see Preconditioners.jl

Alternatives

You may also evaluate alternatives to this package:

Index

diff --git a/dev/internal/index.html b/dev/internal/index.html index 9096315..5be54d2 100644 --- a/dev/internal/index.html +++ b/dev/internal/index.html @@ -90,4 +90,4 @@

Update element of the matrix with operation op. It assumes that op(0,0)==0. If v is zero a new entry is created nevertheless.

source
ExtendableSparse.updateindex!Method
updateindex!(lnk, op, v, i, j)
 

Update element of the matrix with operation op. It assumes that op(0,0)==0. If v is zero, no new entry is created.

source
SparseArrays.nnzMethod
nnz(lnk)
 

Return number of nonzero entries.

source

Misc methods

ExtendableSparse.@makefrommatrixMacro

" @makefrommatrix(fact)

For an AbstractFactorization MyFact, provide methods

    MyFact(A::ExtendableSparseMatrix; kwargs...)
-    MyFact(A::SparseMatrixCSC; kwargs...)
source
+ MyFact(A::SparseMatrixCSC; kwargs...)source diff --git a/dev/iter/index.html b/dev/iter/index.html index 737f135..d3b3c50 100644 --- a/dev/iter/index.html +++ b/dev/iter/index.html @@ -16,7 +16,7 @@ end factorize!(factorization, A) nm2 = norm(factorization \ b) -nm1, nm2
(2308.0241735864874, 2358.620730683219)
using ExtendableSparse, LinearAlgebra
+nm1, nm2
(1998.5383153472162, 2035.7481854031103)
using ExtendableSparse, LinearAlgebra
 A = fdrand(20, 20, 1; matrixtype = ExtendableSparseMatrix)
 n = size(A, 1)
 b = rand(n)
@@ -30,7 +30,7 @@
 end
 update!(factorization)
 nm2 = norm(factorization \ b)
-nm1, nm2
(2118.167095375731, 2304.9119346560983)
ExtendableSparse.LUFactorizationType
LUFactorization()
+nm1, nm2
(2122.671222948463, 2315.981132434167)
Base.:\Function
A

\ for ExtendableSparse. It calls the LU factorization form Sparspak.jl, unless GPL components 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.

source
\(symm_ext, b)
 

\ for Symmetric{ExtendableSparse}

source
\(symm_ext, b)
@@ -49,7 +49,7 @@
 end
 factorize!(preconditioner, A)
 nm2 = norm(bicgstabl(A, b, 1; Pl = preconditioner))
-nm1, nm2
(2174.488762544756, 2222.126365815911)
using ExtendableSparse, LinearAlgebra
+nm1, nm2
(1932.5264182248939, 1969.2588873750851)
using ExtendableSparse, LinearAlgebra
 using IterativeSolvers
 A = fdrand(20, 20, 1; matrixtype = ExtendableSparseMatrix)
 n = size(A, 1)
@@ -64,7 +64,7 @@
 end
 update!(preconditioner)
 nm2 = norm(cg(A, b; Pl = preconditioner))
-nm1, nm2
(1910.2759622947035, 1987.593601527878)
ExtendableSparse.ILUZeroPreconditionerType
ILUZeroPreconditioner()
+nm1, nm2
(2078.7487960797534, 2163.320899179491)
ExtendableSparse.BlockPreconBuilderType
 BlockPreconBuilder(;precs=UMFPACKPreconBuilder(),  
                      partitioning = A -> [1:size(A,1)]

Return callable object constructing a left block Jacobi preconditioner from partition of unknowns.

  • partitioning(A) shall return a vector of AbstractVectors describing the indices of the partitions of the matrix. For a matrix of size n x n, e.g. partitioning could be [ 1:n÷2, (n÷2+1):n] or [ 1:2:n, 2:2:n].

  • precs(A,p) shall return a left precondioner for a matrix block.

source
ExtendableSparse.BlockPreconditionerType
 BlockPreconditioner(;partitioning, factorization=LUFactorization)

Create a block preconditioner from partition of unknowns given by partitioning, a vector of AbstractVectors describing the indices of the partitions of the matrix. For a matrix of size n x n, e.g. partitioning could be [ 1:n÷2, (n÷2+1):n] or [ 1:2:n, 2:2:n]. Factorization is a callable (Function or struct) which allows to create a factorization (with ldiv! methods) from a submatrix of A.

source
ExtendableSparse.allow_viewsMethod
allow_views(::preconditioner_type)

Factorizations on matrix partitions within a block preconditioner may or may not work with array views. 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.

source
ExtendableSparse.AMGCL_AMGPreconditionerFunction
AMGCL_AMGPreconditioner(;kwargs...)
@@ -93,4 +93,4 @@
                  log=false,
                  maxiter=100,
                  P=nothing
-                 ) -> solution, [history]

Simple iteration scheme $u_{i+1}= u_i - P^{-1} (A u_i -b)$ with similar API as the methods in IterativeSolvers.jl.

source
+ ) -> solution, [history]

Simple iteration scheme $u_{i+1}= u_i - P^{-1} (A u_i -b)$ with similar API as the methods in IterativeSolvers.jl.

source
diff --git a/dev/linearsolve/index.html b/dev/linearsolve/index.html index 271598a..7c6b8dd 100644 --- a/dev/linearsolve/index.html +++ b/dev/linearsolve/index.html @@ -4,13 +4,13 @@ x = ones(1000) b = A * x y = A \ b -sum(y)
1000.0

This works as well for number types besides Float64 and related, in this case, by default a LU factorization based on Sparspak is used.

using ExtendableSparse
+sum(y)
1000.0000000000003

This works as well for number types besides Float64 and related, in this case, by default a LU factorization based on Sparspak is used.

using ExtendableSparse
 using MultiFloats
 A = fdrand(Float64x2, 10, 10, 10; matrixtype = ExtendableSparseMatrix)
 x = ones(Float64x2,1000)
 b = A * x
 y = A \ b
-sum(y)
999.999999999999999999999999999741007879743492068

Solving with LinearSolve.jl

Starting with version 0.9.6, ExtendableSparse is compatible with LinearSolve.jl. Since version 0.9.7, this is facilitated via the AbstractSparseMatrixCSC interface.

The same problem can be solved via LinearSolve.jl:

using ExtendableSparse
+sum(y)
999.999999999999999999999999999788686596763687116

Solving with LinearSolve.jl

Starting with version 0.9.6, ExtendableSparse is compatible with LinearSolve.jl. Since version 0.9.7, this is facilitated via the AbstractSparseMatrixCSC interface.

The same problem can be solved via LinearSolve.jl:

using ExtendableSparse
 using LinearSolve
 A = fdrand(10, 10, 10; matrixtype = ExtendableSparseMatrix)
 x = ones(1000)
@@ -23,7 +23,7 @@
 x = ones(Float64x2,1000)
 b = A * x
 y = solve(LinearProblem(A, b), SparspakFactorization()).u
-sum(y)
999.999999999999999999999999999802081959658453042

Preconditioned Krylov solvers with LinearSolve.jl

Since version 1.6, preconditioner constructors can be passed to iterative solvers via the precs keyword argument to the iterative solver specification.

using ExtendableSparse
+sum(y)
999.999999999999999999999999999814021658303361909

Preconditioned Krylov solvers with LinearSolve.jl

Since version 1.6, preconditioner constructors can be passed to iterative solvers via the precs keyword argument to the iterative solver specification.

using ExtendableSparse
 using LinearSolve
 using ExtendableSparse: ILUZeroPreconBuilder
 A = fdrand(10, 10, 10; matrixtype = ExtendableSparseMatrix)
@@ -31,7 +31,7 @@
 b = A * x
 y = LinearSolve.solve(LinearProblem(A, b),
                       KrylovJL_CG(; precs=ILUZeroPreconBuilder())).u
-sum(y)
999.9999999364333

Available preconditioners

ExtendableSparse provides constructors for preconditioners which can be used as precs. These generally return a tuple (Pl,I) of a left preconditioner and a trivial right preconditioner.

ExtendableSparse has a number of package extensions which construct preconditioners from some other packages. In the future, these packages may provide this functionality on their own.

ExtendableSparse.ILUZeroPreconBuilderType
ILUZeroPreconBuilder(;blocksize=1)

Return callable object constructing a left zero fill-in ILU preconditioner using ILUZero.jl

source
ExtendableSparse.ILUTPreconBuilderType
ILUTPreconBuilder(; droptol=0.1)

Return callable object constructing a left ILUT preconditioner using IncompleteLU.jl

source
ExtendableSparse.SmoothedAggregationPreconBuilderType
SmoothedAggregationPreconBuilder(;blocksize=1, kwargs...)

Return callable object constructing a left smoothed aggregation algebraic multigrid preconditioner using AlgebraicMultigrid.jl.

Needs import AlgebraicMultigrid to trigger the corresponding extension.

source
ExtendableSparse.RugeStubenPreconBuilderType

RugeStubenPreconBuilder(;blocksize=1, kwargs...)

Return callable object constructing a left algebraic multigrid preconditioner after Ruge & Stüben using AlgebraicMultigrid.jl.

Needs import AlgebraicMultigrid to trigger the corresponding extension.

source

In addition, ExtendableSparse implements some preconditioners:

ExtendableSparse.JacobiPreconBuilderType
JacobiPreconBuilder()

Return callable object constructing a left Jacobi preconditioner to be passed as the precs parameter to iterative methods wrapped by LinearSolve.jl.

source

LU factorizations of matrices from previous iteration steps may be good preconditioners for Krylov solvers called during a nonlinear solve via Newton's method. For this purpose, ExtendableSparse provides a preconditioner constructor which wraps sparse LU factorizations supported by LinearSolve.jl

ExtendableSparse.LinearSolvePreconBuilderType
    LinearSolvePreconBuilder(; method=UMFPACKFactorization())

Return callable object constructing a formal left preconditioner from a sparse LU factorization using LinearSolve as the precs parameter for a BlockPreconBuilder or iterative methods wrapped by LinearSolve.jl.

source

Block preconditioner constructors are provided as well

ExtendableSparse.BlockPreconBuilderType
 BlockPreconBuilder(;precs=UMFPACKPreconBuilder(),  
+sum(y)
999.999999963754

Available preconditioners

ExtendableSparse provides constructors for preconditioners which can be used as precs. These generally return a tuple (Pl,I) of a left preconditioner and a trivial right preconditioner.

ExtendableSparse has a number of package extensions which construct preconditioners from some other packages. In the future, these packages may provide this functionality on their own.

In addition, ExtendableSparse implements some preconditioners:

ExtendableSparse.JacobiPreconBuilderType
JacobiPreconBuilder()

Return callable object constructing a left Jacobi preconditioner to be passed as the precs parameter to iterative methods wrapped by LinearSolve.jl.

source

LU factorizations of matrices from previous iteration steps may be good preconditioners for Krylov solvers called during a nonlinear solve via Newton's method. For this purpose, ExtendableSparse provides a preconditioner constructor which wraps sparse LU factorizations supported by LinearSolve.jl

Block preconditioner constructors are provided as well

ExtendableSparse.BlockPreconBuilderType
 BlockPreconBuilder(;precs=UMFPACKPreconBuilder(),  
                      partitioning = A -> [1:size(A,1)]

Return callable object constructing a left block Jacobi preconditioner from partition of unknowns.

  • partitioning(A) shall return a vector of AbstractVectors describing the indices of the partitions of the matrix. For a matrix of size n x n, e.g. partitioning could be [ 1:n÷2, (n÷2+1):n] or [ 1:2:n, 2:2:n].

  • precs(A,p) shall return a left precondioner for a matrix block.

source

The example beloww shows how to create a block Jacobi preconditioner where the blocks are defined by even and odd degrees of freedom, and the diagonal blocks are solved using UMFPACK.

using ExtendableSparse
 using LinearSolve
 using ExtendableSparse: LinearSolvePreconBuilder, BlockPreconBuilder
@@ -42,7 +42,7 @@
 umfpackprecs=LinearSolvePreconBuilder(UMFPACKFactorization())
 blockprecs=BlockPreconBuilder(;precs=umfpackprecs, partitioning)
 y = LinearSolve.solve(LinearProblem(A, b), KrylovJL_CG(; precs=blockprecs)).u
-sum(y)
999.9999998962879

umpfackpreconbuilder e.g. could be replaced by SmoothedAggregationPreconBuilder(). Moreover, this approach works for any AbstractSparseMatrixCSC.

Deprecated API

Passing a preconditioner via the Pl or Pr keyword arguments will be deprecated in LinearSolve. ExtendableSparse used to export a number of wrappers for preconditioners from other packages for this purpose. This approach is deprecated as of v1.6 and will be removed with v2.0.

using ExtendableSparse
+sum(y)
1000.00000005058

umpfackpreconbuilder e.g. could be replaced by SmoothedAggregationPreconBuilder(). Moreover, this approach works for any AbstractSparseMatrixCSC.

Deprecated API

Passing a preconditioner via the Pl or Pr keyword arguments will be deprecated in LinearSolve. ExtendableSparse used to export a number of wrappers for preconditioners from other packages for this purpose. This approach is deprecated as of v1.6 and will be removed with v2.0.

using ExtendableSparse
 using LinearSolve
 using SparseArray
 using ILUZero
@@ -51,4 +51,4 @@
 b = A * x
 y = LinearSolve.solve(LinearProblem(A, b), KrylovJL_CG();
                       Pl = ILUZero.ilu0(SparseMatrixCSC(A))).u
-sum(y)
+sum(y)