Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_linear_solver_cg.F90
Go to the documentation of this file.
1 
10 
12  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 #include "sll_working_precision.h"
14 
17 
20 
21  use sll_m_linear_solver_abstract, only: &
23 
24  implicit none
25 
26  public :: &
28 
29  private
30  ! ..................................................
31  sll_int32, parameter :: sll_solver_bool_false = 0
32  sll_int32, parameter :: sll_solver_maxiter = 1000
33  sll_real64, parameter :: sll_solver_tolerance = 1.0d-9
34 
35  ! ..................................................
39  contains
40  procedure :: create => create_linear_solver_cg
41  procedure :: initialize => initialize_linear_solver_cg
42  procedure :: set_guess => set_guess_linear_solver_cg
43  procedure :: check_convergence => check_convergence_linear_solver_cg
44  procedure :: read_from_file => read_from_file_linear_solver_cg
45  procedure :: solve_real => solve_real_linear_solver_cg
46  procedure :: set_verbose => set_verbose_linear_solver_cg
47  procedure :: print_info => print_info_linear_solver_cg
48  procedure :: free => free_linear_solver_cg
49  end type sll_t_linear_solver_cg
50  ! ..................................................
51 
52 contains
53 
54  ! ..................................................
60  subroutine create_linear_solver_cg(self, linear_operator, pc_left, filename)
61  implicit none
62  class(sll_t_linear_solver_cg), intent(inout) :: self
63  class(sll_t_linear_operator_abstract), target, intent(in) :: linear_operator
64  class(sll_t_linear_solver_abstract), optional, target, intent(in) :: pc_left
65  character(len=*), optional, intent(in) :: filename
66 
67  ! ...
68  if( present(pc_left) ) then
69  self%ptr_pc_left => pc_left
70  end if
71  ! ...
72 
73  ! ...
74  call self%initialize(linear_operator)
75  ! ...
76 
77  ! ...
78  allocate(self%x_0(self%n_total_rows))
79  self%x_0 = 0.0_f64
80  ! ...
81 
82  ! ...
83  if (present(filename)) then
84  call self%read_from_file(filename)
85  end if
86  ! ...
87 
88  end subroutine create_linear_solver_cg
89  ! ..................................................
90 
91  ! ..................................................
97  subroutine initialize_linear_solver_cg(self, linear_operator, x_0)
98  implicit none
99  class(sll_t_linear_solver_cg), intent(inout) :: self
100  class(sll_t_linear_operator_abstract), target, intent(in) :: linear_operator
101  sll_real64,dimension(:), optional, intent(in) :: x_0
102  ! local
103 
104  ! ...
105  if (present(x_0)) then
106  self%x_0 = x_0
107  end if
108  ! ...
109 
110  ! ... linear solver abstract initialization
111  call self%initialize_abstract(linear_operator)
112  ! ...
113 
114  ! ... iterative linear solver abstract initialization
115  call self%set_linear_operator(linear_operator)
116  ! ...
117 
118  end subroutine initialize_linear_solver_cg
119  ! ..................................................
120 
121  ! ..................................................
126  subroutine set_guess_linear_solver_cg(self, x_0)
127  implicit none
128  class(sll_t_linear_solver_cg), intent(inout) :: self
129  sll_real64,dimension(:), intent(in) :: x_0
130 
131  self%x_0 = x_0
132 
133  end subroutine set_guess_linear_solver_cg
134  ! ..................................................
135 
136  ! ..................................................
144  ! ............................................
145  subroutine check_convergence_linear_solver_cg(self, i_iteration, flag, r_err, arr_err)
146  implicit none
147  class(sll_t_linear_solver_cg), intent(in) :: self
148  ! local
149  sll_int32, intent(in) :: i_iteration
150  logical, intent(inout) :: flag
151  sll_real64, optional, intent(in) :: r_err
152  sll_real64, dimension(:), optional, intent(in) :: arr_err
153 
154  ! ...
155  if (self%verbose) then
156  if (present(r_err)) then
157  if (i_iteration <= self%n_maxiter) then
158  print*, '* cg: convergence after', i_iteration, 'iterations. Error ', r_err
159  else
160  print *, '* cg: Warning - max iterations', self%n_maxiter, 'achieved without convergence. Error', r_err
161  end if
162  end if
163  end if
164  !...
165 
167  ! ............................................
168 
169  ! ..................................................
174  subroutine read_from_file_linear_solver_cg(self, filename)
175  implicit none
176  class(sll_t_linear_solver_cg), intent(inout) :: self
177  character(len=*) , intent(in) :: filename
178  ! local
179  sll_int32, parameter :: input_file_id = 111
180  sll_int32 :: int_maxiter = sll_solver_maxiter
181  sll_int32 :: int_null_space = sll_solver_bool_false
182  sll_int32 :: int_verbose = sll_solver_bool_false
183  sll_real64 :: real_atol = sll_solver_tolerance
184  ! ...
185  namelist /linear_solver/ int_null_space, &
186  & int_maxiter, &
187  & real_atol, &
188  & int_verbose
189  ! ...
190 
191  ! ...
192  open(unit=input_file_id, file=trim(filename))
193  read( input_file_id, linear_solver)
194  ! ...
195 
196  ! ...
197  self%n_maxiter = int_maxiter
198  self%atol = real_atol
199  ! ...
200 
201  ! ...
202  self%null_space = .false.
203  if (int_null_space == 1) then
204  self%null_space = .true.
205  end if
206  ! ...
207 
208  ! ...
209  self%verbose = .false.
210  if (int_verbose == 1) then
211  self%verbose = .true.
212  end if
213  ! ...
214 
215  ! ...
216  close(input_file_id)
217  ! ...
218 
219  end subroutine read_from_file_linear_solver_cg
220  ! ..................................................
221 
222  ! ..................................................
228  subroutine solve_real_linear_solver_cg(self, rhs, unknown)
229  implicit none
230  class(sll_t_linear_solver_cg), intent(inout) :: self
231  sll_real64, dimension(:), intent(in ) :: rhs
232  sll_real64, dimension(:), intent( out) :: unknown
233  ! local
234  sll_real64, dimension(:), allocatable :: l_rhs
235  sll_int32, parameter :: current_dof = 1
236  sll_int32 :: itr_used
237  sll_real64 :: res
238  logical :: flag
239 
240  ! ...
241  allocate(l_rhs(self%n_total_rows))
242  l_rhs = rhs
243  ! ...
244 
245 
246  ! ...
247  unknown = self%x_0
248  ! ...
249 
250  ! ...
251  call cg_linear_solver(self, unknown, l_rhs, itr_used, res)
252  ! ...
253 
254  ! ...
255  deallocate(l_rhs)
256  ! ...
257 
258  ! ...
259  call self%check_convergence( i_iteration=itr_used, &
260  & flag=flag, &
261  & r_err=res)
262  ! ...
263 
264  end subroutine solve_real_linear_solver_cg
265  ! ..................................................
266 
267  ! ..................................................
275  subroutine cg_linear_solver(self, x, b, niterx, res)
276  implicit none
277 
278  class(sll_t_linear_solver_cg), intent(in) :: self
279  sll_real64, dimension (:), intent(inout) :: x
280  sll_real64, dimension (:), intent(in) :: b
281  sll_int32, intent(out) :: niterx
282  sll_real64, intent(out) :: res
283  ! local
284  sll_int32 :: niterxmax
285  sll_int32 :: k, l
286  sll_int32 :: nb
287  sll_real64 :: epsx
288  sll_real64 :: lambda
289  sll_real64 :: alpha
290  sll_real64 :: w1
291  sll_real64, dimension (self%n_total_rows) :: p
292  sll_real64, dimension (self%n_total_rows) :: r
293  sll_real64, dimension (self%n_total_rows) :: v
294  sll_real64, dimension (self%n_total_rows) :: z
295 
296  ! ...
297  niterxmax = self%n_maxiter
298  nb = self%n_total_rows
299  epsx = self%atol
300  ! ...
301 
302  v = 0.0_f64
303  call self%ptr_linear_operator%dot (x, v)
304  !r_0=b-A x_0
305  r = b - v
306  !p_0=M^{-1}r_0
307  if( associated( self%ptr_pc_left) )then
308  call self%ptr_pc_left%solve(r, p)
309  else
310  p = r
311  end if
312  !alpha_0= <r_0,p_0>
313  alpha = sum(r*p)
314 
315  niterx = 1
316  do k = 1, niterxmax
317 
318  v = 0.0_f64
319  !v_j=A p_j
320  call self%ptr_linear_operator%dot (p, v)
321 
322  !lambda_j=<r_j,z_j>/<A p_j,p_j>
323  lambda = alpha / (sum(p*v)+1.d-25)
324 
325  w1 = 0.0_f64
326  !x_j+1=x_j+lambda_j p_j
327  !r_j+r=r_j-lambda_j Ap_j
328  do l=1,nb
329  x(l) = x(l) + lambda*p(l)
330  r(l) = r(l) - lambda*v(l)
331  w1 = w1 + r(l) * r(l)
332  end do
333 
334  res=sqrt(w1/real(nb,f64))
335  if (res <= epsx) exit
336  if( associated( self%ptr_pc_left) )then
337  !z_j+1=M^{-1}r_j+1
338  call self%ptr_pc_left%solve(r, z)
339  !beta_j= <r_j+1,z_j+1>/<r_j,z_j>
340  w1 = sum(r*z)
341  else
342  z = r
343  end if
344  !p_j+1=z_j+1+beta_j p_j
345  p = z + w1/alpha * p
346  alpha = w1
347 
348  niterx = k + 1
349 
350  end do
351 
352  return
353 
354  end subroutine cg_linear_solver
355  ! ...................................................
356 
357  ! ............................................
362  subroutine set_verbose_linear_solver_cg(self, verbose)
363  implicit none
364  class(sll_t_linear_solver_cg), intent(inout) :: self
365  logical , intent(in) :: verbose
366 
367  ! ...
368  call self%set_verbose_abstract(verbose)
369  ! ...
370 
371  end subroutine set_verbose_linear_solver_cg
372  ! ..................................................
373 
374  ! ............................................
379  implicit none
380  class(sll_t_linear_solver_cg), intent(in) :: self
381  ! local
382 
383  print *, ">>>> linear_solver_cg"
384  print *, "* verbose : ", self%verbose
385  print *, "* atol : ", self%atol
386  print *, "* null_space : ", self%null_space
387  print *, "* n_maxiter : ", self%n_maxiter
388  print *, "<<<< "
389 
390  end subroutine print_info_linear_solver_cg
391  ! ............................................
392 
393  ! ..................................................
397  subroutine free_linear_solver_cg(self)
398  implicit none
399  class(sll_t_linear_solver_cg), intent(inout) :: self
400 
401  deallocate (self%x_0)
402 
403  end subroutine free_linear_solver_cg
404  ! ..................................................
405 
406 end module sll_m_linear_solver_cg
module for abstract linear operator
module for abstract linear solver
module for conjugate gradient method in pure form
subroutine print_info_linear_solver_cg(self)
destroys a finite element cell
subroutine free_linear_solver_cg(self)
destroys the current object
integer(kind=i32), parameter sll_solver_maxiter
default maximum number of iterations for
subroutine initialize_linear_solver_cg(self, linear_operator, x_0)
initializes the linear solver
subroutine cg_linear_solver(self, x, b, niterx, res)
cg interface
subroutine read_from_file_linear_solver_cg(self, filename)
read from file
subroutine create_linear_solver_cg(self, linear_operator, pc_left, filename)
creates a linear solver
subroutine check_convergence_linear_solver_cg(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 solve_real_linear_solver_cg(self, rhs, unknown)
af solves the linear system with real vectors
subroutine set_verbose_linear_solver_cg(self, verbose)
sets the verbose for the linear solver object
subroutine set_guess_linear_solver_cg(self, x_0)
sets the initial guess
integer(kind=i32), parameter sll_solver_bool_false
code id for False
module for abstract iterative linear solvers
    Report Typos and Errors