Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
716b3c5
start iterative solvers
jalvesz Mar 2, 2025
9ed419f
simplify workspace
jalvesz Mar 3, 2025
9106676
add pccg solver and example
jalvesz Mar 8, 2025
297a18d
Merge branch 'fortran-lang:master' into iterative
jalvesz Mar 8, 2025
9eccdd8
Merge branch 'fortran-lang:master' into iterative
jalvesz Mar 28, 2025
a93f6b7
Merge branch 'fortran-lang:master' into iterative
jalvesz Apr 8, 2025
16e5cd7
Merge branch 'fortran-lang:master' into iterative
jalvesz Apr 15, 2025
e551a5d
complete cg with dirichlet flag, add example, fix di filter
jalvesz Apr 21, 2025
9309c5c
Merge branch 'fortran-lang:master' into iterative
jalvesz Apr 22, 2025
19167d5
add other sparse matrices
jalvesz Apr 23, 2025
9324971
add example for custom solver extending the generic interface
jalvesz Apr 23, 2025
71c2630
Merge branch 'iterative' of https://github.com/jalvesz/stdlib into it…
jalvesz Apr 23, 2025
85a70ba
small simplifications for working data
jalvesz Apr 25, 2025
84f4bc9
make default inner_product point to a default dot_product add enum fo…
jalvesz Apr 25, 2025
3ec23a4
make preconditionner a linop
jalvesz Apr 25, 2025
bfafaa5
use facility size
jalvesz Apr 25, 2025
0b01dbd
Add a customizable logger facility, change linop matvec to apply
jalvesz Apr 26, 2025
07b97ce
change internal procedure names for custom example
jalvesz Apr 26, 2025
379cd81
refactor to remove hard dependency on dirichlet BCs
jalvesz Apr 26, 2025
5e15a33
add forward/backward solvers for preconditionning
jalvesz Apr 28, 2025
8c2aa90
fix solve forward/backward
jalvesz Apr 29, 2025
e7bb7ce
Merge branch 'fortran-lang:master' into iterative
jalvesz Apr 29, 2025
517291a
fix colum index
jalvesz Apr 30, 2025
2c2196a
Merge branch 'iterative' of https://github.com/jalvesz/stdlib into it…
jalvesz Apr 30, 2025
367987a
add preconditionners
jalvesz Apr 30, 2025
05c076b
fix cmake
jalvesz May 1, 2025
f027017
add factorizations
jalvesz May 1, 2025
7fd2586
backward solve to use Lt marix
jalvesz May 1, 2025
c596ac0
start unit testing
jalvesz May 1, 2025
acefaaf
review csr factorization
jalvesz May 5, 2025
f413cbf
change name generic for kernel
jalvesz May 5, 2025
5cb2ad7
Merge branch 'fortran-lang:master' into iterative
jalvesz May 9, 2025
ea7d35e
shorten factorization procedures names
jalvesz May 10, 2025
8068f2d
Merge branch 'fortran-lang:master' into iterative
jalvesz May 16, 2025
eeddf7c
change precond ldl name
jalvesz May 17, 2025
b239028
rename to pcg
jalvesz May 18, 2025
724289f
Merge branch 'iterative' of https://github.com/jalvesz/stdlib into it…
jalvesz May 18, 2025
79dbbbe
Merge branch 'fortran-lang:master' into iterative
jalvesz May 23, 2025
463259b
start working on the documentation
jalvesz May 25, 2025
6627f4c
clean docstrings
jalvesz May 26, 2025
fe331f9
add cg and pcg tests
jalvesz May 26, 2025
9e5d000
Update example/linalg/example_solve_cg.f90
jalvesz May 28, 2025
0f9732e
add _type suffix
jalvesz May 28, 2025
177e545
reduce PR scope
jalvesz May 28, 2025
e68ce8e
rename wksp size constants
jalvesz May 28, 2025
1bc601c
rename constant
jalvesz May 28, 2025
64f83f8
Merge branch 'fortran-lang:master' into iterative
jalvesz May 30, 2025
a4d53e1
Merge branch 'fortran-lang:master' into iterative
jalvesz Jun 2, 2025
076a05d
Merge branch 'fortran-lang:master' into iterative
jalvesz Jun 9, 2025
507df75
Merge branch 'fortran-lang:master' into iterative
jalvesz Jul 6, 2025
64cc86e
Merge branch 'fortran-lang:master' into iterative
jalvesz Jul 22, 2025
2c519c2
Merge branch 'fortran-lang:master' into iterative
jalvesz Jul 23, 2025
34b83a0
Merge branch 'fortran-lang:master' into iterative
jalvesz Aug 14, 2025
e5fa984
change signature of linop apply to matvec and add operator input argu…
jalvesz Aug 14, 2025
b8055f3
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
daabef6
Update test/linalg/test_linalg_solve_iterative.fypp
jalvesz Sep 16, 2025
ef196b3
Update test/linalg/test_linalg_solve_iterative.fypp
jalvesz Sep 16, 2025
494a129
Update src/stdlib_linalg_iterative_solvers_cg.fypp
jalvesz Sep 16, 2025
a660e67
Update src/stdlib_linalg_iterative_solvers_cg.fypp
jalvesz Sep 16, 2025
aaaf94e
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
afe20df
Update example/linalg/example_solve_cg.f90
jalvesz Sep 16, 2025
a4b10a4
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
55bba1b
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
dbea562
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
555b512
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 16, 2025
9d64fe6
Update example/linalg/example_solve_cg.f90
jalvesz Sep 16, 2025
b9d74da
Update example/linalg/example_solve_cg.f90
jalvesz Sep 16, 2025
5c86e65
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
97e9a45
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
f1a73e1
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
59cc51a
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
b0f70af
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
24821e0
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
219637a
Update example/linalg/example_solve_custom.f90
jalvesz Sep 16, 2025
1fe49a3
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
403b687
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
5775d10
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
7706e1b
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
05e536d
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
f61224b
Update example/linalg/example_solve_pcg.f90
jalvesz Sep 16, 2025
59aa11c
Update src/stdlib_linalg_iterative_solvers_cg.fypp
jalvesz Sep 16, 2025
bc53766
small fixes
jalvesz Sep 16, 2025
f03506e
add documentation information
jalvesz Sep 16, 2025
6c4fb1d
forgotten attribute in doc
jalvesz Sep 16, 2025
8519e1b
use optval
jalvesz Sep 17, 2025
b3b5f43
explicit use of private/public
jalvesz Sep 17, 2025
1a814fb
Update doc/specs/stdlib_linalg_iterative_solvers.md
jalvesz Sep 18, 2025
8afdf4b
rename with stdlib_ prefix
jalvesz Sep 19, 2025
a246074
Merge branch 'iterative' of https://github.com/jalvesz/stdlib into it…
jalvesz Sep 19, 2025
731a0d6
Update example/linalg/example_solve_custom.f90
jalvesz Sep 19, 2025
945319b
Update src/stdlib_linalg_iterative_solvers_pcg.fypp
jalvesz Sep 19, 2025
f65ad71
replace tol by rtol and atol for convergence test
jalvesz Sep 22, 2025
8ff4866
Merge branch 'iterative' of https://github.com/jalvesz/stdlib into it…
jalvesz Sep 22, 2025
37be20b
change rtol and atol defaults
jalvesz Sep 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions doc/specs/stdlib_linalg_iterative_solvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Subroutine

#### Description

Implements the Conjugate Gradient (CG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments.
Implements the Conjugate Gradient (CG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `stdlib_linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments.

#### Syntax

Expand All @@ -117,7 +117,7 @@ Subroutine

`x`: 1-D array of `real(<kind>)` which serves as the input initial guess and the output solution. This argument is `intent(inout)`.

`tol`: scalar of type `real(<kind>)` specifying the requested tolerance with respect to the relative residual vector norm. This argument is `intent(in)`.
`rtol` and `atol`: scalars of type `real(<kind>)` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). These arguments are `intent(in)`.

`maxiter`: scalar of type `integer` defining the maximum allowed number of iterations. This argument is `intent(in)`.

Expand All @@ -132,7 +132,7 @@ Provides a user-friendly interface to the CG method for solving \( Ax = b \), su

#### Syntax

`call ` [[stdlib_iterative_solvers(module):solve_cg(interface)]] ` (A, b, x [, di, tol, maxiter, restart, workspace])`
`call ` [[stdlib_iterative_solvers(module):solve_cg(interface)]] ` (A, b, x [, di, rtol, atol, maxiter, restart, workspace])`

#### Status

Expand All @@ -152,7 +152,7 @@ Subroutine

`di` (optional): 1-D mask array of type `logical(int8)` defining the degrees of freedom subject to dirichlet boundary conditions. The actual boundary conditions values should be stored in the `b` load array. This argument is `intent(in)`.

`tol` (optional): scalar of type `real(<kind>)` specifying the requested tolerance with respect to the relative residual vector norm. If no value is given, a default value of `1.e-4` is set. This argument is `intent(in)`.
`rtol` and `atol` (optional): scalars of type `real(<kind>)` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). Defaults values are `rtol=1.e-4` and `atol=0`. These arguments are `intent(in)`.

`maxiter` (optional): scalar of type `integer` defining the maximum allowed number of iterations. If no value is given, a default of `N` is set, where `N = size(b)`. This argument is `intent(in)`.

Expand All @@ -169,7 +169,7 @@ Subroutine

#### Description

Implements the Preconditioned Conjugate Gradient (PCG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments.
Implements the Preconditioned Conjugate Gradient (PCG) method for solving the linear system \( Ax = b \), where \( A \) is a symmetric positive-definite linear operator defined via the `stdlib_linop` type. This is the core implementation, allowing flexibility for custom matrix types or parallel environments.

#### Syntax

Expand All @@ -193,7 +193,7 @@ Subroutine

`x`: 1-D array of `real(<kind>)` which serves as the input initial guess and the output solution. This argument is `intent(inout)`.

`tol`: scalar of type `real(<kind>)` specifying the requested tolerance with respect to the relative residual vector norm. This argument is `intent(in)`.
`rtol` and `atol` (optional): scalars of type `real(<kind>)` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). These arguments are `intent(in)`.

`maxiter`: scalar of type `integer` defining the maximum allowed number of iterations. This argument is `intent(in)`.

Expand Down Expand Up @@ -234,7 +234,7 @@ Subroutine

`di` (optional): 1-D mask array of type `logical(int8)` defining the degrees of freedom subject to dirichlet boundary conditions. The actual boundary conditions values should be stored in the `b` load array. This argument is `intent(in)`.

`tol` (optional): scalar of type `real(<kind>)` specifying the requested tolerance with respect to the relative residual vector norm. If no value is given, a default value of `1.e-4` is set. This argument is `intent(in)`.
`rtol` and `atol` (optional): scalars of type `real(<kind>)` specifying the convergence test. For convergence, the following criterion is used \( || b - Ax ||^2 <= max(rtol^2 * || b ||^2 , atol^2 ) \). Defaults values are `rtol=1.e-4` and `atol=0`. These arguments are `intent(in)`.

`maxiter` (optional): scalar of type `integer` defining the maximum allowed number of iterations. If no value is given, a default of `N` is set, where `N = size(b)`. This argument is `intent(in)`.

Expand Down
14 changes: 8 additions & 6 deletions example/linalg/example_solve_custom.f90
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ module custom_solver

contains

subroutine stdlib_solve_pcg_custom(A,b,x,di,tol,maxiter,restart,workspace)
subroutine stdlib_solve_pcg_custom(A,b,x,di,rtol,atol,maxiter,restart,workspace)
type(CSR_dp_type), intent(in) :: A
real(dp), intent(in) :: b(:)
real(dp), intent(inout) :: x(:)
real(dp), intent(in), optional :: tol
real(dp), intent(in), optional :: rtol
real(dp), intent(in), optional :: atol
logical(int8), intent(in), optional, target :: di(:)
integer, intent(in), optional :: maxiter
logical, intent(in), optional :: restart
Expand All @@ -26,7 +27,7 @@ subroutine stdlib_solve_pcg_custom(A,b,x,di,tol,maxiter,restart,workspace)
type(stdlib_linop_dp_type) :: M
type(stdlib_solver_workspace_dp_type), pointer :: workspace_
integer :: n, maxiter_
real(dp) :: tol_
real(dp) :: rtol_, atol_
logical :: restart_
logical(int8), pointer :: di_(:)
real(dp), allocatable :: diagonal(:)
Expand All @@ -35,7 +36,8 @@ subroutine stdlib_solve_pcg_custom(A,b,x,di,tol,maxiter,restart,workspace)
n = size(b)
maxiter_ = optval(x=maxiter, default=n)
restart_ = optval(x=restart, default=.true.)
tol_ = optval(x=tol, default=1.e-4_dp)
rtol_ = optval(x=rtol, default=1.e-4_dp)
atol_ = optval(x=atol, default=0._dp)
norm_sq0 = 0._dp
!-------------------------
! internal memory setup
Expand All @@ -61,7 +63,7 @@ subroutine stdlib_solve_pcg_custom(A,b,x,di,tol,maxiter,restart,workspace)
where(abs(diagonal)>epsilon(0._dp)) diagonal = 1._dp/diagonal
!-------------------------
! main call to the solver
call stdlib_solve_pcg_kernel(op,M,b,x,tol_,maxiter_,workspace_)
call stdlib_solve_pcg_kernel(op,M,b,x,rtol_,atol_,maxiter_,workspace_)

!-------------------------
! internal memory cleanup
Expand Down Expand Up @@ -135,7 +137,7 @@ program example_solve_custom
dirichlet = .false._int8
dirichlet([1,5]) = .true._int8

call stdlib_solve_pcg_custom(laplacian_csr, rhs, x, tol=1.d-6, di=dirichlet)
call stdlib_solve_pcg_custom(laplacian_csr, rhs, x, rtol=1.d-6, di=dirichlet)
print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0]

end program example_solve_custom
4 changes: 2 additions & 2 deletions example/linalg/example_solve_pcg.f90
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ program example_solve_pcg
dirichlet = .false._int8
dirichlet([1,5]) = .true._int8

call stdlib_solve_pcg(laplacian, rhs, x, tol=1.d-6, di=dirichlet)
call stdlib_solve_pcg(laplacian, rhs, x, rtol=1.d-6, di=dirichlet)
print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0]
x = 0._dp

call stdlib_solve_pcg(laplacian_csr, rhs, x, tol=1.d-6, di=dirichlet)
call stdlib_solve_pcg(laplacian_csr, rhs, x, rtol=1.d-6, di=dirichlet)
print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0]
end program
20 changes: 12 additions & 8 deletions src/stdlib_linalg_iterative_solvers.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@ module stdlib_linalg_iterative_solvers
!! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_cg_kernel)
interface stdlib_solve_cg_kernel
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,tol,maxiter,workspace)
module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,rtol,atol,maxiter,workspace)
class(stdlib_linop_${s}$_type), intent(in) :: A !! linear operator
${t}$, intent(in) :: b(:) !! right-hand side vector
${t}$, intent(inout) :: x(:) !! solution vector and initial guess
${t}$, intent(in) :: tol !! tolerance for convergence
${t}$, intent(in) :: rtol !! relative tolerance for convergence
${t}$, intent(in) :: atol !! absolut tolerance for convergence
integer, intent(in) :: maxiter !! maximum number of iterations
type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !! workspace for the solver
end subroutine
Expand All @@ -85,7 +86,7 @@ module stdlib_linalg_iterative_solvers
interface stdlib_solve_cg
#:for matrix in MATRIX_TYPES
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,tol,maxiter,restart,workspace)
module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,workspace)
!! linear operator matrix
#:if matrix == "dense"
${t}$, intent(in) :: A(:,:)
Expand All @@ -94,7 +95,8 @@ module stdlib_linalg_iterative_solvers
#:endif
${t}$, intent(in) :: b(:) !! right-hand side vector
${t}$, intent(inout) :: x(:) !! solution vector and initial guess
${t}$, intent(in), optional :: tol !! tolerance for convergence
${t}$, intent(in), optional :: rtol !! relative tolerance for convergence
${t}$, intent(in), optional :: atol !! absolute tolerance for convergence
logical(1), intent(in), optional, target :: di(:) !! dirichlet conditions mask
integer, intent(in), optional :: maxiter !! maximum number of iterations
logical, intent(in), optional :: restart !! restart flag
Expand All @@ -111,12 +113,13 @@ module stdlib_linalg_iterative_solvers
!! [Specifications](../page/specs/stdlib_linalg_iterative_solvers.html#stdlib_solve_pcg_kernel)
interface stdlib_solve_pcg_kernel
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,tol,maxiter,workspace)
module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace)
class(stdlib_linop_${s}$_type), intent(in) :: A !! linear operator
class(stdlib_linop_${s}$_type), intent(in) :: M !! preconditioner linear operator
${t}$, intent(in) :: b(:) !! right-hand side vector
${t}$, intent(inout) :: x(:) !! solution vector and initial guess
${t}$, intent(in) :: tol !! tolerance for convergence
${t}$, intent(in) :: rtol !! relative tolerance for convergence
${t}$, intent(in) :: atol !! absolute tolerance for convergence
integer, intent(in) :: maxiter !! maximum number of iterations
type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace !! workspace for the solver
end subroutine
Expand All @@ -127,7 +130,7 @@ module stdlib_linalg_iterative_solvers
interface stdlib_solve_pcg
#:for matrix in MATRIX_TYPES
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,tol,maxiter,restart,precond,M,workspace)
module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace)
!! linear operator matrix
#:if matrix == "dense"
${t}$, intent(in) :: A(:,:)
Expand All @@ -136,7 +139,8 @@ module stdlib_linalg_iterative_solvers
#:endif
${t}$, intent(in) :: b(:) !! right-hand side vector
${t}$, intent(inout) :: x(:) !! solution vector and initial guess
${t}$, intent(in), optional :: tol !! tolerance for convergence
${t}$, intent(in), optional :: rtol !! relative tolerance for convergence
${t}$, intent(in), optional :: atol !! absolute tolerance for convergence
logical(1), intent(in), optional, target :: di(:) !! dirichlet conditions mask
integer, intent(in), optional :: maxiter !! maximum number of iterations
logical, intent(in), optional :: restart !! restart flag
Expand Down
19 changes: 10 additions & 9 deletions src/stdlib_linalg_iterative_solvers_cg.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ submodule(stdlib_linalg_iterative_solvers) stdlib_linalg_iterative_cg
contains

#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,tol,maxiter,workspace)
module subroutine stdlib_solve_cg_kernel_${s}$(A,b,x,rtol,atol,maxiter,workspace)
class(stdlib_linop_${s}$_type), intent(in) :: A
${t}$, intent(in) :: b(:), tol
${t}$, intent(in) :: b(:), rtol, atol
${t}$, intent(inout) :: x(:)
integer, intent(in) :: maxiter
type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace
Expand All @@ -40,10 +40,10 @@ contains

P = R

tolsq = tol*tol
tolsq = max(rtol*rtol * norm_sq0, atol*atol)
beta = zero_${s}$
if(associated(workspace%callback)) call workspace%callback(x, norm_sq, iter)
do while( norm_sq > tolsq * norm_sq0 .and. iter < maxiter)
do while( norm_sq >= tolsq .and. iter < maxiter)
call A%matvec(P,Ap, alpha= one_${s}$, beta=zero_${s}$, op='N') ! Ap = A*P

alpha = norm_sq / A%inner_product(P, Ap)
Expand All @@ -67,15 +67,15 @@ contains

#:for matrix in MATRIX_TYPES
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,tol,maxiter,restart,workspace)
module subroutine stdlib_solve_cg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,workspace)
#:if matrix == "dense"
${t}$, intent(in) :: A(:,:)
#:else
type(${matrix}$_${s}$_type), intent(in) :: A
#:endif
${t}$, intent(in) :: b(:)
${t}$, intent(inout) :: x(:)
${t}$, intent(in), optional :: tol
${t}$, intent(in), optional :: rtol, atol
logical(int8), intent(in), optional, target :: di(:)
integer, intent(in), optional :: maxiter
logical, intent(in), optional :: restart
Expand All @@ -84,14 +84,15 @@ contains
type(stdlib_linop_${s}$_type) :: op
type(stdlib_solver_workspace_${s}$_type), pointer :: workspace_
integer :: n, maxiter_
${t}$ :: tol_
${t}$ :: rtol_, atol_
logical :: restart_
logical(int8), pointer :: di_(:)
!-------------------------
n = size(b)
maxiter_ = optval(x=maxiter, default=n)
restart_ = optval(x=restart, default=.true.)
tol_ = optval(x=tol, default=1.e-4_${s}$)
rtol_ = optval(x=rtol, default=1.e-4_${s}$)
atol_ = optval(x=atol, default=zero_${s}$)

!-------------------------
! internal memory setup
Expand All @@ -113,7 +114,7 @@ contains
! main call to the solver
if(restart_) x = zero_${s}$
x = merge( b, x, di_ ) ! copy dirichlet load conditions encoded in B and indicated by di
call stdlib_solve_cg_kernel(op,b,x,tol_,maxiter_,workspace_)
call stdlib_solve_cg_kernel(op,b,x,rtol_,atol_,maxiter_,workspace_)

!-------------------------
! internal memory cleanup
Expand Down
19 changes: 10 additions & 9 deletions src/stdlib_linalg_iterative_solvers_pcg.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ submodule(stdlib_linalg_iterative_solvers) stdlib_linalg_iterative_pcg
contains

#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,tol,maxiter,workspace)
module subroutine stdlib_solve_pcg_kernel_${s}$(A,M,b,x,rtol,atol,maxiter,workspace)
class(stdlib_linop_${s}$_type), intent(in) :: A
class(stdlib_linop_${s}$_type), intent(in) :: M
${t}$, intent(in) :: b(:), tol
${t}$, intent(in) :: b(:), rtol, atol
${t}$, intent(inout) :: x(:)
integer, intent(in) :: maxiter
type(stdlib_solver_workspace_${s}$_type), intent(inout) :: workspace
Expand All @@ -48,11 +48,11 @@ contains

call M%matvec(R,P, alpha= one_${s}$, beta=zero_${s}$, op='N') ! P = M^{-1}*R

tolsq = tol*tol
tolsq = max(rtol*rtol * norm_sq0, atol*atol)

zr1 = zero_${s}$
zr2 = one_${s}$
do while ( (iter < maxiter) .AND. (norm_sq > tolsq * norm_sq0) )
do while ( (iter < maxiter) .AND. (norm_sq >= tolsq) )

call M%matvec(R,S, alpha= one_${s}$, beta=zero_${s}$, op='N') ! S = M^{-1}*R
zr2 = A%inner_product( R, S )
Expand Down Expand Up @@ -84,7 +84,7 @@ contains

#:for matrix in MATRIX_TYPES
#:for k, t, s in R_KINDS_TYPES
module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,tol,maxiter,restart,precond,M,workspace)
module subroutine stdlib_solve_pcg_${matrix}$_${s}$(A,b,x,di,rtol,atol,maxiter,restart,precond,M,workspace)
#:if matrix == "dense"
use stdlib_linalg, only: diag
${t}$, intent(in) :: A(:,:)
Expand All @@ -93,7 +93,7 @@ contains
#:endif
${t}$, intent(in) :: b(:)
${t}$, intent(inout) :: x(:)
${t}$, intent(in), optional :: tol
${t}$, intent(in), optional :: rtol, atol
logical(int8), intent(in), optional, target :: di(:)
integer, intent(in), optional :: maxiter
logical, intent(in), optional :: restart
Expand All @@ -105,7 +105,7 @@ contains
type(stdlib_linop_${s}$_type), pointer :: M_ => null()
type(stdlib_solver_workspace_${s}$_type), pointer :: workspace_
integer :: n, maxiter_
${t}$ :: tol_
${t}$ :: rtol_, atol_
logical :: restart_
logical(int8), pointer :: di_(:)
!-------------------------
Expand All @@ -117,7 +117,8 @@ contains
n = size(b)
maxiter_ = optval(x=maxiter, default=n)
restart_ = optval(x=restart, default=.true.)
tol_ = optval(x=tol, default=1.e-4_${s}$)
rtol_ = optval(x=rtol, default=1.e-4_${s}$)
atol_ = optval(x=atol, default=zero_${s}$)
precond_ = optval(x=precond, default=pc_none)
!-------------------------
! internal memory setup
Expand Down Expand Up @@ -162,7 +163,7 @@ contains
! main call to the solver
if(restart_) x = zero_${s}$
x = merge( b, x, di_ ) ! copy dirichlet load conditions encoded in B and indicated by di
call stdlib_solve_pcg_kernel(op,M_,b,x,tol_,maxiter_,workspace_)
call stdlib_solve_pcg_kernel(op,M_,b,x,rtol_,atol_,maxiter_,workspace_)

!-------------------------
! internal memory cleanup
Expand Down
2 changes: 1 addition & 1 deletion test/linalg/test_linalg_solve_iterative.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module test_linalg_solve_iterative
dirichlet = .false._int8
dirichlet([1,5]) = .true._int8

call stdlib_solve_pcg(A, load, x, di=dirichlet, tol=1.e-6_${k}$)
call stdlib_solve_pcg(A, load, x, di=dirichlet, rtol=1.e-6_${k}$)

call check(error, norm2(x-xref)<1.e-6_${k}$*norm2(xref), 'error in preconditionned conjugate gradient solver')
if (allocated(error)) return
Expand Down
Loading