Octopus
sparskit.F90
Go to the documentation of this file.
1!! Copyright (C) 2005-2006 Heiko Appel
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module sparskit_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use, intrinsic :: iso_fortran_env
27 use parser_oct_m
29
30 implicit none
31
32 private
33
34 integer, public, parameter :: &
35 SK_CG = 1, & !< Conjugate Gradient Method
36 sk_cgnr = 2, &
37 sk_bcg = 3, &
38 sk_dbcg = 4, &
39 sk_bcgstab = 5, &
40 sk_tfqmr = 6, &
41 sk_fom = 7, &
42 sk_gmres = 8, &
43 sk_fgmres = 9, &
44 sk_dqgmres = 10, &
45 sk_minval = sk_cg, &
47
48 public :: &
50
51 public :: &
57
59 private
60 logical :: is_complex
61 integer :: size
62 integer :: solver_type
63 integer :: krylov_size
64 integer :: preconditioning
65 integer :: maxiter
66 integer :: used_iter
67 integer :: iter_out
68 real(real64) :: residual_norm
69 real(real64) :: rel_tolerance
70 real(real64) :: abs_tolerance
71
72 real(real64), allocatable :: sk_work(:), sk_b(:), sk_y(:)
73
74 integer :: ipar(16)
75 real(real64) :: fpar(16)
76 logical :: verbose
77 end type sparskit_solver_t
78
79 interface
80 subroutine cg(n, rhs, sol, ipar, fpar, w)
81 integer n, ipar(16)
82 real*8 rhs(n), sol(n), fpar(16), w(n,*)
83 end subroutine cg
84
85 subroutine cgnr(n, rhs, sol, ipar, fpar, wk)
86 integer n, ipar(16)
87 real*8 rhs(n),sol(n),fpar(16),wk(n,*)
88 end subroutine cgnr
89
90 subroutine bcg(n, rhs, sol, ipar, fpar, w)
91 integer n, ipar(16)
92 real*8 fpar(16), rhs(n), sol(n), w(n,*)
93 end subroutine bcg
94
95 subroutine dbcg(n, rhs, sol, ipar, fpar, w)
96 integer n, ipar(16)
97 real*8 rhs(n), sol(n), fpar(16), w(n,*)
98 end subroutine dbcg
99
100 subroutine bcgstab(n, rhs, sol, ipar, fpar, w)
101 integer n, ipar(16)
102 real*8 rhs(n), sol(n), fpar(16), w(n,8)
103 end subroutine bcgstab
104
105 subroutine tfqmr(n, rhs, sol, ipar, fpar, w)
106 integer n, ipar(16)
107 real*8 rhs(n), sol(n), fpar(16), w(n,*)
108 end subroutine tfqmr
109
110 subroutine fom(n, rhs, sol, ipar, fpar, w)
111 integer n, ipar(16)
112 real*8 rhs(n), sol(n), fpar(16), w(*)
113 end subroutine fom
115 subroutine gmres(n, rhs, sol, ipar, fpar, w)
116 integer n, ipar(16)
117 real*8 rhs(n), sol(n), fpar(16), w(*)
118 end subroutine gmres
119
120 subroutine dqgmres(n, rhs, sol, ipar, fpar, w)
121 integer n, ipar(16)
122 real*8 rhs(n), sol(n), fpar(16), w(*)
123 end subroutine dqgmres
124
125 subroutine fgmres(n, rhs, sol, ipar, fpar, w)
126 integer n, ipar(16)
127 real*8 rhs(n), sol(n), fpar(16), w(*)
128 end subroutine fgmres
129 end interface
130
131contains
132
133 ! ---------------------------------------------------------
134 subroutine sparskit_solver_init(namespace, n, sk, is_complex)
135 type(namespace_t), intent(in) :: namespace
136 integer, intent(in) :: n
137 type(sparskit_solver_t), intent(out) :: sk
138 logical, intent(in) :: is_complex
139
140 integer :: workspace_size, m
141
142 push_sub(sparskit_solver_init)
143
144 sk%is_complex = is_complex
145 ! there might be some incompatibilities to check of real/complex and available methods?
146
147 !%Variable SPARSKITSolver
148 !%Type integer
149 !%Default sk_bcg
150 !%Section Math::SPARSKIT
151 !%Description
152 !% Specifies what kind of linear solver will be used.
153 !%Option sk_cg 1
154 !% Conjugate Gradient Method
155 !%Option sk_cgnr 2
156 !% Conjugate Gradient Method (Normal Residual equation)
157 !%Option sk_bcg 3
158 !% Bi-Conjugate Gradient Method
159 !%Option sk_dbcg 4
160 !% BCG with partial pivoting
161 !%Option sk_bcgstab 5
162 !% BCG stabilized
163 !%Option sk_tfqmr 6
164 !% Transpose-Free Quasi-Minimum Residual method
165 !%Option sk_fom 7
166 !% Full Orthogonalization Method
167 !%Option sk_gmres 8
168 !% Generalized Minimum Residual method
169 !%Option sk_fgmres 9
170 !% Flexible version of Generalized Minimum Residual method
171 !%Option sk_dqgmres 10
172 !% Direct versions of the Quasi-Generalized Minimum Residual method
173 !%End
174 call parse_variable(namespace, 'SPARSKITSolver', sk_bcg, sk%solver_type)
175 if (sk%solver_type < sk_minval.or.sk%solver_type > sk_maxval) then
176 call messages_input_error(namespace, 'SPARSKITSolver')
177 end if
179 !%Variable SPARSKITKrylovSubspaceSize
180 !%Type integer
181 !%Default 15
182 !%Section Math::SPARSKIT
183 !%Description
184 !% Some of the SPARSKIT solvers are Krylov subspace methods.
185 !% This variable determines what size the solver will use
186 !% for the subspace.
187 !%End
188 call parse_variable(namespace, 'SPARSKITKrylovSubspaceSize', 15, sk%krylov_size)
189
190 ! preconditioner not implemented
191 sk%preconditioning = 0
192
193 !%Variable SPARSKITMaxIter
194 !%Type integer
195 !%Default 50000
196 !%Section Math::SPARSKIT
197 !%Description
198 !% This variable controls the maximum number of iteration steps that
199 !% will be performed by the (iterative) linear solver.
200 !%End
201 call parse_variable(namespace, 'SPARSKITMaxIter', 5000, sk%maxiter)
202
203 !%Variable SPARSKITIterOut
204 !%Type integer
205 !%Default -1
206 !%Section Math::SPARSKIT
207 !%Description
208 !% Determines how often status info of the solver is printed.
209 !% If <= 0, will never be printed.
210 !%End
211 call parse_variable(namespace, 'SPARSKITIterOut', -1, sk%iter_out)
212
213 !%Variable SPARSKITRelTolerance
214 !%Type float
215 !%Default 1e-8
216 !%Section Math::SPARSKIT
217 !%Description
218 !% Some SPARSKIT solvers use a relative tolerance as a stopping criterion
219 !% for the iterative solution process. This variable can be used to
220 !% specify the tolerance.
221 !%End
222 call parse_variable(namespace, 'SPARSKITRelTolerance', 1e-8_real64, sk%rel_tolerance)
223
224 !%Variable SPARSKITAbsTolerance
225 !%Type float
226 !%Default 1e-10
227 !%Section Math::SPARSKIT
228 !%Description
229 !% Some SPARSKIT solvers use an absolute tolerance as a stopping criterion
230 !% for the iterative solution process. This variable can be used to
231 !% specify the tolerance.
232 !%End
233 call parse_variable(namespace, 'SPARSKITAbsTolerance', 1e-10_real64, sk%abs_tolerance)
234
235 !%Variable SPARSKITVerboseSolver
236 !%Type logical
237 !%Default no
238 !%Section Math::SPARSKIT
239 !%Description
240 !% When set to yes, the SPARSKIT solver will write more detailed output.
241 !%End
242 call parse_variable(namespace, 'SPARSKITVerboseSolver', .false., sk%verbose)
243
244 ! size of the problem
245 if (is_complex) then
246 sk%size = 2*n
247 else
248 sk%size = n
249 end if
250
251 ! initialize workspace size
252 workspace_size = 0
253
254 ! Krylov subspace size
255 m = sk%krylov_size
256 if (mod(m, 2) /= 0) m = m + 1
257
258 select case (sk%solver_type)
259 case (sk_cg)
260 message(1) = 'Info: SPARSKIT solver type: Conjugate Gradient Method'
261 workspace_size = 5*sk%size
262 case (sk_cgnr)
263 message(1) = 'Info: SPARSKIT solver type: Conjugate Gradient Method (Normal Residual equation)'
264 workspace_size = 5*sk%size
265 case (sk_bcg)
266 message(1) = 'Info: SPARSKIT solver type: Bi-Conjugate Gradient Method'
267 workspace_size = 7*sk%size
268 case (sk_dbcg)
269 message(1) = 'Info: SPARSKIT solver type: BCG with partial pivoting'
270 workspace_size = 11*sk%size
271 case (sk_bcgstab)
272 message(1) = 'Info: SPARSKIT solver type: BCG stabilized'
273 workspace_size = 8*sk%size
274 case (sk_tfqmr)
275 message(1) = 'Info: SPARSKIT solver type: Transpose-Free Quasi-Minimum Residual method'
276 workspace_size = 11*sk%size
277 case (sk_fom)
278 message(1) = 'Info: SPARSKIT solver type: Full Orthogonalization Method'
279 workspace_size = (sk%size+3)*(m+2) + (m+1)*m/2
280 case (sk_gmres)
281 message(1) = 'Info: SPARSKIT solver type: Generalized Minimum Residual method'
282 workspace_size = (sk%size+3)*(m+2) + (m+1)*m/2
283 case (sk_fgmres)
284 message(1) = 'Info: SPARSKIT solver type: Flexible version of Generalized Minimum Residual method'
285 workspace_size = 2*sk%size*(m+1) + (m+1)*m/2 + 3*m + 2
286 case (sk_dqgmres)
287 message(1) = 'Info: SPARSKIT solver type: Direct versions of Quasi-Generalized Minimum Residual method'
288 workspace_size = sk%size + (m+1) * (2*sk%size+4)
289 case default
290 write(message(1), '(a,i4,a)') "Input: '", sk%solver_type, &
291 "' is not a valid SPARSKIT Solver"
292 message(2) = '( SPARSKIT Solver = cg | cgnr | bcg | dbcg | bcgstab | tfqmr | fom | gmres | fgmres | dqgmres )'
293 call messages_fatal(2, namespace=namespace)
294 end select
295 call messages_info(1, namespace=namespace)
296
297 ! Now we initialize the arrays for the reverse communication protocol
298 sk%ipar = 0
299 sk%fpar = 0
300
301 ! A call to the solver with ipar(1) == 0 will initialize the iterative solver.
302 sk%ipar(1) = 0
303
304 ! Stopping criteria; use convergence test scheme 2
305 sk%ipar(3) = 2
306
307 sk%ipar(4) = workspace_size
308 sk%ipar(5) = sk%krylov_size
309
310 ! Maximum number of matrix-vector multiplies
311 sk%ipar(6) = sk%maxiter
312
313 ! Relative tolerance
314 sk%fpar(1) = sk%rel_tolerance
315
316 ! Absolute tolerance
317 sk%fpar(2) = sk%abs_tolerance
318
319 ! allocate and initialize work arrays
320 safe_allocate(sk%sk_b(1:sk%size))
321 safe_allocate(sk%sk_y(1:sk%size))
322 safe_allocate(sk%sk_work(1:workspace_size))
323 sk%sk_work = m_zero
324 sk%sk_y = m_zero
325 sk%sk_b = m_zero
326
327 pop_sub(sparskit_solver_init)
328 end subroutine sparskit_solver_init
329
330 ! ---------------------------------------------------------
331 subroutine sparskit_solver_end(sk)
332 type(sparskit_solver_t), intent(inout) :: sk
333
334 push_sub(sparskit_solver_end)
335
336 safe_deallocate_a(sk%sk_b)
337 safe_deallocate_a(sk%sk_y)
338 safe_deallocate_a(sk%sk_work)
339
340 pop_sub(sparskit_solver_end)
341 end subroutine sparskit_solver_end
342
343 ! ---------------------------------------------------------
344 subroutine sparskit_solver_copy(sko, ski)
345 type(sparskit_solver_t), intent(inout) :: sko
346 type(sparskit_solver_t), intent(in) :: ski
347
348 push_sub(sparskit_solver_end)
349
350 sko%is_complex = ski%is_complex
351 sko%size = ski%size
352 sko%solver_type = ski%solver_type
353 sko%krylov_size = ski%krylov_size
354 sko%preconditioning = ski%preconditioning
355 sko%maxiter = ski%maxiter
356 sko%used_iter = ski%used_iter
357 sko%iter_out = ski%iter_out
358 sko%residual_norm = ski%residual_norm
359 sko%rel_tolerance = ski%rel_tolerance
360 sko%abs_tolerance = ski%abs_tolerance
361 safe_allocate_source_a(sko%sk_work, ski%sk_work)
362 safe_allocate_source_a(sko%sk_b, ski%sk_b)
363 safe_allocate_source_a(sko%sk_y, ski%sk_y)
364 sko%ipar = ski%ipar
365 sko%fpar = ski%fpar
366 sko%verbose = ski%verbose
367
368 pop_sub(sparskit_solver_end)
369 end subroutine sparskit_solver_copy
370
371#include "undef.F90"
372#include "real.F90"
373#include "sparskit_inc.F90"
374
375#include "undef.F90"
376#include "complex.F90"
377#include "sparskit_inc.F90"
378
379! distdot function for dot products is defined in mesh_function_oct_m
380
381end module sparskit_oct_m
382
383!! Local Variables:
384!! mode: f90
385!! coding: utf-8
386!! End:
real(real64), parameter, public m_zero
Definition: global.F90:187
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
subroutine, public sparskit_solver_init(namespace, n, sk, is_complex)
Definition: sparskit.F90:228
integer, parameter, public sk_gmres
Generalized Minimum Residual method.
Definition: sparskit.F90:127
subroutine, public dsparskit_solver_run(namespace, sk, op, opt, sol, rhs)
Definition: sparskit.F90:533
subroutine, public zsparskit_solver_run(namespace, sk, op, opt, sol, rhs)
Definition: sparskit.F90:774
subroutine, public sparskit_solver_end(sk)
Definition: sparskit.F90:425
subroutine, public sparskit_solver_copy(sko, ski)
Definition: sparskit.F90:438
integer, parameter, public sk_dbcg
BCG with partial pivoting.
Definition: sparskit.F90:127
integer, parameter, public sk_bcg
Bi-Conjugate Gradient Method.
Definition: sparskit.F90:127
integer, parameter, public sk_dqgmres
Direct versions of Quasi Generalized Minimum Residual method.
Definition: sparskit.F90:127
integer, parameter, public sk_minval
Definition: sparskit.F90:127
integer, parameter, public sk_fom
Full Orthogonalization Method.
Definition: sparskit.F90:127
integer, parameter, public sk_bcgstab
BCG stabilized.
Definition: sparskit.F90:127
integer, parameter, public sk_cgnr
Conjugate Gradient Method (Normal Residual equation)
Definition: sparskit.F90:127
integer, parameter, public sk_maxval
Definition: sparskit.F90:127
integer, parameter, public sk_tfqmr
Transpose-Free Quasi-Minimum Residual method.
Definition: sparskit.F90:127
integer, parameter, public sk_fgmres
Flexible version of Generalized Minimum Residual method.
Definition: sparskit.F90:127