27 #include "sll_working_precision.h"
28 #include "sll_memory.h"
29 #include "sll_assert.h"
35 use iso_fortran_env,
only: output_unit
72 sll_int32,
pointer :: row_ptr(:)
73 sll_int32,
pointer :: col_ind(:)
74 sll_real64,
pointer :: val(:)
75 sll_int32 :: solver = 0
78 integer(umf_void) :: umf_symbolic
79 integer(umf_void) :: umf_numeric
80 sll_real64,
dimension(:),
pointer :: umf_control
106 if (
associated(mat))
nullify (mat)
127 local_to_global_row, &
129 local_to_global_col, &
134 sll_int32,
intent(in) :: num_rows
135 sll_int32,
intent(in) :: num_cols
136 sll_int32,
intent(in) :: num_elts
137 sll_int32,
dimension(:, :),
intent(in) :: local_to_global_row
138 sll_int32,
dimension(:, :),
intent(in) :: local_to_global_col
139 sll_int32,
intent(in) :: num_local_dof_row
140 sll_int32,
intent(in) :: num_local_dof_col
141 sll_int32,
optional :: solver
145 sll_allocate(mat, ierr)
148 if (
present(solver))
then
165 local_to_global_row, &
167 local_to_global_col, &
189 local_to_global_row, &
191 local_to_global_col, &
195 sll_int32,
intent(in) :: num_rows
196 sll_int32,
intent(in) :: num_cols
197 sll_int32,
intent(in) :: num_elts
198 sll_int32,
dimension(:, :),
intent(in) :: local_to_global_row
199 sll_int32,
intent(in) :: num_local_dof_row
200 sll_int32,
dimension(:, :),
intent(in) :: local_to_global_col
201 sll_int32,
intent(in) :: num_local_dof_col
205 sll_int32,
dimension(:, :),
allocatable :: lpi_col
206 sll_int32,
dimension(:),
allocatable :: lpi_occ
218 print *,
'#sll_s_csr_matrix_init'
223 sll_allocate(lpi_col(num_rows, 0:coef*num_local_dof_col), ierr)
224 sll_allocate(lpi_occ(num_rows + 1), ierr)
230 do ii = 1, num_local_dof_row
231 row = local_to_global_row(ii, elt)
233 do jj = 1, num_local_dof_col
234 col = local_to_global_col(jj, elt)
238 do i = 1, lpi_col(row, 0)
239 if (lpi_col(row, i) == col)
then
244 if (.not. ll_done)
then
245 lpi_occ(row) = lpi_occ(row) + 1
246 lpi_col(row, 0) = lpi_col(row, 0) + 1
247 lpi_col(row, lpi_col(row, 0)) = col
256 num_nz = sum(lpi_occ(1:num_rows))
258 mat%num_rows = num_rows
259 mat%num_cols = num_cols
263 print *,
'#solver =', mat%solver
264 print *,
'#num_rows=', num_rows
265 print *,
'#num_cols=', num_cols
266 print *,
'#num_nz =', num_nz
269 sll_allocate(mat%row_ptr(num_rows + 1), ierr)
270 sll_allocate(mat%col_ind(num_nz), ierr)
271 sll_allocate(mat%val(num_nz), ierr)
275 do i = 1, mat%num_rows
276 mat%row_ptr(i + 1) = mat%row_ptr(1) + sum(lpi_occ(1:i))
280 do ii = 1, num_local_dof_row
281 row = local_to_global_row(ii, elt)
283 if (lpi_col(row, 0) /= 0)
then
287 mat%col_ind(mat%row_ptr(row) + i - 1) = lpi_col(row, i)
296 sll_deallocate_array(lpi_col, ierr)
297 sll_deallocate_array(lpi_occ, ierr)
299 select case (mat%solver)
304 sll_allocate(mat%umf_control(umfpack_control), ierr)
305 mat%row_ptr = mat%row_ptr - 1
306 mat%col_ind = mat%col_ind - 1
307 call umf4def(mat%umf_control)
313 call initialize(mat%pstx, num_rows, num_nz, mat%row_ptr, mat%col_ind, mat%val)
319 call initialize(mat%mmps, num_rows, num_nz, mat%row_ptr, mat%col_ind, mat%val)
332 mat%num_nz = mat_a%num_nz + 2*mat_a%num_rows
333 mat%num_rows = mat_a%num_rows + 1
334 mat%num_cols = mat_a%num_cols + 1
336 print *,
'# sll_s_csr_matrix_with_constraint_init'
337 print *,
'# num_nz mat, num_nz mat_tot', mat_a%num_nz, mat%num_nz
338 print *,
'# num_rows mat, num_rows mat_tot', mat_a%num_rows, mat%num_rows
339 print *,
'# num_cols mat, num_cols mat_tot', mat_a%num_cols, mat%num_cols
342 sll_allocate(mat%row_ptr(mat%num_rows + 1), ierr)
343 sll_allocate(mat%col_ind(mat%num_nz), ierr)
344 sll_clear_allocate(mat%val(1:mat%num_nz), ierr)
346 mat%solver = mat_a%solver
348 select case (mat%solver)
351 sll_allocate(mat%umf_control(umfpack_control), ierr)
352 call umf4def(mat%umf_control)
356 call initialize(mat%pstx, mat%num_rows, mat%num_nz, mat%row_ptr, &
357 mat%col_ind, mat%val)
361 call initialize(mat%mmps, mat%num_rows, mat%num_nz, mat%row_ptr, mat%col_ind, mat%val)
373 sll_allocate(mat, ierr)
388 integer,
dimension(:),
intent(in) :: ia_in
389 integer,
dimension(:),
intent(in) :: ja_in
390 real(8),
dimension(:),
intent(in) :: a_in
391 integer,
intent(in) :: num_rows_in
392 integer,
intent(in) :: num_nz_in
393 real(8),
dimension(:),
intent(in) :: constraint_vec
394 integer,
dimension(:),
intent(out) :: ia_out
395 integer,
dimension(:),
intent(out) :: ja_out
396 real(8),
dimension(:),
intent(out) :: a_out
398 integer :: num_rows_out
399 integer :: num_nz_out
404 num_rows_out = num_rows_in + 1
405 num_nz_out = num_nz_in + 2*num_rows_in
407 sll_assert(
size(ia_in) >= num_rows_in + 1)
408 sll_assert(
size(ja_in) >= num_nz_in)
409 sll_assert(
size(a_in) >= num_nz_in)
410 sll_assert(
size(ia_out) >= num_rows_out + 1)
411 sll_assert(
size(ja_out) == num_nz_out)
412 sll_assert(
size(a_out) >= num_nz_out)
414 if (ia_in(num_rows_in + 1) == num_nz_in)
then
417 do i = 1, num_rows_in
419 do k = ia_in(i) + 1, ia_in(i + 1)
424 a_out(s) = constraint_vec(i)
425 ja_out(s) = num_rows_out - 1
428 ia_out(num_rows_in + 1) = s - 1
429 do i = 1, num_rows_in
430 a_out(s) = constraint_vec(i)
434 ia_out(num_rows_in + 2) = s - 1
436 sll_assert(ia_out(num_rows_out + 1) == num_nz_out)
440 sll_assert(ia_in(num_rows_in + 1) == num_nz_in + 1)
443 do i = 1, num_rows_in
445 do k = ia_in(i), ia_in(i + 1) - 1
450 a_out(s) = constraint_vec(i)
451 ja_out(s) = num_rows_out
454 ia_out(num_rows_in + 1) = s
455 do i = 1, num_rows_in
456 a_out(s) = constraint_vec(i)
460 ia_out(num_rows_in + 2) = s
462 sll_assert(ia_in(num_rows_in + 1) == num_nz_in + 1)
473 sll_real64,
dimension(umfpack_info) :: info
481 print *,
'# begin factorize_csr_matrix '
484 select case (mat%solver)
490 call umf4sym(mat%num_rows, &
499 if (info(1) .lt. 0)
then
500 print *,
'#Error occurred in umf4sym: ', info(1)
505 call umf4num(mat%row_ptr, &
513 if (info(1) .lt. 0)
then
514 print *,
'#Error occurred in umf4num: ', info(1)
529 do i = 1, mat%num_rows
530 do k = mat%row_ptr(i), mat%row_ptr(i + 1) - 1
532 mat%mmps%mumps_par%irn(l) = i
533 mat%mmps%mumps_par%jcn(l) = mat%col_ind(l)
534 mat%mmps%mumps_par%a(l) = mat%val(l)
542 sll_assert(
associated(mat%val))
547 print *,
'# end factorize_csr_matrix '
555 sll_real64,
dimension(:),
intent(in) :: input
556 sll_real64,
dimension(:),
intent(out) :: output
562 do i = 1, mat%num_rows
565 k_2 = mat%row_ptr(i + 1) - 1
567 output(i) = dot_product(mat%val(k_1:k_2), input(mat%col_ind(k_1:k_2)))
576 sll_real64,
intent(in) :: val
577 sll_int32,
intent(in) :: row
578 sll_int32,
intent(in) :: col
583 do k = mat%row_ptr(row) + 1, mat%row_ptr(row + 1)
584 if (mat%col_ind(k) + 1 == col)
then
585 mat%val(k) = mat%val(k) + val
590 do k = mat%row_ptr(row), mat%row_ptr(row + 1) - 1
591 if (mat%col_ind(k) == col)
then
592 mat%val(k) = mat%val(k) + val
603 sll_real64,
dimension(:),
intent(inout) :: b
604 sll_real64,
dimension(:),
intent(out) :: u
609 sll_real64,
dimension(umfpack_info) :: info
614 print *,
'# begin solve_csr_matrix '
617 select case (mat%solver)
623 call umf4sol(sys, u, b, mat%umf_numeric, mat%umf_control, info)
630 call solve(mat%pstx, u)
637 call solve(mat%mmps, u)
647 print *,
'# end solve_csr_matrix '
655 sll_real64,
dimension(:) :: u
656 sll_real64,
dimension(:) :: b
657 sll_real64,
dimension(:),
pointer :: masse_tot
661 sll_real64,
dimension(umfpack_info) :: info
666 select case (mat%solver)
672 call umf4sol(sys, u, b, mat%umf_numeric, mat%umf_control, info)
679 call solve(mat%pstx, u)
686 call solve(mat%mmps, u)
700 sll_real64,
dimension(:, :) :: dense_matrix
701 sll_int32 :: i, j, k, l
705 do i = 1, mat%num_rows
706 do k = mat%row_ptr(i) + 1, mat%row_ptr(i + 1)
708 j = mat%col_ind(l) + 1
709 dense_matrix(i, j) = mat%val(l)
714 do i = 1, mat%num_rows
715 do k = mat%row_ptr(i), mat%row_ptr(i + 1) - 1
718 dense_matrix(i, j) = mat%val(l)
728 sll_real64,
dimension(:) :: u
729 sll_real64,
dimension(:) :: b
734 sll_real64,
dimension(:),
allocatable :: ad
735 sll_real64,
dimension(:),
allocatable :: d
737 sll_real64 :: norm2r1
738 sll_real64 :: norm2r0
739 sll_real64 :: norminfb
740 sll_real64 :: norminfr
750 if (mat%num_rows /= mat%num_cols)
then
751 print *,
'#ERROR Gradient_conj: The matrix must be square'
755 if ((abs(maxval(b)) < eps) .AND. (abs(minval(b)) < eps))
then
760 sll_allocate(ad(mat%num_rows), err)
761 sll_allocate(d(mat%num_rows), err)
766 norminfb = maxval(abs(b))
767 norm2r0 = dot_product(b, b)
778 ps = dot_product(ad, d)
798 norminfr = maxval(abs(b))
799 norm2r1 = dot_product(b, b)
804 beta = norm2r1/norm2r0
811 if (norminfr/norminfb < eps)
exit
815 if (iter == maxiter)
then
816 print *,
'Warning Gradient_conj : iter == maxIter'
817 print *,
'Error after CG =', (norminfr/norminfb)
829 print *,
'print_solver =', mat%solver
830 select case (mat%solver)
832 print *,
"# We use UMFPACK to solve the system "
834 print *,
"# We use PASTIX to solve the system "
836 print *,
"# We use MUMPS to solve the system "
838 print *,
"# We use CG to solve the system "
recursive subroutine, public sll_s_qsortc(A)
Sparse matrix linear solver utilities.
subroutine, public sll_s_csr_add_one_constraint(ia_in, ja_in, a_in, num_rows_in, num_nz_in, constraint_vec, ia_out, ja_out, a_out)
subroutine, public sll_s_add_to_csr_matrix(mat, val, row, col)
type(sll_t_csr_matrix) function, pointer, public sll_f_new_csr_matrix_with_constraint(mat_a)
subroutine, public sll_s_csr_todense(mat, dense_matrix)
subroutine solve_with_cg(mat, b, u)
type(sll_t_csr_matrix) function, pointer new_csr_matrix_with_dof(num_rows, num_cols, num_elts, local_to_global_row, num_local_dof_row, local_to_global_col, num_local_dof_col, solver)
allocates the memory space for a new CSR matrix,
subroutine sll_s_csr_matrix_init(mat, num_rows, num_cols, num_elts, local_to_global_row, num_local_dof_row, local_to_global_col, num_local_dof_col)
initialization of CSR matrix type thanks to the global index of each local dof of each element
subroutine, public sll_s_mult_csr_matrix_vector(mat, input, output)
integer(kind=i32), parameter, public sll_p_pastix
subroutine, public sll_s_solve_csr_matrix(mat, b, u)
subroutine print_solver_type(mat)
integer(kind=i32), parameter, public sll_p_mumps
integer(kind=i32), parameter, public sll_p_umfpack
subroutine, public sll_s_factorize_csr_matrix(mat)
subroutine, public sll_s_free_csr_matrix(mat)
subroutine, public sll_s_solve_csr_matrix_perper(mat, b, u, masse_tot)
subroutine, public sll_s_csr_matrix_with_constraint_init(mat, mat_a)