linalg 1.8.2
A linear algebra library that provides a user-friendly interface to several BLAS and LAPACK routines.
Loading...
Searching...
No Matches
linalg_sparse.f90
1submodule(linalg) linalg_sparse
2 use sparskit
3 use blas
4 implicit none
5contains
6! ******************************************************************************
7! CSR ROUTINES
8! ------------------------------------------------------------------------------
9module function csr_get_element(this, i, j) result(rst)
10 ! Arguments
11 class(csr_matrix), intent(in) :: this
12 integer(int32), intent(in) :: i, j
13 real(real64) :: rst
14
15 ! Local Variables
16 integer(int32) :: iadd
17 logical :: sorted
18
19 ! Initialization
20 sorted = .false.
21
22 ! Process
23 if (.not.allocated(this%row_indices) .or. &
24 .not.allocated(this%column_indices) .or. &
25 .not.allocated(this%values)) &
26 then
27 rst = 0.0d0
28 return
29 end if
30 rst = getelm(i, j, this%values, this%column_indices, this%row_indices, &
31 iadd, sorted)
32end function
33
34! ------------------------------------------------------------------------------
35pure module function csr_size(x, dim) result(rst)
36 ! Arguments
37 class(csr_matrix), intent(in) :: x
38 integer(int32), intent(in) :: dim
39 integer(int32) :: rst
40
41 ! Process
42 select case (dim)
43 case (1)
44 if (allocated(x%row_indices)) then
45 rst = size(x%row_indices) - 1
46 else
47 rst = 0
48 end if
49 case (2)
50 rst = x%n
51 case default
52 rst = 0
53 end select
54end function
55
56! ------------------------------------------------------------------------------
57pure module function nonzero_count_csr(x) result(rst)
58 ! Arguments
59 class(csr_matrix), intent(in) :: x
60 integer(int32) :: rst
61
62 ! Process
63 if (allocated(x%values)) then
64 rst = size(x%values)
65 else
66 rst = 0
67 end if
68end function
69
70! ------------------------------------------------------------------------------
71module function create_empty_csr_matrix(m, n, nnz, err) result(rst)
72 ! Arguments
73 integer(int32), intent(in) :: m, n, nnz
74 class(errors), intent(inout), optional, target :: err
75 type(csr_matrix) :: rst
76
77 ! Local Variables
78 integer(int32) :: flag, m1
79 class(errors), pointer :: errmgr
80 type(errors), target :: deferr
81
82 ! Initialization
83 if (present(err)) then
84 errmgr => err
85 else
86 errmgr => deferr
87 end if
88 m1 = m + 1
89
90 ! Input Checking
91 if (m < 0) 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)
95 return
96 end if
97 if (n < 0) then
98 call errmgr%report_error("create_empty_csr_matrix", &
99 "The number of columns must be a positive value.", &
100 la_invalid_input_error)
101 return
102 end if
103 if (nnz < 0) then
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)
107 return
108 end if
109
110 ! Allocation
111 rst%n = n
112 allocate(rst%row_indices(m1), rst%column_indices(nnz), source = 0, &
113 stat = flag)
114 if (flag == 0) allocate(rst%values(nnz), source = 0.0d0, stat = flag)
115 if (flag /= 0) then
116 call errmgr%report_error("create_empty_csr_matrix", &
117 "Memory allocation error.", la_out_of_memory_error)
118 return
119 end if
120end function
121
122! ------------------------------------------------------------------------------
123module function dense_to_csr(a, err) result(rst)
124 ! Arguments
125 real(real64), intent(in), dimension(:,:) :: a
126 class(errors), intent(inout), optional, target :: err
127 type(csr_matrix) :: rst
128
129 ! Local Variables
130 integer(int32) :: i, j, k, m, n, nnz
131 real(real64) :: t
132 class(errors), pointer :: errmgr
133 type(errors), target :: deferr
134
135 ! Initialization
136 if (present(err)) then
137 errmgr => err
138 else
139 errmgr => deferr
140 end if
141 t = 2.0d0 * epsilon(t)
142 m = size(a, 1)
143 n = size(a, 2)
144 nnz = 0
145
146 ! Determine how many non-zero values exist
147 do j = 1, n
148 do i = 1, m
149 if (abs(a(i,j)) > t) then
150 nnz = nnz + 1
151 end if
152 end do
153 end do
154
155 ! Memory Allocation
156 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
157 if (errmgr%has_error_occurred()) return
158
159 ! Store the non-zero values
160 k = 1
161 rst%row_indices(1) = 1
162 do i = 1, m
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)
167 k = k + 1
168 end do inner_loop
169 rst%row_indices(i+1) = k
170 end do
171end function
172
173! ------------------------------------------------------------------------------
174module function banded_to_csr(m, ml, mu, a, err) result(rst)
175 ! Arguments
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
180
181 ! Local Variables
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
187
188 ! Initialization
189 if (present(err)) then
190 errmgr => err
191 else
192 errmgr => deferr
193 end if
194 lda = size(a, 1)
195 n = size(a, 2)
196 nnz = lda * n
197 lowd = ml + mu + 1
198
199 ! Input Checking
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)
203 return
204 end if
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)
209 return
210 end if
211
212 ! Allocation
213 allocate(ia(m + 1), ja(nnz), v(nnz), stat = flag)
214 if (flag /= 0) go to 10
215
216 ! Process
217 call bndcsr(m, a, lda, lowd, ml, mu, v, ja, ia, nnz, flag)
218 nnz = ia(m + 1) - 1
219
220 ! Put into the sparse matrix structure
221 allocate(rst%row_indices(m + 1), source = ia, stat = flag)
222 if (flag == 0) allocate(rst%column_indices(nnz), source = ja(:nnz), &
223 stat = flag)
224 if (flag == 0) allocate(rst%values(nnz), source = v(:nnz), stat = flag)
225 if (flag /= 0) go to 10
226 rst%n = n
227
228 ! End
229 return
230
231 ! Memory Error
23210 continue
233 call errmgr%report_error("banded_to_csr", "Memory allocation error.", &
234 la_out_of_memory_error)
235 return
236end function
237
238! ------------------------------------------------------------------------------
239module subroutine csr_to_dense(a, x, err)
240 ! Arguments
241 class(csr_matrix), intent(in) :: a
242 real(real64), intent(out), dimension(:,:) :: x
243 class(errors), intent(inout), optional, target :: err
244
245 ! Local Variables
246 integer(int32) :: i, j, k, m, n, nnz, flag
247 class(errors), pointer :: errmgr
248 type(errors), target :: deferr
249
250 ! Initialization
251 if (present(err)) then
252 errmgr => err
253 else
254 errmgr => deferr
255 end if
256 m = size(a, 1)
257 n = size(a, 2)
258 nnz = nonzero_count(a)
259
260 ! Input Check
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.", &
264 la_array_size_error)
265 return
266 end if
267
268 ! Process
269 do i = 1, m
270 x(i,:) = 0.0d0
271 do k = a%row_indices(i), a%row_indices(i+1) - 1
272 j = a%column_indices(k)
273 x(i,j) = a%values(k)
274 end do
275 end do
276end subroutine
277
278! ------------------------------------------------------------------------------
279module function diag_to_csr(a, err) result(rst)
280 ! Arguments
281 real(real64), intent(in), dimension(:) :: a
282 class(errors), intent(inout), optional, target :: err
283 type(csr_matrix) :: rst
284
285 ! Local Variables
286 integer(int32) :: i, n, n1, flag
287 class(errors), pointer :: errmgr
288 type(errors), target :: deferr
289
290 ! Initialization
291 if (present(err)) then
292 errmgr => err
293 else
294 errmgr => deferr
295 end if
296 n = size(a)
297 n1 = n + 1
298
299 ! Allocation
300 allocate(rst%row_indices(n1), rst%column_indices(n), stat = flag)
301 if (flag == 0) allocate(rst%values(n), source = a, stat = flag)
302 if (flag /= 0) then
303 call errmgr%report_error("diag_to_csr", "Memory allocation error.", &
304 la_out_of_memory_error)
305 return
306 end if
307 rst%n = n
308
309 ! Populate IA & JA
310 do i = 1, n
311 rst%column_indices(i) = i
312 rst%row_indices(i) = i
313 end do
314 rst%row_indices(n1) = n1
315end function
316
317! ------------------------------------------------------------------------------
318module subroutine csr_assign_to_dense(dense, sparse)
319 ! Arguments
320 real(real64), intent(out), dimension(:,:) :: dense
321 class(csr_matrix), intent(in) :: sparse
322
323 ! Process
324 call csr_to_dense(sparse, dense)
325end subroutine
326
327! ------------------------------------------------------------------------------
328module subroutine dense_assign_to_csr(sparse, dense)
329 ! Arguments
330 type(csr_matrix), intent(out) :: sparse
331 real(real64), intent(in), dimension(:,:) :: dense
332
333 ! Process
334 sparse = dense_to_csr(dense)
335end subroutine
336
337! ------------------------------------------------------------------------------
338module function csr_mtx_mtx_mult(a, b) result(rst)
339 ! Arguments
340 class(csr_matrix), intent(in) :: a, b
341 type(csr_matrix) :: rst
342
343 ! Local Variables
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
350
351 ! Initialization
352 m = size(a, 1)
353 n = size(b, 2)
354 k = size(a, 2)
355 nnza = nonzero_count(a)
356 nnzb = nonzero_count(b)
357 nnzc = nnza + nnzb
358
359 ! Input Check
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)
363 return
364 end if
365
366 ! Local Memory Allocations
367 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
368 if (flag /= 0) go to 10
369
370 ! Determine the structure of C
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, &
373 nnzc, iw, ierr)
374 if (ierr /= 0) then
375 ! NNZC was too small - try increasing it
376 do while (ierr /= 0)
377 deallocate(jc)
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)
384 end do
385 end if
386
387 ! Determine the actual NNZ for C & allocate space for the output
388 nnzc = ic(m + 1) - 1
389 deallocate(ic)
390 deallocate(jc)
391 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
392 if (errmgr%has_error_occurred()) return
393
394 ! Compute the actual product
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)
398
399 ! End
400 return
401
402 ! Memory Error
40310 continue
404 call errmgr%report_error("csr_mtx_mtx_mult", &
405 "Memory allocation error.", la_out_of_memory_error)
406 return
407end function
408
409! ------------------------------------------------------------------------------
410module function csr_mtx_vec_mult(a, b) result(rst)
411 ! Arguments
412 class(csr_matrix), intent(in) :: a
413 real(real64), intent(in), dimension(:) :: b
414 real(real64), allocatable, dimension(:) :: rst
415
416 ! Local Variables
417 integer(int32) :: i, k, k1, k2, n, p, flag
418 real(real64) :: t
419 type(errors) :: errmgr
420
421 ! Initialization
422 n = size(a, 1)
423 p = size(a, 2)
424
425 ! Input Check
426 if (size(b) /= p) then
427 call errmgr%report_error("csr_mtx_vec_mult", &
428 "Inner matrix dimension error.", la_array_size_error)
429 return
430 end if
431
432 ! Memory Allocation
433 allocate(rst(n), stat = flag)
434 if (flag /= 0) then
435 call errmgr%report_error("csr_mtx_vec_mult", &
436 "Memory allocation error.", la_out_of_memory_error)
437 return
438 end if
439
440 ! Process
441 do i = 1, n
442 t = 0.0d0
443 k1 = a%row_indices(i)
444 k2 = a%row_indices(i+1) - 1
445 do k = k1, k2
446 t = t + a%values(k) * b(a%column_indices(k))
447 end do
448 rst(i) = t
449 end do
450end function
451
452! ------------------------------------------------------------------------------
453module function csr_mtx_add(a, b) result(rst)
454 ! Arguments
455 class(csr_matrix), intent(in) :: a, b
456 type(csr_matrix) :: rst
457
458 ! Local Variables
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
465
466 ! Initialization
467 m = size(a, 1)
468 n = size(a, 2)
469 nnza = nonzero_count(a)
470 nnzb = nonzero_count(b)
471 nnzc = nnza + nnzb
472
473 ! Input Checking
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)
477 return
478 end if
479
480 ! Local Memory Allocations
481 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
482 if (flag /= 0) go to 10
483
484 ! Determine the structure of C
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, &
487 nnzc, iw, ierr)
488 if (ierr /= 0) then
489 ! NNZC was too small - try increasing it
490 do while (ierr /= 0)
491 deallocate(jc)
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)
498 end do
499 end if
500
501 ! Determine the actuall NNZ for C & allocate space for the output
502 nnzc = ic(m + 1) - 1
503 deallocate(ic)
504 deallocate(jc)
505 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
506 if (errmgr%has_error_occurred()) return
507
508 ! Compute the actual sum
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)
512
513 ! End
514 return
515
516 ! Memory Error
51710 continue
518 call errmgr%report_error("csr_mtx_add", "Memory allocation error.", &
519 la_out_of_memory_error)
520 return
521end function
522
523! ------------------------------------------------------------------------------
524module function csr_mtx_sub(a, b) result(rst)
525 ! Arguments
526 class(csr_matrix), intent(in) :: a, b
527 type(csr_matrix) :: rst
528
529 ! Local Variables
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
535
536 ! Initialization
537 m = size(a, 1)
538 n = size(a, 2)
539 nnza = nonzero_count(a)
540 nnzb = nonzero_count(b)
541 nnzc = nnza + nnzb
542
543 ! Input Checking
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)
547 return
548 end if
549
550 ! Local Memory Allocations
551 allocate(ic(m + 1), jc(nnzc), iw(n), stat = flag)
552 if (flag /= 0) go to 10
553
554 ! Determine the structure of C
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, &
557 nnzc, iw, ierr)
558 if (ierr /= 0) then
559 ! NNZC was too small - try increasing it
560 do while (ierr /= 0)
561 deallocate(jc)
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)
568 end do
569 end if
570
571 ! Determine the actuall NNZ for C & allocate space for the output
572 nnzc = ic(m + 1) - 1
573 deallocate(ic)
574 deallocate(jc)
575 rst = create_empty_csr_matrix(m, n, nnzc, errmgr)
576 if (errmgr%has_error_occurred()) return
577
578 ! Compute the actual sum
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)
582
583 ! End
584 return
585
586 ! Memory Error
58710 continue
588 call errmgr%report_error("csr_mtx_sub", "Memory allocation error.", &
589 la_out_of_memory_error)
590 return
591end function
592
593! ------------------------------------------------------------------------------
594module function csr_mtx_mult_scalar_1(a, b) result(rst)
595 ! Arguments
596 class(csr_matrix), intent(in) :: a
597 real(real64), intent(in) :: b
598 type(csr_matrix) :: rst
599
600 ! Local Variables
601 integer(int32) :: m, n, nnz
602 type(errors) :: errmgr
603
604 ! Initialization
605 m = size(a, 1)
606 n = size(a, 2)
607 nnz = nonzero_count(a)
608
609 ! Process
610 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
611 if (errmgr%has_error_occurred()) return
612
613 ! Compute the product
614 rst%row_indices = a%row_indices
615 rst%column_indices = a%column_indices
616 rst%values = b * a%values
617end function
618
619! ------------------------------------------------------------------------------
620module function csr_mtx_mult_scalar_2(a, b) result(rst)
621 ! Arguments
622 real(real64), intent(in) :: a
623 class(csr_matrix), intent(in) :: b
624 type(csr_matrix) :: rst
625
626 ! Local Variables
627 integer(int32) :: m, n, nnz
628 type(errors) :: errmgr
629
630 ! Initialization
631 m = size(b, 1)
632 n = size(b, 2)
633 nnz = nonzero_count(b)
634
635 ! Process
636 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
637 if (errmgr%has_error_occurred()) return
638
639 ! Compute the product
640 rst%row_indices = b%row_indices
641 rst%column_indices = b%column_indices
642 rst%values = a * b%values
643end function
644
645! ------------------------------------------------------------------------------
646module function csr_mtx_divide_scalar_1(a, b) result(rst)
647 ! Arguments
648 class(csr_matrix), intent(in) :: a
649 real(real64), intent(in) :: b
650 type(csr_matrix) :: rst
651
652 ! Local Variables
653 integer(int32) :: m, n, nnz
654 type(errors) :: errmgr
655
656 ! Initialization
657 m = size(a, 1)
658 n = size(a, 2)
659 nnz = nonzero_count(a)
660
661 ! Process
662 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
663 if (errmgr%has_error_occurred()) return
664
665 ! Compute the product
666 rst%row_indices = a%row_indices
667 rst%column_indices = a%column_indices
668 rst%values = a%values / b
669end function
670
671! ------------------------------------------------------------------------------
672module function csr_transpose(a) result(rst)
673 ! Arguments
674 class(csr_matrix), intent(in) :: a
675 type(csr_matrix) :: rst
676
677 ! Local Variables
678 integer(int32) :: m, n, nnz
679 type(errors) :: errmgr
680
681 ! Initialization
682 m = size(a, 1)
683 n = size(a, 2)
684 nnz = nonzero_count(a)
685 rst = create_empty_csr_matrix(n, m, nnz, errmgr)
686 if (errmgr%has_error_occurred()) return
687
688 ! Process
689 call csrcsc2(m, n, 1, 1, a%values, a%column_indices, a%row_indices, &
690 rst%values, rst%column_indices, rst%row_indices)
691end function
692
693! ------------------------------------------------------------------------------
694module subroutine extract_diagonal_csr(a, diag, err)
695 ! Arguments
696 class(csr_matrix), intent(in) :: a
697 real(real64), intent(out), dimension(:) :: diag
698 class(errors), intent(inout), optional, target :: err
699
700 ! Local Variables
701 integer(int32) :: m, n, mn, len, flag
702 integer(int32), allocatable, dimension(:) :: idiag
703 class(errors), pointer :: errmgr
704 type(errors), target :: deferr
705
706 ! Initialization
707 if (present(err)) then
708 errmgr => err
709 else
710 errmgr => deferr
711 end if
712 m = size(a, 1)
713 n = size(a, 2)
714 mn = min(m, n)
715
716 ! Input Check
717 if (size(diag) /= mn) then
718 call errmgr%report_error("extract_diagonal_csr", &
719 "The is expected to have MIN(M, N) elements.", &
720 la_array_size_error)
721 return
722 end if
723
724 ! Memory Allocation
725 allocate(idiag(mn), stat = flag)
726 if (flag /= 0) then
727 call errmgr%report_error("extract_diagonal_csr", &
728 "Memory allocation error.", la_out_of_memory_error)
729 return
730 end if
731
732 ! Process
733 call getdia(m, n, 0, a%values, a%column_indices, a%row_indices, len, &
734 diag, idiag, 0)
735end subroutine
736
737! ------------------------------------------------------------------------------
738module subroutine csr_solve_sparse_direct(a, b, x, droptol, err)
739 ! Arguments
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
745
746 ! Local Variables
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
750 real(real64) :: dt
751 class(errors), pointer :: errmgr
752 type(errors), target :: deferr
753
754 ! Initialization
755 if (present(err)) then
756 errmgr => err
757 else
758 errmgr => deferr
759 end if
760 if (present(droptol)) then
761 dt = droptol
762 else
763 dt = sqrt(epsilon(dt))
764 end if
765 m = size(a, 1)
766 n = size(a, 2)
767 nnz = nonzero_count(a)
768
769 ! Input Checking
770 if (m /= n) then
771 call errmgr%report_error("csr_solve_sparse_direct", &
772 "The matrix must be square.", la_array_size_error)
773 return
774 end if
775 if (size(x) /= n) then
776 call errmgr%report_error("csr_solve_sparse_direct", &
777 "Inner matrix dimension mismatch.", la_array_size_error)
778 return
779 end if
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.", &
783 la_array_size_error)
784 return
785 end if
786
787 ! Parameter Determination
788 lfil = 1
789 do i = 1, m
790 lfil = max(lfil, a%row_indices(i+1) - a%row_indices(i))
791 end do
792 iwk = max(lfil * m, nnz) ! somewhat arbitrary - can be adjusted
793
794 ! Local Memory Allocation
795 allocate(alu(iwk), w(n+1), jlu(iwk), ju(n), jw(2 * n), stat = flag)
796 if (flag /= 0) go to 10
797
798 ! Factorization
799 do
800 ! Factor the matrix
801 call ilut(n, a%values, a%column_indices, a%row_indices, lfil, dt, &
802 alu, jlu, ju, iwk, w, jw, ierr)
803
804 ! Check the error flag
805 if (ierr == 0) then
806 ! Success
807 exit
808 else if (ierr > 0) then
809 ! Zero pivot
810 else if (ierr == -1) then
811 ! The input matrix is not formatted correctly
812 go to 20
813 else if (ierr == -2 .or. ierr == -3) then
814 ! ALU and JLU are too small - try something larger
815 iwk = min(iwk + m + n, m * n)
816 deallocate(alu)
817 deallocate(jlu)
818 allocate(alu(iwk), jlu(iwk), stat = flag)
819 if (flag /= 0) go to 10
820 else if (ierr == -4) then
821 ! Illegal value for LFIL - reset and try again
822 lfil = n
823 else if (ierr == -5) then
824 ! Zero row encountered
825 go to 30
826 else
827 ! We should never get here, but just in case
828 go to 40
829 end if
830 end do
831
832 ! Solution
833 call lusol(n, b, x, alu, jlu, ju)
834
835 ! End
836 return
837
838 ! Memory Error
83910 continue
840 call errmgr%report_error("csr_solve_sparse_direct", &
841 "Memory allocation error.", la_out_of_memory_error)
842 return
843
844 ! Matrix Format Error
84520 continue
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)
849 return
850
851 ! Zero Row Error
85230 continue
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)
856 return
857
858 ! Unknown Error
85940 continue
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)
863 return
864
865 ! Zero Pivot Error
86650 continue
867 call errmgr%report_error("csr_solve_sparse_direct", &
868 "A zero pivot was encountered.", la_singular_matrix_error)
869 return
870end subroutine
871
872! ******************************************************************************
873! MSR ROUTINES
874! ------------------------------------------------------------------------------
875! TO DO: MSR_GET_ELEMENT
876
877! ------------------------------------------------------------------------------
878pure module function msr_size(x, dim) result(rst)
879 ! Arguments
880 class(msr_matrix), intent(in) :: x
881 integer(int32), intent(in) :: dim
882 integer(int32) :: rst
883
884 ! Process
885 select case (dim)
886 case (1)
887 rst = x%m
888 case (2)
889 rst = x%n
890 case default
891 rst = 0
892 end select
893end function
894
895! ------------------------------------------------------------------------------
896pure module function nonzero_count_msr(x) result(rst)
897 ! Arguments
898 class(msr_matrix), intent(in) :: x
899 integer(int32) :: rst
900
901 ! Process
902 rst = x%nnz
903end function
904
905! ------------------------------------------------------------------------------
906module function create_empty_msr_matrix(m, n, nnz, err) result(rst)
907 ! Arguments
908 integer(int32), intent(in) :: m, n, nnz
909 class(errors), intent(inout), optional, target :: err
910 type(msr_matrix) :: rst
911
912 ! Local Variables
913 integer(int32) :: nelem, mn, flag
914 class(errors), pointer :: errmgr
915 type(errors), target :: deferr
916
917 ! Initialization
918 if (present(err)) then
919 errmgr => err
920 else
921 errmgr => deferr
922 end if
923
924 ! Input Checking
925 if (m < 0) 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)
929 return
930 end if
931 if (n < 0) then
932 call errmgr%report_error("create_empty_msr_matrix", &
933 "The number of columns must be a positive value.", &
934 la_invalid_input_error)
935 return
936 end if
937 if (nnz < 0) then
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)
941 return
942 end if
943
944 ! Allocation
945 rst%m = m
946 rst%n = n
947 rst%nnz = nnz
948 mn = min(m, n)
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)
952 if (flag /= 0) then
953 call errmgr%report_error("create_empty_msr_matrix", &
954 "Memory allocation error.", la_out_of_memory_error)
955 return
956 end if
957end function
958
959! ------------------------------------------------------------------------------
960module function csr_to_msr(a, err) result(rst)
961 ! Arguments
962 class(csr_matrix), intent(in) :: a
963 class(errors), intent(inout), optional, target :: err
964 type(msr_matrix) :: rst
965
966 ! Local Variables
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
972
973 ! Initialization
974 if (present(err)) then
975 errmgr => err
976 else
977 errmgr => deferr
978 end if
979 m = size(a, 1)
980 n = size(a, 2)
981 nnz = nonzero_count(a)
982
983 ! Memory Allocation
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)
990 if (flag /= 0) then
991 call errmgr%report_error("csr_to_msr", "Memory allocation error.", &
992 la_out_of_memory_error)
993 return
994 end if
995
996 ! Perform the conversion
997 call csrmsr(m, ac, jc, ic, rst%values, rst%indices, work, iwork)
998end function
999
1000! ------------------------------------------------------------------------------
1001module function msr_to_csr(a, err) result(rst)
1002 ! Arguments
1003 class(msr_matrix), intent(in) :: a
1004 class(errors), intent(inout), optional, target :: err
1005 type(csr_matrix) :: rst
1006
1007 ! Local Variables
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
1013
1014 ! Initialization
1015 if (present(err)) then
1016 errmgr => err
1017 else
1018 errmgr => deferr
1019 end if
1020 m = size(a, 1)
1021 n = size(a, 2)
1022 nnz = nonzero_count(a)
1023
1024 ! Memory Allocation
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)
1028 if (flag /= 0) then
1029 call errmgr%report_error("msr_to_csr", "Memory allocation error.", &
1030 la_out_of_memory_error)
1031 return
1032 end if
1033
1034 ! Process
1035 call msrcsr(m, a%values, a%indices, rst%values, rst%column_indices, &
1036 rst%row_indices, work, iwork)
1037end function
1038
1039! ------------------------------------------------------------------------------
1040module function dense_to_msr(a, err) result(rst)
1041 ! Arguments
1042 real(real64), intent(in), dimension(:,:) :: a
1043 class(errors), intent(inout), optional, target :: err
1044 type(msr_matrix) :: rst
1045
1046 ! Local Variables
1047 type(csr_matrix) :: csr
1048 class(errors), pointer :: errmgr
1049 type(errors), target :: deferr
1050
1051 ! Initialization
1052 if (present(err)) then
1053 errmgr => err
1054 else
1055 errmgr => deferr
1056 end if
1057
1058 ! Convert to CSR, and then from CSR to MSR
1059 csr = dense_to_csr(a, errmgr)
1060
1061 ! Convert to MSR
1062 rst = csr_to_msr(csr, errmgr)
1063end function
1064
1065! ------------------------------------------------------------------------------
1066module subroutine msr_to_dense(a, x, err)
1067 ! Arguments
1068 class(msr_matrix), intent(in) :: a
1069 real(real64), intent(out), dimension(:,:) :: x
1070 class(errors), intent(inout), optional, target :: err
1071
1072 ! Local Variables
1073 integer(int32) :: m, n, flag
1074 type(csr_matrix) :: csr
1075 class(errors), pointer :: errmgr
1076 type(errors), target :: deferr
1077
1078 ! Initialization
1079 if (present(err)) then
1080 errmgr => err
1081 else
1082 errmgr => deferr
1083 end if
1084 m = size(a, 1)
1085 n = size(a, 2)
1086
1087 ! Input Check
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)
1092 return
1093 end if
1094
1095 ! Process
1096 csr = msr_to_csr(a, errmgr)
1097 if (errmgr%has_error_occurred()) return
1098 call csr_to_dense(csr, x, errmgr)
1099end subroutine
1100
1101! ------------------------------------------------------------------------------
1102module subroutine msr_assign_to_dense(dense, msr)
1103 ! Arguments
1104 real(real64), intent(out), dimension(:,:) :: dense
1105 class(msr_matrix), intent(in) :: msr
1106
1107 ! Process
1108 call msr_to_dense(msr, dense)
1109end subroutine
1110
1111! ------------------------------------------------------------------------------
1112module subroutine dense_assign_to_msr(msr, dense)
1113 ! Arguments
1114 type(msr_matrix), intent(out) :: msr
1115 real(real64), intent(in), dimension(:,:) :: dense
1116
1117 ! Process
1118 msr = dense_to_msr(dense)
1119end subroutine
1120
1121! ------------------------------------------------------------------------------
1122module subroutine csr_assign_to_msr(msr, csr)
1123 ! Arguments
1124 type(msr_matrix), intent(out) :: msr
1125 class(csr_matrix), intent(in) :: csr
1126
1127 ! Process
1128 msr = csr_to_msr(csr)
1129end subroutine
1130
1131! ------------------------------------------------------------------------------
1132module subroutine msr_assign_to_csr(csr, msr)
1133 ! Arguments
1134 type(csr_matrix), intent(out) :: csr
1135 class(msr_matrix), intent(in) :: msr
1136
1137 ! Process
1138 csr = msr_to_csr(msr)
1139end subroutine
1140
1141! ------------------------------------------------------------------------------
1142module function create_csr_matrix(m, n, rows, cols, vals, err) result(rst)
1143 ! Arguments
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
1149
1150 ! Local Variables
1151 integer(int32) :: i, flag, nnz
1152 integer(int32), allocatable, dimension(:) :: ir
1153 class(errors), pointer :: errmgr
1154 type(errors), target :: deferr
1155
1156 ! Initialization
1157 if (present(err)) then
1158 errmgr => err
1159 else
1160 errmgr => deferr
1161 end if
1162 nnz = size(rows)
1163
1164 ! Input Checking
1165 if (m < 0) then
1166 call errmgr%report_error("create_csr_matrix", &
1167 "The number of rows must be a positive value.", &
1168 la_invalid_input_error)
1169 return
1170 end if
1171 if (n < 0) then
1172 call errmgr%report_error("create_csr_matrix", &
1173 "The number of columns must be a positive value.", &
1174 la_invalid_input_error)
1175 return
1176 end if
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)
1181 return
1182 end if
1183 do i = 1, nnz
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)
1188 return
1189 end if
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)
1194 return
1195 end if
1196 end do
1197 allocate(ir(nnz), source = rows, stat = flag)
1198 if (flag /= 0) then
1199 call errmgr%report_error("create_csr_matrix", &
1200 "Memory allocation error.", la_out_of_memory_error)
1201 return
1202 end if
1203
1204 ! Create an empty matrix
1205 rst = create_empty_csr_matrix(m, n, nnz, errmgr)
1206 if (errmgr%has_error_occurred()) return
1207
1208 ! Populate the empty matrix
1209 call coocsr(m, nnz, vals, ir, cols, rst%values, rst%column_indices, &
1210 rst%row_indices)
1211 call csort(m, rst%values, rst%column_indices, rst%row_indices, .true.)
1212end function
1213
1214! ******************************************************************************
1215! LU PRECONDITIONER ROUTINES
1216! ------------------------------------------------------------------------------
1217module subroutine csr_lu_factor(a, lu, ju, droptol, err)
1218 ! Arguments
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
1224
1225 ! Local Variables
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
1229 real(real64) :: dt
1230 class(errors), pointer :: errmgr
1231 type(errors), target :: deferr
1232
1233 ! Initialization
1234 if (present(err)) then
1235 errmgr => err
1236 else
1237 errmgr => deferr
1238 end if
1239 if (present(droptol)) then
1240 dt = droptol
1241 else
1242 dt = sqrt(epsilon(dt))
1243 end if
1244 m = size(a, 1)
1245 n = size(a, 2)
1246 nnz = nonzero_count(a)
1247
1248 ! Input Check
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)
1252 return
1253 end if
1254
1255 ! Parameter Determination
1256 lfil = 1
1257 do i = 1, m
1258 lfil = max(lfil, a%row_indices(i+1) - a%row_indices(i))
1259 end do
1260 iwk = max(lfil * m, nnz) ! somewhat arbitrary - can be adjusted
1261
1262 ! Local Memory Allocation
1263 allocate(alu(iwk), w(n+1), jlu(iwk), jw(2 * n), stat = flag)
1264 if (flag /= 0) go to 10
1265
1266 ! Factorization
1267 do
1268 ! Factor the matrix
1269 call ilut(n, a%values, a%column_indices, a%row_indices, lfil, dt, &
1270 alu, jlu, ju, iwk, w, jw, ierr)
1271
1272 ! Check the error flag
1273 if (ierr == 0) then
1274 ! Success
1275 exit
1276 else if (ierr > 0) then
1277 ! Zero pivot
1278 else if (ierr == -1) then
1279 ! The input matrix is not formatted correctly
1280 go to 20
1281 else if (ierr == -2 .or. ierr == -3) then
1282 ! ALU and JLU are too small - try something larger
1283 ! This is the main reason for the loop - to offload worrying about
1284 ! workspace size from the user
1285 iwk = min(iwk + m + n, m * n)
1286 deallocate(alu)
1287 deallocate(jlu)
1288 allocate(alu(iwk), jlu(iwk), stat = flag)
1289 if (flag /= 0) go to 10
1290 else if (ierr == -4) then
1291 ! Illegal value for LFIL - reset and try again
1292 lfil = n
1293 else if (ierr == -5) then
1294 ! Zero row encountered
1295 go to 30
1296 else
1297 ! We should never get here, but just in case
1298 go to 40
1299 end if
1300 end do
1301
1302 ! Determine the actual number of non-zero elements
1303 nnz = jlu(m+1) - 1
1304
1305 ! Copy the contents to the output arrays
1306 lu%m = m
1307 lu%n = n
1308 lu%nnz = nnz
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)
1313
1314 ! End
1315 return
1316
1317 ! Memory Error
131810 continue
1319 call errmgr%report_error("csr_lu_factor", &
1320 "Memory allocation error.", la_out_of_memory_error)
1321 return
1322
1323 ! Matrix Format Error
132420 continue
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)
1328 return
1329
1330 ! Zero Row Error
133130 continue
1332 call errmgr%report_error("csr_lu_factor", &
1333 "A row with all zeros was encountered in the matrix.", &
1334 la_singular_matrix_error)
1335 return
1336
1337 ! Unknown Error
133840 continue
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)
1342 return
1343
1344 ! Zero Pivot Error
134550 continue
1346 call errmgr%report_error("csr_lu_factor", &
1347 "A zero pivot was encountered.", la_singular_matrix_error)
1348 return
1349end subroutine
1350
1351! ------------------------------------------------------------------------------
1352module subroutine csr_lu_solve(lu, ju, b, x, err)
1353 ! Arguments
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
1359
1360 ! Local Variables
1361 integer(int32) :: m, n
1362 class(errors), pointer :: errmgr
1363 type(errors), target :: deferr
1364
1365 ! Initialization
1366 if (present(err)) then
1367 errmgr => err
1368 else
1369 errmgr => deferr
1370 end if
1371 m = size(lu, 1)
1372 n = size(lu, 2)
1373
1374 ! Input Check
1375 if (m /= n) then
1376 call errmgr%report_error("csr_lu_solve", &
1377 "The input matrix is expected to be square.", la_array_size_error)
1378 return
1379 end if
1380 if (size(x) /= m) then
1381 call errmgr%report_error("csr_lu_solve", &
1382 "Inner matrix dimension mismatch.", la_array_size_error)
1383 return
1384 end if
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)
1389 return
1390 end if
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)
1395 return
1396 end if
1397
1398 ! Process
1399 call lusol(m, b, x, lu%values, lu%indices, ju)
1400end subroutine
1401
1402! ******************************************************************************
1403! ITERATIVE SOLVERS
1404! ------------------------------------------------------------------------------
1405! Additional References:
1406! - https://www.diva-portal.org/smash/get/diva2:360739/FULLTEXT01.pdf
1407module subroutine csr_pgmres_solver(a, lu, ju, b, x, im, tol, maxits, iout, err)
1408 ! Arguments
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
1417
1418 ! Local Variables
1419 integer(int32) :: n, ierr, flag, io, mit, krylov
1420 real(real64) :: eps
1421 real(real64), allocatable, dimension(:,:) :: vv
1422 class(errors), pointer :: errmgr
1423 type(errors), target :: deferr
1424
1425 ! Initialization
1426 n = size(a, 1)
1427 if (present(err)) then
1428 errmgr => err
1429 else
1430 errmgr => deferr
1431 end if
1432 if (present(im)) then
1433 krylov = im
1434 else
1435 krylov = min(n, 50)
1436 end if
1437 if (present(tol)) then
1438 eps = tol
1439 else
1440 eps = sqrt(epsilon(eps))
1441 end if
1442 if (present(maxits)) then
1443 mit = maxits
1444 else
1445 mit = 100
1446 end if
1447 if (present(iout)) then
1448 io = iout
1449 else
1450 io = 0
1451 end if
1452
1453 ! Input Checking
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)
1457 return
1458 end if
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)
1463 return
1464 end if
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)
1469 return
1470 end if
1471 if (size(x) /= n) then
1472 call errmgr%report_error("csr_pgmres_solver", &
1473 "Inner matrix dimension mismatch.", la_array_size_error)
1474 return
1475 end if
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)
1479 return
1480 end if
1481 if (mit < 1) then
1482 call errmgr%report_error("csr_pgmres_solver", &
1483 "Too few iterations allowed.", la_invalid_input_error)
1484 return
1485 end if
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)
1490 return
1491 end if
1492
1493 ! Memory Allocation
1494 allocate(vv(n,krylov+1), stat = flag)
1495 if (flag /= 0) then
1496 call errmgr%report_error("csr_pgmres_solver", &
1497 "Memory allocation error.", la_out_of_memory_error)
1498 return
1499 end if
1500
1501 ! Process
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)
1504 if (ierr == 1) then
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)
1508 return
1509 end if
1510end subroutine
1511
1512! ------------------------------------------------------------------------------
1513end submodule
Computes the matrix product: C = A * B.
Definition sparskit.f90:31
Computes the matrix sum: C = A + B, where the matrices are given in CSR format.
Definition sparskit.f90:63
Computes the matrix sum: C = A + s * B, where the matrices are given in CSR format.
Definition sparskit.f90:96
Converts the LINPACK, BLAS, LAPACK banded matrix format into a CSR format.
Definition sparskit.f90:150
Converte a matrix stored in coordinate format to CSR format.
Definition sparskit.f90:212
Sorces the elements of a CSR matrix in increasing order of their column indices within each row.
Definition sparskit.f90:273
Converts a CSR matrix into a CSC matrix (transposition).
Definition sparskit.f90:124
Converts a CSR matrix to an MSR matrix.
Definition sparskit.f90:170
Extracts the diagonal from a matrix.
Definition sparskit.f90:256
Gets element A(i,j) of matrix A for any pair (i,j).
Definition sparskit.f90:236
Computes the incomplete LU factorization of a sparse matrix in CSR format using a dual truncation mec...
Definition sparskit.f90:343
Solves the LU-factored system (LU) x = y.
Definition sparskit.f90:559
Converts and MSR matrix to a CSR matrix.
Definition sparskit.f90:191
An ILUT preconditioned GMRES algorithm. This routine utilizes the L and U matrices generated by the I...
Definition sparskit.f90:540
A module providing explicit interfaces to BLAS routines.
Definition blas.f90:2
Provides a set of common linear algebra routines.
Definition linalg.f90:145
An interface to the SPARSKIT library available at https://www-users.cse.umn.edu/~saad/software/SPARSK...
Definition sparskit.f90:3