13 #include "sll_working_precision.h"
40 sll_real64 :: rtol = 1.0d-14
72 character(len=*),
optional,
intent(in) :: filename
75 if (
present(pc_left))
then
76 self%ptr_pc_left => pc_left
81 call self%initialize(linear_operator)
85 allocate(self%x_0(self%n_total_rows))
90 if (
present(filename))
then
91 call self%read_from_file(filename)
108 sll_real64,
dimension(:),
optional,
intent(in) :: x_0
111 if (
present(x_0))
then
117 call self%initialize_abstract(linear_operator)
121 call self%set_linear_operator(linear_operator)
135 sll_real64,
dimension(:),
intent(in) :: x_0
154 sll_int32,
intent(in) :: i_iteration
155 logical,
intent(inout) :: flag
156 sll_real64,
optional,
intent(in) :: r_err
157 sll_real64,
dimension(:),
optional,
intent(in) :: arr_err
160 if (self%verbose)
then
161 if (
present(r_err))
then
162 if (i_iteration <= self%n_maxiter)
then
163 print*,
'* mgmres: convegence after', i_iteration,
'iterations. Error ', r_err
165 print *,
'* mgmres: Warning - max iterations', self%n_maxiter,
'achieved without convergence. Error', r_err
182 character(len=*) ,
intent(in) :: filename
184 sll_int32,
parameter :: input_file_id = 111
193 namelist /linear_solver/ int_null_space, &
202 open(unit=input_file_id, file=trim(filename))
203 read( input_file_id, linear_solver)
207 self%n_maxiter = int_maxiter
208 self%n_mr = int_restart
209 self%rtol = real_rtol
210 self%atol = real_atol
214 self%null_space = .false.
215 if (int_null_space == 1)
then
216 self%null_space = .true.
221 self%verbose = .false.
222 if (int_verbose == 1)
then
223 self%verbose = .true.
242 logical ,
intent(in) :: verbose
245 call self%set_verbose_abstract(verbose)
260 sll_real64,
dimension(:),
intent(in ) :: rhs
261 sll_real64,
dimension(:),
intent( out) :: unknown
263 sll_real64,
dimension(:),
allocatable :: l_rhs
264 sll_int32 :: itr_used
269 allocate(l_rhs(self%n_total_rows))
274 if (
associated(self%ptr_pc_left))
then
275 call self%ptr_pc_left % solve(rhs, l_rhs)
285 & self%n_maxiter, self%n_mr, &
286 & self%atol, self%rtol, &
295 call self%check_convergence( i_iteration=itr_used, &
306 & tol_abs, tol_rel, itr_used, rho )
398 sll_real64 :: c(1:mr)
399 sll_real64,
parameter :: delta = 1.0d-03
400 sll_real64 :: g(1:mr+1)
401 sll_real64 :: h(1:mr+1,1:mr)
406 sll_int32 :: itr_used
411 sll_real64 :: r(1:self%n_total_rows)
412 sll_real64 :: p(1:self%n_total_rows)
414 sll_real64 :: rho_tol
415 sll_real64 :: rhs(1:self%n_total_rows)
416 sll_real64 :: s(1:mr)
417 sll_real64 :: tol_abs
418 sll_real64 :: tol_rel
419 sll_real64 :: v(1:self%n_total_rows,1:mr+1)
421 sll_real64 :: x(1:self%n_total_rows)
422 sll_real64 :: y(1:mr+1)
426 if ( self%verbose .and. ( self%n_total_rows < mr ) )
then
427 write ( *,
'(a)' )
' '
428 write ( *,
'(a)' )
'mgmres_csr - fatal error!'
429 write ( *,
'(a)' )
' n < mr.'
430 write ( *,
'(a,i8)' )
' n = ', self%n_total_rows
431 write ( *,
'(a,i8)' )
' mr = ', mr
439 call self%ptr_linear_operator % dot(x, r)
442 if (
associated(self%ptr_pc_left))
then
443 call self%ptr_pc_left % solve(r, p)
448 r(1:self%n_total_rows) = rhs(1:self%n_total_rows) - r(1:self%n_total_rows)
450 rho = sqrt( dot_product( r(1:self%n_total_rows), r(1:self%n_total_rows) ) )
457 rho_tol = rho * tol_rel
460 if ( rho <= rho_tol .or. rho <= tol_abs )
then
463 v(1:self%n_total_rows,1) = r(1:self%n_total_rows) / rho
469 h(1:mr+1,1:mr) = 0.0d+00
475 call self%ptr_linear_operator % dot(v(1:self%n_total_rows,k), v(1:self%n_total_rows,k+1))
478 if (
associated(self%ptr_pc_left))
then
479 call self%ptr_pc_left % solve(v(1:self%n_total_rows,k+1), p)
480 v(1:self%n_total_rows,k+1) = p
484 av = sqrt( dot_product( v(1:self%n_total_rows,k+1), v(1:self%n_total_rows,k+1) ) )
488 h(j,k) = dot_product( v(1:self%n_total_rows,k+1), v(1:self%n_total_rows,j) )
489 v(1:self%n_total_rows,k+1) = v(1:self%n_total_rows,k+1) - h(j,k) * v(1:self%n_total_rows,j)
492 h(k+1,k) = sqrt( dot_product( v(1:self%n_total_rows,k+1), v(1:self%n_total_rows,k+1) ) )
494 if ( av + delta * h(k+1,k) == av )
then
497 htmp = dot_product( v(1:self%n_total_rows,k+1), v(1:self%n_total_rows,j) )
498 h(j,k) = h(j,k) + htmp
499 v(1:self%n_total_rows,k+1) = v(1:self%n_total_rows,k+1) - htmp * v(1:self%n_total_rows,j)
502 h(k+1,k) = sqrt( dot_product( v(1:self%n_total_rows,k+1), v(1:self%n_total_rows,k+1) ) )
506 if ( h(k+1,k) /= 0.0d+00 )
then
507 v(1:self%n_total_rows,k+1) = v(1:self%n_total_rows,k+1) / h(k+1,k)
512 y(1:k+1) = h(1:k+1,k)
518 h(1:k+1,k) = y(1:k+1)
522 mu = sqrt( h(k,k)**2 + h(k+1,k)**2 )
524 s(k) = -h(k+1,k) / mu
525 h(k,k) = c(k) * h(k,k) - s(k) * h(k+1,k)
530 itr_used = itr_used + 1
536 if ( rho <= rho_tol .or. rho <= tol_abs )
then
544 y(k+1) = g(k+1) / h(k+1,k+1)
547 y(i) = ( g(i) - dot_product( h(i,i+1:k+1), y(i+1:k+1) ) ) / h(i,i)
550 do i = 1, self%n_total_rows
551 x(i) = x(i) + dot_product( v(i,1:k+1), y(1:k+1) )
554 if ( rho <= rho_tol .or. rho <= tol_abs )
then
560 if ( self%verbose )
then
561 write ( *,
'(a)' )
' '
562 write ( *,
'(a)' )
'mgmres_csr:'
563 write ( *,
'(a,i8)' )
' iterations = ', itr_used
564 write ( *,
'(a,g14.6)' )
' final residual = ', rho
635 sll_real64 :: g(1:k+1)
640 g1 = c * g(k) - s * g(k+1)
641 g2 = s * g(k) + c * g(k+1)
659 print *,
">>>> linear_solver_mgmres"
660 print *,
"* verbose : ", self%verbose
661 print *,
"* n_mr : ", self%n_mr
662 print *,
"* rtol : ", self%rtol
663 print *,
"* atol : ", self%atol
664 print *,
"* null_space : ", self%null_space
665 print *,
"* n_maxiter : ", self%n_maxiter
679 deallocate (self%x_0)
module for abstract linear operator
module for abstract linear solver
module for abstract iterative linear solvers
module for a sequential gmres
subroutine initialize_linear_solver_mgmres(self, linear_operator, x_0)
initializes the linear solver
subroutine mgmres_linear_solver(self, x, rhs, itr_max, mr, tol_abs, tol_rel, itr_used, rho)
integer(kind=i32), parameter sll_solver_maxiter
default maximum number of iterations for
subroutine create_linear_solver_mgmres(self, linear_operator, pc_left, filename)
creates a linear solver
integer(kind=i32), parameter sll_solver_restart
default number of restarts for gmres
subroutine free_linear_solver_mgmres(self)
destroys the current object
subroutine solve_real_linear_solver_mgmres(self, rhs, unknown)
solves the linear system with real vectors
subroutine read_from_file_linear_solver_mgmres(self, filename)
read from file
subroutine mult_givens(c, s, k, g)
subroutine set_guess_linear_solver_mgmres(self, x_0)
sets the initial guess
subroutine check_convergence_linear_solver_mgmres(self, i_iteration, flag, r_err, arr_err)
check the convergence of the current linear solver
real(kind=f64), parameter sll_solver_tolerance
default tolerance for iterative solvers
subroutine set_verbose_linear_solver_mgmres(self, verbose)
sets the verbose for the linear solver object
subroutine print_info_linear_solver_mgmres(self)
destroys a finite element cell
integer(kind=i32), parameter sll_solver_bool_false
code id for False
class for abstract linear operator
class for abstract linear solver
class for abstract iterative linear solver
class for a sequential gmres linear solver