Skip to content

Commit 9324971

Browse files
committed
add example for custom solver extending the generic interface
1 parent 19167d5 commit 9324971

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

example/linalg/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ ADD_EXAMPLE(solve2)
4343
ADD_EXAMPLE(solve3)
4444
ADD_EXAMPLE(solve_cg)
4545
ADD_EXAMPLE(solve_pccg)
46+
ADD_EXAMPLE(solve_custom)
4647
ADD_EXAMPLE(sparse_from_ijv)
4748
ADD_EXAMPLE(sparse_data_accessors)
4849
ADD_EXAMPLE(sparse_spmv)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
module custom_solver
2+
use stdlib_kinds, only: dp
3+
use stdlib_sparse
4+
use stdlib_linalg_iterative_solvers, only: linop_dp, solver_workspace_dp, solve_pccg_generic
5+
implicit none
6+
contains
7+
subroutine solve_pccg_custom(A,b,x,di,tol,maxiter,restart,workspace)
8+
type(CSR_dp_type), intent(in) :: A
9+
real(dp), intent(in) :: b(:)
10+
real(dp), intent(inout) :: x(:)
11+
real(dp), intent(in), optional :: tol
12+
logical(1), intent(in), optional, target :: di(:)
13+
integer, intent(in), optional :: maxiter
14+
logical, intent(in), optional :: restart
15+
type(solver_workspace_dp), optional, intent(inout), target :: workspace
16+
!-------------------------
17+
type(linop_dp) :: op
18+
type(solver_workspace_dp), pointer :: workspace_
19+
integer :: n, maxiter_
20+
real(dp) :: tol_
21+
logical :: restart_
22+
logical(1), pointer :: di_(:)
23+
real(dp), allocatable :: diagonal(:)
24+
!-------------------------
25+
n = size(b)
26+
maxiter_ = n; if(present(maxiter)) maxiter_ = maxiter
27+
restart_ = .true.; if(present(restart)) restart_ = restart
28+
tol_ = 1.e-4_dp; if(present(tol)) tol_ = tol
29+
30+
!-------------------------
31+
! internal memory setup
32+
op%matvec => my_matvec
33+
op%inner_product => my_dot
34+
op%preconditionner => jacobi_preconditionner
35+
if(present(di))then
36+
di_ => di
37+
else
38+
allocate(di_(n),source=.false._1)
39+
end if
40+
41+
if(present(workspace)) then
42+
if(.not.allocated(workspace_%tmp)) allocate( workspace_%tmp(n,4) )
43+
workspace_ => workspace
44+
else
45+
allocate( workspace_ )
46+
allocate( workspace_%tmp(n,4) , source = 0._dp )
47+
end if
48+
call diag(A,diagonal)
49+
where(abs(diagonal)>epsilon(0.d0)) diagonal = 1._dp/diagonal
50+
!-------------------------
51+
! main call to the solver
52+
call solve_pccg_generic(op,b,x,di_,tol_,maxiter_,restart_,workspace_)
53+
54+
!-------------------------
55+
! internal memory cleanup
56+
if(present(di))then
57+
di_ => null()
58+
else
59+
deallocate(di_)
60+
end if
61+
if(present(workspace)) then
62+
workspace_ => null()
63+
else
64+
deallocate( workspace_%tmp )
65+
deallocate( workspace_ )
66+
end if
67+
contains
68+
69+
subroutine my_matvec(x,y)
70+
real(dp), intent(in) :: x(:)
71+
real(dp), intent(inout) :: y(:)
72+
call spmv( A , x, y )
73+
end subroutine
74+
subroutine jacobi_preconditionner(x,y)
75+
real(dp), intent(in) :: x(:)
76+
real(dp), intent(inout) :: y(:)
77+
y = diagonal * x
78+
end subroutine
79+
pure real(dp) function my_dot(x,y) result(r)
80+
real(dp), intent(in) :: x(:)
81+
real(dp), intent(in) :: y(:)
82+
r = dot_product(x,y)
83+
end function
84+
end subroutine
85+
86+
end module custom_solver
87+
88+
89+
program example_solve_custom
90+
use custom_solver
91+
implicit none
92+
93+
type(CSR_dp_type) :: laplacian_csr
94+
type(COO_dp_type) :: COO
95+
real(dp) :: laplacian(5,5)
96+
real(dp) :: x(5), load(5)
97+
logical(1) :: dirichlet(5)
98+
99+
laplacian = reshape( [1, -1, 0, 0, 0,&
100+
-1, 2, -1, 0, 0,&
101+
0, -1, 2, -1, 0,&
102+
0, 0, -1, 2, -1,&
103+
0, 0, 0, -1, 1] , [5,5])
104+
call dense2coo(laplacian,COO)
105+
call coo2csr(COO,laplacian_csr)
106+
107+
x = 0._dp
108+
load = dble( [0,0,5,0,0] )
109+
110+
dirichlet = .false._1
111+
dirichlet([1,5]) = .true._1
112+
113+
call solve_pccg_custom(laplacian_csr, load, x, tol=1.d-6, di=dirichlet)
114+
print *, x !> solution: [0.0, 2.5, 5.0, 2.5, 0.0]
115+
116+
end program example_solve_custom

0 commit comments

Comments
 (0)