15 public :: hecmwst_mf_map
22 public :: hecmwst_mf_gmat
38 integer(kind=kint) :: nprocs = 1
39 integer(kind=kint) :: myrank = 0
40 integer(kind=kint) :: comm = 0
41 integer(kind=kint) :: nupper = 0
42 integer(kind=kint),
allocatable :: owner(:)
43 logical,
allocatable :: upper(:)
44 integer(kind=kint),
allocatable :: uplist(:)
45 integer(kind=kint),
allocatable :: rbeg(:)
46 integer(kind=kint),
allocatable :: rcnt(:)
47 end type hecmwst_mf_map
60 type(hecmwST_matrix) :: mat
61 integer(kind=kint) :: nblk = 0
62 integer(kind=kint),
allocatable :: nn(:)
63 integer(kind=kint),
allocatable :: ndisp(:)
64 integer(kind=kint),
allocatable :: vblk(:)
65 integer(kind=kint),
allocatable :: stream(:)
66 integer(kind=kint),
allocatable :: xptr(:)
67 integer(kind=kint),
allocatable :: xcol(:)
68 integer(kind=kint),
allocatable :: gid(:)
69 integer(kind=kint),
allocatable :: g2s(:)
70 integer(kind=kint),
allocatable :: scnt(:)
71 integer(kind=kint),
allocatable :: ssel(:)
72 integer(kind=kint),
allocatable :: rcnt(:)
73 integer(kind=kint),
allocatable :: rdst(:)
74 end type hecmwst_mf_gmat
79 real(kind=
kreal),
parameter :: mf_map_promote = 1.2d0
85 real(kind=
kreal),
parameter :: mf_map_promote_heavy = 0.5d0
86 integer(kind=8),
parameter :: MF_MAP_PROMOTE_ABS = 500000000000_8
90 integer(kind=8),
parameter :: MF_MAP_WPF = 2500_8
95 integer(kind=kint),
parameter :: MF_2D_FSTPR = 8
109 type(hecmwst_mf_symbolic),
intent(in) :: sym
110 type(hecmwst_mf_map),
intent(out) :: map
111 integer(kind=8),
allocatable :: wt(:)
112 integer(kind=kint),
allocatable :: cptr(:), clist(:), wptr(:)
113 integer(kind=kint) :: ns, s, p, c, i, nroot, nup, cbest
114 integer(kind=8) :: w, wbest, b
120 allocate(map%owner(ns), map%upper(ns))
130 do i = sym%rptr(s), sym%rptr(s+1) - 1
131 w = w + sym%ndof(sym%rlist(i))
133 b = w - sym_cdofcount(s)
134 wt(s) = (w*(w+1)*(2*w+1) - b*(b+1)*(2*b+1))/6 + mf_map_wpf*w*sym_cdofcount(s)
138 if (p /= 0) wt(p) = wt(p) + wt(s)
142 allocate(cptr(ns+1), clist(max(ns, 1)), wptr(ns))
146 if (p /= 0) cptr(p+1) = cptr(p+1) + 1
150 cptr(s+1) = cptr(s) + cptr(s+1)
152 wptr(1:ns) = cptr(1:ns)
157 wptr(p) = wptr(p) + 1
165 allocate(map%rbeg(ns), map%rcnt(ns))
169 if (sym%sparent(s) == 0) nroot = nroot + 1
173 if (sym%sparent(s) == 0)
then
178 call mf_map_split(wt, wptr(1:nroot), 0, map%nprocs, map%rbeg, map%rcnt)
180 if (map%rcnt(s) < 0)
then
182 map%rbeg(s) = map%rbeg(p)
185 if (map%rcnt(s) > 1)
call mf_map_pack(s)
192 if (map%rcnt(s) <= 1)
then
193 map%owner(s) = map%rbeg(s)
194 map%upper(s) = .false.
198 do i = cptr(s), cptr(s+1) - 1
200 if (wt(c) > wbest)
then
206 map%owner(s) = map%owner(cbest)
208 map%owner(s) = map%rbeg(s)
210 map%upper(s) = .true.
215 allocate(map%uplist(max(nup, 1)))
218 if (map%upper(s))
then
223 deallocate(wt, cptr, clist, wptr)
228 function sym_cdofcount(s0)
result(nc)
229 integer(kind=kint),
intent(in) :: s0
230 integer(kind=kint) :: nc, k
232 do k = sym%sptr(s0), sym%sptr(s0+1) - 1
233 nc = nc + sym%ndof(k)
235 end function sym_cdofcount
245 subroutine mf_map_pack(s0)
246 integer(kind=kint),
intent(in) :: s0
247 integer(kind=kint),
allocatable :: pool(:)
248 integer(kind=8),
allocatable :: load(:)
249 integer(kind=kint) :: npool, i0, j0, c0, r0, nr0, rmin
250 integer(kind=8) :: tot
251 real(kind=
kreal) :: th
256 allocate(pool(ns), load(0:nr0-1))
259 do i0 = cptr(s0), cptr(s0+1) - 1
261 if (map%rcnt(c0) < 0)
then
271 do while (i0 <= npool)
274 if (wt(c0) >= mf_map_promote_abs) th = mf_map_promote_heavy
275 if (real(wt(c0), kind=
kreal)*nr0 > th*real(tot, kind=
kreal))
then
279 pool(i0) = pool(npool)
281 do j0 = cptr(c0), cptr(c0+1) - 1
283 pool(npool) = clist(j0)
284 tot = tot + wt(clist(j0))
292 call mf_sort_lpt(pool, npool)
297 if (load(j0) < load(rmin)) rmin = j0
300 map%rbeg(c0) = r0 + rmin
303 load(rmin) = load(rmin) + max(wt(c0), 1_8)
305 deallocate(pool, load)
306 end subroutine mf_map_pack
310 subroutine mf_sort_lpt(list, n0)
311 integer(kind=kint),
intent(inout) :: list(:)
312 integer(kind=kint),
intent(in) :: n0
313 integer(kind=kint) :: i0, j0, k0, t0
321 if (lpt_after(list(k0+1), list(k0))) k0 = k0 + 1
323 if (.not. lpt_after(list(k0), list(j0)))
exit
337 if (k0 > i0 - 1)
exit
338 if (k0 < i0 - 1)
then
339 if (lpt_after(list(k0+1), list(k0))) k0 = k0 + 1
341 if (.not. lpt_after(list(k0), list(j0)))
exit
348 end subroutine mf_sort_lpt
351 logical function lpt_after(a0, b0)
352 integer(kind=kint),
intent(in) :: a0, b0
353 lpt_after = (wt(a0) < wt(b0)) .or. (wt(a0) == wt(b0) .and. a0 > b0)
354 end function lpt_after
361 subroutine mf_map_split(wt, list, r0, np, rbeg, rcnt)
363 integer(kind=8),
intent(in) :: wt(:)
364 integer(kind=kint),
intent(in) :: list(:)
365 integer(kind=kint),
intent(in) :: r0, np
366 integer(kind=kint),
intent(inout) :: rbeg(:), rcnt(:)
367 integer(kind=8) :: ctot, c
368 integer(kind=kint) :: i, s, b0, b1
372 ctot = ctot + wt(list(i))
380 b0 = int((2_8*np*c + ctot)/(2_8*ctot), kind=
kint)
382 b1 = int((2_8*np*c + ctot)/(2_8*ctot), kind=
kint)
387 if (b0 > np - 1) b0 = np - 1
388 if (b1 <= b0) b1 = b0 + 1
390 rcnt(s) = min(b1, np) - b0
392 end subroutine mf_map_split
396 type(hecmwst_mf_map),
intent(inout) :: map
400 if (
allocated(map%owner))
deallocate(map%owner)
401 if (
allocated(map%upper))
deallocate(map%upper)
402 if (
allocated(map%uplist))
deallocate(map%uplist)
403 if (
allocated(map%rbeg))
deallocate(map%rbeg)
404 if (
allocated(map%rcnt))
deallocate(map%rcnt)
417 type(hecmwst_mf_symbolic),
intent(in) :: sym
418 type(hecmwst_mf_map),
intent(in) :: map
419 integer(kind=kint),
intent(in) :: tile, s, ndel
420 integer(kind=kint),
intent(out) :: ncbt
421 integer(kind=kint),
allocatable,
intent(inout) :: ctb(:)
422 integer(kind=kint),
allocatable,
intent(inout) :: towner(:)
423 integer(kind=kint) :: nown, nrow_nodes, ncol, i, k, nd, rel, cur, nr, t, b
424 integer(kind=8) :: ctot, c, w
426 nown = sym%sptr(s+1) - sym%sptr(s)
427 nrow_nodes = sym%rptr(s+1) - sym%rptr(s)
429 do k = sym%sptr(s), sym%sptr(s+1) - 1
430 ncol = ncol + sym%ndof(k)
432 if (
allocated(ctb))
then
433 if (
size(ctb) < nrow_nodes - nown + 1)
deallocate(ctb, towner)
435 if (.not.
allocated(ctb))
allocate(ctb(0:max(nrow_nodes - nown, 1)), towner(max(nrow_nodes - nown, 1)))
440 do i = nown + 1, nrow_nodes
441 nd = sym%ndof(sym%rlist(sym%rptr(s)+i-1))
442 if (rel > cur .and. rel + nd - cur > tile)
then
449 if (rel > cur .or. ncbt == 0)
then
455 if (ncbt == 0)
return
460 ctot = ctot + int(ctb(t) - ctb(t-1), 8)*(ncol + ctb(t))
464 w = int(ctb(t) - ctb(t-1), 8)*(ncol + ctb(t))
465 b = int(((2_8*c + w)*nr)/(2_8*ctot), kind=
kint)
466 if (b > nr - 1) b = nr - 1
467 towner(t) = map%rbeg(s) + b
479 type(hecmwst_mf_map),
intent(in) :: map
480 integer(kind=kint),
intent(in) :: s, ntc
481 integer(kind=kint),
intent(out) :: pr, pc
482 integer(kind=kint) :: ng
484 ng = (ntc*(ntc+1)/2) / mf_2d_fstpr
485 if (ng > map%rcnt(s)) ng = map%rcnt(s)
488 do while ((pc+1)*(pc+1) <= ng)
499 type(hecmwst_mf_map),
intent(in) :: map
500 integer(kind=kint),
intent(in) :: s, pr, pc, i, j
501 integer(kind=kint) :: r, gp
503 gp = mod(i-1, pr)*pc + mod(j-1, pc)
507 r = map%rbeg(s) + gp - 1
508 if (r >= map%owner(s)) r = r + 1
516 type(hecmwst_mf_symbolic),
intent(inout) :: sym
517 integer(kind=kint),
intent(in) :: root
518 integer(kind=kint) :: hdr(6)
519 integer(kind=kint) :: n, ns, nrl, ncm, comm
527 hdr(4) = sym%max_front
528 hdr(5) = sym%rptr(sym%nsuper+1) - 1
529 hdr(6) = sym%cmap_ptr(sym%nsuper+1) - 1
541 sym%max_front = hdr(4)
542 allocate(sym%perm(n), sym%invp(n), sym%ndof(n), sym%parent(n), sym%colcnt(n))
543 allocate(sym%sptr(ns+1), sym%sparent(ns), sym%rptr(ns+1), sym%rlist(nrl))
544 allocate(sym%cmap_ptr(ns+1), sym%cmap(max(ncm, 1)))
568 type(hecmwst_mf_gmat),
intent(inout) :: gmat
569 integer(kind=kint),
allocatable :: ibuf(:), ilen(:), idisp(:), gc(:), sidx(:), itmp(:)
570 integer(kind=kint) :: np, me, comm, nd, n, ng, i, j, k, l, m, r, ptr, ncols, grow, maxcols
571 integer(kind=kint) :: nl, nu, g
579 allocate(gmat%nn(np), gmat%ndisp(np+1), gmat%vblk(np), ilen(np), idisp(np))
583 gmat%ndisp(r+1) = gmat%ndisp(r) + gmat%nn(r)
585 ng = gmat%ndisp(np+1)
586 allocate(gmat%gid(ng))
590 allocate(gmat%g2s(ng), sidx(ng), itmp(ng))
594 call sort_by_gid(sidx, ng)
596 gmat%g2s(sidx(k)) = k
597 itmp(k) = gmat%gid(sidx(k))
599 gmat%gid(1:ng) = itmp(1:ng)
600 deallocate(sidx, itmp)
603 m = n + (hecmat%indexL(n) - hecmat%indexL(0)) + (hecmat%indexU(n) - hecmat%indexU(0))
604 allocate(ibuf(max(m, 1)))
608 ibuf(ptr) = (hecmat%indexL(i) - hecmat%indexL(i-1)) + (hecmat%indexU(i) - hecmat%indexU(i-1))
609 do k = hecmat%indexL(i-1)+1, hecmat%indexL(i)
611 ibuf(ptr) = mf_global_node(hecmesh, gmat, me, hecmat%itemL(k))
613 do k = hecmat%indexU(i-1)+1, hecmat%indexU(i)
615 ibuf(ptr) = mf_global_node(hecmesh, gmat, me, hecmat%itemU(k))
621 idisp(r) = idisp(r-1) + ilen(r-1)
623 allocate(gmat%stream(idisp(np) + ilen(np)))
628 gmat%vblk(1:np) = ilen(1:np)
629 gmat%nblk = idisp(np) + ilen(np)
634 ncols = gmat%stream(ptr+1)
636 gmat%stream(ptr+1+j) = gmat%g2s(gmat%stream(ptr+1+j))
638 ptr = ptr + 1 + ncols
640 call mf_gmat_closure(gmat, ng)
644 nullify(gmat%mat%indexL, gmat%mat%indexU, gmat%mat%itemL, gmat%mat%itemU)
645 nullify(gmat%mat%D, gmat%mat%AL, gmat%mat%AU)
646 nullify(gmat%mat%B, gmat%mat%X, gmat%mat%A, gmat%mat%indexA, gmat%mat%itemA)
647 deallocate(ilen, idisp)
652 allocate(gmat%mat%indexL(0:ng), gmat%mat%indexU(0:ng))
653 gmat%mat%indexL(0:ng) = 0
654 gmat%mat%indexU(0:ng) = 0
659 grow = gmat%g2s(gmat%ndisp(r) + i)
660 ncols = gmat%stream(ptr+1)
661 maxcols = max(maxcols, ncols + gmat%xptr(grow) - gmat%xptr(grow-1))
663 g = gmat%stream(ptr+1+j)
665 gmat%mat%indexL(grow) = gmat%mat%indexL(grow) + 1
667 gmat%mat%indexU(grow) = gmat%mat%indexU(grow) + 1
670 do k = gmat%xptr(grow-1)+1, gmat%xptr(grow)
671 if (gmat%xcol(k) < grow)
then
672 gmat%mat%indexL(grow) = gmat%mat%indexL(grow) + 1
674 gmat%mat%indexU(grow) = gmat%mat%indexU(grow) + 1
677 ptr = ptr + 1 + ncols
681 gmat%mat%indexL(i) = gmat%mat%indexL(i-1) + gmat%mat%indexL(i)
682 gmat%mat%indexU(i) = gmat%mat%indexU(i-1) + gmat%mat%indexU(i)
684 gmat%mat%NPL = gmat%mat%indexL(ng)
685 gmat%mat%NPU = gmat%mat%indexU(ng)
686 allocate(gmat%mat%itemL(max(gmat%mat%NPL, 1)), gmat%mat%itemU(max(gmat%mat%NPU, 1)))
687 allocate(gc(max(maxcols, 1)))
691 grow = gmat%g2s(gmat%ndisp(r) + i)
692 ncols = gmat%stream(ptr+1)
694 gc(j) = gmat%stream(ptr+1+j)
696 ptr = ptr + 1 + ncols
697 do k = gmat%xptr(grow-1)+1, gmat%xptr(grow)
699 gc(ncols) = gmat%xcol(k)
715 if (gc(j) < grow)
then
717 gmat%mat%itemL(gmat%mat%indexL(grow-1) + nl) = gc(j)
720 gmat%mat%itemU(gmat%mat%indexU(grow-1) + nu) = gc(j)
730 subroutine sort_by_gid(idx, n0)
731 integer(kind=kint),
intent(inout) :: idx(:)
732 integer(kind=kint),
intent(in) :: n0
733 integer(kind=kint) :: i0, t0
735 call sift_by_gid(idx, i0, n0)
741 call sift_by_gid(idx, 1, i0-1)
743 end subroutine sort_by_gid
745 subroutine sift_by_gid(idx, s0, e0)
746 integer(kind=kint),
intent(inout) :: idx(:)
747 integer(kind=kint),
intent(in) :: s0, e0
748 integer(kind=kint) :: p0, c0, t0
754 if (gmat%gid(idx(c0+1)) > gmat%gid(idx(c0))) c0 = c0 + 1
756 if (gmat%gid(idx(c0)) <= gmat%gid(idx(p0)))
exit
762 end subroutine sift_by_gid
771 subroutine mf_gmat_closure(gmat, ng)
773 type(hecmwst_mf_gmat),
intent(inout) :: gmat
774 integer(kind=kint),
intent(in) :: ng
775 integer(kind=kint),
allocatable :: rp(:), cols(:), fil(:)
776 integer(kind=kint) :: ptr, i, j, k, g, grow, ncols, nmiss
779 allocate(rp(0:ng), fil(ng))
784 fil(grow) = gmat%stream(ptr+1)
785 ptr = ptr + 1 + gmat%stream(ptr+1)
789 rp(i) = rp(i-1) + fil(i)
791 allocate(cols(max(rp(ng), 1)))
795 ncols = gmat%stream(ptr+1)
797 cols(rp(grow-1)+j) = gmat%stream(ptr+1+j)
799 ptr = ptr + 1 + ncols
803 do j = rp(i-1)+2, rp(i)
806 do while (k >= rp(i-1)+1)
807 if (cols(k) <= g)
exit
814 allocate(gmat%xptr(0:ng))
817 do j = rp(i-1)+1, rp(i)
819 if (.not. found(g, i)) gmat%xptr(g) = gmat%xptr(g) + 1
823 gmat%xptr(i) = gmat%xptr(i-1) + gmat%xptr(i)
825 nmiss = gmat%xptr(ng)
826 allocate(gmat%xcol(max(nmiss, 1)))
831 do j = rp(i-1)+1, rp(i)
833 if (.not. found(g, i))
then
835 gmat%xcol(gmat%xptr(g-1) + fil(g)) = i
840 deallocate(rp, cols, fil)
845 logical function found(r0, c0)
846 integer(kind=kint),
intent(in) :: r0, c0
847 integer(kind=kint) :: lo0, hi0, mid0
851 do while (lo0 <= hi0)
852 mid0 = (lo0 + hi0) / 2
853 if (cols(mid0) == c0)
then
856 else if (cols(mid0) < c0)
then
864 end subroutine mf_gmat_closure
869 function mf_global_node(hecMESH, gmat, me, j)
result(g)
872 type(hecmwst_mf_gmat),
intent(in) :: gmat
873 integer(kind=kint),
intent(in) :: me, j
874 integer(kind=kint) :: g
876 if (j <= hecmesh%nn_internal)
then
877 g = gmat%ndisp(me+1) + j
879 g = gmat%ndisp(hecmesh%node_ID(2*j) + 1) + hecmesh%node_ID(2*j-1)
881 end function mf_global_node
893 type(hecmwst_mf_symbolic),
intent(in) :: sym
894 type(hecmwst_mf_map),
intent(in) :: map
895 type(hecmwst_mf_gmat),
intent(inout) :: gmat
896 integer(kind=kint),
allocatable :: c2s(:), gc(:), bb(:), sptr(:)
897 integer(kind=kint) :: np, me, ng, nd2, i, j, l, m, r, g, b, ptr, ncols, grow, maxcols
898 integer(kind=kint) :: ka, nl, nu, nkeep, nrecv, pos, r0, nr0, d
902 ng = gmat%ndisp(np+1)
903 nd2 = gmat%mat%NDOF * gmat%mat%NDOF
904 if (
associated(gmat%mat%indexL))
then
905 deallocate(gmat%mat%indexL, gmat%mat%indexU, gmat%mat%itemL, gmat%mat%itemU)
907 allocate(c2s(sym%nnode))
908 call mf_gmat_c2s(sym, c2s)
911 allocate(gmat%rcnt(np), gmat%mat%indexL(0:ng), gmat%mat%indexU(0:ng))
913 gmat%mat%indexL(0:ng) = 0
914 gmat%mat%indexU(0:ng) = 0
919 grow = gmat%g2s(gmat%ndisp(r) + i)
921 ncols = gmat%stream(ptr+1)
922 maxcols = max(maxcols, ncols + gmat%xptr(grow) - gmat%xptr(grow-1))
923 if (mine(ka, ka)) gmat%rcnt(r) = gmat%rcnt(r) + 1
925 g = gmat%stream(ptr+1+j)
926 if (mine(ka, sym%invp(g)))
then
927 gmat%rcnt(r) = gmat%rcnt(r) + 1
929 gmat%mat%indexL(grow) = gmat%mat%indexL(grow) + 1
931 gmat%mat%indexU(grow) = gmat%mat%indexU(grow) + 1
936 do j = gmat%xptr(grow-1)+1, gmat%xptr(grow)
938 if (mine(ka, sym%invp(g)))
then
940 gmat%mat%indexL(grow) = gmat%mat%indexL(grow) + 1
942 gmat%mat%indexU(grow) = gmat%mat%indexU(grow) + 1
946 ptr = ptr + 1 + ncols
950 gmat%mat%indexL(i) = gmat%mat%indexL(i-1) + gmat%mat%indexL(i)
951 gmat%mat%indexU(i) = gmat%mat%indexU(i-1) + gmat%mat%indexU(i)
953 gmat%mat%NPL = gmat%mat%indexL(ng)
954 gmat%mat%NPU = gmat%mat%indexU(ng)
955 allocate(gmat%mat%itemL(max(gmat%mat%NPL, 1)), gmat%mat%itemU(max(gmat%mat%NPU, 1)))
956 allocate(gmat%mat%D(int(ng, 8)*nd2))
957 allocate(gmat%mat%AL(max(int(gmat%mat%NPL, 8)*nd2, 1_8)))
958 allocate(gmat%mat%AU(max(int(gmat%mat%NPU, 8)*nd2, 1_8)))
960 gmat%mat%D(:) = 0.0d0
961 gmat%mat%AL(:) = 0.0d0
962 gmat%mat%AU(:) = 0.0d0
968 nrecv = nrecv + gmat%rcnt(r)
970 allocate(gmat%rdst(max(nrecv, 1)), gc(max(maxcols, 1)), bb(max(maxcols, 1)))
975 grow = gmat%g2s(gmat%ndisp(r) + i)
977 ncols = gmat%stream(ptr+1)
978 if (mine(ka, ka))
then
980 gmat%rdst(b) = gmat%mat%NPL + gmat%mat%NPU + grow
984 g = gmat%stream(ptr+1+j)
985 if (mine(ka, sym%invp(g)))
then
993 do j = gmat%xptr(grow-1)+1, gmat%xptr(grow)
995 if (mine(ka, sym%invp(g)))
then
1001 ptr = ptr + 1 + ncols
1008 if (gc(l) <= g)
exit
1019 if (gc(j) < grow)
then
1021 pos = gmat%mat%indexL(grow-1) + nl
1022 gmat%mat%itemL(pos) = gc(j)
1023 if (bb(j) > 0) gmat%rdst(bb(j)) = pos
1026 pos = gmat%mat%indexU(grow-1) + nu
1027 gmat%mat%itemU(pos) = gc(j)
1028 if (bb(j) > 0) gmat%rdst(bb(j)) = gmat%mat%NPL + pos
1036 allocate(gmat%scnt(np), sptr(np))
1040 ptr = ptr + gmat%vblk(r)
1043 do i = 1, gmat%nn(me+1)
1044 grow = gmat%g2s(gmat%ndisp(me+1) + i)
1046 ncols = gmat%stream(ptr+1)
1047 call destrange(ka, ka, r0, nr0)
1048 gmat%scnt(r0+1:r0+nr0) = gmat%scnt(r0+1:r0+nr0) + 1
1050 call destrange(ka, sym%invp(gmat%stream(ptr+1+j)), r0, nr0)
1051 gmat%scnt(r0+1:r0+nr0) = gmat%scnt(r0+1:r0+nr0) + 1
1053 ptr = ptr + 1 + ncols
1057 sptr(r) = sptr(r-1) + gmat%scnt(r-1)
1059 i = sptr(np) + gmat%scnt(np)
1060 allocate(gmat%ssel(max(i, 1)))
1063 do i = 1, gmat%nn(me+1)
1064 grow = gmat%g2s(gmat%ndisp(me+1) + i)
1066 ncols = gmat%stream(ptr+1)
1068 call destrange(ka, ka, r0, nr0)
1069 do d = r0 + 1, r0 + nr0
1070 sptr(d) = sptr(d) + 1
1071 gmat%ssel(sptr(d)) = b
1075 call destrange(ka, sym%invp(gmat%stream(ptr+1+j)), r0, nr0)
1076 do d = r0 + 1, r0 + nr0
1077 sptr(d) = sptr(d) + 1
1078 gmat%ssel(sptr(d)) = b
1081 ptr = ptr + 1 + ncols
1083 deallocate(gmat%stream, gmat%xptr, gmat%xcol, c2s, gc, bb, sptr)
1088 logical function mine(ka0, kb0)
1089 integer(kind=kint),
intent(in) :: ka0, kb0
1090 integer(kind=kint) :: s0
1091 s0 = c2s(min(ka0, kb0))
1092 mine = me >= map%rbeg(s0) .and. me < map%rbeg(s0) + map%rcnt(s0)
1096 subroutine destrange(ka0, kb0, r1, nr1)
1097 integer(kind=kint),
intent(in) :: ka0, kb0
1098 integer(kind=kint),
intent(out) :: r1, nr1
1099 integer(kind=kint) :: s0
1100 s0 = c2s(min(ka0, kb0))
1103 end subroutine destrange
1114 type(hecmwst_mf_gmat),
intent(inout) :: gmat
1115 real(kind=
kreal),
allocatable :: vbuf(:), sbuf(:), rbuf(:)
1116 integer(kind=kint),
allocatable :: scs(:), sdisp(:), rcs(:), rdisp(:)
1117 integer(kind=kint) :: np, me, comm, nd2, n, i, k, r, t, nsend, nrecv
1118 integer(kind=8) :: ptr, b, base
1123 gmat%mat%symmetric = hecmat%symmetric
1124 nd2 = hecmat%NDOF * hecmat%NDOF
1126 allocate(vbuf(max(int(gmat%vblk(me+1), 8)*nd2, 1_8)))
1129 vbuf(ptr+1:ptr+nd2) = hecmat%D(int(i-1, 8)*nd2+1:int(i, 8)*nd2)
1131 do k = hecmat%indexL(i-1)+1, hecmat%indexL(i)
1132 vbuf(ptr+1:ptr+nd2) = hecmat%AL(int(k-1, 8)*nd2+1:int(k, 8)*nd2)
1135 do k = hecmat%indexU(i-1)+1, hecmat%indexU(i)
1136 vbuf(ptr+1:ptr+nd2) = hecmat%AU(int(k-1, 8)*nd2+1:int(k, 8)*nd2)
1140 allocate(scs(np), sdisp(np), rcs(np), rdisp(np))
1144 scs(r) = gmat%scnt(r) * nd2
1145 rcs(r) = gmat%rcnt(r) * nd2
1146 sdisp(r) = nsend * nd2
1147 rdisp(r) = nrecv * nd2
1148 nsend = nsend + gmat%scnt(r)
1149 nrecv = nrecv + gmat%rcnt(r)
1151 allocate(sbuf(max(int(nsend, 8)*nd2, 1_8)), rbuf(max(int(nrecv, 8)*nd2, 1_8)))
1153 b = int(gmat%ssel(i) - 1, 8)*nd2
1154 base = int(i-1, 8)*nd2
1155 sbuf(base+1:base+nd2) = vbuf(b+1:b+nd2)
1161 if (t <= gmat%mat%NPL)
then
1162 gmat%mat%AL(int(t-1, 8)*nd2+1:int(t, 8)*nd2) = rbuf(base+1:base+nd2)
1163 else if (t <= gmat%mat%NPL + gmat%mat%NPU)
then
1164 t = t - gmat%mat%NPL
1165 gmat%mat%AU(int(t-1, 8)*nd2+1:int(t, 8)*nd2) = rbuf(base+1:base+nd2)
1167 t = t - gmat%mat%NPL - gmat%mat%NPU
1168 gmat%mat%D(int(t-1, 8)*nd2+1:int(t, 8)*nd2) = rbuf(base+1:base+nd2)
1171 deallocate(vbuf, sbuf, rbuf, scs, sdisp, rcs, rdisp)
1179 type(hecmwst_mf_gmat),
intent(in) :: gmat
1180 integer(kind=8),
intent(out) :: wpart, wrepl
1181 integer(kind=8) :: ng, ni, nd2
1183 ng =
size(gmat%mat%indexL, kind=8) - 1
1184 nd2 = int(gmat%mat%NDOF, 8)**2
1185 wpart =
size(gmat%mat%D, kind=8) +
size(gmat%mat%AL, kind=8) +
size(gmat%mat%AU, kind=8)
1186 ni = 2*(ng+1) +
size(gmat%mat%itemL, kind=8) +
size(gmat%mat%itemU, kind=8) &
1187 +
size(gmat%ssel, kind=8) +
size(gmat%rdst, kind=8) &
1188 +
size(gmat%scnt, kind=8) +
size(gmat%rcnt, kind=8) + 3*
size(gmat%nn, kind=8) + 1
1189 wpart = wpart + (ni + 1)/2
1190 wrepl = int(gmat%nblk, 8)*nd2 + (int(gmat%nblk, 8) - ng + 2*(ng+1) + int(gmat%nblk, 8) + 1)/2
1194 subroutine mf_gmat_c2s(sym, c2s)
1196 type(hecmwst_mf_symbolic),
intent(in) :: sym
1197 integer(kind=kint),
intent(out) :: c2s(:)
1198 integer(kind=kint) :: s, k
1200 do s = 1, sym%nsuper
1201 do k = sym%sptr(s), sym%sptr(s+1) - 1
1205 end subroutine mf_gmat_c2s
1218 type(hecmwst_mf_symbolic),
intent(in) :: sym
1219 type(hecmwst_mf_map),
intent(in) :: map
1221 integer(kind=kint),
allocatable :: c2s(:)
1222 integer(kind=kint) :: me, nd2, ng, i, k, ka, nl, nu
1223 integer(kind=8) :: bs, bd
1226 nd2 = full%NDOF * full%NDOF
1230 part%NDOF = full%NDOF
1231 part%symmetric = full%symmetric
1232 allocate(c2s(sym%nnode))
1233 call mf_gmat_c2s(sym, c2s)
1234 allocate(part%indexL(0:ng), part%indexU(0:ng))
1240 do k = full%indexL(i-1)+1, full%indexL(i)
1241 if (mine(ka, sym%invp(full%itemL(k)))) nl = nl + 1
1244 do k = full%indexU(i-1)+1, full%indexU(i)
1245 if (mine(ka, sym%invp(full%itemU(k)))) nu = nu + 1
1247 part%indexL(i) = part%indexL(i-1) + nl
1248 part%indexU(i) = part%indexU(i-1) + nu
1250 part%NPL = part%indexL(ng)
1251 part%NPU = part%indexU(ng)
1252 allocate(part%itemL(max(part%NPL, 1)), part%itemU(max(part%NPU, 1)))
1253 allocate(part%D(int(ng, 8)*nd2))
1254 allocate(part%AL(max(int(part%NPL, 8)*nd2, 1_8)))
1255 allocate(part%AU(max(int(part%NPU, 8)*nd2, 1_8)))
1256 nullify(part%B, part%X, part%A, part%indexA, part%itemA)
1261 bd = int(i-1, 8)*nd2
1262 if (mine(ka, ka))
then
1263 part%D(bd+1:bd+nd2) = full%D(bd+1:bd+nd2)
1265 part%D(bd+1:bd+nd2) = 0.0d0
1267 do k = full%indexL(i-1)+1, full%indexL(i)
1268 if (.not. mine(ka, sym%invp(full%itemL(k)))) cycle
1270 part%itemL(nl) = full%itemL(k)
1271 bs = int(k-1, 8)*nd2
1272 bd = int(nl-1, 8)*nd2
1273 part%AL(bd+1:bd+nd2) = full%AL(bs+1:bs+nd2)
1275 do k = full%indexU(i-1)+1, full%indexU(i)
1276 if (.not. mine(ka, sym%invp(full%itemU(k)))) cycle
1278 part%itemU(nu) = full%itemU(k)
1279 bs = int(k-1, 8)*nd2
1280 bd = int(nu-1, 8)*nd2
1281 part%AU(bd+1:bd+nd2) = full%AU(bs+1:bs+nd2)
1289 logical function mine(ka0, kb0)
1290 integer(kind=kint),
intent(in) :: ka0, kb0
1291 integer(kind=kint) :: s0
1292 s0 = c2s(min(ka0, kb0))
1293 mine = me >= map%rbeg(s0) .and. me < map%rbeg(s0) + map%rcnt(s0)
1302 type(hecmwst_mf_gmat),
intent(in) :: gmat
1303 real(kind=
kreal),
intent(in) :: v(:)
1304 real(kind=
kreal),
intent(out) :: gv(:)
1305 real(kind=
kreal),
allocatable :: vg(:)
1306 integer(kind=kint),
allocatable :: vlen(:), vdisp(:)
1307 integer(kind=kint) :: np, me, comm, nd, r, k, d, g
1313 allocate(vlen(np), vdisp(np), vg(gmat%ndisp(np+1)*nd))
1315 vlen(r) = gmat%nn(r) * nd
1316 vdisp(r) = gmat%ndisp(r) * nd
1320 do k = 1, gmat%ndisp(np+1)
1323 gv((g-1)*nd + d) = vg((k-1)*nd + d)
1326 deallocate(vlen, vdisp, vg)
1331 type(hecmwst_mf_gmat),
intent(inout) :: gmat
1334 if (
allocated(gmat%nn))
then
1335 deallocate(gmat%nn, gmat%ndisp, gmat%vblk)
1336 if (
allocated(gmat%stream))
deallocate(gmat%stream)
1337 if (
allocated(gmat%xptr))
deallocate(gmat%xptr, gmat%xcol)
1338 if (
allocated(gmat%gid))
deallocate(gmat%gid)
1339 if (
allocated(gmat%g2s))
deallocate(gmat%g2s)
1340 if (
allocated(gmat%scnt))
deallocate(gmat%scnt, gmat%ssel, gmat%rcnt, gmat%rdst)
1341 if (
associated(gmat%mat%indexL))
then
1342 deallocate(gmat%mat%indexL, gmat%mat%indexU, gmat%mat%itemL, gmat%mat%itemU)
1344 if (
associated(gmat%mat%D))
deallocate(gmat%mat%D, gmat%mat%AL, gmat%mat%AU)
1345 nullify(gmat%mat%indexL, gmat%mat%indexU, gmat%mat%itemL, gmat%mat%itemU)
1346 nullify(gmat%mat%D, gmat%mat%AL, gmat%mat%AU)
MPI distribution layer of the multifrontal solver: the supernode-to-rank mapping and the broadcast of...
subroutine, public hecmw_mf_dist_gmat_finalize(gmat)
subroutine, public hecmw_mf_dist_gmat_extract(full, sym, map, part)
Extract from the replicated matrix the part this rank reads under the distribution: the block pairs o...
subroutine, public hecmw_mf_dist_rowtiles(sym, map, tile, s, ndel, ncbt, ctb, towner)
Contribution row tiles of upper front s and their owning ranks. The boundaries ctb (0:ncbt) are offse...
subroutine, public hecmw_mf_dist_gather_vec(gmat, v, gv)
Gather the internal parts of a distributed nodal vector into the replicated global vector,...
integer(kind=kint) function, public hecmw_mf_dist_fsrank(map, s, pr, pc, i, j)
Owning rank of fully summed tile (i, j), j <= i, of upper front s on its pr x pc grid: block cyclic o...
subroutine, public hecmw_mf_dist_fsgrid(map, s, ntc, pr, pc)
2D process grid pr x pc of the fully summed part of upper front s, from its fully summed tile count n...
subroutine, public hecmw_mf_dist_map_build(sym, map)
Build the mapping from the symbolic structure. The roots share all ranks (several roots split them pr...
subroutine, public hecmw_mf_dist_symbolic_bcast(sym, root)
Broadcast the symbolic structure built on the root rank to all ranks. The int8 estimates (factor_nnz,...
subroutine, public hecmw_mf_dist_gmat_part(sym, map, gmat)
Derive from the mapping the partial profile of this rank and the value routing, and drop the gathered...
subroutine, public hecmw_mf_dist_gmat_words(gmat, wpart, wrepl)
Words this rank holds for the matrix (the values with the integer structure and routing at two intege...
subroutine, public hecmw_mf_dist_gmat_vals(hecMAT, gmat)
Move the values of the internal rows to their holding ranks through the routing of hecmw_mf_dist_gmat...
subroutine, public hecmw_mf_dist_map_finalize(map)
subroutine, public hecmw_mf_dist_gmat_build(hecMESH, hecMAT, gmat)
Gather the nonzero structure of the internal rows of every rank. The stream carries,...
Symbolic factorization (elimination tree, column counts, supernodes, row structure) for the multifron...
subroutine, public hecmw_mf_symbolic_finalize(sym)
integer(kind=kint) function hecmw_comm_get_size()
integer(kind=4), parameter kint
integer(kind=kint) function hecmw_comm_get_comm()
integer(kind=4), parameter kreal
integer(kind=kint) function hecmw_comm_get_rank()
subroutine hecmw_allgatherv_int(sbuf, sc, rbuf, rcs, disp, comm)
subroutine hecmw_alltoallv_real(sbuf, scs, sdisp, rbuf, rcs, rdisp, comm)
subroutine hecmw_allgatherv_real(sbuf, sc, rbuf, rcs, disp, comm)
subroutine hecmw_bcast_i_comm(val, n, nbase, comm)
subroutine hecmw_allgather_int_1(sval, rbuf, comm)