Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_matrix_csr.F90
Go to the documentation of this file.
1 
4 
11 
13  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14 #include "sll_working_precision.h"
15 
16  use sll_m_matrix_abstract, only: &
18 
19 #ifdef OPENMP_ENABLED
20  use omp_lib
21 #endif
22 
23 
24  implicit none
25 
26  public :: &
28 
29  private
30  ! ..................................................
34 
35  sll_int32 :: n_nnz = 0
36  logical :: is_allocated_ia = .false.
37  logical :: is_allocated_jaa = .false.
38 
39  sll_int32, dimension(:), allocatable :: arr_ia
40  sll_int32, dimension(:), allocatable :: arr_ja
41  sll_real64, dimension(:,:), allocatable :: arr_a
42 
43  contains
44  procedure :: create => create_matrix_csr
45  procedure :: free => free_matrix_csr
46  procedure :: dot => dot_matrix_csr
47  procedure :: add_values => add_values_matrix_csr
48  procedure :: set_values => set_values_matrix_csr
49  procedure :: get_diagonal_default => get_diagonal_default_matrix_csr
50  procedure :: get_diagonal_block => get_diagonal_block_matrix_csr
51  procedure :: print_info => print_info_matrix_csr
52  procedure :: multiply => multiply_matrix_csr
53 
54 
55  end type sll_t_matrix_csr
56  ! ...................................................
57 
58 contains
59 
60  ! ............................................
69  subroutine create_matrix_csr( self, &
70  & n_rows, n_cols, n_nnz, &
71  & n_block_rows, n_block_cols)
72  implicit none
74  class(sll_t_matrix_csr), intent(inout) :: self
76  sll_int32, optional, intent(in) :: n_cols
78  sll_int32, optional, intent(in) :: n_rows
80  sll_int32, optional, intent(in) :: n_nnz
81  sll_int32, optional, intent(in) :: n_block_rows
82  sll_int32, optional, intent(in) :: n_block_cols
83 
84  ! ...
85  if ( (present(n_rows)) &
86  & .or. (present(n_cols)) &
87  & .or. (present(n_nnz)) ) then
88 
89  ! ...
90  call allocate_matrix_csr( self, &
91  n_rows=n_rows, &
92  n_cols=n_cols, &
93  n_nnz=n_nnz, &
94  n_block_rows=n_block_rows, &
95  n_block_cols=n_block_cols)
96  ! ...
97 
98  ! ...
99  self % n_global_rows = self % n_rows
100  self % n_global_cols = self % n_cols
101  ! ...
102  elseif ((present(n_block_rows)) .or. (present(n_block_cols))) then
103  ! ...
104  if ((present(n_block_rows))) then
105  self % n_block_rows = n_block_rows
106  end if
107  ! ...
108 
109  ! ...
110  if ((present(n_block_cols))) then
111  self % n_block_cols = n_block_cols
112  end if
113  ! ...
114 
115  ! ...
116  call self % initialize_abstract ()
117  ! ...
118 
119  else
120  stop "create_matrix_csr: wrong arguments"
121  end if
122  ! ...
123 
124  end subroutine create_matrix_csr
125 
126 
127  ! ............................................
134  subroutine allocate_matrix_csr( self, &
135  & n_rows, n_cols, n_nnz, &
136  & n_block_rows, n_block_cols)
137  implicit none
139  class(sll_t_matrix_csr), intent(inout) :: self
141  sll_int32, optional, intent(in) :: n_cols
143  sll_int32, optional, intent(in) :: n_rows
145  sll_int32, optional, intent(in) :: n_nnz
146  sll_int32, optional, intent(in) :: n_block_rows
147  sll_int32, optional, intent(in) :: n_block_cols
148 
149  ! ...
150  if ((present(n_block_rows))) then
151  self % n_block_rows = n_block_rows
152  end if
153  ! ...
154 
155  ! ...
156  if ((present(n_block_cols))) then
157  self % n_block_cols = n_block_cols
158  end if
159  ! ...
160 
161  ! ...
162  call self % initialize_abstract ()
163  ! ...
164 
165  if (present(n_rows)) then
166  self%n_rows = n_rows
167 
168  allocate(self%arr_ia(self%n_rows+1))
169  self % is_allocated_ia = .true.
170  end if
171 
172  if (present(n_cols)) then
173  self%n_cols = n_cols
174  end if
175 
176  if (present(n_nnz)) then
177  self%n_nnz = n_nnz
178 
179  allocate(self%arr_ja(self%n_nnz))
180  allocate(self%arr_a(self % n_dof, self%n_nnz))
181 
182  self % is_allocated = .true.
183  self % is_allocated_jaa = .true.
184  self%arr_a = 0.0_f64
185  end if
186 
187 
188  end subroutine allocate_matrix_csr
189  ! ...................................................
190 
191  ! ............................................
195  subroutine free_matrix_csr(self)
196  implicit none
197  class(sll_t_matrix_csr), intent(inout) :: self
198 
199  ! ...
200  if (self % is_allocated_ia) then
201  deallocate(self%arr_ia)
202 
203  self % is_allocated = .false.
204  self % is_allocated_ia = .false.
205  end if
206  ! ...
207 
208  ! ...
209  if (self % is_allocated_jaa) then
210  deallocate(self%arr_ja)
211  deallocate(self%arr_a)
212 
213  self % is_allocated = .false.
214  self % is_allocated_jaa = .false.
215  end if
216  ! ...
217 
218  end subroutine free_matrix_csr
219  ! ...................................................
220 
221  ! ...................................................
227  subroutine dot_matrix_csr(self, x, y)
228  implicit none
229  class(sll_t_matrix_csr) , intent(in) :: self
230  sll_real64,dimension(:), intent(in ) :: x
231  sll_real64,dimension(:), intent( out) :: y
232 
233  call dot_vector_default(self, x, y)
234 
235  end subroutine dot_matrix_csr
236  ! ...................................................
237 
238 
239  ! ...................................................
245  subroutine dot_vector_default(self, x, y)
246  implicit none
247  class(sll_t_matrix_csr) , intent(in) :: self
248  sll_real64,dimension(:), intent(in ) :: x
249  sll_real64,dimension(:), intent( out) :: y
250  !local var
251  sll_int32 :: i
252  sll_int32 :: i_row
253  sll_int32 :: i_col
254  sll_int32 :: k_min
255  sll_int32 :: k_max
256  sll_int32 :: i_dof
257  sll_int32 :: i_block_row
258  sll_int32 :: i_block_col
259  sll_int32 :: n_rows
260  sll_int32 :: n_cols
261  sll_int32 :: n_block_rows
262  sll_int32 :: n_block_cols
263  sll_int32 :: n_global_rows
264  sll_int32 :: n_global_cols
265  sll_real64, dimension(:,:), allocatable :: arr_x
266 
267  ! ...
268  n_rows = self % n_rows
269  n_cols = self % n_cols
270  n_block_rows = self % n_block_rows
271  n_block_cols = self % n_block_cols
272  n_global_rows = self % n_global_rows
273  n_global_cols = self % n_global_cols
274  ! ...
275 
276  ! ...
277  allocate(arr_x(n_block_cols, self % n_global_cols))
278  ! ...
279 
280  ! ...
281  i = 0
282  do i_col = 1, n_global_cols
283  do i_block_col = 1, n_block_cols
284  i = i + 1
285 
286  arr_x(i_block_col, i_col) = x(i)
287  end do
288  end do
289  ! ...
290 
291  y = 0.0_f64
292 
293  ! ...
294 !!$#ifdef OPENMP_ENABLED
295 !!$ !export OMP_NUM_THREADS=2
296 !!$ !call omp_set_num_threads(4)
297 !!$
298 !!$ seconds = omp_get_wtime()
299 !!$#endif
300  !$OMP PARALLEL SHARED( y, n_block_rows, n_block_cols, arr_x, self ) PRIVATE( k_min, k_max, i_dof, i_block_row, i_block_col, i)
301  !write(*,*)'Total Thread number: ', OMP_GET_NUM_THREADS()
302  !write(*,*)'Thread rank: ', OMP_GET_THREAD_NUM()
303  !$OMP DO
304  do i_row = 1, n_rows
305  ! ...
306  k_min = self % arr_ia ( i_row )
307  k_max = self % arr_ia ( i_row + 1 ) - 1
308  ! ...
309 
310  ! ...
311  i_dof = 0
312  do i_block_row = 1, n_block_rows
313  do i_block_col = 1, n_block_cols
314  i_dof = i_dof + 1
315 
316  i = i_block_row + (i_row - 1) * n_block_rows
317  y(i) = y(i) + dot_product( self % arr_a (i_dof, k_min : k_max ), &
318  arr_x(i_block_col, self%arr_ja ( k_min : k_max ) ) )
319 
320  end do
321  end do
322  ! ...
323  end do
324  !$OMP END DO
325  !$OMP END PARALLEL
326 !!$#ifdef OPENMP_ENABLED
327 !!$ seconds = omp_get_wtime()-seconds
328 !!$ print*, 'time elapsed', seconds
329 !!$#endif
330  ! ...
331 
332  end subroutine dot_vector_default
333 
334 
335 
336  ! ............................................
343  subroutine add_values_matrix_csr(self, i_row, i_col, arr_x)
344  implicit none
345  class(sll_t_matrix_csr) , intent(inout) :: self
346  sll_int32 , intent(in) :: i_row
347  sll_int32 , intent(in) :: i_col
348  sll_real64, dimension(:), intent(in) :: arr_x
349  ! local
350  sll_int32 :: j
351  sll_int32 :: k
352 
353  ! the current line is self%arr_ia(i_row)
354  do k = self % arr_ia(i_row), self % arr_ia(i_row+1)-1
355  j = self % arr_ja(k)
356  if ( j == i_col ) then
357  self % arr_a(:, k) = self % arr_a(:, k) + arr_x(:)
358  exit
359  end if
360  end do
361 
362  end subroutine add_values_matrix_csr
363  ! ...................................................
364 
365  ! ............................................
372  subroutine set_values_matrix_csr(self, i_row, i_col, arr_x)
373  implicit none
374  class(sll_t_matrix_csr) , intent(inout) :: self
375  sll_int32 , intent(in) :: i_row
376  sll_int32 , intent(in) :: i_col
377  sll_real64, dimension(:), intent(in) :: arr_x
378  ! local
379  sll_int32 :: j
380  sll_int32 :: k
381 
382  ! the current line is self%arr_ia(i_row)
383  do k = self % arr_ia(i_row), self % arr_ia(i_row+1)-1
384  j = self % arr_ja(k)
385  if ( j == i_col ) then
386  self % arr_a(:, k) = arr_x(:)
387  exit
388  end if
389  end do
390 
391  end subroutine set_values_matrix_csr
392  ! ...................................................
393 
394  ! ............................................
400  subroutine get_diagonal_default_matrix_csr(self, diag, i_diag)
401  implicit none
402  class(sll_t_matrix_csr) , intent(in) :: self
403  sll_real64, dimension(:), intent(inout) :: diag
404  sll_int32, optional, intent(in) :: i_diag
405  !local
406  sll_int32 :: i_row
407  sll_int32 :: n_rows
408  sll_int32 :: n_cols
409  sll_int32 :: i
410  sll_int32 :: i_dof
411  sll_int32 :: i_block_row
412  sll_int32 :: i_block_col
413  sll_int32 :: n_block_rows
414  sll_int32 :: n_block_cols
415  sll_real64, dimension(:,:,:), allocatable :: block_diag
416 
417  ! ...
418  n_block_rows = self % n_block_rows * self %n_block_rows
419  n_block_cols = self % n_block_cols * self %n_block_cols
420  n_rows = self % n_rows * self %n_block_rows
421  n_cols = self % n_cols* self %n_block_cols
422 
423  ! ...
424 
425  ! ...
426  diag = 0.0_f64
427  ! ...
428 
429  ! ...
430  allocate(block_diag(n_block_rows, n_block_cols, min(n_rows, n_cols)))
431  block_diag = 0.0_f64
432  ! ...
433 
434  ! ...
435  call self % get_diagonal_block(block_diag, i_diag=i_diag)
436  ! ...
437 
438  ! ...
439  do i_row = 1, n_rows
440  ! ...
441  i_dof = 0
442  do i_block_row = 1, n_block_rows
443  do i_block_col = 1, n_block_cols
444  i_dof = i_dof + 1
445 
446  if (i_block_row == i_block_col) then
447  i = i_block_row + (i_row - 1) * n_block_rows
448  diag(i) = block_diag(i_block_row, i_block_row, i_row)
449  end if
450 
451  end do
452  end do
453  ! ...
454  end do
455  ! ...
456 
457  end subroutine get_diagonal_default_matrix_csr
458  ! ...................................................
459 
460  ! ............................................
466  subroutine get_diagonal_block_matrix_csr(self, diag, i_diag)
467  implicit none
468  class(sll_t_matrix_csr) , intent(in) :: self
469  sll_real64, dimension(:,:,:), intent(inout) :: diag
470  sll_int32, optional, intent(in) :: i_diag
471  !local
472  sll_int32, parameter :: job = 0 ! don't altered the scr matrix
473  sll_int32 :: n_nnz_diag
474  ! poisitions in array arr_ja of the diagonal elements
475  sll_int32 , dimension(:), allocatable :: arr_ind_diag
476  sll_int32 :: l_i_diag
477  sll_int32 :: i_dof
478  sll_int32 :: n_rows
479  sll_int32 :: n_cols
480  sll_int32 :: i_block_row
481  sll_int32 :: i_block_col
482  sll_int32 :: n_block_rows
483  sll_int32 :: n_block_cols
484 
485  ! ... 0 => extart the main diagonal
486  l_i_diag = 0
487  if (present(i_diag)) then
488  l_i_diag = i_diag
489  end if
490  ! ...
491 
492  ! ...
493  n_block_rows = self % n_block_rows
494  n_block_cols = self % n_block_cols
495  n_rows = self % n_rows
496  n_cols = self % n_cols
497  ! ...
498 
499  ! ...
500  diag = 0.0_f64
501  ! ...
502 
503  ! ...
504  allocate(arr_ind_diag(min(n_rows, n_cols)))
505  ! ...
506 
507  ! ...
508  i_dof = 0
509  do i_block_row = 1, n_block_rows
510  do i_block_col = 1, n_block_cols
511  i_dof = i_dof + 1
512 
513  call getdia(n_rows, n_cols, job, &
514  & self % arr_a(i_dof, :), self % arr_ja, self % arr_ia, &
515  & n_nnz_diag, diag(i_block_row,i_block_col,:), arr_ind_diag, l_i_diag)
516 
517  end do
518  end do
519  ! ...
520 
521  ! ...
522  deallocate(arr_ind_diag)
523  ! ...
524 
525  end subroutine get_diagonal_block_matrix_csr
526  ! ...................................................
527 
528 
529 
530 
531  ! ............................................
535  subroutine print_info_matrix_csr(self)
536  implicit none
537  class(sll_t_matrix_csr), intent(in) :: self
538  ! local
539 
540  print *, ">>>>> matrix_csr"
541  print *, "* n_bloc_rows : ", self % n_block_rows
542  print *, "* n_bloc_cols : ", self % n_block_cols
543  print *, "* n_rows : ", self % n_rows
544  print *, "* n_cols : ", self % n_cols
545  print *, "* n_global_rows : ", self % n_global_rows
546  print *, "* n_global_cols : ", self % n_global_cols
547  print *, "* n_nnz : ", self % n_nnz
548  print *, "<<<<<"
549 
550  end subroutine print_info_matrix_csr
551  ! ............................................
552 
553 
554  ! ............................................
556  ! mat_b = self * mat_a
560  subroutine multiply_matrix_csr(self, mat_a, mat_b)
561  implicit none
562  class(sll_t_matrix_csr), intent(in) :: self
563  class(sll_t_matrix_abstract), intent(in) :: mat_a
564  class(sll_t_matrix_abstract), intent(inout) :: mat_b
565  ! local
566  sll_real64, dimension(:), allocatable :: arr_a
567  sll_int32, dimension(:), allocatable :: arr_ia
568  sll_int32, dimension(:), allocatable :: arr_ja
569  sll_int32, dimension(:), allocatable :: arr_iw
570  sll_int32 :: i
571  sll_int32 :: n_rows
572  sll_int32 :: n_cols
573  sll_int32 :: n_nnz
574  sll_int32 :: i_err
575  sll_int32 :: n_nnz_max
576  sll_int32, parameter :: i_job = 1
577  sll_int32, parameter :: i_current_dof = 1
578 
579  ! ...
580  if((self % n_dof)*(mat_a % n_dof).ne.1) then
581  stop "multiply_matrix_csr: not implemented yet if n_dof > 1."
582  endif
583  ! ...
584 
585  ! ...
586  n_rows = self % n_rows
587  n_cols = mat_a % n_cols
588  n_nnz_max = n_rows * n_cols
589  ! ...
590 
591  ! ...
592  allocate(arr_iw(n_cols))
593  allocate(arr_ia(n_rows +1))
594  allocate(arr_ja(n_nnz_max))
595  allocate(arr_a(n_nnz_max))
596  ! ...
597 
598  ! ...
599  select type(mat_a)
600  class is(sll_t_matrix_csr)
601 
602  call amub ( n_rows, n_cols, i_job, &
603  & self % arr_a(i_current_dof,:), &
604  & self % arr_ja, self % arr_ia, &
605  & mat_a % arr_a(i_current_dof,:), &
606  & mat_a % arr_ja, mat_a % arr_ia, &
607  & arr_a, arr_ja, arr_ia, &
608  & n_nnz_max, arr_iw, i_err)
609 
610  class default
611  stop "Error in multiply_matrix_csr: bad matrix_a type."
612  end select
613  ! ...
614 
615  ! ...
616  n_nnz = arr_ia(n_rows + 1) -1
617 
618  select type(mat_b)
619  class is(sll_t_matrix_csr)
620 
621  call mat_b % create( n_rows=n_rows, &
622  & n_cols=n_cols, &
623  & n_nnz=n_nnz)
624 
625  mat_b % arr_ia = arr_ia
626 
627  do i = 1, n_nnz
628  mat_b % arr_ja(i) = arr_ja(i)
629  mat_b % arr_a(i_current_dof, i) = arr_a(i)
630  end do
631  class default
632  stop "Error in multiply_matrix_csr: bad matrix_b type."
633  end select
634  ! ...
635 
636  ! ...
637  deallocate(arr_iw)
638  deallocate(arr_ja)
639  deallocate(arr_ia)
640  deallocate(arr_a)
641  ! ...
642 
643  end subroutine multiply_matrix_csr
644  ! ...................................................
645 
646 
647 
648 end module sll_m_matrix_csr
649 
module for abstract matrix
module for Compressed Sparse Row Matrix (CSR)
subroutine get_diagonal_default_matrix_csr(self, diag, i_diag)
extracts a specified diagonal from a matrix IMPORTANT: diag is a 1-rank array
subroutine create_matrix_csr(self, n_rows, n_cols, n_nnz, n_block_rows, n_block_cols)
creates a csr matrix
subroutine dot_matrix_csr(self, x, y)
apply the dot operation of real vector
subroutine add_values_matrix_csr(self, i_row, i_col, arr_x)
adds values to the matrix
subroutine allocate_matrix_csr(self, n_rows, n_cols, n_nnz, n_block_rows, n_block_cols)
allocates a csr matrix
subroutine set_values_matrix_csr(self, i_row, i_col, arr_x)
sets values to the matrix
subroutine get_diagonal_block_matrix_csr(self, diag, i_diag)
extracts a specified block diagonal from a matrix IMPORTANT: diag is a 3-rank array
subroutine multiply_matrix_csr(self, mat_a, mat_b)
performs the matrix by matrix product
subroutine dot_vector_default(self, x, y)
sequential dot operation
subroutine print_info_matrix_csr(self)
prints the current object
subroutine free_matrix_csr(self)
destroys the current object
    Report Typos and Errors