22 public :: hecmwst_saamg_bcsr
46 type hecmwst_saamg_bcsr
47 integer(kind=kint) :: n = 0
48 integer(kind=kint) :: ncol = 0
49 integer(kind=kint) :: nb = 0
50 integer(kind=kint) :: mb = 0
51 integer(kind=kint) :: nnz = 0
52 integer(kind=kint) :: nbrow = 0
53 integer(kind=kint) :: nbcol = 0
54 integer(kind=kint) :: nnzb = 0
55 integer(kind=kint),
allocatable :: browptr(:)
56 integer(kind=kint),
allocatable :: bcol(:)
57 real(kind=
kreal),
allocatable :: bval(:)
58 end type hecmwst_saamg_bcsr
65 type(hecmwst_saamg_bcsr),
intent(inout) :: a
66 if (
allocated(a%browptr))
deallocate(a%browptr)
67 if (
allocated(a%bcol))
deallocate(a%bcol)
68 if (
allocated(a%bval))
deallocate(a%bval)
69 a%n = 0; a%ncol = 0; a%nb = 0; a%mb = 0; a%nnz = 0
70 a%nbrow = 0; a%nbcol = 0; a%nnzb = 0
76 type(hecmwst_saamg_bcsr),
intent(in) :: a
77 type(hecmwst_saamg_bcsr),
intent(out) :: b
78 integer(kind=kint) :: astat
80 b%n = a%n; b%ncol = a%ncol; b%nb = a%nb; b%mb = a%mb; b%nnz = a%nnz
81 b%nbrow = a%nbrow; b%nbcol = a%nbcol; b%nnzb = a%nnzb
82 if (
allocated(a%browptr))
then
83 allocate(b%browptr(a%nbrow+1), b%bcol(a%nnzb), b%bval(a%nb*a%mb*a%nnzb), stat=astat)
85 b%browptr = a%browptr; b%bcol = a%bcol; b%bval = a%bval
93 type(hecmwst_saamg_bcsr),
intent(inout) :: a
94 type(hecmwst_saamg_bcsr),
intent(out) :: b
96 b%n = a%n; b%ncol = a%ncol; b%nb = a%nb; b%mb = a%mb; b%nnz = a%nnz
97 b%nbrow = a%nbrow; b%nbcol = a%nbcol; b%nnzb = a%nnzb
98 if (
allocated(a%browptr))
call move_alloc(a%browptr, b%browptr)
99 if (
allocated(a%bcol))
call move_alloc(a%bcol, b%bcol)
100 if (
allocated(a%bval))
call move_alloc(a%bval, b%bval)
109 integer(kind=kint),
intent(in) :: n, nb
110 real(kind=
kreal),
intent(in) :: dense(n,n)
111 type(hecmwst_saamg_bcsr),
intent(out) :: a
112 integer(kind=kint),
optional,
intent(in) :: mb
113 real(kind=
kreal),
allocatable :: blk(:)
114 integer(kind=kint) :: mb_, nbrow, nbcol, bs, i, j, ii, jj, kout, rbase, cbase
117 mb_ = nb;
if (
present(mb)) mb_ = mb
119 a%n = n; a%ncol = n; a%nb = nb; a%mb = mb_
120 nbrow = n / nb; nbcol = n / mb_; bs = nb*mb_
121 a%nbrow = nbrow; a%nbcol = nbcol
122 allocate(a%browptr(nbrow+1), blk(bs))
125 a%browptr(1) = 1; a%nnzb = 0
128 if (block_nonzero(i, j)) a%nnzb = a%nnzb + 1
130 a%browptr(i+1) = a%nnzb + 1
132 allocate(a%bcol(a%nnzb), a%bval(bs*a%nnzb)); a%nnz = bs*a%nnzb
139 cbase = (j-1)*mb_; any_nz = .false.
142 blk((jj-1)*nb+ii) = dense(rbase+ii, cbase+jj)
143 if (blk((jj-1)*nb+ii) /= 0.0d0) any_nz = .true.
147 kout = kout + 1; a%bcol(kout) = j
148 a%bval((kout-1)*bs+1:kout*bs) = blk(1:bs)
154 logical function block_nonzero(ib, jb)
result(nz)
155 integer(kind=kint),
intent(in) :: ib, jb
156 integer(kind=kint) :: a, b
160 if (dense((ib-1)*nb+a, (jb-1)*mb_+b) /= 0.0d0) then; nz = .true.; return;
end if
163 end function block_nonzero
169 type(hecmwst_saamg_bcsr),
intent(in) :: a
170 real(kind=
kreal),
intent(in) :: x(:)
171 real(kind=
kreal),
intent(out) :: y(:)
181 type(hecmwst_saamg_comm),
intent(in) :: cmt
182 type(hecmwst_saamg_bcsr),
intent(in) :: a
183 real(kind=
kreal),
intent(inout) :: x(:)
184 real(kind=
kreal),
intent(out) :: y(:)
193 type(hecmwst_saamg_bcsr),
intent(in) :: a
194 real(kind=
kreal) :: rel
195 real(kind=
kreal) :: nrm, dif, aij, aji
196 integer(kind=kint) :: i, j, t, tt, ii, jj, m, boff, foff
200 nrm = 0.0d0; dif = 0.0d0
202 do t = a%browptr(i), a%browptr(i+1)-1
203 j = a%bcol(t); boff = (t-1)*m*m
205 found = .false.; foff = 0
206 do tt = a%browptr(j), a%browptr(j+1)-1
207 if (a%bcol(tt) == i) then; found = .true.; foff = (tt-1)*m*m; exit;
end if
211 aij = a%bval(boff + (jj-1)*m + ii)
214 if (found) aji = a%bval(foff + (ii-1)*m + jj)
215 dif = dif + (aij - aji)**2
220 if (nrm > 0.0d0)
then
221 rel = sqrt(dif) / sqrt(nrm)
233 integer(kind=kint),
intent(in) :: nrow, ncol, nb, nt
234 integer(kind=kint),
intent(in) :: ti(:), tj(:)
235 real(kind=
kreal),
intent(in) :: tv(:)
236 type(hecmwst_saamg_bcsr),
intent(out) :: a
237 integer(kind=kint),
optional,
intent(in) :: mb
238 integer(kind=kint),
allocatable :: rcnt(:), rpos(:), jtmp(:), otmp(:), mark(:), touched(:)
239 real(kind=
kreal),
allocatable :: vtmp(:)
240 integer(kind=kint) :: mb_, nbrow, nbcol, bs, t, i, br, rr, bc, cc, j, p, q, ntouch, kout, blk, astat
242 mb_ = nb;
if (
present(mb)) mb_ = mb
244 a%n = nrow; a%ncol = ncol; a%nb = nb; a%mb = mb_
245 nbrow = nrow / nb; nbcol = ncol / mb_; bs = nb*mb_
246 a%nbrow = nbrow; a%nbcol = nbcol
249 allocate(rcnt(nbrow+1)); rcnt = 0
251 br = (ti(t)-1)/nb + 1; rcnt(br+1) = rcnt(br+1) + 1
254 rcnt(i+1) = rcnt(i+1) + rcnt(i)
256 allocate(jtmp(nt), otmp(nt), vtmp(nt), rpos(nbrow), stat=astat)
262 br = (ti(t)-1)/nb + 1; rr = ti(t) - (br-1)*nb
263 bc = (tj(t)-1)/mb_ + 1; cc = tj(t) - (bc-1)*mb_
264 rpos(br) = rpos(br) + 1
265 jtmp(rpos(br)) = bc; otmp(rpos(br)) = (cc-1)*nb + rr; vtmp(rpos(br)) = tv(t)
269 allocate(mark(nbcol), touched(nbcol)); mark = 0
273 do p = rcnt(i)+1, rcnt(i+1)
274 if (mark(jtmp(p)) == 0)
then
275 ntouch = ntouch + 1; touched(ntouch) = jtmp(p); mark(jtmp(p)) = 1
278 a%nnzb = a%nnzb + ntouch
284 allocate(a%browptr(nbrow+1), a%bcol(a%nnzb), a%bval(bs*a%nnzb), stat=astat)
286 a%bval = 0.0d0; a%browptr(1) = 1; kout = 0
289 do p = rcnt(i)+1, rcnt(i+1)
291 if (mark(j) == 0)
then
292 ntouch = ntouch + 1; touched(ntouch) = j; mark(j) = ntouch
293 kout = kout + 1; a%bcol(kout) = j
295 blk = kout - ntouch + mark(j)
296 a%bval((blk-1)*bs + otmp(p)) = a%bval((blk-1)*bs + otmp(p)) + vtmp(p)
301 a%browptr(i+1) = kout + 1
305 deallocate(rcnt, rpos, jtmp, otmp, vtmp, mark, touched)
314 integer(kind=kint),
intent(in) :: nbrow, nbcol, nb, mb, nt
315 integer(kind=kint),
intent(in) :: bi(:), bj(:)
316 real(kind=
kreal),
intent(in) :: bv(:,:)
317 type(hecmwst_saamg_bcsr),
intent(out) :: a
318 integer(kind=kint),
allocatable :: rcnt(:), rpos(:), btmp(:), mark(:), touched(:)
319 real(kind=
kreal),
allocatable :: vtmp(:,:)
320 integer(kind=kint) :: t, i, j, p, q, r, ntouch, kout, bs, astat
324 a%n = nbrow*nb; a%ncol = nbcol*mb; a%nb = nb; a%mb = mb
325 a%nbrow = nbrow; a%nbcol = nbcol
328 allocate(rcnt(nbrow+1)); rcnt = 0
330 rcnt(bi(t)+1) = rcnt(bi(t)+1) + 1
333 rcnt(i+1) = rcnt(i+1) + rcnt(i)
335 allocate(btmp(nt), vtmp(bs, nt), rpos(nbrow), stat=astat)
342 rpos(i) = rpos(i) + 1
343 btmp(rpos(i)) = bj(t)
344 vtmp(1:bs, rpos(i)) = bv(1:bs, t)
348 allocate(mark(nbcol), touched(nbcol)); mark = 0
352 do p = rcnt(i)+1, rcnt(i+1)
353 if (mark(btmp(p)) == 0)
then
354 ntouch = ntouch + 1; touched(ntouch) = btmp(p); mark(btmp(p)) = 1
357 a%nnzb = a%nnzb + ntouch
363 allocate(a%browptr(nbrow+1), a%bcol(a%nnzb), a%bval(bs*a%nnzb), stat=astat)
365 a%bval = 0.0d0; a%browptr(1) = 1; kout = 0
368 do p = rcnt(i)+1, rcnt(i+1)
370 if (mark(j) == 0)
then
371 ntouch = ntouch + 1; touched(ntouch) = j; mark(j) = ntouch
374 a%bval((kout-1)*bs+1:kout*bs) = vtmp(1:bs, p)
376 r = kout - ntouch + mark(j)
377 a%bval((r-1)*bs+1:r*bs) = a%bval((r-1)*bs+1:r*bs) + vtmp(1:bs, p)
383 a%browptr(i+1) = kout + 1
387 deallocate(rcnt, rpos, btmp, vtmp, mark, touched)
393 type(hecmwst_saamg_bcsr),
intent(in) :: a
394 type(hecmwst_saamg_bcsr),
intent(out) :: at
401 type(hecmwst_saamg_bcsr),
intent(in) :: a, b
402 type(hecmwst_saamg_bcsr),
intent(out) :: c
409 type(hecmwst_saamg_bcsr),
intent(in) :: a, p
410 integer(kind=kint),
intent(in) :: mblk
411 type(hecmwst_saamg_bcsr),
intent(out) :: ac
418 type(hecmwst_saamg_bcsr),
intent(in) :: a
419 real(kind=
kreal),
intent(out) :: dense(:,:)
430 type(hecmwst_saamg_bcsr),
intent(in) :: a
431 real(kind=
kreal),
intent(out) :: dense(:,:)
432 integer(kind=kint) :: i, t, j, ii, jj, rbase, cbase, boff
436 do t = a%browptr(i), a%browptr(i+1)-1
437 j = a%bcol(t); cbase = (j-1)*a%mb; boff = (t-1)*a%nb*a%mb
440 dense(rbase+ii, cbase+jj) = dense(rbase+ii, cbase+jj) + a%bval(boff+(jj-1)*a%nb+ii)
450 type(hecmwst_saamg_bcsr),
intent(in) :: a
451 real(kind=
kreal),
intent(in) :: x(:)
452 real(kind=
kreal),
intent(out) :: y(:)
453 integer(kind=kint) :: i, t, j, ii, jj, rbase, cbase, boff, nb, mb
454 real(kind=
kreal) :: xj
467 y(rbase+1:rbase+nb) = 0.0d0
469 do t = a%browptr(i), a%browptr(i+1)-1
470 j = a%bcol(t); cbase = (j-1)*mb; boff = (t-1)*nb*mb
476 y(rbase+ii) = y(rbase+ii) + a%bval(boff+(jj-1)*nb+ii) * xj
489 type(hecmwst_saamg_bcsr),
intent(in) :: a
490 type(hecmwst_saamg_bcsr),
intent(out) :: at
491 integer(kind=kint),
allocatable :: pos(:)
492 integer(kind=kint) :: i, t, j, ii, jj, nb, mb, p, boff, aoff, astat
495 at%n = a%ncol; at%ncol = a%n; at%nb = mb; at%mb = nb
496 at%nbrow = a%nbcol; at%nbcol = a%nbrow; at%nnzb = a%nnzb; at%nnz = a%nnz
497 allocate(at%browptr(at%nbrow+1), at%bcol(at%nnzb), at%bval(nb*mb*at%nnzb), pos(at%nbrow), stat=astat)
501 at%browptr(a%bcol(t)+1) = at%browptr(a%bcol(t)+1) + 1
505 at%browptr(j+1) = at%browptr(j+1) + at%browptr(j)
508 pos(j) = at%browptr(j)
511 do t = a%browptr(i), a%browptr(i+1)-1
512 j = a%bcol(t); p = pos(j)
514 boff = (p-1)*mb*nb; aoff = (t-1)*nb*mb
517 at%bval(boff + (ii-1)*mb + jj) = a%bval(aoff + (jj-1)*nb + ii)
530 type(hecmwst_saamg_bcsr),
intent(in) :: a, b
531 type(hecmwst_saamg_bcsr),
intent(out) :: c
532 integer(kind=kint),
allocatable :: mark(:), clist(:)
533 real(kind=
kreal),
allocatable :: spa(:,:)
534 integer(kind=kint) :: rb, kb, cb, ncb, i, ta, kk, tb, l, ii, jj, pp, cnt, nci, t, pos
535 integer(kind=kint) :: aoff, boff, coff, astat
536 real(kind=
kreal) :: bkl
538 if (a%mb /= b%nb .or. a%nbcol /= b%nbrow)
then
539 write(*,*)
'hecmw_saamg_spgemm_blk: inner dim mismatch (mb,nbcol)=', a%mb, a%nbcol, &
540 ' vs (nb,nbrow)=', b%nb, b%nbrow
543 rb = a%nb; kb = a%mb; cb = b%mb; ncb = b%nbcol
545 c%n = a%n; c%ncol = b%ncol; c%nb = rb; c%mb = cb
546 c%nbrow = a%nbrow; c%nbcol = ncb
547 allocate(c%browptr(a%nbrow+1), stat=astat)
554 allocate(mark(ncb)); mark = 0
558 do ta = a%browptr(i), a%browptr(i+1)-1
560 do tb = b%browptr(kk), b%browptr(kk+1)-1
562 if (mark(l) /= i) then; mark(l) = i; cnt = cnt + 1;
end if
573 c%browptr(i+1) = c%browptr(i) + c%browptr(i+1)
575 c%nnzb = c%browptr(a%nbrow+1) - 1
576 allocate(c%bcol(c%nnzb), c%bval(rb*cb*c%nnzb), stat=astat)
584 allocate(mark(ncb), clist(ncb), spa(rb*cb, ncb)); mark = 0
588 do ta = a%browptr(i), a%browptr(i+1)-1
589 kk = a%bcol(ta); aoff = (ta-1)*rb*kb
590 do tb = b%browptr(kk), b%browptr(kk+1)-1
591 l = b%bcol(tb); boff = (tb-1)*kb*cb
592 if (mark(l) /= i)
then
593 mark(l) = i; nci = nci + 1; clist(nci) = l; spa(1:rb*cb, l) = 0.0d0
597 bkl = b%bval(boff + (jj-1)*kb + pp)
598 if (bkl == 0.0d0) cycle
600 spa((jj-1)*rb+ii, l) = spa((jj-1)*rb+ii, l) + a%bval(aoff+(pp-1)*rb+ii) * bkl
606 pos = c%browptr(i) - 1
612 c%bval(coff+1:coff+rb*cb) = spa(1:rb*cb, l)
616 deallocate(mark, clist, spa)
624 type(hecmwst_saamg_bcsr),
intent(in) :: a, p
625 integer(kind=kint),
intent(in) :: mblk
626 type(hecmwst_saamg_bcsr),
intent(out) :: ac
627 type(hecmwst_saamg_bcsr) :: pt, c
631 ac%nb = mblk; ac%mb = mblk
641 type(hecmwst_saamg_bcsr),
intent(in) :: a
642 integer(kind=kint),
intent(in) :: nbrow_keep
643 type(hecmwst_saamg_bcsr),
intent(out) :: at
644 integer(kind=kint),
allocatable :: pos(:)
645 integer(kind=kint) :: i, t, j, ii, jj, nb, mb, p, boff, aoff, nnzb, astat
647 nnzb = a%browptr(nbrow_keep+1) - 1
649 at%n = a%ncol; at%ncol = nbrow_keep*nb; at%nb = mb; at%mb = nb
650 at%nbrow = a%nbcol; at%nbcol = nbrow_keep; at%nnzb = nnzb; at%nnz = nnzb*nb*mb
651 allocate(at%browptr(at%nbrow+1), at%bcol(nnzb), at%bval(nb*mb*nnzb), pos(at%nbrow), stat=astat)
655 at%browptr(a%bcol(t)+1) = at%browptr(a%bcol(t)+1) + 1
659 at%browptr(j+1) = at%browptr(j+1) + at%browptr(j)
662 pos(j) = at%browptr(j)
665 do t = a%browptr(i), a%browptr(i+1)-1
666 j = a%bcol(t); p = pos(j)
668 boff = (p-1)*mb*nb; aoff = (t-1)*nb*mb
671 at%bval(boff + (ii-1)*mb + jj) = a%bval(aoff + (jj-1)*nb + ii)
688 type(hecmwst_saamg_bcsr),
intent(in) :: l, a, r
689 type(hecmwst_saamg_bcsr),
intent(out) :: ac
690 integer(kind=kint),
allocatable :: mark(:), clist(:)
691 real(kind=
kreal),
allocatable :: spa(:,:), la(:)
692 integer(kind=kint) :: rb, k1, k2, cb, ncr, i, jt, j, kt, k, lt, ll, p, q, rr, c
693 integer(kind=kint) :: cnt, nci, t, pos, loff, aoff, roff, coff, astat
694 real(kind=
kreal) :: av, rv
696 if (l%mb /= a%nb .or. a%mb /= r%nb .or. l%nbcol /= a%nbrow .or. a%nbcol /= r%nbrow)
then
699 rb = l%nb; k1 = l%mb; k2 = a%mb; cb = r%mb; ncr = r%nbcol
701 ac%n = l%n; ac%ncol = r%ncol; ac%nb = rb; ac%mb = cb
702 ac%nbrow = l%nbrow; ac%nbcol = ncr
703 allocate(ac%browptr(l%nbrow+1), stat=astat)
708 allocate(mark(ncr)); mark = 0
712 do jt = l%browptr(i), l%browptr(i+1)-1
714 do kt = a%browptr(j), a%browptr(j+1)-1
716 do lt = r%browptr(k), r%browptr(k+1)-1
718 if (mark(ll) /= i) then; mark(ll) = i; cnt = cnt + 1;
end if
722 ac%browptr(i+1) = cnt
730 ac%browptr(i+1) = ac%browptr(i) + ac%browptr(i+1)
732 ac%nnzb = ac%browptr(l%nbrow+1) - 1
733 allocate(ac%bcol(ac%nnzb), ac%bval(rb*cb*ac%nnzb), stat=astat); ac%nnz = rb*cb*ac%nnzb
741 allocate(mark(ncr), clist(ncr), spa(rb*cb, ncr), la(rb*k2)); mark = 0
745 do jt = l%browptr(i), l%browptr(i+1)-1
746 j = l%bcol(jt); loff = (jt-1)*rb*k1
747 do kt = a%browptr(j), a%browptr(j+1)-1
748 k = a%bcol(kt); aoff = (kt-1)*k1*k2
753 av = a%bval(aoff + (q-1)*k1 + p)
754 if (av == 0.0d0) cycle
756 la((q-1)*rb+rr) = la((q-1)*rb+rr) + l%bval(loff+(p-1)*rb+rr) * av
761 do lt = r%browptr(k), r%browptr(k+1)-1
762 ll = r%bcol(lt); roff = (lt-1)*k2*cb
763 if (mark(ll) /= i)
then
764 mark(ll) = i; nci = nci + 1; clist(nci) = ll; spa(1:rb*cb, ll) = 0.0d0
768 rv = r%bval(roff + (c-1)*k2 + q)
769 if (rv == 0.0d0) cycle
771 spa((c-1)*rb+rr, ll) = spa((c-1)*rb+rr, ll) + la((q-1)*rb+rr) * rv
778 pos = ac%browptr(i) - 1
781 ll = clist(t); ac%bcol(pos) = ll
783 ac%bval(coff+1:coff+rb*cb) = spa(1:rb*cb, ll)
787 deallocate(mark, clist, spa, la)
Smoothed Aggregation AMG preconditioner : lightweight comm table.
subroutine, public hecmw_saamg_comm_update(cmt, nb, X)
Halo exchange of a block vector X (length nb*nnode): fill the halo region nb*nint+1....
subroutine, public hecmw_saamg_check_alloc(ier, what)
Report a failed allocation (stat /= 0) with a clear message and a collective abort,...
subroutine, public hecmw_saamg_abort(msg)
Fatal-error termination with a clear message. Under MPI this is a COLLECTIVE abort (hecmw_abort -> MP...
Smoothed Aggregation AMG preconditioner : internal block-CSR matrix.
subroutine, public hecmw_saamg_matvec_d(cmt, A, x, y)
Distributed matvec y = A x : refresh x's halo region from the owning ranks (via the level comm table)...
subroutine, public hecmw_saamg_bcsr_transpose(A, At)
Transpose: At = A^T (At is ncol x n).
subroutine, public hecmw_saamg_spgemm_blk(A, B, C)
Block SpGEMM C = A * B : block Gustavson with dense block GEMM accumulation. Requires Amb == Bnb (inn...
subroutine, public hecmw_saamg_bcsr_to_dense(A, dense)
Densify a matrix into a (n x ncol) array (verification helper).
subroutine, public hecmw_saamg_bcsr_from_dense(dense, n, nb, A, mb)
Build a block-CSR matrix from a dense n x n array. A block is stored when any of its entries is nonze...
subroutine, public hecmw_saamg_bcsr_from_triplets(nrow, ncol, nb, ti, tj, tv, nt, A, mb)
Assemble a block-CSR (nrow x ncol) from a scalar triplet list (i,j,v): each entry is scattered into i...
subroutine, public hecmw_saamg_bcsr_move(A, B)
Move: B = A, transferring A's storage (move_alloc, no copy); A is emptied. Use when the source is no ...
subroutine, public hecmw_saamg_galerkin_local(A, P, mblk, Ac)
Galerkin coarse operator Ac = P^T A P. mblk = coarse block size.
subroutine, public hecmw_saamg_transpose_blk(A, At)
Block transpose At = A^T : swap block dims and transpose each block.
subroutine, public hecmw_saamg_matvec_blk(A, x, y)
Block matvec y = A x (x indexed by column blocks, y by row blocks).
subroutine, public hecmw_saamg_to_dense_blk(A, dense)
Densify from the block-CSR storage.
subroutine, public hecmw_saamg_triple_blk(L, A, R, Ac)
FUSED block triple product Ac = L * A * R, computed WITHOUT materializing the intermediate A*R (or L*...
subroutine, public hecmw_saamg_transpose_blk_rows(A, nbrow_keep, At)
Transpose only the first nbrow_keep block rows of A : At = (A[1:nbrow_keep])^T. Used to form the rest...
subroutine, public hecmw_saamg_bcsr_free(A)
Release the storage held by a hecmwST_saamg_bcsr.
subroutine, public hecmw_saamg_bcsr_copy(A, B)
Copy: B = A.
subroutine, public hecmw_saamg_galerkin_blk(A, P, mblk, Ac)
Block Galerkin Ac = P^T A P (block transpose + two block SpGEMM). mblk = coarse block size,...
subroutine, public hecmw_saamg_matvec(A, x, y)
Sparse matrix-vector product : y = A x.
real(kind=kreal) function, public hecmw_saamg_is_symmetric(A)
Relative asymmetry ||A - A^T||_F / ||A||_F (debug / verification helper). Returns 0 for a structurall...
subroutine, public hecmw_saamg_bcsr_from_block_triplets(nbrow, nbcol, nb, mb, bi, bj, bv, nt, A)
Assemble a block-CSR (nbrow x nbcol block grid, nb x mb blocks) from a list of block triplets (bi,...
subroutine, public hecmw_saamg_spgemm(A, B, C)
Sparse matrix-matrix product C = A * B. Requires Amb == Bnb.
Smoothed Aggregation AMG preconditioner : kind parameters.
integer(kind=4), parameter kreal