1submodule(
linalg) linalg_sparse
9module function csr_get_element(this, i, j) result(rst)
11 class(csr_matrix),
intent(in) :: this
12 integer(int32),
intent(in) :: i, j
16 integer(int32) :: iadd
23 if (.not.
allocated(this%row_indices) .or. &
24 .not.
allocated(this%column_indices) .or. &
25 .not.
allocated(this%values)) &
30 rst =
getelm(i, j, this%values, this%column_indices, this%row_indices, &
35pure module function csr_size(x, dim) result(rst)
37 class(csr_matrix),
intent(in) :: x
38 integer(int32),
intent(in) :: dim
44 if (
allocated(x%row_indices))
then
45 rst =
size(x%row_indices) - 1
57pure module function nonzero_count_csr(x) result(rst)
59 class(csr_matrix),
intent(in) :: x
63 if (
allocated(x%values))
then
71module function create_empty_csr_matrix(m, n, nnz, err) result(rst)
73 integer(int32),
intent(in) :: m, n, nnz
74 class(errors),
intent(inout),
optional,
target :: err
75 type(csr_matrix) :: rst
78 integer(int32) :: flag, m1
79 class(errors),
pointer :: errmgr
80 type(errors),
target :: deferr
83 if (
present(err))
then
92 call errmgr%report_error(
"create_empty_csr_matrix", &
93 "The number of rows must be a positive value.", &
94 la_invalid_input_error)
98 call errmgr%report_error(
"create_empty_csr_matrix", &
99 "The number of columns must be a positive value.", &
100 la_invalid_input_error)
104 call errmgr%report_error(
"create_empty_csr_matrix", &
105 "The number of non-zero values must be a positive value.", &
106 la_invalid_input_error)
112 allocate(rst%row_indices(m1), rst%column_indices(nnz), source = 0, &
114 if (flag == 0)
allocate(rst%values(nnz), source = 0.0d0, stat = flag)
116 call errmgr%report_error(
"create_empty_csr_matrix", &
117 "Memory allocation error.", la_out_of_memory_error)
123module function dense_to_csr(a, err) result(rst)
125 real(real64),
intent(in),
dimension(:,:) :: a
126 class(errors),
intent(inout),
optional,
target :: err
127 type(csr_matrix) :: rst
130 integer(int32) :: i, j, k, m, n, nnz
132 class(errors),
pointer :: errmgr
133 type(errors),
target :: deferr
136 if (
present(err))
then
141 t = 2.0d0 * epsilon(t)
149 if (abs(a(i,j)) > t)
then
156 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
157 if (errmgr%has_error_occurred())
return
161 rst%row_indices(1) = 1
163 inner_loop :
do j = 1, n
164 if (abs(a(i,j)) < t) cycle inner_loop
165 rst%column_indices(k) = j
166 rst%values(k) = a(i,j)
169 rst%row_indices(i+1) = k
174module function banded_to_csr(m, ml, mu, a, err) result(rst)
176 integer(int32),
intent(in) :: m, ml, mu
177 real(real64),
intent(in),
dimension(:,:) :: a
178 class(errors),
intent(inout),
optional,
target :: err
179 type(csr_matrix) :: rst
182 integer(int32) :: n, nnz, flag, lowd, lda
183 integer(int32),
allocatable,
dimension(:) :: ia, ja
184 real(real64),
allocatable,
dimension(:) :: v
185 class(errors),
pointer :: errmgr
186 type(errors),
target :: deferr
189 if (
present(err))
then
200 if (ml < 0 .or. mu < 0)
then
201 call errmgr%report_error(
"banded_to_csr",
"The bandwidth " // &
202 "dimensions cannot be negative.", la_invalid_input_error)
205 if (lda /= ml + mu + 1)
then
206 call errmgr%report_error(
"banded_to_csr",
"The number of rows in " // &
207 "the banded matrix does not match the supplied bandwidth " // &
208 "dimensions.", la_matrix_format_error)
213 allocate(ia(m + 1), ja(nnz), v(nnz), stat = flag)
214 if (flag /= 0)
go to 10
217 call bndcsr(m, a, lda, lowd, ml, mu, v, ja, ia, nnz, flag)
221 allocate(rst%row_indices(m + 1), source = ia, stat = flag)
222 if (flag == 0)
allocate(rst%column_indices(nnz), source = ja(:nnz), &
224 if (flag == 0)
allocate(rst%values(nnz), source = v(:nnz), stat = flag)
225 if (flag /= 0)
go to 10
233 call errmgr%report_error(
"banded_to_csr",
"Memory allocation error.", &
234 la_out_of_memory_error)
239module subroutine csr_to_dense(a, x, err)
241 class(csr_matrix),
intent(in) :: a
242 real(real64),
intent(out),
dimension(:,:) :: x
243 class(errors),
intent(inout),
optional,
target :: err
246 integer(int32) :: i, j, k, m, n, nnz, flag
247 class(errors),
pointer :: errmgr
248 type(errors),
target :: deferr
251 if (
present(err))
then
258 nnz = nonzero_count(a)
261 if (
size(x, 1) /= m .or.
size(x, 2) /= n)
then
262 call errmgr%report_error(
"csr_to_dense", &
263 "The output matrix dimensions are not correct.", &
271 do k = a%row_indices(i), a%row_indices(i+1) - 1
272 j = a%column_indices(k)
279module function diag_to_csr(a, err) result(rst)
281 real(real64),
intent(in),
dimension(:) :: a
282 class(errors),
intent(inout),
optional,
target :: err
283 type(csr_matrix) :: rst
286 integer(int32) :: i, n, n1, flag
287 class(errors),
pointer :: errmgr
288 type(errors),
target :: deferr
291 if (
present(err))
then
300 allocate(rst%row_indices(n1), rst%column_indices(n), stat = flag)
301 if (flag == 0)
allocate(rst%values(n), source = a, stat = flag)
303 call errmgr%report_error(
"diag_to_csr",
"Memory allocation error.", &
304 la_out_of_memory_error)
311 rst%column_indices(i) = i
312 rst%row_indices(i) = i
314 rst%row_indices(n1) = n1
318module subroutine csr_assign_to_dense(dense, sparse)
320 real(real64),
intent(out),
dimension(:,:) :: dense
321 class(csr_matrix),
intent(in) :: sparse
324 call csr_to_dense(sparse, dense)
328module subroutine dense_assign_to_csr(sparse, dense)
330 type(csr_matrix),
intent(out) :: sparse
331 real(real64),
intent(in),
dimension(:,:) :: dense
334 sparse = dense_to_csr(dense)
338module function csr_mtx_mtx_mult(a, b) result(rst)
340 class(csr_matrix),
intent(in) :: a, b
341 type(csr_matrix) :: rst
344 integer(int32),
parameter :: sym_mult = 0
345 integer(int32),
parameter :: full_mult = 1
346 integer(int32) :: flag, m, n, k, nnza, nnzb, nnzc, ierr
347 integer(int32),
allocatable,
dimension(:) :: ic, jc, iw
348 real(real64) :: dummy(1)
349 type(errors) :: errmgr
355 nnza = nonzero_count(a)
356 nnzb = nonzero_count(b)
360 if (
size(b, 1) /= k)
then
361 call errmgr%report_error(
"csr_mtx_mtx_mult", &
362 "Inner matrix dimension mismatch.", la_array_size_error)
367 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
368 if (flag /= 0)
go to 10
371 call amub(m, n, sym_mult, a%values, a%column_indices, a%row_indices, &
372 b%values, b%column_indices, b%row_indices, dummy, jc, ic, &
378 nnzc = nnzc + nnza + nnzb
379 allocate(jc(nnzc), stat = flag)
380 if (flag /= 0)
go to 10
381 call amub(m, n, sym_mult, a%values, a%column_indices, &
382 a%row_indices, b%values, b%column_indices, b%row_indices, &
383 dummy, jc, ic, nnzc, iw, ierr)
391 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
392 if (errmgr%has_error_occurred())
return
395 call amub(m, n, full_mult, a%values, a%column_indices, a%row_indices, &
396 b%values, b%column_indices, b%row_indices, rst%values, &
397 rst%column_indices, rst%row_indices, nnzc, iw, ierr)
404 call errmgr%report_error(
"csr_mtx_mtx_mult", &
405 "Memory allocation error.", la_out_of_memory_error)
410module function csr_mtx_vec_mult(a, b) result(rst)
412 class(csr_matrix),
intent(in) :: a
413 real(real64),
intent(in),
dimension(:) :: b
414 real(real64),
allocatable,
dimension(:) :: rst
417 integer(int32) :: i, k, k1, k2, n, p, flag
419 type(errors) :: errmgr
426 if (
size(b) /= p)
then
427 call errmgr%report_error(
"csr_mtx_vec_mult", &
428 "Inner matrix dimension error.", la_array_size_error)
433 allocate(rst(n), stat = flag)
435 call errmgr%report_error(
"csr_mtx_vec_mult", &
436 "Memory allocation error.", la_out_of_memory_error)
443 k1 = a%row_indices(i)
444 k2 = a%row_indices(i+1) - 1
446 t = t + a%values(k) * b(a%column_indices(k))
453module function csr_mtx_add(a, b) result(rst)
455 class(csr_matrix),
intent(in) :: a, b
456 type(csr_matrix) :: rst
459 integer(int32),
parameter :: sym_add = 0
460 integer(int32),
parameter :: full_add = 1
461 integer(int32) :: m, n, nnza, nnzb, nnzc, ierr, flag
462 integer(int32),
allocatable,
dimension(:) :: ic, jc, iw
463 real(real64) :: dummy(1)
464 type(errors) :: errmgr
469 nnza = nonzero_count(a)
470 nnzb = nonzero_count(b)
474 if (
size(b, 1) /= m .or.
size(b, 2) /= n)
then
475 call errmgr%report_error(
"csr_mtx_add", &
476 "The matrix sizes must match.", la_array_size_error)
481 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
482 if (flag /= 0)
go to 10
485 call aplb(m, n, sym_add, a%values, a%column_indices, a%row_indices, &
486 b%values, b%column_indices, b%row_indices, dummy, jc, ic, &
492 nnzc = nnzc + nnza + nnzb
493 allocate(jc(nnzc), stat = flag)
494 if (flag /= 0)
go to 10
495 call aplb(m, n, sym_add, a%values, a%column_indices, &
496 a%row_indices, b%values, b%column_indices, b%row_indices, &
497 dummy, jc, ic, nnzc, iw, ierr)
505 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
506 if (errmgr%has_error_occurred())
return
509 call aplb(m, n, full_add, a%values, a%column_indices, a%row_indices, &
510 b%values, b%column_indices, b%row_indices, rst%values, &
511 rst%column_indices, rst%row_indices, nnzc, iw, ierr)
518 call errmgr%report_error(
"csr_mtx_add",
"Memory allocation error.", &
519 la_out_of_memory_error)
524module function csr_mtx_sub(a, b) result(rst)
526 class(csr_matrix),
intent(in) :: a, b
527 type(csr_matrix) :: rst
530 integer(int32),
parameter :: sym_add = 0
531 integer(int32) :: m, n, nnza, nnzb, nnzc, ierr, flag
532 integer(int32),
allocatable,
dimension(:) :: ic, jc, iw
533 real(real64) :: dummy(1)
534 type(errors) :: errmgr
539 nnza = nonzero_count(a)
540 nnzb = nonzero_count(b)
544 if (
size(b, 1) /= m .or.
size(b, 2) /= n)
then
545 call errmgr%report_error(
"csr_mtx_sub", &
546 "The matrix sizes must match.", la_array_size_error)
551 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
552 if (flag /= 0)
go to 10
555 call aplb(m, n, sym_add, a%values, a%column_indices, a%row_indices, &
556 b%values, b%column_indices, b%row_indices, dummy, jc, ic, &
562 nnzc = nnzc + nnza + nnzb
563 allocate(jc(nnzc), stat = flag)
564 if (flag /= 0)
go to 10
565 call aplb(m, n, sym_add, a%values, a%column_indices, &
566 a%row_indices, b%values, b%column_indices, b%row_indices, &
567 dummy, jc, ic, nnzc, iw, ierr)
575 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
576 if (errmgr%has_error_occurred())
return
579 call aplsb(m, n, a%values, a%column_indices, a%row_indices, -1.0d0, &
580 b%values, b%column_indices, b%row_indices, rst%values, &
581 rst%column_indices, rst%row_indices, nnzc, iw, ierr)
588 call errmgr%report_error(
"csr_mtx_sub",
"Memory allocation error.", &
589 la_out_of_memory_error)
594module function csr_mtx_mult_scalar_1(a, b) result(rst)
596 class(csr_matrix),
intent(in) :: a
597 real(real64),
intent(in) :: b
598 type(csr_matrix) :: rst
601 integer(int32) :: m, n, nnz
602 type(errors) :: errmgr
607 nnz = nonzero_count(a)
610 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
611 if (errmgr%has_error_occurred())
return
614 rst%row_indices = a%row_indices
615 rst%column_indices = a%column_indices
616 rst%values = b * a%values
620module function csr_mtx_mult_scalar_2(a, b) result(rst)
622 real(real64),
intent(in) :: a
623 class(csr_matrix),
intent(in) :: b
624 type(csr_matrix) :: rst
627 integer(int32) :: m, n, nnz
628 type(errors) :: errmgr
633 nnz = nonzero_count(b)
636 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
637 if (errmgr%has_error_occurred())
return
640 rst%row_indices = b%row_indices
641 rst%column_indices = b%column_indices
642 rst%values = a * b%values
646module function csr_mtx_divide_scalar_1(a, b) result(rst)
648 class(csr_matrix),
intent(in) :: a
649 real(real64),
intent(in) :: b
650 type(csr_matrix) :: rst
653 integer(int32) :: m, n, nnz
654 type(errors) :: errmgr
659 nnz = nonzero_count(a)
662 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
663 if (errmgr%has_error_occurred())
return
666 rst%row_indices = a%row_indices
667 rst%column_indices = a%column_indices
668 rst%values = a%values / b
672module function csr_transpose(a) result(rst)
674 class(csr_matrix),
intent(in) :: a
675 type(csr_matrix) :: rst
678 integer(int32) :: m, n, nnz
679 type(errors) :: errmgr
684 nnz = nonzero_count(a)
685 rst = create_empty_csr_matrix(n, m, nnz, errmgr)
686 if (errmgr%has_error_occurred())
return
689 call csrcsc2(m, n, 1, 1, a%values, a%column_indices, a%row_indices, &
690 rst%values, rst%column_indices, rst%row_indices)
694module subroutine extract_diagonal_csr(a, diag, err)
696 class(csr_matrix),
intent(in) :: a
697 real(real64),
intent(out),
dimension(:) :: diag
698 class(errors),
intent(inout),
optional,
target :: err
701 integer(int32) :: m, n, mn, len, flag
702 integer(int32),
allocatable,
dimension(:) :: idiag
703 class(errors),
pointer :: errmgr
704 type(errors),
target :: deferr
707 if (
present(err))
then
717 if (
size(diag) /= mn)
then
718 call errmgr%report_error(
"extract_diagonal_csr", &
719 "The is expected to have MIN(M, N) elements.", &
725 allocate(idiag(mn), stat = flag)
727 call errmgr%report_error(
"extract_diagonal_csr", &
728 "Memory allocation error.", la_out_of_memory_error)
733 call getdia(m, n, 0, a%values, a%column_indices, a%row_indices, len, &
738module subroutine csr_solve_sparse_direct(a, b, x, droptol, err)
740 class(csr_matrix),
intent(in) :: a
741 real(real64),
intent(in),
dimension(:) :: b
742 real(real64),
intent(out),
dimension(:) :: x
743 real(real64),
intent(in),
optional :: droptol
744 class(errors),
intent(inout),
optional,
target :: err
747 integer(int32) :: i, m, n, nnz, lfil, iwk, ierr, flag
748 integer(int32),
allocatable,
dimension(:) :: jlu, ju, jw
749 real(real64),
allocatable,
dimension(:) :: alu, w
751 class(errors),
pointer :: errmgr
752 type(errors),
target :: deferr
755 if (
present(err))
then
760 if (
present(droptol))
then
763 dt = sqrt(epsilon(dt))
767 nnz = nonzero_count(a)
771 call errmgr%report_error(
"csr_solve_sparse_direct", &
772 "The matrix must be square.", la_array_size_error)
775 if (
size(x) /= n)
then
776 call errmgr%report_error(
"csr_solve_sparse_direct", &
777 "Inner matrix dimension mismatch.", la_array_size_error)
780 if (
size(b) /= n)
then
781 call errmgr%report_error(
"csr_solve_sparse_direct", &
782 "The output array dimension does not match the rest of the problem.", &
790 lfil = max(lfil, a%row_indices(i+1) - a%row_indices(i))
792 iwk = max(lfil * m, nnz)
795 allocate(alu(iwk), w(n+1), jlu(iwk), ju(n), jw(2 * n), stat = flag)
796 if (flag /= 0)
go to 10
801 call ilut(n, a%values, a%column_indices, a%row_indices, lfil, dt, &
802 alu, jlu, ju, iwk, w, jw, ierr)
808 else if (ierr > 0)
then
810 else if (ierr == -1)
then
813 else if (ierr == -2 .or. ierr == -3)
then
815 iwk = min(iwk + m + n, m * n)
818 allocate(alu(iwk), jlu(iwk), stat = flag)
819 if (flag /= 0)
go to 10
820 else if (ierr == -4)
then
823 else if (ierr == -5)
then
833 call lusol(n, b, x, alu, jlu, ju)
840 call errmgr%report_error(
"csr_solve_sparse_direct", &
841 "Memory allocation error.", la_out_of_memory_error)
846 call errmgr%report_error(
"csr_solve_sparse_direct", &
847 "The input matrix was incorrectly formatted. A row with more " // &
848 "than N entries was found.", la_matrix_format_error)
853 call errmgr%report_error(
"csr_solve_sparse_direct", &
854 "A row with all zeros was encountered in the matrix.", &
855 la_singular_matrix_error)
860 call errmgr%report_error(
"csr_solve_sparse_direct",
"ILUT encountered " // &
861 "an unknown error. The error code from the ILUT routine is " // &
862 "provided in the output.", ierr)
867 call errmgr%report_error(
"csr_solve_sparse_direct", &
868 "A zero pivot was encountered.", la_singular_matrix_error)
878pure module function msr_size(x, dim) result(rst)
880 class(msr_matrix),
intent(in) :: x
881 integer(int32),
intent(in) :: dim
882 integer(int32) :: rst
896pure module function nonzero_count_msr(x) result(rst)
898 class(msr_matrix),
intent(in) :: x
899 integer(int32) :: rst
906module function create_empty_msr_matrix(m, n, nnz, err) result(rst)
908 integer(int32),
intent(in) :: m, n, nnz
909 class(errors),
intent(inout),
optional,
target :: err
910 type(msr_matrix) :: rst
913 integer(int32) :: nelem, mn, flag
914 class(errors),
pointer :: errmgr
915 type(errors),
target :: deferr
918 if (
present(err))
then
926 call errmgr%report_error(
"create_empty_msr_matrix", &
927 "The number of rows must be a positive value.", &
928 la_invalid_input_error)
932 call errmgr%report_error(
"create_empty_msr_matrix", &
933 "The number of columns must be a positive value.", &
934 la_invalid_input_error)
938 call errmgr%report_error(
"create_empty_msr_matrix", &
939 "The number of non-zero values must be a positive value.", &
940 la_invalid_input_error)
949 nelem = m + 1 + nnz - mn
950 allocate(rst%indices(nelem), source = 0, stat = flag)
951 if (flag == 0)
allocate(rst%values(nelem), source = 0.0d0, stat = flag)
953 call errmgr%report_error(
"create_empty_msr_matrix", &
954 "Memory allocation error.", la_out_of_memory_error)
960module function csr_to_msr(a, err) result(rst)
962 class(csr_matrix),
intent(in) :: a
963 class(errors),
intent(inout),
optional,
target :: err
964 type(msr_matrix) :: rst
967 integer(int32) :: m, n, nnz, flag
968 integer(int32),
allocatable,
dimension(:) :: iwork, jc, ic
969 real(real64),
allocatable,
dimension(:) :: work, ac
970 class(errors),
pointer :: errmgr
971 type(errors),
target :: deferr
974 if (
present(err))
then
981 nnz = nonzero_count(a)
984 rst = create_empty_msr_matrix(m, n, nnz, errmgr)
985 if (errmgr%has_error_occurred())
return
986 allocate(work(m), iwork(m + 1), stat = flag)
987 if (flag == 0)
allocate(ac(nnz), source = a%values, stat = flag)
988 if (flag == 0)
allocate(jc(nnz), source = a%column_indices, stat = flag)
989 if (flag == 0)
allocate(ic(m+1), source = a%row_indices, stat = flag)
991 call errmgr%report_error(
"csr_to_msr",
"Memory allocation error.", &
992 la_out_of_memory_error)
997 call csrmsr(m, ac, jc, ic, rst%values, rst%indices, work, iwork)
1001module function msr_to_csr(a, err) result(rst)
1003 class(msr_matrix),
intent(in) :: a
1004 class(errors),
intent(inout),
optional,
target :: err
1005 type(csr_matrix) :: rst
1008 integer(int32) :: m, n, nnz, flag
1009 integer(int32),
allocatable,
dimension(:) :: iwork
1010 real(real64),
allocatable,
dimension(:) :: work
1011 class(errors),
pointer :: errmgr
1012 type(errors),
target :: deferr
1015 if (
present(err))
then
1022 nnz = nonzero_count(a)
1025 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
1026 if (errmgr%has_error_occurred())
return
1027 allocate(work(m), iwork(m+1), stat = flag)
1029 call errmgr%report_error(
"msr_to_csr",
"Memory allocation error.", &
1030 la_out_of_memory_error)
1035 call msrcsr(m, a%values, a%indices, rst%values, rst%column_indices, &
1036 rst%row_indices, work, iwork)
1040module function dense_to_msr(a, err) result(rst)
1042 real(real64),
intent(in),
dimension(:,:) :: a
1043 class(errors),
intent(inout),
optional,
target :: err
1044 type(msr_matrix) :: rst
1047 type(csr_matrix) :: csr
1048 class(errors),
pointer :: errmgr
1049 type(errors),
target :: deferr
1052 if (
present(err))
then
1059 csr = dense_to_csr(a, errmgr)
1062 rst = csr_to_msr(csr, errmgr)
1066module subroutine msr_to_dense(a, x, err)
1068 class(msr_matrix),
intent(in) :: a
1069 real(real64),
intent(out),
dimension(:,:) :: x
1070 class(errors),
intent(inout),
optional,
target :: err
1073 integer(int32) :: m, n, flag
1074 type(csr_matrix) :: csr
1075 class(errors),
pointer :: errmgr
1076 type(errors),
target :: deferr
1079 if (
present(err))
then
1088 if (
size(x, 1) /= m .or.
size(x, 2) /= n)
then
1089 call errmgr%report_error(
"msr_to_dense", &
1090 "The output matrix dimensions are not correct.", &
1091 la_array_size_error)
1096 csr = msr_to_csr(a, errmgr)
1097 if (errmgr%has_error_occurred())
return
1098 call csr_to_dense(csr, x, errmgr)
1102module subroutine msr_assign_to_dense(dense, msr)
1104 real(real64),
intent(out),
dimension(:,:) :: dense
1105 class(msr_matrix),
intent(in) :: msr
1108 call msr_to_dense(msr, dense)
1112module subroutine dense_assign_to_msr(msr, dense)
1114 type(msr_matrix),
intent(out) :: msr
1115 real(real64),
intent(in),
dimension(:,:) :: dense
1118 msr = dense_to_msr(dense)
1122module subroutine csr_assign_to_msr(msr, csr)
1124 type(msr_matrix),
intent(out) :: msr
1125 class(csr_matrix),
intent(in) :: csr
1128 msr = csr_to_msr(csr)
1132module subroutine msr_assign_to_csr(csr, msr)
1134 type(csr_matrix),
intent(out) :: csr
1135 class(msr_matrix),
intent(in) :: msr
1138 csr = msr_to_csr(msr)
1142module function create_csr_matrix(m, n, rows, cols, vals, err) result(rst)
1144 integer(int32),
intent(in) :: m, n
1145 integer(int32),
intent(in),
dimension(:) :: rows, cols
1146 real(real64),
intent(in),
dimension(:) :: vals
1147 class(errors),
intent(inout),
optional,
target :: err
1148 type(csr_matrix) :: rst
1151 integer(int32) :: i, flag, nnz
1152 integer(int32),
allocatable,
dimension(:) :: ir
1153 class(errors),
pointer :: errmgr
1154 type(errors),
target :: deferr
1157 if (
present(err))
then
1166 call errmgr%report_error(
"create_csr_matrix", &
1167 "The number of rows must be a positive value.", &
1168 la_invalid_input_error)
1172 call errmgr%report_error(
"create_csr_matrix", &
1173 "The number of columns must be a positive value.", &
1174 la_invalid_input_error)
1177 if (
size(cols) /= nnz .or.
size(vals) /= nnz)
then
1178 call errmgr%report_error(
"create_csr_matrix", &
1179 "The size of the input arrays must be the same.", &
1180 la_array_size_error)
1184 if (rows(i) < 1 .or. rows(i) > m)
then
1185 call errmgr%report_error(
"create_csr_matrix", &
1186 "All row indices must be within the bounds of the matrix.", &
1187 la_invalid_input_error)
1190 if (cols(i) < 1 .or. cols(i) > n)
then
1191 call errmgr%report_error(
"create_csr_matrix", &
1192 "All column indices must be within the bounds of the matrix.", &
1193 la_invalid_input_error)
1197 allocate(ir(nnz), source = rows, stat = flag)
1199 call errmgr%report_error(
"create_csr_matrix", &
1200 "Memory allocation error.", la_out_of_memory_error)
1205 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
1206 if (errmgr%has_error_occurred())
return
1209 call coocsr(m, nnz, vals, ir, cols, rst%values, rst%column_indices, &
1211 call csort(m, rst%values, rst%column_indices, rst%row_indices, .true.)
1217module subroutine csr_lu_factor(a, lu, ju, droptol, err)
1219 class(csr_matrix),
intent(in) :: a
1220 type(msr_matrix),
intent(out) :: lu
1221 integer(int32),
intent(out),
dimension(:) :: ju
1222 real(real64),
intent(in),
optional :: droptol
1223 class(errors),
intent(inout),
optional,
target :: err
1226 integer(int32) :: i, m, n, nn, nnz, lfil, iwk, ierr, flag
1227 integer(int32),
allocatable,
dimension(:) :: jlu, jw
1228 real(real64),
allocatable,
dimension(:) :: alu, w
1230 class(errors),
pointer :: errmgr
1231 type(errors),
target :: deferr
1234 if (
present(err))
then
1239 if (
present(droptol))
then
1242 dt = sqrt(epsilon(dt))
1246 nnz = nonzero_count(a)
1249 if (
size(ju) /= m)
then
1250 call errmgr%report_error(
"csr_lu_factor", &
1251 "U row tracking array is not sized correctly.", la_array_size_error)
1258 lfil = max(lfil, a%row_indices(i+1) - a%row_indices(i))
1260 iwk = max(lfil * m, nnz)
1263 allocate(alu(iwk), w(n+1), jlu(iwk), jw(2 * n), stat = flag)
1264 if (flag /= 0)
go to 10
1269 call ilut(n, a%values, a%column_indices, a%row_indices, lfil, dt, &
1270 alu, jlu, ju, iwk, w, jw, ierr)
1276 else if (ierr > 0)
then
1278 else if (ierr == -1)
then
1281 else if (ierr == -2 .or. ierr == -3)
then
1285 iwk = min(iwk + m + n, m * n)
1288 allocate(alu(iwk), jlu(iwk), stat = flag)
1289 if (flag /= 0)
go to 10
1290 else if (ierr == -4)
then
1293 else if (ierr == -5)
then
1309 nn = m + 1 + nnz - min(m, n)
1310 allocate(lu%values(nn), source = alu(:nn), stat = flag)
1311 if (flag /= 0)
go to 10
1312 allocate(lu%indices(nn), source = jlu(:nn), stat = flag)
1319 call errmgr%report_error(
"csr_lu_factor", &
1320 "Memory allocation error.", la_out_of_memory_error)
1325 call errmgr%report_error(
"csr_lu_factor", &
1326 "The input matrix was incorrectly formatted. A row with more " // &
1327 "than N entries was found.", la_matrix_format_error)
1332 call errmgr%report_error(
"csr_lu_factor", &
1333 "A row with all zeros was encountered in the matrix.", &
1334 la_singular_matrix_error)
1339 call errmgr%report_error(
"csr_solve_sparse_direct",
"ILUT encountered " // &
1340 "an unknown error. The error code from the ILUT routine is " // &
1341 "provided in the output.", ierr)
1346 call errmgr%report_error(
"csr_lu_factor", &
1347 "A zero pivot was encountered.", la_singular_matrix_error)
1352module subroutine csr_lu_solve(lu, ju, b, x, err)
1354 class(msr_matrix),
intent(in) :: lu
1355 integer(int32),
intent(in),
dimension(:) :: ju
1356 real(real64),
intent(in),
dimension(:) :: b
1357 real(real64),
intent(out),
dimension(:) :: x
1358 class(errors),
intent(inout),
optional,
target :: err
1361 integer(int32) :: m, n
1362 class(errors),
pointer :: errmgr
1363 type(errors),
target :: deferr
1366 if (
present(err))
then
1376 call errmgr%report_error(
"csr_lu_solve", &
1377 "The input matrix is expected to be square.", la_array_size_error)
1380 if (
size(x) /= m)
then
1381 call errmgr%report_error(
"csr_lu_solve", &
1382 "Inner matrix dimension mismatch.", la_array_size_error)
1385 if (
size(b) /= m)
then
1386 call errmgr%report_error(
"csr_lu_solve", &
1387 "The output array dimension does not match the rest of the problem.", &
1388 la_array_size_error)
1391 if (
size(ju) /= m)
then
1392 call errmgr%report_error(
"csr_lu_solve", &
1393 "The U row tracking array is not sized correctly.", &
1394 la_array_size_error)
1399 call lusol(m, b, x, lu%values, lu%indices, ju)
1407module subroutine csr_pgmres_solver(a, lu, ju, b, x, im, tol, maxits, iout, err)
1409 class(csr_matrix),
intent(in) :: a
1410 class(msr_matrix),
intent(in) :: lu
1411 integer(int32),
intent(in),
dimension(:) :: ju
1412 real(real64),
intent(inout),
dimension(:) :: b
1413 real(real64),
intent(out),
dimension(:) :: x
1414 integer(int32),
intent(in),
optional :: im, maxits, iout
1415 real(real64),
intent(in),
optional :: tol
1416 class(errors),
intent(inout),
optional,
target :: err
1419 integer(int32) :: n, ierr, flag, io, mit, krylov
1421 real(real64),
allocatable,
dimension(:,:) :: vv
1422 class(errors),
pointer :: errmgr
1423 type(errors),
target :: deferr
1427 if (
present(err))
then
1432 if (
present(im))
then
1437 if (
present(tol))
then
1440 eps = sqrt(epsilon(eps))
1442 if (
present(maxits))
then
1447 if (
present(iout))
then
1454 if (
size(a, 2) /= n)
then
1455 call errmgr%report_error(
"csr_pgmres_solver", &
1456 "The input matrix is not square.", la_array_size_error)
1459 if (
size(lu, 1) /= n .or.
size(lu, 2) /= n)
then
1460 call errmgr%report_error(
"csr_pgmres_solver", &
1461 "The LU factored matrix size is not compatible with the " // &
1462 "input matrix.", la_array_size_error)
1465 if (
size(b) /= n)
then
1466 call errmgr%report_error(
"csr_pgmres_solver", &
1467 "The output array dimension does not match the rest of the problem.", &
1468 la_array_size_error)
1471 if (
size(x) /= n)
then
1472 call errmgr%report_error(
"csr_pgmres_solver", &
1473 "Inner matrix dimension mismatch.", la_array_size_error)
1476 if (eps < epsilon(eps))
then
1477 call errmgr%report_error(
"csr_pgmres_solver", &
1478 "The convergence tolerance is too small.", la_invalid_input_error)
1482 call errmgr%report_error(
"csr_pgmres_solver", &
1483 "Too few iterations allowed.", la_invalid_input_error)
1486 if (krylov < 1)
then
1487 call errmgr%report_error(
"csr_pgmres_solver", &
1488 "The requested Krylov subspace size is too small.", &
1489 la_invalid_input_error)
1494 allocate(vv(n,krylov+1), stat = flag)
1496 call errmgr%report_error(
"csr_pgmres_solver", &
1497 "Memory allocation error.", la_out_of_memory_error)
1502 call pgmres(n, krylov, b, x, vv, eps, mit, io, a%values, a%column_indices, &
1503 a%row_indices, lu%values, lu%indices, ju, ierr)
1505 call errmgr%report_error(
"csr_pgmres_solver", &
1506 "Convergence could not be achieved to the requested tolerance " // &
1507 "in the allowed number of iterations.", la_convergence_error)
Computes the matrix product: C = A * B.
Computes the matrix sum: C = A + B, where the matrices are given in CSR format.
Computes the matrix sum: C = A + s * B, where the matrices are given in CSR format.
Converts the LINPACK, BLAS, LAPACK banded matrix format into a CSR format.
Converte a matrix stored in coordinate format to CSR format.
Sorces the elements of a CSR matrix in increasing order of their column indices within each row.
Converts a CSR matrix into a CSC matrix (transposition).
Converts a CSR matrix to an MSR matrix.
Extracts the diagonal from a matrix.
Gets element A(i,j) of matrix A for any pair (i,j).
Computes the incomplete LU factorization of a sparse matrix in CSR format using a dual truncation mec...
Solves the LU-factored system (LU) x = y.
Converts and MSR matrix to a CSR matrix.
An ILUT preconditioned GMRES algorithm. This routine utilizes the L and U matrices generated by the I...
A module providing explicit interfaces to BLAS routines.
Provides a set of common linear algebra routines.
An interface to the SPARSKIT library available at https://www-users.cse.umn.edu/~saad/software/SPARSK...