Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_linear_solver_kron.F90
Go to the documentation of this file.
1 
10 
12  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 #include "sll_working_precision.h"
14 
17 
18  use sll_m_linear_solver_abstract, only: &
20 
21  use sll_m_linear_solver_mgmres, only: &
23 
24  use sll_m_linear_solver_cg, only: &
26 
27  use sll_m_linear_operator_kron, only: &
29  sll_transpose, &
32 
33  use sll_m_matrix_abstract, only: &
35 
36  implicit none
37 
38  public :: &
40 
41  private
42  ! ..................................................
46  sll_int32 :: nrowcol(3,2)
47 
48  class(sll_t_linear_solver_abstract), pointer :: ptr_linear_solver_a => null()
49  class(sll_t_linear_solver_abstract), pointer :: ptr_linear_solver_b => null()
50  class(sll_t_linear_solver_abstract), pointer :: ptr_linear_solver_c => null()
51 
52  class(sll_t_linear_solver_abstract), private, allocatable :: p_linear_solver_a
53  class(sll_t_linear_solver_abstract), private, allocatable :: p_linear_solver_b
54  class(sll_t_linear_solver_abstract), private, allocatable :: p_linear_solver_c
55  contains
56  procedure :: create => create_linear_solver_kron
57  procedure :: read_from_file => read_from_file_linear_solver_kron
58  procedure :: set_verbose => set_verbose_linear_solver_kron
59  procedure :: solve_real => solve_real_linear_solver_kron
60  procedure :: print_info => print_info_linear_solver_kron
61  procedure :: free => free_linear_solver_kron
63  ! ..................................................
64 
65 contains
66 
67  ! ..................................................
78  subroutine create_linear_solver_kron( self, &
79  & linear_operator_a, &
80  & linear_operator_b, &
81  & linear_operator_c, &
82  & linear_solver_a, &
83  & linear_solver_b, &
84  & linear_solver_c, &
85  & filename)
86  implicit none
87  class(sll_t_linear_solver_kron), target, intent(inout) :: self
88  class(sll_t_linear_operator_abstract), target, optional, intent(in) :: linear_operator_a
89  class(sll_t_linear_operator_abstract), target, optional, intent(in) :: linear_operator_b
90  class(sll_t_linear_operator_abstract), target, optional, intent(in) :: linear_operator_c
91  class(sll_t_linear_solver_abstract), target, optional, intent(in) :: linear_solver_a
92  class(sll_t_linear_solver_abstract), target, optional, intent(in) :: linear_solver_b
93  class(sll_t_linear_solver_abstract), target, optional, intent(in) :: linear_solver_c
94  character(len=*), optional, intent(in) :: filename
95  ! local
96  sll_int32, parameter :: input_file_id = 111
97  character(len=256) :: solver_filename_a = ""
98  character(len=20) :: solver_name_a = ""
99  character(len=256) :: solver_filename_b = ""
100  character(len=20) :: solver_name_b = ""
101  character(len=256) :: solver_filename_c = ""
102  character(len=20) :: solver_name_c = ""
103  logical :: flag_a
104  logical :: flag_b
105  logical :: flag_c
106 
107  namelist /linear_solver/ solver_name_a, &
108  & solver_filename_a, &
109  & solver_name_b, &
110  & solver_filename_b, &
111  & solver_name_c, &
112  & solver_filename_c
113 
114  ! ... the linear solvers are either given in the parameters namelist
115  ! otherwise we create the lapack_lu linear solver
116  if (present(filename)) then
117  ! ... in opposition to the concrete solvers,
118  ! reading the file is mandatory in order
119  ! to allocate the right type for p_linear_solver
120  open(unit=input_file_id, file=trim(filename))
121  read( input_file_id, linear_solver)
122  close(input_file_id)
123  ! ...
124  else
125  solver_name_a = "lapack_lu"
126  solver_name_b = "lapack_lu"
127  solver_name_c = "lapack_lu"
128  end if
129  ! ...
130 
131  ! ...
132  if (present(linear_solver_a)) then
133  self % ptr_linear_solver_a => linear_solver_a
134  else
135  ! ...
136  if (present(linear_operator_a)) then
137  ! ...
138  call sll_create_linear_solver_with_name( solver_name_a, &
139  & linear_operator_a, &
140  & self % p_linear_solver_a, &
141  & flag_a)
142 
143  if (flag_a) then
144  self % ptr_linear_solver_a => self % p_linear_solver_a
145  end if
146  ! ...
147  else
148  stop "create_linear_solver_kron: linear_operator_a is expected"
149  end if
150  ! ...
151  end if
152  ! ...
153 
154  ! ...
155  if (present(linear_solver_b)) then
156  self % ptr_linear_solver_b => linear_solver_b
157  else
158  ! ...
159  if (present(linear_operator_b)) then
160  ! ...
161  call sll_create_linear_solver_with_name( solver_name_b, &
162  & linear_operator_b, &
163  & self % p_linear_solver_b, &
164  & flag_b)
165 
166  if (flag_b) then
167  self % ptr_linear_solver_b => self % p_linear_solver_b
168  end if
169  ! ...
170  else
171  stop "create_linear_solver_kron: linear_operator_b is expected"
172  end if
173  ! ...
174  end if
175  ! ...
176 
177  ! ...
178  if (present(linear_solver_c)) then
179  self % ptr_linear_solver_c => linear_solver_c
180  else
181  ! ...
182  if (present(linear_operator_c)) then
183  ! ...
184  call sll_create_linear_solver_with_name( solver_name_c, &
185  & linear_operator_c, &
186  & self % p_linear_solver_c, &
187  & flag_c)
188 
189  if (flag_c) then
190  self % ptr_linear_solver_c => self % p_linear_solver_c
191  end if
192  ! ...
193  end if
194  ! ...
195  end if
196  ! ...
197 
198  ! ...
199  self % nrowcol = 0
200  ! ...
201 
202  ! ... sets number of rows ans columns for the first direction
203  self % nrowcol(1, 1) = self % ptr_linear_solver_a % n_global_rows
204  self % nrowcol(1, 2) = self % ptr_linear_solver_a % n_global_cols
205  ! ...
206 
207  ! ... sets number of rows ans columns for the second direction
208  self % nrowcol(2, 1) = self % ptr_linear_solver_b % n_global_rows
209  self % nrowcol(2, 2) = self % ptr_linear_solver_b % n_global_cols
210  ! ...
211 
212  ! ... sets number of rows ans columns for the third direction
213  if (associated(self % ptr_linear_solver_c)) then
214  self % nrowcol(3, 1) = self % ptr_linear_solver_c % n_global_rows
215  self % nrowcol(3, 2) = self % ptr_linear_solver_c % n_global_cols
216  end if
217  ! ...
218 
219  end subroutine create_linear_solver_kron
220  ! ..................................................
221 
222  ! ..................................................
230  subroutine sll_create_linear_solver_with_name( solver_name, &
231  & linear_operator, &
232  & linear_solver, &
233  & flag, &
234  & pc_left)
235  implicit none
236  character(len=*) , intent(in) :: solver_name
237  class(sll_t_linear_operator_abstract) ,target , intent(in) :: linear_operator
238  class(sll_t_linear_solver_abstract) , allocatable, intent(inout) :: linear_solver
239  logical , intent(out) :: flag
240  class(sll_t_linear_solver_abstract) , optional, intent(in) :: pc_left
241  ! local
242  class(sll_t_matrix_abstract), pointer :: ptr_matrix => null()
243 
244  ! ...
245  flag = .true.
246  ! ...
247 
248  ! ...
249  if (.not. allocated(linear_solver)) then
250  call sll_allocate_linear_solver(solver_name, linear_solver, flag)
251  end if
252  ! ...
253 
254  ! ...
255  select type (matrix => linear_operator)
256  class is (sll_t_matrix_abstract)
257  ptr_matrix => matrix
258  end select
259  ! ...
260 
261  ! ...
262  if (flag) then
263  flag = .false.
264  select type (solver => linear_solver)
265  class is (sll_t_linear_solver_mgmres)
266  call solver % create( linear_operator, &
267  & pc_left=pc_left)
268  flag = .true.
269  class is (sll_t_linear_solver_cg)
270  call solver % create( linear_operator, &
271  & pc_left=pc_left)
272  flag = .true.
273  end select
274  ! ...
275  else
276  stop 'sll_create_linear_solver_with_name: could not allocate the linear solver'
277  end if
278  ! ...
279 
281 
282  ! ............................................
288  subroutine sll_allocate_linear_solver(solver_name, linear_solver, flag)
289  implicit none
290  character(len=*) , intent(in) :: solver_name
291  class(sll_t_linear_solver_abstract), allocatable, intent(inout) :: linear_solver
292  logical , intent(out) :: flag
293 
294  ! ...
295  flag = .false.
296  ! ...
297 
298  ! ...
299  select case (solver_name)
300  case ("mgmres")
301  allocate(sll_t_linear_solver_mgmres::linear_solver)
302  flag = .true.
303  case ("cg")
304  allocate(sll_t_linear_solver_cg::linear_solver)
305  flag = .true.
306  end select
307  ! ...
308 
309  end subroutine sll_allocate_linear_solver
310 
311  ! ............................................
316  subroutine set_verbose_linear_solver_kron(self, verbose)
317  implicit none
318  class(sll_t_linear_solver_kron), intent(inout) :: self
319  logical , intent(in) :: verbose
320 
321  ! ...
322  call self % set_verbose_abstract(verbose)
323  ! ...
324 
325  end subroutine set_verbose_linear_solver_kron
326  ! ..................................................
327 
328  ! ..................................................
333  subroutine read_from_file_linear_solver_kron(self, filename)
334  implicit none
335  class(sll_t_linear_solver_kron), intent(inout) :: self
336  character(len=*) , intent(in) :: filename
337  ! local
338 
339  end subroutine read_from_file_linear_solver_kron
340  ! ..................................................
341 
342  ! ..................................................
348  subroutine solve_real_linear_solver_kron(self, rhs, unknown)
349  implicit none
350  class(sll_t_linear_solver_kron), intent(inout) :: self
351  sll_real64, dimension(:), intent(in ) :: rhs
352  sll_real64, dimension(:), intent( out) :: unknown
353  ! local
354 
355  ! ...
356  if (.not. associated(self % ptr_linear_solver_c)) then
357  call solve_2_real_linear_solver_kron( self, &
358  & self % ptr_linear_solver_a, &
359  & self % ptr_linear_solver_b, &
360  & rhs, unknown)
361  else
362  call solve_3_real_linear_solver_kron(self, rhs, unknown)
363  end if
364  ! ...
365 
366  end subroutine solve_real_linear_solver_kron
367  ! ..................................................
368 
369  ! ..................................................
376  & linear_solver_a, linear_solver_b, &
377  & rhs, unknown)
378  implicit none
379  class(sll_t_linear_solver_kron), intent(inout) :: self
380  class(sll_t_linear_solver_abstract), intent(inout) :: linear_solver_a
381  class(sll_t_linear_solver_abstract), intent(inout) :: linear_solver_b
382  sll_real64, dimension(:), intent(in ) :: rhs
383  sll_real64, dimension(:), intent( out) :: unknown
384  ! local
385  sll_real64, dimension(:,:), allocatable :: y
386  sll_real64, dimension(:,:), allocatable :: xprim
387  sll_real64, dimension(:,:), allocatable :: xprim_trans
388  sll_real64, dimension(:,:), allocatable :: x_sol_trans
389  sll_real64, dimension(:,:), allocatable :: x_sol
390  sll_int32 :: n_rows_a
391  sll_int32 :: n_rows_b
392  sll_int32 :: n_cols_a
393  sll_int32 :: n_cols_b
394  sll_int32 :: i_col_b
395 
396  ! ...
397  n_cols_a = linear_solver_a % n_global_cols
398  n_rows_a = linear_solver_a % n_global_rows
399  n_cols_b = linear_solver_b % n_global_cols
400  n_rows_b = linear_solver_b % n_global_rows
401  ! ...
402 
403  ! ... TODO to be optimized, we don't need all these arrays
404  allocate(y(n_rows_b, n_rows_a))
405  allocate(xprim(n_cols_b, n_rows_a))
406  allocate(xprim_trans(n_rows_a, n_cols_b))
407  allocate(x_sol_trans(n_rows_a, n_cols_b))
408  allocate(x_sol(n_cols_b, n_rows_a))
409  ! ...
410 
411  ! ...
412  y = 0.0_f64
413 
414  call sll_vector_to_matrix(rhs, y)
415  ! ...
416 
417  ! ... solve every direction
418  xprim = 0.0_f64
419  do i_col_b = 1, n_cols_b
420  call linear_solver_b % solve_real( y(:, i_col_b), &
421  & xprim(:, i_col_b))
422  end do
423  ! ...
424 
425  ! ...
426  call sll_transpose(xprim, xprim_trans)
427  ! ...
428 
429  ! ...
430  x_sol_trans = 0.0_f64
431  do i_col_b = 1, n_cols_b
432  call linear_solver_a % solve_real( xprim_trans(:, i_col_b), &
433  & x_sol_trans(:, i_col_b))
434  end do
435  ! ...
436 
437  ! ...
438  call sll_transpose(x_sol_trans, x_sol)
439  ! ...
440 
441  ! ...
442  unknown = 0.0_f64
443  call sll_matrix_to_vector(x_sol, unknown)
444  ! ...
445 
447  if(self%verbose) then
448  print*, 'solve_2_real_linear_solver_kron, verbose = true: not yet implemented'
449  end if
450  !...
451 
452  end subroutine solve_2_real_linear_solver_kron
453  ! ..................................................
454 
455  ! ..................................................
461  subroutine solve_3_real_linear_solver_kron(self, rhs, unknown)
462  implicit none
463  class(sll_t_linear_solver_kron), intent(in) :: self
464  sll_real64, dimension(:), intent(in ) :: rhs
465  sll_real64, dimension(:), intent( out) :: unknown
466 
467  !local
468  sll_int32 :: i,j,k,istart,iend
469  sll_int32 :: stride, counter, ind3d
470  ! scratch data
471  sll_real64 :: scratch_nrow_a( self%nrowcol(1,1) )
472  sll_real64 :: scratch_nrow_b( self%nrowcol(2,1) )
473  sll_real64 :: scratch_nrow_c( self%nrowcol(3,1) )
474  sll_real64 :: scratch_2_13( self%nrowcol(2,2), self%nrowcol(1,1)*self%nrowcol(3,2) )
475  sll_real64 :: scratch_3_21( self%nrowcol(3,2), self%nrowcol(2,1)*self%nrowcol(1,1) )
476 
477  stride = self%nrowcol(1,1)
478  istart = 1
479  iend = self%nrowcol(1,2)
480  do k=1, self%nrowcol(3,2)
481  do j=1, self%nrowcol(2,2)
482  call self % ptr_linear_solver_a%solve ( rhs(istart:iend), scratch_nrow_a )
483  do i=1, self%nrowcol(1,1)
484  scratch_2_13(j,(k-1)*stride+i) = scratch_nrow_a(i)
485  end do
486  istart = iend + 1
487  iend = iend + self%nrowcol(1,2)
488  end do
489  end do
490 
491  stride = self%nrowcol(2,1)
492  counter = 1
493  do k=1, self%nrowcol(3,2)
494  do i=1, self%nrowcol(1,1)
495  call self % ptr_linear_solver_b%solve ( scratch_2_13(:, counter), scratch_nrow_b )
496  do j=1, self%nrowcol(2,1)
497  scratch_3_21(k,(i-1)*stride+j) = scratch_nrow_b(j)
498  end do
499  counter = counter +1
500  end do
501  end do
502 
503 
504  stride = self%nrowcol(3,1)
505  counter = 1
506  do i=1, self%nrowcol(1,1)
507  do j=1, self%nrowcol(2,1)
508  call self % ptr_linear_solver_c%solve ( scratch_3_21(:, counter), scratch_nrow_c )
509  ind3d = i+(j-1)*self%nrowcol(1,1)
510  do k=1, self%nrowcol(3,1)
511  unknown(ind3d) = scratch_nrow_c(k)
512  ind3d = ind3d + self%nrowcol(1,1)*self%nrowcol(2,1)
513  end do
514  counter = counter +1
515  end do
516  end do
517 
518 
520  if(self%verbose) then
521  print*, 'solve_3_real_linear_solver_kron, verbose = true: not yet implemented'
522  end if
523  !...
524 
525 
526  end subroutine solve_3_real_linear_solver_kron
527  ! ..................................................
528 
529  ! ............................................
534  implicit none
535  class(sll_t_linear_solver_kron), intent(in) :: self
536  ! local
537 
538  print *, ">>>> linear_solver_kron"
539  print *, "* verbose : ", self % verbose
540  print *, "<<<< "
541 
542  end subroutine print_info_linear_solver_kron
543  ! ............................................
544 
545  ! ..................................................
549  subroutine free_linear_solver_kron(self)
550  implicit none
551  class(sll_t_linear_solver_kron), intent(inout) :: self
552  ! local
553 
554  ! ...
555  if (allocated(self % p_linear_solver_a)) then
556  call self % p_linear_solver_a % free()
557  deallocate(self % p_linear_solver_a)
558  self % ptr_linear_solver_a => null()
559  end if
560  ! ...
561 
562  ! ...
563  if (allocated(self % p_linear_solver_b)) then
564  call self % p_linear_solver_b % free()
565  deallocate(self % p_linear_solver_b)
566  self % ptr_linear_solver_b => null()
567  end if
568  ! ...
569 
570  ! ...
571  if (allocated(self % p_linear_solver_c)) then
572  call self % p_linear_solver_c % free()
573  deallocate(self % p_linear_solver_c)
574  self % ptr_linear_solver_c => null()
575  end if
576  ! ...
577 
578  end subroutine free_linear_solver_kron
579  ! ..................................................
580 
581 end module sll_m_linear_solver_kron
module for abstract linear operator
module for a linear operator of kronecker solver
recursive subroutine, public sll_transpose(x, x_t)
returnes the transpose of a 2d array
subroutine, public sll_matrix_to_vector(mat, vec)
converts a matrix to a vector
subroutine, public sll_vector_to_matrix(vec, mat)
converts a vector to a matrix
module for abstract linear solver
module for conjugate gradient method in pure form
module for kronecker linear solver
subroutine solve_3_real_linear_solver_kron(self, rhs, unknown)
apply the solve operation with real vectors
subroutine set_verbose_linear_solver_kron(self, verbose)
sets the verbose for the linear solver object
subroutine free_linear_solver_kron(self)
destroys the current object
subroutine sll_allocate_linear_solver(solver_name, linear_solver, flag)
allocate the linear solver object
subroutine solve_2_real_linear_solver_kron(self, linear_solver_a, linear_solver_b, rhs, unknown)
solves the linear system with real vectors
subroutine solve_real_linear_solver_kron(self, rhs, unknown)
solves the linear system with real vectors
subroutine read_from_file_linear_solver_kron(self, filename)
read from file
subroutine create_linear_solver_kron(self, linear_operator_a, linear_operator_b, linear_operator_c, linear_solver_a, linear_solver_b, linear_solver_c, filename)
creates a kronecker linear solver the user must provide
subroutine print_info_linear_solver_kron(self)
destroys a finite element cell
subroutine sll_create_linear_solver_with_name(solver_name, linear_operator, linear_solver, flag, pc_left)
create an linear solver using its name and a linear operator
module for a sequential gmres
module for abstract matrix
    Report Typos and Errors