11 public :: hecmwst_local_matrix
27 type hecmwst_local_matrix
28 integer :: nr, nc, nnz, ndof
29 integer(kind=kint),
pointer :: index(:)
30 integer(kind=kint),
pointer :: item(:)
31 real(kind=
kreal),
pointer :: a(:)
32 end type hecmwst_local_matrix
34 integer(kind=kint),
parameter :: cNCOL_ITEM = 3
35 integer(kind=kint),
parameter :: cLID = 1
36 integer(kind=kint),
parameter :: cRANK = 2
37 integer(kind=kint),
parameter :: cGID = 3
39 integer(kind=kint),
parameter :: DEBUG = 0
40 integer(kind=kint),
parameter :: DEBUG_MATRIX = 0
41 integer(kind=kint),
parameter :: TIMER = 0
47 type (hecmwst_local_matrix),
intent(in) :: tmat
48 integer(kind=kint),
intent(in) :: iunit
49 integer(kind=kint) :: nr, nc, nnz, ndof, ndof2, i, js, je, j, jj
50 character(len=64) :: fmt
56 write(iunit,
'(a,4i10)')
'nr, nc, nnz, ndof', nr, nc, nnz, ndof
57 write(iunit,
'(a)')
'i, j, A'
58 write(fmt,
'(a,i0,a)')
'(',ndof,
'f12.3)'
65 write(iunit,
'(2i10,f12.3)') i, jj, tmat%A(j)
67 write(iunit,
'(2i10)') i, jj
68 write(iunit,fmt) tmat%A((j-1)*ndof2+1:j*ndof2)
74 subroutine hecmw_localmat_write_size(Tmat,iunit)
76 type (hecmwst_local_matrix),
intent(in) :: tmat
77 integer(kind=kint),
intent(in) :: iunit
78 integer(kind=kint) :: nr, nc, nnz, ndof
83 write(iunit,
'(a,4i10)')
'nr, nc, nnz, ndof', nr, nc, nnz, ndof
84 end subroutine hecmw_localmat_write_size
86 subroutine hecmw_localmat_write_ij(Tmat,iunit)
88 type (hecmwst_local_matrix),
intent(in) :: tmat
89 integer(kind=kint),
intent(in) :: iunit
90 integer(kind=kint) :: nr, nc, nnz, ndof, i, js, je, j, jj
95 write(iunit,
'(a,4i10)')
'nr, nc, nnz, ndof', nr, nc, nnz, ndof
96 write(iunit,
'(a)')
'i, j'
102 write(iunit,
'(2i10)') i, jj
105 end subroutine hecmw_localmat_write_ij
109 type (hecmwst_local_matrix),
intent(in) :: tmat
110 integer,
intent(in) :: ndof
111 type (hecmwst_local_matrix),
intent(out) :: btmat
112 integer,
allocatable :: iw(:)
113 integer :: ndof2, i, icnt, idof, idx, ls, le, l, j, jb, k, lb0, jdof, ks, ke
116 if (mod(tmat%nr, ndof) /= 0 .or. mod(tmat%nc, ndof) /= 0)
then
117 write(0,*) tmat%nr, tmat%nc, ndof
118 stop
'ERROR: blocking_Tmat failed'
120 btmat%nr=tmat%nr/ndof
121 btmat%nc=tmat%nc/ndof
124 allocate(iw(btmat%nc))
125 allocate(btmat%index(0:btmat%nr))
132 ls=tmat%index(idx-1)+1
138 if (iw(k)==jb) cycle lcol
144 btmat%index(i)=btmat%index(i-1)+icnt
147 btmat%nnz=btmat%index(btmat%nr)
148 allocate(btmat%item(btmat%nnz))
149 allocate(btmat%A(btmat%nnz*ndof2))
156 ls=tmat%index(idx-1)+1
162 if (iw(k)==jb) cycle lcol2
172 btmat%item(lb0+k)=iw(k)
176 ls=tmat%index(idx-1)+1
181 jdof=mod((j-1), ndof)+1
182 ks=btmat%index(i-1)+1
185 if (btmat%item(k)==jb)
then
186 btmat%A((k-1)*ndof2+(idof-1)*ndof+jdof)=tmat%A(l)
190 stop
'ERROR: something wrong in blocking Tmat'
198 type (hecmwst_local_matrix),
intent(inout) :: tmat
199 deallocate(tmat%index)
200 if (
associated(tmat%item))
deallocate(tmat%item)
201 if (
associated(tmat%A))
deallocate(tmat%A)
209 iwS, num_lagrange, hecTKT)
213 type (hecmwst_local_matrix),
intent(inout) :: bttmat, btmat
215 integer(kind=kint),
intent(in) :: iws(:)
216 integer(kind=kint),
intent(in) :: num_lagrange
218 if (hecmesh%n_neighbor_pe == 0)
then
220 iws, num_lagrange, hectkt)
223 iws, num_lagrange, hectkt)
228 iwS, num_lagrange, hecTKT)
232 type (hecmwst_local_matrix),
intent(in) :: bttmat, btmat
234 integer(kind=kint),
intent(in) :: iws(:)
235 integer(kind=kint),
intent(in) :: num_lagrange
237 type (hecmwst_local_matrix) :: bttkt
238 real(kind=
kreal) :: num
242 call debug_write_matrix(bttkt,
'BTtKT(MPC)', debug_matrix)
247 call place_num_on_diag(bttkt, iws, num_lagrange, num)
248 call debug_write_matrix(bttkt,
'BTtKT(MPC) (place 1.0 on slave diag)', debug_matrix)
251 call make_new_hecmat(hecmat, bttkt, hectkt)
256 iwS, num_lagrange, hecTKT)
259 type (hecmwST_local_mesh),
intent(inout) :: hecMESH
260 type (hecmwST_local_matrix),
intent(inout) :: BTtmat, BTmat
261 type (hecmwST_matrix),
intent(in) :: hecMAT
262 integer(kind=kint),
intent(in) :: iwS(:)
263 integer(kind=kint),
intent(in) :: num_lagrange
264 type (hecmwST_matrix),
intent(inout) :: hecTKT
265 type (hecmwST_local_matrix) :: BKmat, BTtKmat, BTtKTmat
266 real(kind=
kreal) :: num
267 real(kind=
kreal) :: t0, t1
272 call debug_write_matrix(bkmat,
'BKmat (hecMAT)', debug_matrix)
274 if (timer >= 1)
write(0,
'(A,f10.4)')
"#### hecmw_trimatmul_TtKT_parallel (1) : ",t1-t0
278 if (debug >= 2)
write(0,*)
' DEBUG2: multiply Tt and K done'
279 call debug_write_matrix(bttkmat,
'BTtKmat', debug_matrix)
282 if (timer >= 1)
write(0,
'(A,f10.4)')
"#### hecmw_trimatmul_TtKT_parallel (2) : ",t1-t0
286 if (debug >= 2)
write(0,*)
' DEBUG2: multiply TtK and T done'
287 call debug_write_matrix(bttktmat,
'BTtKTmat', debug_matrix)
290 if (timer >= 1)
write(0,
'(A,f10.4)')
"#### hecmw_trimatmul_TtKT_parallel (3) : ",t1-t0
296 call place_num_on_diag(bttktmat, iws, num_lagrange, num)
304 call debug_write_matrix(bttktmat,
'BTtKTmat (place 1.0 on slave diag)', debug_matrix)
306 if (timer >= 1)
write(0,
'(A,f10.4)')
"#### hecmw_trimatmul_TtKT_parallel (4) : ",t1-t0
310 call make_new_hecmat(hecmat, bttktmat, hectkt)
313 if (timer >= 1)
write(0,
'(A,f10.4)')
"#### hecmw_trimatmul_TtKT_parallel (5) : ",t1-t0
318 type (hecmwST_local_matrix),
intent(in) :: BTtmat, BTmat
319 type (hecmwST_matrix),
intent(in) :: hecMAT
320 type (hecmwST_local_matrix),
intent(out) :: BTtKT
321 integer :: nr, nc, ndof, ndof2, i, icnt, js, je, j, jj, ks, ke, k, kk
322 integer :: ls, le, l, ll, m, ms, me, mm
323 integer,
allocatable :: iw(:)
324 real(kind=
kreal),
pointer :: ttp(:), kp(:), tp(:), ttktp(:)
335 allocate(bttkt%index(0:nr))
346 js=bttmat%index(i-1)+1
351 ks=hecmat%indexL(jj-1)+1
355 ls=btmat%index(kk-1)+1
360 if (iw(m)==ll) cycle ll1
368 ls=btmat%index(jj-1)+1
373 if (iw(m)==ll) cycle ll2
380 ks=hecmat%indexU(jj-1)+1
384 ls=btmat%index(kk-1)+1
389 if (iw(m)==ll) cycle ll3
397 if (icnt == 0) icnt=1
410 bttkt%index(i)=bttkt%index(i-1)+bttkt%index(i)
414 bttkt%nnz=bttkt%index(nr)
415 allocate(bttkt%item(bttkt%nnz))
416 allocate(bttkt%A(bttkt%nnz*ndof2))
429 ms=bttkt%index(i-1)+1
431 js=bttmat%index(i-1)+1
435 ttp=>bttmat%A((j-1)*ndof2+1:j*ndof2)
437 ks=hecmat%indexL(jj-1)+1
441 kp=>hecmat%AL((k-1)*ndof2+1:k*ndof2)
442 ls=btmat%index(kk-1)+1
446 tp=>btmat%A((l-1)*ndof2+1:l*ndof2)
450 if (bttkt%item(m)==ll) mm=m
458 ttktp=>bttkt%A((mm-1)*ndof2+1:mm*ndof2)
459 call blk_trimatmul_add(ndof, ttp, kp, tp, ttktp)
463 kp=>hecmat%D((jj-1)*ndof2+1:jj*ndof2)
464 ls=btmat%index(jj-1)+1
468 tp=>btmat%A((l-1)*ndof2+1:l*ndof2)
472 if (bttkt%item(m)==ll) mm=m
480 ttktp=>bttkt%A((mm-1)*ndof2+1:mm*ndof2)
481 call blk_trimatmul_add(ndof, ttp, kp, tp, ttktp)
484 ks=hecmat%indexU(jj-1)+1
488 kp=>hecmat%AU((k-1)*ndof2+1:k*ndof2)
489 ls=btmat%index(kk-1)+1
493 tp=>btmat%A((l-1)*ndof2+1:l*ndof2)
497 if (bttkt%item(m)==ll) mm=m
505 ttktp=>bttkt%A((mm-1)*ndof2+1:mm*ndof2)
506 call blk_trimatmul_add(ndof, ttp, kp, tp, ttktp)
517 if (ms-1+icnt /= bttkt%index(i)) stop
'ERROR: trimatmul'
526 subroutine blk_trimatmul_add(ndof, A, B, C, ABC)
528 integer,
intent(in) :: ndof
529 real(kind=
kreal),
intent(in) :: a(:), b(:), c(:)
530 real(kind=
kreal),
intent(inout) :: abc(:)
531 real(kind=
kreal),
allocatable :: ab(:)
532 integer :: ndof2, i, j, k, i0, j0, ij, ik, jk
546 ab(ik)=ab(ik)+a(ij)*b(jk)
559 abc(ik)=abc(ik)+ab(ij)*c(jk)
565 end subroutine blk_trimatmul_add
567 subroutine place_num_on_diag(BTtKT, iwS, num_lagrange, num)
569 type (hecmwST_local_matrix),
intent(inout) :: BTtKT
570 integer(kind=kint),
intent(in) :: iwS(:)
571 integer(kind=kint),
intent(in) :: num_lagrange
572 real(kind=
kreal),
intent(in) :: num
573 integer(kind=kint) :: ndof, ndof2, ilag, i, idof, js, je, j, jj
574 integer(kind=kint) :: nmissing, k, ks, ke
575 integer(kind=kint),
allocatable :: missing(:), cnt(:)
576 integer(kind=kint),
pointer :: index(:), item(:)
577 real(kind=
kreal),
pointer :: a(:)
583 allocate(missing(num_lagrange))
585 outer1:
do ilag=1,num_lagrange
586 i=(iws(ilag)-1)/ndof+1
587 idof=mod(iws(ilag)-1, ndof)+1
588 js=bttkt%index(i-1)+1
592 if (jj==i) cycle outer1
596 if (missing(k) == i) cycle outer1
598 nmissing = nmissing + 1
599 missing(nmissing) = i
603 if (nmissing > 0)
then
604 allocate(cnt(bttkt%nr))
605 allocate(index(0:bttkt%nr))
607 cnt(i) = bttkt%index(i) - bttkt%index(i-1)
610 cnt(missing(i)) = cnt(missing(i)) + 1
612 call make_index(bttkt%nr, cnt, index)
613 allocate(item(bttkt%nnz + nmissing))
614 allocate(a(ndof2 * (bttkt%nnz + nmissing)))
617 js=bttkt%index(i-1)+1
619 item(ks:ks+(je-js))=bttkt%item(js:je)
620 a(ndof2*(ks-1)+1:ndof2*(ks+(je-js)))=bttkt%A(ndof2*(js-1)+1:ndof2*je)
625 a(ndof2*(ke-1)+1:ndof2*ke)=0.d0
627 deallocate(bttkt%index)
628 deallocate(bttkt%item)
633 bttkt%nnz = index(bttkt%nr)
639 outer:
do ilag=1,num_lagrange
640 i=(iws(ilag)-1)/ndof+1
641 idof=mod(iws(ilag)-1, ndof)+1
642 js=bttkt%index(i-1)+1
648 bttkt%A((j-1)*ndof2+(idof-1)*ndof+idof)=num
653 end subroutine place_num_on_diag
655 subroutine replace_hecmat(hecMAT, BTtKT)
657 type (hecmwST_matrix),
intent(inout) :: hecMAT
658 type (hecmwST_local_matrix),
intent(in) :: BTtKT
659 integer :: nr, nc, ndof, ndof2, i, nl, nu, js, je, j, jj
660 integer :: ksl, ksu, k
668 if (
associated(hecmat%AL))
deallocate(hecmat%AL)
669 if (
associated(hecmat%AU))
deallocate(hecmat%AU)
670 if (
associated(hecmat%itemL))
deallocate(hecmat%itemL)
671 if (
associated(hecmat%itemU))
deallocate(hecmat%itemU)
682 js=bttkt%index(i-1)+1
703 hecmat%indexL(i)=hecmat%indexL(i-1)+hecmat%indexL(i)
704 hecmat%indexU(i)=hecmat%indexU(i-1)+hecmat%indexU(i)
706 hecmat%NPL=hecmat%indexL(nc)
707 hecmat%NPU=hecmat%indexU(nc)
710 allocate(hecmat%itemL(hecmat%NPL), hecmat%itemU(hecmat%NPU))
711 allocate(hecmat%AL(hecmat%NPL*ndof2), hecmat%AU(hecmat%NPU*ndof2))
725 js=bttkt%index(i-1)+1
727 ksl=hecmat%indexL(i-1)+1
728 ksu=hecmat%indexU(i-1)+1
734 hecmat%AL((k-1)*ndof2+1:k*ndof2)=bttkt%A((j-1)*ndof2+1:j*ndof2)
739 hecmat%AU((k-1)*ndof2+1:k*ndof2)=bttkt%A((j-1)*ndof2+1:j*ndof2)
742 hecmat%D((i-1)*ndof2+1:i*ndof2)=bttkt%A((j-1)*ndof2+1:j*ndof2)
759 end subroutine replace_hecmat
761 subroutine make_new_hecmat(hecMAT, BTtKT, hecTKT)
764 type(hecmwst_local_matrix),
intent(in) :: BTtKT
766 integer(kind=kint) :: nr, nc, ndof, ndof2
782 if (
associated(hectkt%D))
deallocate(hectkt%D)
783 allocate(hectkt%D(nc*ndof2))
785 if (
associated(hectkt%indexL))
deallocate(hectkt%indexL)
786 if (
associated(hectkt%indexU))
deallocate(hectkt%indexU)
787 allocate(hectkt%indexL(0:nc))
788 allocate(hectkt%indexU(0:nc))
790 hectkt%Iarray=hecmat%Iarray
791 hectkt%Rarray=hecmat%Rarray
793 call replace_hecmat(hectkt, bttkt)
794 end subroutine make_new_hecmat
798 type (hecmwst_local_matrix),
intent(in) :: btmat
799 real(kind=
kreal),
intent(in),
target :: v(:)
800 real(kind=
kreal),
intent(out),
target :: tv(:)
801 real(kind=
kreal),
pointer :: tvp(:), tp(:), vp(:)
802 integer :: nr, ndof, ndof2, i, js, je, j, jj, k, kl0, l
821 tvp=>tv((i-1)*ndof+1:i*ndof)
822 js=btmat%index(i-1)+1
826 tp=>btmat%A((j-1)*ndof2+1:j*ndof2)
827 vp=>v((jj-1)*ndof+1:jj*ndof)
831 tvp(k)=tvp(k)+tp(kl0+l)*vp(l)
845 type (hecmwst_local_matrix) :: btmat, bttmat
846 integer(kind=kint),
allocatable :: iws(:)
847 integer(kind=kint) :: ndof, n_mpc, i_mpc
848 integer(kind=kint) :: i, j, k, kk, ilag
849 integer(kind=kint) :: num_lagrange
850 real(kind=
kreal) :: t0, t1
854 outer:
do i=1,hecmesh%mpc%n_mpc
855 do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
856 if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
862 outer2:
do i=1,hecmesh%mpc%n_mpc
863 do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
864 if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer2
867 k=hecmesh%mpc%mpc_index(i-1)+1
868 kk=ndof*(hecmesh%mpc%mpc_item(k)-1)+hecmesh%mpc%mpc_dof(k)
875 if (timer >= 1)
write(0,
'(A,f10.4)')
"### hecmw_trimatmul_TtKT_mpc (1) : ",t1-t0
877 call make_btmat_mpc(hecmesh, ndof, btmat)
878 call debug_write_matrix(btmat,
'BTmat(MPC)', debug_matrix)
880 if (timer >= 1)
write(0,
'(A,f10.4)')
"### hecmw_trimatmul_TtKT_mpc (2) : ",t1-t0
888 call debug_write_matrix(bttmat,
'BTtmat(MPC)', debug_matrix)
892 do i=hecmesh%nn_internal+1, hecmesh%n_node
893 write(700+
hecmw_comm_get_rank(),*) i,hecmesh%node_ID(2*i-1),hecmesh%node_ID(2*i),hecmesh%global_node_ID(i)
897 if (timer >= 1)
write(0,
'(A,f10.4)')
"### hecmw_trimatmul_TtKT_mpc (3) : ",t1-t0
901 if (timer >= 1)
write(0,
'(A,f10.4)')
"### hecmw_trimatmul_TtKT_mpc (4) : ",t1-t0
905 do i=hecmesh%nn_internal+1, hecmesh%n_node
906 write(700+
hecmw_comm_get_rank(),*) i,hecmesh%node_ID(2*i-1),hecmesh%node_ID(2*i),hecmesh%global_node_ID(i)
910 if (
associated(hectkt%B))
deallocate(hectkt%B)
911 if (
associated(hectkt%X))
deallocate(hectkt%X)
912 num_lagrange =
size(hecmat%B) - hecmat%NP*ndof
913 allocate(hectkt%B(ndof*hectkt%NP + num_lagrange))
914 allocate(hectkt%X(ndof*hectkt%NP + num_lagrange))
917 do i=1, ndof*hecmat%NP
918 hectkt%B(i) = hecmat%B(i)
919 hectkt%X(i) = hecmat%X(i)
922 hectkt%B(ndof*hectkt%NP+i) = hecmat%B(ndof*hecmat%NP+i)
923 hectkt%X(ndof*hectkt%NP+i) = hecmat%X(ndof*hecmat%NP+i)
926 hectkt%X(iws(ilag)) = 0.d0
934 if (timer >= 1)
write(0,
'(A,f10.4)')
"### hecmw_trimatmul_TtKT_mpc (5) : ",t1-t0
937 subroutine make_btmat_mpc(hecMESH, ndof, BTmat)
940 integer(kind=kint),
intent(in) :: ndof
941 type (hecmwst_local_matrix),
intent(out) :: btmat
942 type (hecmwst_local_matrix) :: tmat
943 integer(kind=kint) :: n_mpc
944 integer(kind=kint) :: i,j,k,js,jj,kk
946 outer:
do i=1,hecmesh%mpc%n_mpc
947 do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
948 if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer
952 tmat%nr=hecmesh%n_node*ndof
955 allocate(tmat%index(0:tmat%nr))
957 tmat%index(1:tmat%nr)=1
958 outer2:
do i=1,hecmesh%mpc%n_mpc
959 do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
960 if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer2
962 k=hecmesh%mpc%mpc_index(i-1)+1
963 kk=ndof*(hecmesh%mpc%mpc_item(k)-1)+hecmesh%mpc%mpc_dof(k)
964 tmat%index(kk)=hecmesh%mpc%mpc_index(i)-hecmesh%mpc%mpc_index(i-1)-1
969 tmat%index(i)=tmat%index(i-1)+tmat%index(i)
971 tmat%nnz=tmat%index(tmat%nr)
972 allocate(tmat%item(tmat%nnz), tmat%A(tmat%nnz))
980 outer3:
do i=1,hecmesh%mpc%n_mpc
981 do j= hecmesh%mpc%mpc_index(i-1) + 1, hecmesh%mpc%mpc_index(i)
982 if (hecmesh%mpc%mpc_dof(j) > ndof) cycle outer3
984 k=hecmesh%mpc%mpc_index(i-1)+1
985 kk=ndof*(hecmesh%mpc%mpc_item(k)-1)+hecmesh%mpc%mpc_dof(k)
986 js=tmat%index(kk-1)+1
987 do j= hecmesh%mpc%mpc_index(i-1) + 2, hecmesh%mpc%mpc_index(i)
988 jj = ndof * (hecmesh%mpc%mpc_item(j) - 1) + hecmesh%mpc%mpc_dof(j)
990 tmat%A(js)=-hecmesh%mpc%mpc_val(j)
997 end subroutine make_btmat_mpc
1002 type (hecmwst_local_matrix),
intent(in) :: tmat
1003 type (hecmwst_local_matrix),
intent(out) :: ttmat
1004 integer(kind=kint),
allocatable :: iw(:)
1005 integer(kind=kint) :: i, j, jj, ndof, ndof2, k, idof, jdof
1006 allocate(iw(tmat%nc))
1009 do j = tmat%index(i-1)+1, tmat%index(i)
1016 ttmat%nnz = tmat%nnz
1017 ttmat%ndof = tmat%ndof
1020 allocate(ttmat%index(0:ttmat%nr))
1021 allocate(ttmat%item(ttmat%nnz))
1022 allocate(ttmat%A(ttmat%nnz*ndof2))
1025 ttmat%index(i) = ttmat%index(i-1) + iw(i)
1026 iw(i) = ttmat%index(i-1) + 1
1029 do j = tmat%index(i-1)+1, tmat%index(i)
1035 ttmat%A((k-1)*ndof2+(idof-1)*ndof+jdof) = &
1036 tmat%A((j-1)*ndof2+(jdof-1)*ndof+idof)
1044 function hecmw_localmat_equal(Tmat1, Tmat2)
1046 type (hecmwst_local_matrix),
intent(in) :: tmat1, tmat2
1047 integer(kind=kint) :: hecmw_localmat_equal
1048 integer(kind=kint) :: i, j, k0, k, ndof, ndof2
1049 hecmw_localmat_equal = 0
1050 if (tmat1%nr /= tmat2%nr)
return
1051 if (tmat1%nc /= tmat2%nc)
return
1052 if (tmat1%nnz /= tmat2%nnz)
return
1053 if (tmat1%ndof /= tmat2%ndof)
return
1057 if (tmat1%index(i) /= tmat2%index(i))
return
1058 do j = tmat1%index(i-1)+1, tmat1%index(i)
1059 if (tmat1%item(j) /= tmat2%item(j))
return
1062 if (tmat1%A(k0+k) /= tmat2%A(k0+k))
return
1066 hecmw_localmat_equal = 1
1067 end function hecmw_localmat_equal
1075 type (hecmwst_local_matrix),
intent(inout) :: btmat
1078 integer(kind=kint) :: nn_int, np, ndof, ndof2, nr_ext, nnz_ext
1079 integer(kind=kint),
allocatable :: exp_rows_index(:), exp_cols_index(:)
1080 integer(kind=kint),
allocatable :: exp_rows_item(:,:), exp_cols_item(:,:)
1081 type (hecmwst_local_matrix),
allocatable :: bt_ext(:)
1082 type (hecmwst_local_matrix) :: bt_int
1083 type (hecmwst_local_matrix) :: btnew
1085 if (debug >= 1)
write(0,*)
'DEBUG: nr,nc,nnz,ndof',btmat%nr,btmat%nc,btmat%nnz,btmat%ndof
1086 if (btmat%nr /= hecmesh%n_node) stop
'ERROR: invalid size in hecmw_localmat_assemble'
1088 nn_int = hecmesh%nn_internal
1093 nr_ext = np - nn_int
1094 nnz_ext = btmat%index(np) - btmat%index(nn_int)
1096 call prepare_bt_ext(btmat, hecmesh, exp_rows_index, exp_rows_item, bt_ext)
1097 if (debug >= 1)
write(0,*)
'DEBUG: prepare_BT_ext done'
1099 call prepare_column_info(hecmesh, bt_ext, exp_cols_index, exp_cols_item)
1100 if (debug >= 1)
write(0,*)
'DEBUG: prepare_column info done'
1102 call send_bt_ext_and_recv_bt_int(hecmesh, exp_rows_index, exp_rows_item, bt_ext, &
1103 exp_cols_index, exp_cols_item, bt_int, hecmeshnew)
1104 if (debug >= 1)
write(0,*)
'DEBUG: send BT_ext and recv BT_int done'
1108 if (debug >= 1)
write(0,*)
'DEBUG: localmat_add done'
1115 btmat%nnz = btnew%nnz
1116 btmat%ndof = btnew%ndof
1117 btmat%index => btnew%index
1118 btmat%item => btnew%item
1138 if (debug >= 1)
write(0,*)
'DEBUG: update BTmat and hecMESH done'
1141 subroutine prepare_bt_ext(BTmat, hecMESH, exp_rows_index, exp_rows_item, BT_ext)
1143 type (hecmwst_local_matrix),
intent(in) :: btmat
1145 integer(kind=kint),
allocatable,
intent(out) :: exp_rows_index(:)
1146 integer(kind=kint),
allocatable,
intent(out) :: exp_rows_item(:,:)
1147 type (hecmwst_local_matrix),
allocatable,
intent(out) :: bt_ext(:)
1148 integer(kind=kint),
allocatable :: incl_nz(:), exp_cols_per_row(:), exp_rows_per_rank(:)
1149 integer(kind=kint) :: nn_int
1150 logical,
parameter :: flg_check_nonzero_numerically = .true.
1151 nn_int = hecmesh%nn_internal
1153 if (flg_check_nonzero_numerically)
then
1156 call check_external_nz_blocks(btmat, nn_int, incl_nz)
1159 call incl_all_external_nz_blocks(btmat, nn_int, incl_nz)
1162 call count_ext_rows_with_nz(btmat, nn_int, incl_nz, exp_cols_per_row)
1164 call count_exp_rows_per_rank(hecmesh, exp_cols_per_row, exp_rows_per_rank)
1166 allocate(exp_rows_index(0:hecmesh%n_neighbor_pe))
1167 call make_index(hecmesh%n_neighbor_pe, exp_rows_per_rank, exp_rows_index)
1170 deallocate(exp_rows_per_rank)
1172 call make_exp_rows_item(hecmesh, exp_cols_per_row, exp_rows_index, exp_rows_item)
1174 deallocate(exp_cols_per_row)
1176 allocate(bt_ext(hecmesh%n_neighbor_pe))
1177 call extract_bt_ext(hecmesh, btmat, incl_nz, exp_rows_index, exp_rows_item, bt_ext)
1180 end subroutine prepare_bt_ext
1182 subroutine check_external_nz_blocks(BTmat, nn_internal, incl_nz)
1184 type (hecmwst_local_matrix),
intent(in) :: btmat
1185 integer(kind=kint),
intent(in) :: nn_internal
1186 integer(kind=kint),
allocatable,
intent(out) :: incl_nz(:)
1187 integer(kind=kint) :: ndof2, i0, nnz_ext, i, k, nnz_blk
1188 if (nn_internal > btmat%nr) stop
'ERROR: invalid nn_internal'
1189 ndof2 = btmat%ndof ** 2
1190 i0 = btmat%index(nn_internal)
1191 nnz_ext = btmat%index(btmat%nr) - i0
1192 allocate(incl_nz(nnz_ext))
1197 if (btmat%A(ndof2*(i0+i-1)+k) /= 0.0d0)
then
1199 nnz_blk = nnz_blk + 1
1204 if (debug >= 1)
write(0,*)
'DEBUG: nnz_blk',nnz_blk
1205 end subroutine check_external_nz_blocks
1207 subroutine incl_all_external_nz_blocks(BTmat, nn_internal, incl_nz)
1209 type (hecmwst_local_matrix),
intent(in) :: btmat
1210 integer(kind=kint),
intent(in) :: nn_internal
1211 integer(kind=kint),
allocatable,
intent(out) :: incl_nz(:)
1212 integer(kind=kint) :: i0, nnz_ext
1213 if (nn_internal > btmat%nr) stop
'ERROR: invalid nn_internal'
1214 i0 = btmat%index(nn_internal)
1215 nnz_ext = btmat%index(btmat%nr) - i0
1216 allocate(incl_nz(nnz_ext))
1217 incl_nz(1:nnz_ext) = 1
1218 end subroutine incl_all_external_nz_blocks
1220 subroutine count_ext_rows_with_nz(BTmat, nn_internal, incl_nz, exp_cols_per_row)
1222 type (hecmwst_local_matrix),
intent(in) :: btmat
1223 integer(kind=kint),
intent(in) :: nn_internal
1224 integer(kind=kint),
intent(in) :: incl_nz(:)
1225 integer(kind=kint),
allocatable,
intent(out) :: exp_cols_per_row(:)
1226 integer(kind=kint) :: nr_ext, nnz_int, i, irow, js, je, j, jcol
1227 nr_ext = btmat%nr - nn_internal
1228 nnz_int = btmat%index(nn_internal)
1229 allocate(exp_cols_per_row(nr_ext))
1230 exp_cols_per_row(:) = 0
1232 irow = nn_internal+i
1233 js = btmat%index(irow-1)+1
1234 je = btmat%index(irow)
1236 jcol = btmat%item(j)
1237 if (incl_nz(j-nnz_int) == 1) exp_cols_per_row(i) = exp_cols_per_row(i) + 1
1241 end subroutine count_ext_rows_with_nz
1243 subroutine count_exp_rows_per_rank(hecMESH, exp_cols_per_row, exp_rows_per_rank)
1246 integer(kind=kint),
intent(in) :: exp_cols_per_row(:)
1247 integer(kind=kint),
allocatable,
intent(out) :: exp_rows_per_rank(:)
1248 integer(kind=kint) :: nn_int, np, nr_ext, i, irow, exp_rank, idom
1249 allocate(exp_rows_per_rank(hecmesh%n_neighbor_pe))
1250 exp_rows_per_rank(1:hecmesh%n_neighbor_pe) = 0
1251 nn_int = hecmesh%nn_internal
1253 nr_ext = np - nn_int
1255 if (exp_cols_per_row(i) > 0)
then
1257 exp_rank = hecmesh%node_ID(2*irow)
1258 call rank_to_idom(hecmesh, exp_rank, idom)
1259 exp_rows_per_rank(idom) = exp_rows_per_rank(idom) + 1
1263 end subroutine count_exp_rows_per_rank
1265 subroutine rank_to_idom(hecMESH, rank, idom)
1268 integer(kind=kint),
intent(in) :: rank
1269 integer(kind=kint),
intent(out) :: idom
1270 integer(kind=kint) :: i
1271 do i = 1, hecmesh%n_neighbor_pe
1272 if (hecmesh%neighbor_pe(i) == rank)
then
1277 stop
'ERROR: exp_rank not found in neighbor_pe'
1278 end subroutine rank_to_idom
1280 subroutine make_index(len, cnt, index)
1282 integer(kind=kint),
intent(in) :: len
1283 integer(kind=kint),
intent(in) :: cnt(len)
1284 integer(kind=kint),
intent(out) :: index(0:)
1285 integer(kind=kint) :: i
1289 index(i) = index(i-1) + cnt(i)
1291 end subroutine make_index
1293 subroutine make_exp_rows_item(hecMESH, exp_cols_per_row, exp_rows_index, exp_rows_item)
1296 integer(kind=kint),
intent(in) :: exp_cols_per_row(:)
1297 integer(kind=kint),
allocatable,
intent(in) :: exp_rows_index(:)
1298 integer(kind=kint),
allocatable,
intent(out) :: exp_rows_item(:,:)
1299 integer(kind=kint),
allocatable :: cnt(:)
1300 integer(kind=kint) :: nn_int, np, nr_ext, i, irow, exp_rank, idom, idx
1301 allocate(exp_rows_item(2,exp_rows_index(hecmesh%n_neighbor_pe)))
1302 allocate(cnt(hecmesh%n_neighbor_pe))
1304 nn_int = hecmesh%nn_internal
1306 nr_ext = np - nn_int
1308 if (exp_cols_per_row(i) > 0)
then
1310 exp_rank = hecmesh%node_ID(2*irow)
1311 call rank_to_idom(hecmesh, exp_rank, idom)
1312 cnt(idom) = cnt(idom) + 1
1313 idx = exp_rows_index(idom-1) + cnt(idom)
1314 exp_rows_item(1,idx) = irow
1315 exp_rows_item(2,idx) = exp_cols_per_row(i)
1319 do idom = 1, hecmesh%n_neighbor_pe
1320 if (cnt(idom) /= exp_rows_index(idom)-exp_rows_index(idom-1)) stop
'ERROR: make exp_rows_item'
1324 end subroutine make_exp_rows_item
1326 subroutine extract_bt_ext(hecMESH, BTmat, incl_nz, exp_rows_index, exp_rows_item, BT_ext)
1329 type (hecmwst_local_matrix),
intent(in) :: btmat
1330 integer(kind=kint),
intent(in) :: incl_nz(:)
1331 integer(kind=kint),
allocatable,
intent(in) :: exp_rows_index(:)
1332 integer(kind=kint),
intent(in) :: exp_rows_item(:,:)
1333 type (hecmwst_local_matrix),
allocatable,
intent(out) :: bt_ext(:)
1334 integer(kind=kint) :: ndof, ndof2, nn_int, nnz_int, idom, j, idx, ncol, cnt, jrow, ks, ke, k, kcol
1335 allocate(bt_ext(hecmesh%n_neighbor_pe))
1338 nn_int = hecmesh%nn_internal
1339 nnz_int = btmat%index(nn_int)
1340 do idom = 1, hecmesh%n_neighbor_pe
1341 bt_ext(idom)%nr = exp_rows_index(idom) - exp_rows_index(idom-1)
1342 bt_ext(idom)%nc = btmat%nc
1343 bt_ext(idom)%nnz = 0
1344 bt_ext(idom)%ndof = ndof
1345 allocate(bt_ext(idom)%index(0:bt_ext(idom)%nr))
1346 bt_ext(idom)%index(0) = 0
1347 do j = 1, bt_ext(idom)%nr
1348 idx = exp_rows_index(idom-1) + j
1349 ncol = exp_rows_item(2,idx)
1350 bt_ext(idom)%index(j) = bt_ext(idom)%index(j-1) + ncol
1352 bt_ext(idom)%nnz = bt_ext(idom)%index(bt_ext(idom)%nr)
1353 if (debug >= 1)
write(0,*)
'DEBUG: idom,nr,nc,nnz,ndof', &
1354 idom,bt_ext(idom)%nr,bt_ext(idom)%nc,bt_ext(idom)%nnz,bt_ext(idom)%ndof
1355 allocate(bt_ext(idom)%item(bt_ext(idom)%nnz))
1356 allocate(bt_ext(idom)%A(bt_ext(idom)%nnz * ndof2))
1358 do j = 1, bt_ext(idom)%nr
1359 idx = exp_rows_index(idom-1) + j
1360 jrow = exp_rows_item(1,idx)
1361 if (jrow < 1 .or. btmat%nr < jrow) stop
'ERROR: extract BT_ext: jrow'
1362 ks = btmat%index(jrow-1)+1
1363 ke = btmat%index(jrow)
1365 kcol = btmat%item(k)
1366 if (incl_nz(k-nnz_int) == 0) cycle
1368 bt_ext(idom)%item(cnt) = kcol
1369 bt_ext(idom)%A(ndof2*(cnt-1)+1:ndof2*cnt) = btmat%A(ndof2*(k-1)+1:ndof2*k)
1371 if (cnt /= bt_ext(idom)%index(j)) stop
'ERROR: extract BT_ext'
1376 end subroutine extract_bt_ext
1378 subroutine prepare_column_info(hecMESH, BT_ext, exp_cols_index, exp_cols_item)
1381 type (hecmwst_local_matrix),
intent(in) :: bt_ext(:)
1382 integer(kind=kint),
allocatable,
intent(out) :: exp_cols_index(:)
1383 integer(kind=kint),
allocatable,
intent(out) :: exp_cols_item(:,:)
1385 call make_exp_cols_index(hecmesh%n_neighbor_pe, bt_ext, exp_cols_index)
1386 if (debug >= 2)
write(0,*)
' DEBUG2: make exp_cols_index done'
1387 if (debug >= 3)
write(0,*)
' DEBUG3: exp_cols_index', exp_cols_index(0:hecmesh%n_neighbor_pe)
1391 call make_exp_cols_item(hecmesh, bt_ext, exp_cols_index, exp_cols_item)
1392 if (debug >= 2)
write(0,*)
' DEBUG2: make exp_cols_item done'
1394 end subroutine prepare_column_info
1396 subroutine make_exp_cols_index(nnb, BT_ext, exp_cols_index)
1398 integer(kind=kint),
intent(in) :: nnb
1399 type (hecmwst_local_matrix),
intent(in) :: bt_ext(:)
1400 integer(kind=kint),
allocatable,
intent(out) :: exp_cols_index(:)
1401 integer(kind=kint) :: idom
1402 allocate(exp_cols_index(0:nnb))
1403 exp_cols_index(0) = 0
1405 exp_cols_index(idom) = exp_cols_index(idom-1) + bt_ext(idom)%nnz
1407 end subroutine make_exp_cols_index
1409 subroutine make_exp_cols_item(hecMESH, BT_ext, exp_cols_index, exp_cols_item)
1412 type (hecmwst_local_matrix),
intent(in) :: bt_ext(:)
1413 integer(kind=kint),
allocatable,
intent(in) :: exp_cols_index(:)
1414 integer(kind=kint),
allocatable,
intent(out) :: exp_cols_item(:,:)
1415 integer(kind=kint) :: cnt, idom, j, jcol
1416 allocate(exp_cols_item(cncol_item,exp_cols_index(hecmesh%n_neighbor_pe)))
1418 do idom = 1, hecmesh%n_neighbor_pe
1419 do j = 1, bt_ext(idom)%nnz
1421 jcol = bt_ext(idom)%item(j)
1427 exp_cols_item(clid,cnt) = hecmesh%node_ID(2*jcol-1)
1428 exp_cols_item(crank,cnt) = hecmesh%node_ID(2*jcol)
1429 if (cncol_item >= 3) exp_cols_item(cgid,cnt) = hecmesh%global_node_ID(jcol)
1432 if (cnt /= exp_cols_index(idom)) stop
'ERROR: make exp_cols_item'
1434 end subroutine make_exp_cols_item
1436 subroutine send_bt_ext_and_recv_bt_int(hecMESH, exp_rows_index, exp_rows_item, BT_ext, &
1437 exp_cols_index, exp_cols_item, BT_int, hecMESHnew)
1440 integer(kind=kint),
allocatable,
intent(inout) :: exp_rows_index(:), exp_cols_index(:)
1441 integer(kind=kint),
allocatable,
intent(inout) :: exp_rows_item(:,:), exp_cols_item(:,:)
1442 type (hecmwst_local_matrix),
allocatable,
intent(inout) :: bt_ext(:)
1443 type (hecmwst_local_matrix),
intent(out) :: bt_int
1445 integer(kind=kint),
allocatable :: imp_rows_index(:), imp_cols_index(:)
1446 integer(kind=kint),
allocatable :: imp_rows_item(:,:), imp_cols_item(:,:)
1447 real(kind=
kreal),
allocatable :: imp_vals_item(:)
1448 integer(kind=kint),
allocatable :: map(:), add_nodes(:,:)
1449 integer(kind=kint) :: ndof, ndof2, idom, n_add_node, i0
1450 if (hecmesh%n_neighbor_pe == 0)
return
1451 ndof = bt_ext(1)%ndof
1454 call convert_rowid_to_remote_localid(hecmesh, exp_rows_index(hecmesh%n_neighbor_pe), exp_rows_item)
1455 if (debug >= 2)
write(0,*)
' DEBUG2: convert rowID to remote localID done'
1457 call send_recv_bt_ext_nr_nnz(hecmesh, bt_ext, imp_rows_index, imp_cols_index)
1458 if (debug >= 2)
write(0,*)
' DEBUG2: send recv BT_ext nr and nnz done'
1461 exp_rows_index, exp_cols_index, exp_rows_item, exp_cols_item, &
1462 imp_rows_index, imp_cols_index, &
1463 imp_rows_item, imp_cols_item, imp_vals_item)
1464 if (debug >= 2)
write(0,*)
' DEBUG2: send recv BT_ext contents done'
1466 do idom = 1, hecmesh%n_neighbor_pe
1471 call allocate_bt_int(hecmesh, ndof, imp_rows_index, imp_rows_item, bt_int)
1472 if (debug >= 2)
write(0,*)
' DEBUG2: allocate BT_int done'
1477 call map_imported_cols(hecmeshnew, imp_cols_index(hecmesh%n_neighbor_pe), &
1478 imp_cols_item, n_add_node, add_nodes, map, i0)
1479 if (debug >= 2)
write(0,*)
' DEBUG2: map imported cols done'
1481 call update_comm_table(hecmeshnew, n_add_node, add_nodes, i0)
1482 if (debug >= 2)
write(0,*)
' DEBUG2: update comm_table done'
1484 bt_int%nc = hecmeshnew%n_node
1486 call copy_vals_to_bt_int(hecmesh%n_neighbor_pe, imp_rows_index, imp_cols_index, &
1487 imp_rows_item, map, ndof2, imp_vals_item, bt_int)
1488 if (debug >= 2)
write(0,*)
' DEBUG2: copy vals to BT_int done'
1490 deallocate(imp_rows_index)
1491 deallocate(imp_cols_index)
1492 deallocate(imp_rows_item)
1493 deallocate(imp_cols_item)
1494 deallocate(imp_vals_item)
1497 call sort_and_uniq_rows(bt_int)
1498 if (debug >= 2)
write(0,*)
' DEBUG2: sort and uniq rows of BT_int done'
1499 end subroutine send_bt_ext_and_recv_bt_int
1501 subroutine convert_rowid_to_remote_localid(hecMESH, len, exp_rows_item)
1504 integer(kind=kint),
intent(in) :: len
1505 integer(kind=kint),
intent(out) :: exp_rows_item(:,:)
1506 integer(kind=kint) :: i
1508 exp_rows_item(1,i) = hecmesh%node_ID(2 * exp_rows_item(1,i) - 1)
1510 end subroutine convert_rowid_to_remote_localid
1512 subroutine send_recv_bt_ext_nr_nnz(hecMESH, BT_ext, imp_rows_index, imp_cols_index)
1516 type (hecmwst_local_matrix),
intent(in) :: bt_ext(:)
1517 integer(kind=kint),
allocatable,
intent(out) :: imp_rows_index(:), imp_cols_index(:)
1518 integer(kind=kint) :: nnb, idom, irank, tag, recvbuf(2)
1519 integer(kind=kint),
allocatable :: sendbuf(:,:)
1520 integer(kind=kint),
allocatable :: requests(:)
1521 integer(kind=kint),
allocatable :: statuses(:,:)
1522 nnb = hecmesh%n_neighbor_pe
1523 allocate(imp_rows_index(0:nnb))
1524 allocate(imp_cols_index(0:nnb))
1525 allocate(requests(nnb))
1527 allocate(sendbuf(2,nnb))
1529 irank = hecmesh%neighbor_pe(idom)
1531 sendbuf(1,idom) = bt_ext(idom)%nr
1532 sendbuf(2,idom) = bt_ext(idom)%nnz
1534 call hecmw_isend_int(sendbuf(1,idom), 2, irank, tag, hecmesh%MPI_COMM, &
1537 imp_rows_index(0) = 0
1538 imp_cols_index(0) = 0
1540 irank = hecmesh%neighbor_pe(idom)
1543 hecmesh%MPI_COMM, statuses(:,1))
1544 imp_rows_index(idom) = imp_rows_index(idom-1) + recvbuf(1)
1545 imp_cols_index(idom) = imp_cols_index(idom-1) + recvbuf(2)
1548 deallocate(requests)
1549 deallocate(statuses)
1551 end subroutine send_recv_bt_ext_nr_nnz
1554 exp_rows_index, exp_cols_index, exp_rows_item, exp_cols_item, &
1555 imp_rows_index, imp_cols_index, &
1556 imp_rows_item, imp_cols_item, imp_vals_item)
1559 type (hecmwST_local_mesh),
intent(in) :: hecMESH
1560 type (hecmwST_local_matrix),
intent(in) :: BT_ext(:)
1561 integer(kind=kint),
allocatable,
intent(inout) :: exp_rows_index(:), exp_cols_index(:)
1562 integer(kind=kint),
allocatable,
intent(inout) :: exp_rows_item(:,:), exp_cols_item(:,:)
1563 integer(kind=kint),
allocatable,
intent(in) :: imp_rows_index(:), imp_cols_index(:)
1564 integer(kind=kint),
allocatable,
intent(out) :: imp_rows_item(:,:), imp_cols_item(:,:)
1565 real(kind=
kreal),
allocatable,
intent(out) :: imp_vals_item(:)
1566 integer(kind=kint) :: nnb, ndof2, n_send, idom, irank, tag, nr, nnz
1567 integer(kind=kint),
allocatable :: requests(:)
1568 integer(kind=kint),
allocatable :: statuses(:,:)
1569 nnb = hecmesh%n_neighbor_pe
1571 ndof2 = bt_ext(1)%ndof ** 2
1572 allocate(imp_rows_item(2,imp_rows_index(nnb)))
1573 allocate(imp_cols_item(cncol_item,imp_cols_index(nnb)))
1574 allocate(imp_vals_item(ndof2*imp_cols_index(nnb)))
1575 allocate(requests(3*nnb))
1579 irank = hecmesh%neighbor_pe(idom)
1580 if (bt_ext(idom)%nr > 0)
then
1584 2*bt_ext(idom)%nr, irank, tag, hecmesh%MPI_COMM, &
1589 cncol_item*bt_ext(idom)%nnz, irank, tag, hecmesh%MPI_COMM, &
1593 call hecmw_isend_r(bt_ext(idom)%A, ndof2*bt_ext(idom)%nnz, irank, &
1594 tag, hecmesh%MPI_COMM, requests(n_send))
1598 irank = hecmesh%neighbor_pe(idom)
1599 nr = imp_rows_index(idom) - imp_rows_index(idom-1)
1600 nnz = imp_cols_index(idom) - imp_cols_index(idom-1)
1604 2*nr, irank, tag, hecmesh%MPI_COMM, statuses(:,1))
1607 cncol_item*nnz, irank, tag, hecmesh%MPI_COMM, statuses(:,1))
1609 call hecmw_recv_r(imp_vals_item(ndof2*imp_cols_index(idom-1)+1), &
1610 ndof2*nnz, irank, tag, hecmesh%MPI_COMM, statuses(:,1))
1614 deallocate(exp_rows_index)
1615 deallocate(exp_rows_item)
1616 deallocate(exp_cols_index)
1617 deallocate(exp_cols_item)
1622 type (hecmwST_local_mesh),
intent(in) :: hecMESH
1623 integer(kind=kint),
intent(in) :: ndof
1624 integer(kind=kint),
allocatable,
intent(in) :: imp_rows_index(:), imp_rows_item(:,:)
1625 type (hecmwST_local_matrix),
intent(out) :: BT_int
1626 integer(kind=kint),
allocatable :: cnt(:)
1627 integer(kind=kint) :: idom, is, ie, i, irow, ncol, ndof2
1629 bt_int%nr = hecmesh%nn_internal
1630 bt_int%nc = hecmesh%n_node
1633 allocate(cnt(bt_int%nr))
1635 do idom = 1, hecmesh%n_neighbor_pe
1636 is = imp_rows_index(idom-1)+1
1637 ie = imp_rows_index(idom)
1639 irow = imp_rows_item(1,i)
1640 ncol = imp_rows_item(2,i)
1641 if (irow < 1 .or. bt_int%nr < irow) stop
'ERROR: allocate BT_int'
1642 cnt(irow) = cnt(irow) + ncol
1646 allocate(bt_int%index(0:bt_int%nr))
1647 call make_index(bt_int%nr, cnt, bt_int%index)
1649 bt_int%nnz = bt_int%index(bt_int%nr)
1650 allocate(bt_int%item(bt_int%nnz))
1651 allocate(bt_int%A(bt_int%nnz * ndof2))
1655 subroutine copy_mesh(src, dst)
1657 type (hecmwST_local_mesh),
intent(in) :: src
1658 type (hecmwST_local_mesh),
intent(out) :: dst
1660 dst%MPI_COMM = src%MPI_COMM
1661 dst%PETOT = src%PETOT
1662 dst%PEsmpTOT = src%PEsmpTOT
1663 dst%my_rank = src%my_rank
1664 dst%n_subdomain = src%n_subdomain
1665 dst%n_node = src%n_node
1666 dst%nn_internal = src%nn_internal
1667 dst%n_dof = src%n_dof
1668 dst%n_neighbor_pe = src%n_neighbor_pe
1669 allocate(dst%neighbor_pe(dst%n_neighbor_pe))
1670 dst%neighbor_pe(:) = src%neighbor_pe(:)
1671 allocate(dst%import_index(0:dst%n_neighbor_pe))
1672 allocate(dst%export_index(0:dst%n_neighbor_pe))
1673 dst%import_index(:)= src%import_index(:)
1674 dst%export_index(:)= src%export_index(:)
1675 allocate(dst%import_item(dst%import_index(dst%n_neighbor_pe)))
1676 dst%import_item(:) = src%import_item(:)
1677 allocate(dst%export_item(dst%export_index(dst%n_neighbor_pe)))
1678 dst%export_item(:) = src%export_item(:)
1679 allocate(dst%node_ID(2*dst%n_node))
1680 dst%node_ID(1:2*dst%n_node) = src%node_ID(1:2*src%n_node)
1681 allocate(dst%global_node_ID(dst%n_node))
1682 dst%global_node_ID(1:dst%n_node) = src%global_node_ID(1:src%n_node)
1684 dst%node => src%node
1685 end subroutine copy_mesh
1687 subroutine map_imported_cols(hecMESHnew, ncols, cols, n_add_node, add_nodes, map, i0)
1689 type (hecmwST_local_mesh),
intent(inout) :: hecMESHnew
1690 integer(kind=kint),
intent(in) :: ncols
1691 integer(kind=kint),
intent(in) :: cols(cNCOL_ITEM,ncols)
1692 integer(kind=kint),
allocatable,
intent(out) :: map(:)
1693 integer(kind=kint),
intent(out) :: n_add_node
1694 integer(kind=kint),
allocatable,
intent(out) :: add_nodes(:,:)
1695 integer(kind=kint),
intent(out) :: i0
1696 allocate(map(ncols))
1698 call map_present_nodes(hecmeshnew, ncols, cols, map, n_add_node)
1702 call extract_add_nodes(ncols, cols, map, n_add_node, add_nodes)
1704 call append_nodes(hecmeshnew, n_add_node, add_nodes, i0)
1706 call map_additional_nodes(ncols, cols, n_add_node, add_nodes, i0, map)
1707 end subroutine map_imported_cols
1709 subroutine map_present_nodes(hecMESH, ncols, cols, map, n_add_node)
1711 type (hecmwST_local_mesh),
intent(in) :: hecMESH
1712 integer(kind=kint),
intent(in) :: ncols
1713 integer(kind=kint),
intent(in) :: cols(cNCOL_ITEM,ncols)
1714 integer(kind=kint),
intent(out) :: map(ncols)
1715 integer(kind=kint),
intent(out) :: n_add_node
1716 integer(kind=kint) :: i, j, lid, rank, llid, n_ext_node, idx
1717 integer(kind=kint),
allocatable :: ext_node(:)
1718 type (hecmwST_pair_array) :: parray
1721 do i = hecmesh%nn_internal + 1, hecmesh%n_node
1728 allocate(ext_node(ncols))
1736 rank = cols(crank,i)
1738 if (rank == hecmesh%my_rank)
then
1742 n_ext_node = n_ext_node + 1
1750 do j = 1, n_ext_node
1753 rank = cols(crank,i)
1760 n_add_node = n_add_node + 1
1765 deallocate(ext_node)
1768 end subroutine map_present_nodes
1770 subroutine extract_add_nodes(ncols, cols, map, n_add_node, add_nodes)
1772 integer(kind=kint),
intent(in) :: ncols
1773 integer(kind=kint),
intent(in) :: cols(cNCOL_ITEM,ncols), map(ncols)
1774 integer(kind=kint),
intent(inout) :: n_add_node
1775 integer(kind=kint),
allocatable,
intent(out) :: add_nodes(:,:)
1776 integer(kind=kint) :: cnt, i
1777 allocate(add_nodes(cncol_item,n_add_node))
1780 if (map(i) == -1)
then
1782 add_nodes(1:cncol_item,cnt) = cols(1:cncol_item,i)
1785 if (cnt /= n_add_node) stop
'ERROR: extract add_nodes'
1786 call sort_and_uniq_add_nodes(n_add_node, add_nodes)
1787 end subroutine extract_add_nodes
1789 subroutine sort_and_uniq_add_nodes(n_add_node, add_nodes)
1791 integer(kind=kint),
intent(inout) :: n_add_node
1792 integer(kind=kint),
intent(inout) :: add_nodes(cNCOL_ITEM,n_add_node)
1793 integer(kind=kint) :: ndup
1794 call sort_add_nodes(add_nodes, 1, n_add_node)
1795 call uniq_add_nodes(add_nodes, n_add_node, ndup)
1796 n_add_node = n_add_node - ndup
1797 end subroutine sort_and_uniq_add_nodes
1799 recursive subroutine sort_add_nodes(add_nodes, id1, id2)
1801 integer(kind=kint),
intent(inout) :: add_nodes(:,:)
1802 integer(kind=kint),
intent(in) :: id1, id2
1803 integer(kind=kint) :: center, left, right
1804 integer(kind=kint) :: pivot(cNCOL_ITEM), tmp(cNCOL_ITEM)
1805 if (id1 >= id2)
return
1806 center = (id1 + id2) / 2
1807 pivot(1:cncol_item) = add_nodes(1:cncol_item,center)
1811 do while ((add_nodes(crank,left) < pivot(crank)) .or. &
1812 (add_nodes(crank,left) == pivot(crank) .and. add_nodes(clid,left) < pivot(clid)))
1815 do while ((pivot(crank) < add_nodes(crank,right)) .or. &
1816 (pivot(crank) == add_nodes(crank,right) .and. pivot(clid) < add_nodes(clid,right)))
1819 if (left >= right)
exit
1820 tmp(1:cncol_item) = add_nodes(1:cncol_item,left)
1821 add_nodes(1:cncol_item,left) = add_nodes(1:cncol_item,right)
1822 add_nodes(1:cncol_item,right) = tmp(1:cncol_item)
1826 if (id1 < left-1)
call sort_add_nodes(add_nodes, id1, left-1)
1827 if (right+1 < id2)
call sort_add_nodes(add_nodes, right+1, id2)
1829 end subroutine sort_add_nodes
1831 subroutine uniq_add_nodes(add_nodes, len, ndup)
1833 integer(kind=kint),
intent(inout) :: add_nodes(:,:)
1834 integer(kind=kint),
intent(in) :: len
1835 integer(kind=kint),
intent(out) :: ndup
1836 integer(kind=kint) :: i
1839 if (add_nodes(clid,i) == add_nodes(clid,i-1-ndup) .and. &
1840 add_nodes(crank,i) == add_nodes(crank,i-1-ndup))
then
1842 else if (ndup > 0)
then
1843 add_nodes(1:cncol_item,i-ndup) = add_nodes(1:cncol_item,i)
1846 end subroutine uniq_add_nodes
1848 subroutine search_add_nodes(n_add_node, add_nodes, rank, lid, idx)
1850 integer(kind=kint),
intent(in) :: n_add_node
1851 integer(kind=kint),
intent(in) :: add_nodes(cNCOL_ITEM,n_add_node)
1852 integer(kind=kint),
intent(in) :: rank
1853 integer(kind=kint),
intent(in) :: lid
1854 integer(kind=kint),
intent(out) :: idx
1855 integer(kind=kint) :: left, right, center
1858 do while (left <= right)
1859 center = (left + right) / 2
1860 if ((rank == add_nodes(crank,center)) .and. (lid == add_nodes(clid,center)))
then
1863 else if ((rank < add_nodes(crank,center)) .or. &
1864 (rank == add_nodes(crank,center) .and. lid < add_nodes(clid,center)))
then
1866 else if ((add_nodes(crank,center) < rank) .or. &
1867 (add_nodes(crank,center) == rank .and. add_nodes(clid,center) < lid))
then
1872 end subroutine search_add_nodes
1874 subroutine append_nodes(hecMESHnew, n_add_node, add_nodes, i0)
1876 type (hecmwST_local_mesh),
intent(inout) :: hecMESHnew
1877 integer(kind=kint),
intent(in) :: n_add_node
1878 integer(kind=kint),
intent(in) :: add_nodes(:,:)
1879 integer(kind=kint),
intent(out) :: i0
1880 integer(kind=kint) :: n_node, i, ii
1881 integer(kind=kint),
pointer :: node_ID(:), global_node_ID(:)
1882 i0 = hecmeshnew%n_node
1883 n_node = hecmeshnew%n_node + n_add_node
1884 allocate(node_id(2*n_node))
1885 allocate(global_node_id(n_node))
1886 do i = 1, hecmeshnew%n_node
1887 node_id(2*i-1) = hecmeshnew%node_ID(2*i-1)
1888 node_id(2*i ) = hecmeshnew%node_ID(2*i )
1889 global_node_id(i) = hecmeshnew%global_node_ID(i)
1891 do i = 1, n_add_node
1892 ii = hecmeshnew%n_node + i
1893 node_id(2*ii-1) = add_nodes(clid,i)
1894 node_id(2*ii ) = add_nodes(crank,i)
1895 if (cncol_item >= 3)
then
1896 global_node_id(ii) = add_nodes(cgid,i)
1898 global_node_id(ii) = -1
1901 deallocate(hecmeshnew%node_ID)
1902 deallocate(hecmeshnew%global_node_ID)
1903 hecmeshnew%n_node = n_node
1904 hecmeshnew%node_ID => node_id
1905 hecmeshnew%global_node_ID => global_node_id
1906 end subroutine append_nodes
1908 subroutine map_additional_nodes(ncols, cols, n_add_node, add_nodes, i0, map)
1910 integer(kind=kint),
intent(in) :: ncols
1911 integer(kind=kint),
intent(in) :: cols(cNCOL_ITEM,ncols)
1912 integer(kind=kint),
intent(in) :: n_add_node
1913 integer(kind=kint),
intent(in) :: add_nodes(cNCOL_ITEM,n_add_node)
1914 integer(kind=kint),
intent(in) :: i0
1915 integer(kind=kint),
intent(inout) :: map(ncols)
1916 integer(kind=kint) :: i, j
1918 if (map(i) > 0) cycle
1919 call search_add_nodes(n_add_node, add_nodes, cols(crank,i), cols(clid,i), j)
1920 if (j == -1) stop
'ERROR: map_additional_nodes'
1923 end subroutine map_additional_nodes
1925 subroutine update_comm_table(hecMESHnew, n_add_node, add_nodes, i0)
1928 type (hecmwST_local_mesh),
intent(inout) :: hecMESHnew
1929 integer(kind=kint),
intent(in) :: n_add_node
1930 integer(kind=kint),
allocatable,
intent(inout) :: add_nodes(:,:)
1931 integer(kind=kint),
intent(in) :: i0
1932 integer(kind=kint),
allocatable :: n_add_imp(:), add_imp_index(:)
1933 integer(kind=kint),
allocatable :: add_imp_item_remote(:), add_imp_item_local(:)
1934 integer(kind=kint),
allocatable :: n_add_exp(:), add_exp_index(:), add_exp_item(:)
1935 integer(kind=kint),
allocatable :: n_new_imp(:), n_new_exp(:)
1936 integer(kind=kint) :: npe, nnb, comm, new_nnb
1937 integer(kind=kint),
pointer :: nbpe(:), new_nbpe(:)
1938 integer(kind=kint),
pointer :: import_index(:), export_index(:), import_item(:), export_item(:)
1939 integer(kind=kint),
pointer :: new_import_index(:), new_export_index(:)
1940 integer(kind=kint),
pointer :: new_import_item(:), new_export_item(:)
1941 npe = hecmeshnew%PETOT
1942 nnb = hecmeshnew%n_neighbor_pe
1943 comm = hecmeshnew%MPI_COMM
1944 nbpe => hecmeshnew%neighbor_pe
1945 import_index => hecmeshnew%import_index
1946 export_index => hecmeshnew%export_index
1947 import_item => hecmeshnew%import_item
1948 export_item => hecmeshnew%export_item
1951 if (debug >= 3)
write(0,*)
' DEBUG3: count add_imp per rank done'
1953 allocate(add_imp_index(0:npe))
1954 call make_index(npe, n_add_imp, add_imp_index)
1955 if (debug >= 3)
write(0,*)
' DEBUG3: make add_imp_index done'
1957 call make_add_imp_item(n_add_node, add_nodes, npe, i0, add_imp_index, &
1958 add_imp_item_remote, add_imp_item_local)
1959 if (debug >= 3)
write(0,*)
' DEBUG3: make add_imp_item done'
1961 deallocate(add_nodes)
1965 allocate(n_add_exp(npe))
1967 if (debug >= 3)
write(0,*)
' DEBUG3: alltoall n_add_imp to n_add_exp done'
1969 allocate(add_exp_index(0:npe))
1970 call make_index(npe, n_add_exp, add_exp_index)
1971 if (debug >= 3)
write(0,*)
' DEBUG3: make add_exp_index done'
1973 call send_recv_add_imp_exp_item(npe, add_imp_index, add_imp_item_remote, &
1974 add_exp_index, add_exp_item, comm)
1975 if (debug >= 3)
write(0,*)
' DEBUG3: send recv add_imp/exp_item done'
1980 if (debug >= 3)
write(0,*)
' DEBUG3: count new comm_nodes (import) done'
1985 if (debug >= 3)
write(0,*)
' DEBUG3: count new comm_nodes (export) done'
1987 call update_neighbor_pe(npe, n_new_imp, n_new_exp, new_nnb, new_nbpe)
1988 if (debug >= 3)
write(0,*)
' DEBUG3: update neighbor_pe done'
1992 call merge_comm_table(npe, nnb, nbpe, import_index, import_item, &
1993 new_nnb, new_nbpe, add_imp_index, add_imp_item_local, n_add_imp, n_new_imp, &
1994 new_import_index, new_import_item)
1995 if (debug >= 3)
write(0,*)
' DEBUG3: merge comm_table (import) done'
1997 deallocate(n_add_imp)
1998 deallocate(add_imp_index)
1999 deallocate(add_imp_item_remote, add_imp_item_local)
2000 deallocate(n_new_imp)
2004 call merge_comm_table(npe, nnb, nbpe, export_index, export_item, &
2005 new_nnb, new_nbpe, add_exp_index, add_exp_item, n_add_exp, n_new_exp, &
2006 new_export_index, new_export_item)
2007 if (debug >= 3)
write(0,*)
' DEBUG3: merge comm_table (export) done'
2009 deallocate(n_add_exp)
2010 deallocate(add_exp_index)
2011 deallocate(add_exp_item)
2012 deallocate(n_new_exp)
2015 deallocate(import_index,import_item)
2016 deallocate(export_index,export_item)
2017 hecmeshnew%n_neighbor_pe = new_nnb
2018 hecmeshnew%neighbor_pe => new_nbpe
2019 hecmeshnew%import_index => new_import_index
2020 hecmeshnew%export_index => new_export_index
2021 hecmeshnew%import_item => new_import_item
2022 hecmeshnew%export_item => new_export_item
2023 end subroutine update_comm_table
2027 integer(kind=kint),
intent(in) :: n_add_node
2028 integer(kind=kint),
intent(in) :: add_nodes(cNCOL_ITEM,n_add_node)
2029 integer(kind=kint),
intent(in) :: npe
2030 integer(kind=kint),
allocatable,
intent(out) :: n_add_imp(:)
2031 integer(kind=kint) :: i, rank
2032 allocate(n_add_imp(npe))
2034 do i = 1, n_add_node
2035 rank = add_nodes(crank,i)
2036 n_add_imp(rank+1) = n_add_imp(rank+1) + 1
2040 subroutine make_add_imp_item(n_add_node, add_nodes, npe, i0, add_imp_index, &
2041 add_imp_item_remote, add_imp_item_local)
2043 integer(kind=kint),
intent(in) :: n_add_node
2044 integer(kind=kint),
intent(in) :: add_nodes(cNCOL_ITEM,n_add_node)
2045 integer(kind=kint),
intent(in) :: npe, i0
2046 integer(kind=kint),
allocatable,
intent(in) :: add_imp_index(:)
2047 integer(kind=kint),
allocatable,
intent(out) :: add_imp_item_remote(:), add_imp_item_local(:)
2048 integer(kind=kint),
allocatable :: cnt(:)
2049 integer(kind=kint) :: i, lid, rank, ipe
2050 allocate(add_imp_item_remote(add_imp_index(npe)))
2051 allocate(add_imp_item_local(add_imp_index(npe)))
2054 do i = 1, n_add_node
2055 lid = add_nodes(clid,i)
2056 rank = add_nodes(crank,i)
2058 cnt(ipe) = cnt(ipe) + 1
2059 add_imp_item_remote(add_imp_index(ipe-1) + cnt(ipe)) = lid
2060 add_imp_item_local(add_imp_index(ipe-1) + cnt(ipe)) = i0 + i
2063 end subroutine make_add_imp_item
2065 subroutine send_recv_add_imp_exp_item(npe, add_imp_index, add_imp_item_remote, &
2066 add_exp_index, add_exp_item, mpi_comm)
2069 integer(kind=kint),
intent(in) :: npe
2070 integer(kind=kint),
allocatable,
intent(in) :: add_imp_index(:), add_imp_item_remote(:)
2071 integer(kind=kint),
allocatable,
intent(in) :: add_exp_index(:)
2072 integer(kind=kint),
allocatable,
intent(out) :: add_exp_item(:)
2073 integer(kind=kint),
intent(in) :: mpi_comm
2074 integer(kind=kint) :: n_send, i, irank, is, ie, len, tag
2075 integer(kind=kint),
allocatable :: requests(:)
2076 integer(kind=kint),
allocatable :: statuses(:,:)
2077 allocate(add_exp_item(add_exp_index(npe)))
2078 allocate(requests(npe))
2083 is = add_imp_index(i-1)+1
2084 ie = add_imp_index(i)
2090 mpi_comm, requests(n_send))
2095 is = add_exp_index(i-1)+1
2096 ie = add_exp_index(i)
2101 mpi_comm, statuses(:,1))
2104 end subroutine send_recv_add_imp_exp_item
2108 integer(kind=kint),
intent(in) :: npe, org_nnb
2110 integer(kind=kint),
pointer,
intent(in) :: org_nbpe(:), org_index(:)
2111 integer(kind=kint),
intent(in) :: n_add(:)
2112 integer(kind=kint),
allocatable,
intent(out) :: n_new(:)
2113 integer(kind=kint) :: i, irank, n_org
2114 allocate(n_new(npe))
2118 n_org = org_index(i) - org_index(i-1)
2119 n_new(irank+1) = n_new(irank+1) + n_org
2123 subroutine update_neighbor_pe(npe, n_new_imp, n_new_exp, &
2126 integer(kind=kint),
intent(in) :: npe
2127 integer(kind=kint),
intent(in) :: n_new_imp(npe), n_new_exp(npe)
2128 integer(kind=kint),
intent(out) :: new_nnb
2129 integer(kind=kint),
pointer,
intent(out) :: new_nbpe(:)
2130 integer(kind=kint) :: i
2133 if (n_new_imp(i) > 0 .or. n_new_exp(i) > 0) new_nnb = new_nnb+1
2135 allocate(new_nbpe(new_nnb))
2138 if (n_new_imp(i) > 0 .or. n_new_exp(i) > 0)
then
2140 new_nbpe(new_nnb) = i-1
2143 end subroutine update_neighbor_pe
2145 subroutine merge_comm_table(npe, org_nnb, org_nbpe, org_index, org_item, &
2146 new_nnb, new_nbpe, add_index, add_item, n_add, n_new, new_index, new_item)
2148 integer(kind=kint),
intent(in) :: npe, org_nnb
2150 integer(kind=kint),
pointer,
intent(in) :: org_nbpe(:), org_index(:), org_item(:)
2151 integer(kind=kint),
intent(in) :: new_nnb
2153 integer(kind=kint),
pointer,
intent(in) :: new_nbpe(:)
2154 integer(kind=kint),
allocatable,
intent(in) :: add_index(:), add_item(:)
2155 integer(kind=kint),
intent(in) :: n_add(npe), n_new(npe)
2156 integer(kind=kint),
pointer,
intent(out) :: new_index(:), new_item(:)
2157 integer(kind=kint),
allocatable :: cnt(:)
2158 integer(kind=kint) :: i, irank, j, jrank, i0, j0, len
2161 allocate(new_index(0:new_nnb))
2165 new_index(i) = new_index(i-1) + n_new(irank+1)
2167 allocate(new_item(new_index(new_nnb)))
2173 if (org_index(i) - org_index(i-1) == 0) cycle
2175 do while (jrank < irank)
2177 if (j > new_nnb)
exit
2180 if (jrank /= irank) stop
'ERROR: merging comm table: org into new'
2182 len = org_index(i) - i0
2184 new_item(j0+1:j0+len) = org_item(i0+1:i0+len)
2190 if (n_add(i) == 0) cycle
2192 do while (jrank < irank)
2196 if (jrank /= irank) stop
'ERROR: merging comm table: add into new'
2198 len = add_index(i) - i0
2199 j0 = new_index(j-1) + cnt(jrank+1)
2200 new_item(j0+1:j0+len) = add_item(i0+1:i0+len)
2201 cnt(jrank+1) = cnt(jrank+1) + len
2202 if (cnt(jrank+1) /= new_index(j)-new_index(j-1)) stop
'ERROR: merging comm table'
2205 end subroutine merge_comm_table
2207 subroutine copy_vals_to_bt_int(nnb, imp_rows_index, imp_cols_index, &
2208 imp_rows_item, map, ndof2, imp_vals_item, BT_int)
2210 integer(kind=kint),
intent(in) :: nnb
2211 integer(kind=kint),
allocatable,
intent(in) :: imp_rows_index(:), imp_cols_index(:)
2212 integer(kind=kint),
intent(in) :: imp_rows_item(:,:), map(:)
2213 integer(kind=kint),
intent(in) :: ndof2
2214 real(kind=
kreal),
intent(in) :: imp_vals_item(:)
2215 type (hecmwST_local_matrix),
intent(inout) :: BT_int
2216 integer(kind=kint),
allocatable :: cnt(:)
2217 integer(kind=kint) :: idom, is, ie, ic0, i, irow, ncol, j0, j
2218 allocate(cnt(bt_int%nr))
2221 is = imp_rows_index(idom-1)+1
2222 ie = imp_rows_index(idom)
2223 ic0 = imp_cols_index(idom-1)
2225 irow = imp_rows_item(1,i)
2226 ncol = imp_rows_item(2,i)
2227 if (irow < 1 .or. bt_int%nr < irow) stop
'ERROR: copy vals to BT_int: irow'
2228 j0 = bt_int%index(irow-1) + cnt(irow)
2230 bt_int%item(j0+j) = map(ic0+j)
2231 bt_int%A(ndof2*(j0+j-1)+1:ndof2*(j0+j)) = imp_vals_item(ndof2*(ic0+j-1)+1:ndof2*(ic0+j))
2233 cnt(irow) = cnt(irow) + ncol
2236 if (ic0 /= imp_cols_index(idom)) stop
'ERROR: copy vals to BT_int: ic0'
2239 end subroutine copy_vals_to_bt_int
2241 subroutine sort_and_uniq_rows(BTmat)
2244 type (hecmwST_local_matrix),
intent(inout) :: BTmat
2245 integer(kind=kint) :: nr, ndof, ndof2
2246 integer(kind=kint) :: irow, is, ie, is_new, ie_new, i, i_new
2247 integer(kind=kint) :: ndup, ndup_tot
2248 integer(kind=kint) :: js, je, js_new, je_new
2249 integer(kind=kint) :: new_nnz
2250 integer(kind=kint),
allocatable :: cnt(:)
2251 integer(kind=kint),
pointer :: sort_item(:), new_index(:), new_item(:)
2252 real(kind=
kreal),
pointer :: new_a(:)
2254 real(kind=
kreal) :: t0, t1
2259 outer:
do irow = 1, nr
2260 is = btmat%index(irow-1)+1
2261 ie = btmat%index(irow)
2263 if (btmat%item(i) >= btmat%item(i+1))
then
2270 if (timer >= 4)
write(0,
'(A,f10.4,L2)')
"####### sort_and_uniq_rows (1) : ",t1-t0,sorted
2277 allocate(sort_item(btmat%nnz))
2279 sort_item(i) = btmat%item(i)
2290 is = btmat%index(irow-1)+1
2291 ie = btmat%index(irow)
2294 cnt(irow) = (ie-is+1) - ndup
2295 ndup_tot = ndup_tot + ndup
2299 if (timer >= 4)
write(0,
'(A,f10.4,I5)')
"####### sort_and_uniq_rows (2) : ",t1-t0,ndup_tot
2302 if (ndup_tot == 0)
then
2303 new_index => btmat%index
2305 new_item => sort_item
2307 allocate(new_index(0:nr))
2308 call make_index(nr, cnt, new_index)
2309 new_nnz = new_index(nr)
2310 allocate(new_item(new_nnz))
2312 is = btmat%index(irow-1)+1
2314 is_new = new_index(irow-1)+1
2315 ie_new = is_new+cnt(irow)-1
2316 new_item(is_new:ie_new) = sort_item(is:ie)
2318 deallocate(sort_item)
2322 if (timer >= 4)
write(0,
'(A,f10.4)')
"####### sort_and_uniq_rows (3) : ",t1-t0
2325 allocate(new_a(ndof2*new_nnz))
2333 is = btmat%index(irow-1)+1
2334 ie = btmat%index(irow)
2335 is_new = new_index(irow-1)+1
2336 ie_new = new_index(irow)
2341 if (i_new == -1) stop
'ERROR: sort_and_uniq_rows'
2344 js_new = ndof2*(i_new-1)+1
2345 je_new = ndof2*i_new
2346 new_a(js_new:je_new) = new_a(js_new:je_new) + btmat%A(js:je)
2351 if (timer >= 4)
write(0,
'(A,f10.4)')
"####### sort_and_uniq_rows (4) : ",t1-t0
2354 if (ndup_tot == 0)
then
2355 deallocate(btmat%item)
2356 btmat%item => new_item
2361 deallocate(btmat%index)
2362 btmat%index => new_index
2363 deallocate(btmat%item)
2364 btmat%item => new_item
2368 end subroutine sort_and_uniq_rows
2372 type (hecmwst_local_matrix),
intent(in) :: amat
2373 type (hecmwst_local_matrix),
intent(in) :: bmat
2374 type (hecmwst_local_matrix),
intent(out) :: cmat
2375 integer(kind=kint) :: ndof, ndof2, nr, nc, i, icnt, js, je, j, jcol, idx, i0, k
2376 integer(kind=kint),
allocatable :: iw(:)
2377 if (amat%ndof /= bmat%ndof) stop
'ERROR: hecmw_localmat_add: non-matching ndof'
2380 nr = min(amat%nr, bmat%nr)
2381 nc = max(amat%nc, bmat%nc)
2386 allocate(cmat%index(0:nr))
2392 js = amat%index(i-1)+1
2400 js = bmat%index(i-1)+1
2405 if (iw(k) == jcol) cycle lj1
2410 cmat%index(i) = cmat%index(i-1) + icnt
2412 cmat%nnz = cmat%index(nr)
2413 allocate(cmat%item(cmat%nnz))
2414 allocate(cmat%A(ndof2*cmat%nnz))
2416 i0 = cmat%index(i-1)
2419 js = amat%index(i-1)+1
2425 cmat%item(idx) = jcol
2426 cmat%A(ndof2*(idx-1)+1:ndof2*idx) = amat%A(ndof2*(j-1)+1:ndof2*j)
2429 js = bmat%index(i-1)+1
2435 if (cmat%item(idx) == jcol)
then
2436 cmat%A(ndof2*(idx-1)+1:ndof2*idx) = &
2437 cmat%A(ndof2*(idx-1)+1:ndof2*idx) + bmat%A(ndof2*(j-1)+1:ndof2*j)
2443 cmat%item(idx) = jcol
2444 cmat%A(ndof2*(idx-1)+1:ndof2*idx) = bmat%A(ndof2*(j-1)+1:ndof2*j)
2446 if (i0 + icnt /= cmat%index(i)) stop
'ERROR: merge localmat'
2448 call sort_and_uniq_rows(cmat)
2496 type (hecmwst_local_matrix),
intent(inout) :: bkmat
2498 integer(kind=kint),
optional,
intent(in) :: num_lagrange
2499 integer(kind=kint) :: ndof, ndof2, i, idx, idx2, js, je, j, k
2500 integer(kind=kint),
allocatable :: incl_nz(:), cnt(:)
2501 logical :: check_nonzero
2502 check_nonzero = .false.
2508 bkmat%nr = hecmat%NP
2509 bkmat%nc = hecmat%NP
2512 if (
present(num_lagrange))
then
2513 check_nonzero = .true.
2516 if (check_nonzero)
then
2517 allocate(incl_nz(hecmat%NPL + hecmat%NPU + hecmat%NP))
2518 allocate(cnt(bkmat%nr))
2525 idx = hecmat%indexL(i-1) + (i-1) + hecmat%indexU(i-1)
2528 js = hecmat%indexL(i-1)+1
2529 je = hecmat%indexL(i)
2533 if (hecmat%AL(ndof2*(j-1)+k) /= 0.0d0)
then
2543 if (hecmat%D(ndof2*(i-1)+k) /= 0.0d0)
then
2550 js = hecmat%indexU(i-1)+1
2551 je = hecmat%indexU(i)
2555 if (hecmat%AU(ndof2*(j-1)+k) /= 0.0d0)
then
2562 if (idx /= hecmat%indexL(i) + i + hecmat%indexU(i)) stop
'ERROR: hecmw_localmat_init_with_hecmat: count'
2567 allocate(bkmat%index(0:bkmat%nr))
2568 call make_index(bkmat%nr, cnt, bkmat%index)
2570 bkmat%nnz = bkmat%index(bkmat%nr)
2572 allocate(bkmat%item(bkmat%nnz))
2573 allocate(bkmat%A(ndof2 * bkmat%nnz))
2579 idx = hecmat%indexL(i-1) + (i-1) + hecmat%indexU(i-1)
2580 idx2 = bkmat%index(i-1)
2582 js = hecmat%indexL(i-1)+1
2583 je = hecmat%indexL(i)
2586 if (incl_nz(idx) == 1)
then
2588 bkmat%item(idx2) = hecmat%itemL(j)
2589 bkmat%A(ndof2*(idx2-1)+1:ndof2*idx2) = hecmat%AL(ndof2*(j-1)+1:ndof2*j)
2594 if (incl_nz(idx) == 1)
then
2596 bkmat%item(idx2) = i
2597 bkmat%A(ndof2*(idx2-1)+1:ndof2*idx2) = hecmat%D(ndof2*(i-1)+1:ndof2*i)
2600 js = hecmat%indexU(i-1)+1
2601 je = hecmat%indexU(i)
2604 if (incl_nz(idx) == 1)
then
2606 bkmat%item(idx2) = hecmat%itemU(j)
2607 bkmat%A(ndof2*(idx2-1)+1:ndof2*idx2) = hecmat%AU(ndof2*(j-1)+1:ndof2*j)
2610 if (idx /= hecmat%indexL(i) + i + hecmat%indexU(i)) stop
'ERROR: hecmw_localmat_init_with_hecmat: copy'
2611 if (idx2 /= bkmat%index(i)) stop
'ERROR: hecmw_localmat_init_with_hecmat: index'
2617 bkmat%nnz = hecmat%NPL + hecmat%NP + hecmat%NPU
2618 allocate(bkmat%index(0:bkmat%nr))
2619 allocate(bkmat%item(bkmat%nnz))
2620 allocate(bkmat%A(ndof2 * bkmat%nnz))
2626 idx = hecmat%indexL(i-1) + (i-1) + hecmat%indexU(i-1)
2628 js = hecmat%indexL(i-1)+1
2629 je = hecmat%indexL(i)
2632 bkmat%item(idx) = hecmat%itemL(j)
2633 bkmat%A(ndof2*(idx-1)+1:ndof2*idx) = hecmat%AL(ndof2*(j-1)+1:ndof2*j)
2638 bkmat%A(ndof2*(idx-1)+1:ndof2*idx) = hecmat%D(ndof2*(i-1)+1:ndof2*i)
2640 js = hecmat%indexU(i-1)+1
2641 je = hecmat%indexU(i)
2644 bkmat%item(idx) = hecmat%itemU(j)
2645 bkmat%A(ndof2*(idx-1)+1:ndof2*idx) = hecmat%AU(ndof2*(j-1)+1:ndof2*j)
2647 bkmat%index(i) = idx
2648 if (idx /= hecmat%indexL(i) + i + hecmat%indexU(i)) stop
'ERROR: hecmw_localmat_init_with_hecmat: copy'
2656 type (hecmwst_local_matrix),
intent(inout) :: bkmat
2658 type (hecmwst_local_matrix) :: w1mat, w2mat
2661 call debug_write_matrix(w1mat,
'BKmat (hecMAT)', debug_matrix)
2667 bkmat%nnz = w2mat%nnz
2668 bkmat%ndof = w2mat%ndof
2669 bkmat%index => w2mat%index
2670 bkmat%item => w2mat%item
2676 type (hecmwst_local_matrix),
intent(in) :: bkmat
2677 type (hecmwst_local_matrix),
intent(inout) :: btmat
2679 type (hecmwst_local_matrix),
intent(out) :: bktmat
2682 type (hecmwst_local_matrix),
allocatable :: bt_exp(:)
2683 type (hecmwst_local_matrix) :: bt_imp, bt_all
2684 integer(kind=kint),
allocatable :: exp_cols_index(:)
2685 integer(kind=kint),
allocatable :: exp_cols_item(:,:)
2686 real(kind=
kreal) :: t0, t1
2689 if (hecmesh%PETOT > 1)
then
2690 call make_comm_table(bkmat, hecmesh, heccomm)
2691 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: make_comm_table done'
2693 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (1) : ',t1-t0
2696 if (btmat%nr > hecmesh%nn_internal)
then
2698 if (debug >= 1)
write(0,
'(A)')
'DEBUG: hecmw_localmat_multmat: ignore external part of BTmat'
2699 btmat%nr = hecmesh%nn_internal
2700 btmat%nnz = btmat%index(btmat%nr)
2703 call extract_bt_exp(btmat, heccomm, bt_exp)
2704 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: extract_BT_exp done'
2706 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (2) : ',t1-t0
2709 call prepare_column_info(hecmesh, bt_exp, exp_cols_index, exp_cols_item)
2710 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: prepare column info done'
2712 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (3) : ',t1-t0
2715 call send_bt_exp_and_recv_bt_imp(hecmesh, heccomm, bt_exp, exp_cols_index, exp_cols_item, bt_imp, hecmeshnew)
2716 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: send BT_exp and recv BT_imp done'
2718 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (4) : ',t1-t0
2722 call concat_btmat_and_bt_imp(btmat, bt_imp, bt_all)
2723 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: concat BTmat and BT_imp into BT_all done'
2725 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (5) : ',t1-t0
2729 call multiply_mat_mat(bkmat, bt_all, bktmat)
2730 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: multiply BKmat and BT_all into BKTmat done'
2732 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (6) : ',t1-t0
2736 if (hecmesh%n_neighbor_pe > 0)
then
2737 hecmesh%n_node = hecmeshnew%n_node
2738 hecmesh%n_neighbor_pe = hecmeshnew%n_neighbor_pe
2739 deallocate(hecmesh%neighbor_pe)
2740 deallocate(hecmesh%import_index)
2741 deallocate(hecmesh%export_index)
2742 deallocate(hecmesh%import_item)
2743 deallocate(hecmesh%export_item)
2744 deallocate(hecmesh%node_ID)
2745 deallocate(hecmesh%global_node_ID)
2746 hecmesh%neighbor_pe => hecmeshnew%neighbor_pe
2747 hecmesh%import_index => hecmeshnew%import_index
2748 hecmesh%export_index => hecmeshnew%export_index
2749 hecmesh%import_item => hecmeshnew%import_item
2750 hecmesh%export_item => hecmeshnew%export_item
2751 hecmesh%node_ID => hecmeshnew%node_ID
2752 hecmesh%global_node_ID => hecmeshnew%global_node_ID
2753 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: update hecMESH done'
2755 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat (7) : ',t1-t0
2758 call multiply_mat_mat(bkmat, btmat, bktmat)
2759 if (debug >= 1)
write(0,*)
'DEBUG: hecmw_localmat_multmat: multiply BKmat and BTmat into BKTmat done'
2761 if (timer >= 2)
write(0,
'(A,f10.4)')
'##### hecmw_localmat_multmat : ',t1-t0
2765 subroutine make_comm_table(BKmat, hecMESH, hecCOMM)
2768 type (hecmwst_local_matrix),
intent(in) :: bkmat
2771 integer(kind=kint) :: nn_int, nn_ext, nnb, i, icol, irank, idom, idx, n_send, tag, js, je, len
2772 integer(kind=kint),
allocatable :: is_nz_col(:), imp_cnt(:), exp_cnt(:), import_item_remote(:)
2773 integer(kind=kint),
allocatable :: requests(:), statuses(:,:)
2774 heccomm%zero = hecmesh%zero
2775 heccomm%HECMW_COMM = hecmesh%MPI_COMM
2776 heccomm%PETOT = hecmesh%PETOT
2777 heccomm%PEsmpTOT = hecmesh%PEsmpTOT
2778 heccomm%my_rank = hecmesh%my_rank
2779 heccomm%errnof = hecmesh%errnof
2780 heccomm%n_subdomain = hecmesh%n_subdomain
2781 heccomm%n_neighbor_pe = hecmesh%n_neighbor_pe
2782 allocate(heccomm%neighbor_pe(heccomm%n_neighbor_pe))
2783 heccomm%neighbor_pe(:) = hecmesh%neighbor_pe(:)
2785 nn_int = hecmesh%nn_internal
2786 nn_ext = hecmesh%n_node - hecmesh%nn_internal
2787 nnb = heccomm%n_neighbor_pe
2790 allocate(is_nz_col(nn_ext))
2792 do i = 1, bkmat%index(nn_int)
2793 icol = bkmat%item(i)
2794 if (icol > nn_int) is_nz_col(icol - nn_int) = 1
2798 allocate(imp_cnt(nnb))
2801 if (is_nz_col(i) == 1)
then
2802 irank = hecmesh%node_ID(2*(nn_int+i))
2803 call rank_to_idom(hecmesh, irank, idom)
2804 imp_cnt(idom) = imp_cnt(idom) + 1
2807 if (debug >= 3)
write(0,*)
' DEBUG3: imp_cnt',imp_cnt(:)
2810 allocate(heccomm%import_index(0:nnb))
2811 call make_index(nnb, imp_cnt, heccomm%import_index)
2812 if (debug >= 3)
write(0,*)
' DEBUG3: import_index',heccomm%import_index(:)
2815 allocate(heccomm%import_item(heccomm%import_index(nnb)))
2818 if (is_nz_col(i) == 1)
then
2819 irank = hecmesh%node_ID(2*(nn_int+i))
2820 call rank_to_idom(hecmesh, irank, idom)
2821 imp_cnt(idom) = imp_cnt(idom) + 1
2822 idx = heccomm%import_index(idom-1)+imp_cnt(idom)
2823 heccomm%import_item(idx) = nn_int+i
2826 if (debug >= 3)
write(0,*)
' DEBUG3: import_item',heccomm%import_item(:)
2828 allocate(import_item_remote(heccomm%import_index(nnb)))
2829 do i = 1, heccomm%import_index(nnb)
2830 import_item_remote(i) = hecmesh%node_ID(2*heccomm%import_item(i)-1)
2832 if (debug >= 3)
write(0,*)
' DEBUG3: import_item_remote',import_item_remote(:)
2834 allocate(requests(2*nnb))
2840 irank = heccomm%neighbor_pe(idom)
2843 call hecmw_isend_int(imp_cnt(idom), 1, irank, tag, heccomm%HECMW_COMM, requests(n_send))
2844 if (imp_cnt(idom) > 0)
then
2845 js = heccomm%import_index(idom-1)+1
2846 je = heccomm%import_index(idom)
2851 heccomm%HECMW_COMM, requests(n_send))
2856 allocate(exp_cnt(nnb))
2858 irank = heccomm%neighbor_pe(idom)
2860 call hecmw_recv_int(exp_cnt(idom), 1, irank, tag, heccomm%HECMW_COMM, statuses(:,1))
2862 allocate(heccomm%export_index(0:nnb))
2863 call make_index(nnb, exp_cnt, heccomm%export_index)
2864 if (debug >= 3)
write(0,*)
' DEBUG3: export_index',heccomm%export_index(:)
2867 allocate(heccomm%export_item(heccomm%export_index(nnb)))
2869 if (exp_cnt(idom) <= 0) cycle
2870 irank = heccomm%neighbor_pe(idom)
2871 js = heccomm%export_index(idom-1)+1
2872 je = heccomm%export_index(idom)
2875 call hecmw_recv_int(heccomm%export_item(js:je), len, irank, tag, &
2876 heccomm%HECMW_COMM, statuses(:,1))
2878 if (debug >= 3)
write(0,*)
' DEBUG3: export_item',heccomm%export_item(:)
2883 deallocate(import_item_remote)
2884 end subroutine make_comm_table
2888 type (hecmwST_matrix_comm),
intent(inout) :: hecCOMM
2889 deallocate(heccomm%neighbor_pe)
2890 deallocate(heccomm%import_index)
2891 deallocate(heccomm%import_item)
2892 deallocate(heccomm%export_index)
2893 deallocate(heccomm%export_item)
2896 subroutine extract_bt_exp(BTmat, hecCOMM, BT_exp)
2898 type (hecmwST_local_matrix),
intent(in) :: BTmat
2899 type (hecmwST_matrix_comm),
intent(in) :: hecCOMM
2900 type (hecmwST_local_matrix),
allocatable,
intent(out) :: BT_exp(:)
2901 integer(kind=kint) :: ndof, ndof2, idom, idx_0, idx_n, j, jrow, nnz_row, idx, ks, ke, k
2902 if (heccomm%n_neighbor_pe == 0)
return
2903 allocate(bt_exp(heccomm%n_neighbor_pe))
2906 do idom = 1, heccomm%n_neighbor_pe
2907 idx_0 = heccomm%export_index(idom-1)
2908 idx_n = heccomm%export_index(idom)
2909 bt_exp(idom)%nr = idx_n - idx_0
2910 bt_exp(idom)%nc = btmat%nc
2911 bt_exp(idom)%nnz = 0
2912 bt_exp(idom)%ndof = ndof
2913 allocate(bt_exp(idom)%index(0:bt_exp(idom)%nr))
2914 bt_exp(idom)%index(0) = 0
2915 do j = 1, bt_exp(idom)%nr
2916 jrow = heccomm%export_item(idx_0 + j)
2917 nnz_row = btmat%index(jrow) - btmat%index(jrow-1)
2918 bt_exp(idom)%index(j) = bt_exp(idom)%index(j-1) + nnz_row
2920 bt_exp(idom)%nnz = bt_exp(idom)%index(bt_exp(idom)%nr)
2921 allocate(bt_exp(idom)%item(bt_exp(idom)%nnz))
2922 allocate(bt_exp(idom)%A(ndof2 * bt_exp(idom)%nnz))
2924 do j = 1, bt_exp(idom)%nr
2925 jrow = heccomm%export_item(idx_0 + j)
2926 ks = btmat%index(jrow-1) + 1
2927 ke = btmat%index(jrow)
2930 bt_exp(idom)%item(idx) = btmat%item(k)
2931 bt_exp(idom)%A(ndof2*(idx-1)+1:ndof2*idx) = btmat%A(ndof2*(k-1)+1:ndof2*k)
2933 if (idx /= bt_exp(idom)%index(j)) stop
'ERROR: extract BT_exp'
2936 end subroutine extract_bt_exp
2938 subroutine send_bt_exp_and_recv_bt_imp(hecMESH, hecCOMM, BT_exp, exp_cols_index, exp_cols_item, BT_imp, hecMESHnew)
2941 type (hecmwST_local_mesh),
intent(in) :: hecMESH
2942 type (hecmwST_matrix_comm),
intent(in) :: hecCOMM
2943 type (hecmwST_local_matrix),
allocatable,
intent(inout) :: BT_exp(:)
2944 integer(kind=kint),
allocatable,
intent(inout) :: exp_cols_index(:)
2945 integer(kind=kint),
allocatable,
intent(inout) :: exp_cols_item(:,:)
2946 type (hecmwST_local_matrix),
intent(out) :: BT_imp
2947 type (hecmwST_local_mesh),
intent(inout) :: hecMESHnew
2948 integer(kind=kint),
allocatable :: nnz_imp(:), cnt(:), index_imp(:)
2949 integer(kind=kint),
allocatable :: imp_cols_index(:)
2950 integer(kind=kint),
allocatable :: imp_cols_item(:,:)
2951 real(kind=
kreal),
allocatable :: imp_vals_item(:)
2952 integer(kind=kint) :: nnb, ndof, ndof2, idom, irank, nr, n_send, tag, idx_0, idx_n, j, jj, nnz
2953 integer(kind=kint),
allocatable :: requests(:)
2954 integer(kind=kint),
allocatable :: statuses(:,:)
2955 integer(kind=kint),
allocatable :: map(:), add_nodes(:,:)
2956 integer(kind=kint) :: n_add_node, i0
2957 nnb = heccomm%n_neighbor_pe
2963 allocate(bt_imp%index(0:0))
2967 ndof = bt_exp(1)%ndof
2969 allocate(requests(nnb*3))
2973 irank = heccomm%neighbor_pe(idom)
2974 nr = bt_exp(idom)%nr
2978 call hecmw_isend_int(bt_exp(idom)%index(0:bt_exp(idom)%nr), bt_exp(idom)%nr + 1, &
2979 irank, tag, heccomm%HECMW_COMM, requests(n_send))
2980 if (bt_exp(idom)%nnz == 0) cycle
2984 cncol_item * bt_exp(idom)%nnz, irank, tag, heccomm%HECMW_COMM, requests(n_send))
2987 call hecmw_isend_r(bt_exp(idom)%A, ndof2 * bt_exp(idom)%nnz, &
2988 irank, tag, heccomm%HECMW_COMM, requests(n_send))
2992 bt_imp%nr = hecmesh%n_node - hecmesh%nn_internal
2997 allocate(nnz_imp(nnb))
2998 allocate(cnt(bt_imp%nr))
3002 irank = heccomm%neighbor_pe(idom)
3003 idx_0 = heccomm%import_index(idom-1)
3004 idx_n = heccomm%import_index(idom)
3010 allocate(index_imp(0:nr))
3013 heccomm%HECMW_COMM, statuses(:,1))
3014 nnz_imp(idom) = index_imp(nr)
3016 jj = heccomm%import_item(idx_0 + j) - hecmesh%nn_internal
3017 if (jj < 1 .or. bt_imp%nr < jj) stop
'ERROR: jj out of range'
3018 if (cnt(jj) /= 0) stop
import rows?
'
3019 cnt(jj) = index_imp(j) - index_imp(j-1)
3021 deallocate(index_imp)
3024 allocate(imp_cols_index(0:nnb))
3025 call make_index(nnb, nnz_imp, imp_cols_index)
3028 allocate(BT_imp%index(0:BT_imp%nr))
3029 call make_index(BT_imp%nr, cnt, BT_imp%index)
3032 BT_imp%nnz = BT_imp%index(BT_imp%nr)
3033 if (BT_imp%nnz /= imp_cols_index(nnb)) &
3034 stop 'error: total num of nonzero of bt_imp
'
3036 allocate(imp_cols_item(cNCOL_ITEM, BT_imp%nnz))
3037 allocate(imp_vals_item(ndof2 * BT_imp%nnz))
3040 irank = hecCOMM%neighbor_pe(idom)
3041 idx_0 = imp_cols_index(idom-1)
3042 idx_n = imp_cols_index(idom)
3046 call HECMW_RECV_INT(imp_cols_item(1, idx_0 + 1), cNCOL_ITEM * nnz, &
3047 irank, tag, hecCOMM%HECMW_COMM, statuses(:,1))
3049 call HECMW_RECV_R(imp_vals_item(ndof2*idx_0 + 1), ndof2 * nnz, &
3050 irank, tag, hecCOMM%HECMW_COMM, statuses(:,1))
3052 call HECMW_Waitall(n_send, requests, statuses)
3053 if (DEBUG >= 2) write(0,*) ' debug2: send bt_imp and recv into temporary data done
'
3055 deallocate(requests)
3056 deallocate(statuses)
3059 call hecmw_localmat_free(BT_exp(idom))
3062 deallocate(exp_cols_index)
3063 deallocate(exp_cols_item)
3065 call copy_mesh(hecMESH, hecMESHnew)
3067 call map_imported_cols(hecMESHnew, imp_cols_index(nnb), imp_cols_item, n_add_node, add_nodes, map, i0)
3068 if (DEBUG >= 2) write(0,*) ' debug2: map imported cols done
'
3070 call update_comm_table(hecMESHnew, n_add_node, add_nodes, i0)
3071 if (DEBUG >= 2) write(0,*) ' debug2: update comm_table done
'
3073 BT_imp%nc = hecMESHnew%n_node
3075 allocate(BT_imp%item(BT_imp%nnz))
3076 allocate(BT_imp%A(ndof2 * BT_imp%nnz))
3077 call copy_vals_to_BT_imp(hecCOMM, hecMESH%nn_internal, imp_cols_index, map, imp_vals_item, BT_imp)
3078 if (DEBUG >= 2) write(0,*) ' debug2: copy vals to bt_imp done
'
3080 deallocate(imp_cols_index)
3081 deallocate(imp_cols_item)
3082 deallocate(imp_vals_item)
3084 end subroutine send_BT_exp_and_recv_BT_imp
3086 subroutine copy_vals_to_BT_imp(hecCOMM, nn_internal, imp_cols_index, map, imp_vals_item, BT_imp)
3088 type (hecmwST_matrix_comm), intent(in) :: hecCOMM
3089 integer(kind=kint), intent(in) :: nn_internal
3090 integer(kind=kint), allocatable, intent(in) :: imp_cols_index(:)
3091 integer(kind=kint), intent(in) :: map(:)
3092 real(kind=kreal), intent(in) :: imp_vals_item(:)
3093 type (hecmwST_local_matrix), intent(inout) :: BT_imp
3094 integer(kind=kint) :: nnb, ndof2, idx, idom, idx_0, idx_n, nr, j, jrow, ks, ke, k
3095 nnb = hecCOMM%n_neighbor_pe
3096 ndof2 = BT_imp%ndof ** 2
3099 idx_0 = hecCOMM%import_index(idom-1)
3100 idx_n = hecCOMM%import_index(idom)
3104 jrow = hecCOMM%import_item(idx_0 + j) - nn_internal
3105 ks = BT_imp%index(jrow-1)+1
3106 ke = BT_imp%index(jrow)
3109 BT_imp%item(k) = map(idx)
3110 BT_imp%A(ndof2*(k-1)+1:ndof2*k) = imp_vals_item(ndof2*(idx-1)+1:ndof2*idx)
3113 if (idx /= imp_cols_index(idom)) stop 'error: copy vals to bt_imp
'
3115 end subroutine copy_vals_to_BT_imp
3117 subroutine concat_BTmat_and_BT_imp(BTmat, BT_imp, BT_all)
3119 type (hecmwST_local_matrix), intent(in) :: BTmat
3120 type (hecmwST_local_matrix), intent(in) :: BT_imp
3121 type (hecmwST_local_matrix), intent(out) :: BT_all
3122 integer(kind=kint) :: ndof, ndof2, i, ii
3124 .and.
if (BT_imp%nr > 0 BT_imp%ndof /= ndof) stop 'error: concat btmat and bt_imp: ndof
'
3126 BT_all%nr = BTmat%nr + BT_imp%nr
3127 BT_all%nc = max(BTmat%nc, BT_imp%nc)
3128 BT_all%nnz = BTmat%nnz + BT_imp%nnz
3130 allocate(BT_all%index(0:BT_all%nr))
3131 allocate(BT_all%item(BT_all%nnz))
3132 allocate(BT_all%A(ndof2 * BT_all%nnz))
3135 BT_all%index(i) = BTmat%index(i)
3138 BT_all%index(BTmat%nr+i) = BT_all%index(BTmat%nr+i-1) + &
3139 BT_imp%index(i) - BT_imp%index(i-1)
3142 BT_all%item(i) = BTmat%item(i)
3143 BT_all%A(ndof2*(i-1)+1:ndof2*i) = BTmat%A(ndof2*(i-1)+1:ndof2*i)
3145 do i = 1, BT_imp%nnz
3147 BT_all%item(ii) = BT_imp%item(i)
3148 BT_all%A(ndof2*(ii-1)+1:ndof2*ii) = BT_imp%A(ndof2*(i-1)+1:ndof2*i)
3150 end subroutine concat_BTmat_and_BT_imp
3152 subroutine multiply_mat_mat(Amat, Bmat, Cmat)
3154 type (hecmwST_local_matrix), intent(in) :: Amat
3155 type (hecmwST_local_matrix), intent(in) :: Bmat
3156 type (hecmwST_local_matrix), intent(out) :: Cmat
3157 integer(kind=kint) :: ndof, ndof2, nr, nc, nnz, i, icnt
3158 integer(kind=kint) :: js, je, j, jj, ks, ke, k, kk, l, ll, l0
3159 integer(kind=kint), allocatable :: iw(:)
3160 real(kind=kreal), pointer :: Ap(:), Bp(:), Cp(:)
3161 real(kind=kreal) :: t0, t1
3163 if (Amat%ndof /= Bmat%ndof) stop 'error: multiply_mat_mat: unmatching ndof
'
3168 if (Amat%nc /= Bmat%nr) then
3169 write(0,*) 'amat: nr, nc =
', Amat%nr, Amat%nc
3170 write(0,*) 'bmat: nr, nc =
', Bmat%nr, Bmat%nc
3171 stop 'error: multiply_mat_mat: unmatching size
'
3176 allocate(Cmat%index(0:nr))
3178 !$omp parallel default(none), &
3179 !$omp& private(iw,i,icnt,js,je,j,jj,ks,ke,k,kk,l), &
3180 !$omp& shared(nr,nc,Amat,Bmat,Cmat)
3185 js = Amat%index(i-1)+1
3189 ks = Bmat%index(jj-1)+1
3194 if (iw(l) == kk) cycle kl1
3200 Cmat%index(i) = icnt
3206 Cmat%index(i) = Cmat%index(i-1) + Cmat%index(i)
3208 nnz = Cmat%index(nr)
3210 !write(0,*) 'nnz
',nnz
3212 if (TIMER >= 3) write(0, '(a,f10.4)
') "###### multiply_mat_mat (1) : ",t1-t0
3214 allocate(Cmat%item(nnz))
3215 allocate(Cmat%A(ndof2 * nnz))
3217 !$omp parallel default(none), &
3218 !$omp& private(i,icnt,l0,js,je,j,jj,Ap,ks,ke,k,kk,Bp,ll,l,Cp), &
3219 !$omp& shared(nr,Cmat,Amat,Bmat,ndof2,ndof)
3223 l0 = Cmat%index(i-1)
3225 js = Amat%index(i-1)+1
3229 Ap => Amat%A(ndof2*(j-1)+1:ndof2*j)
3230 ks = Bmat%index(jj-1)+1
3234 Bp => Bmat%A(ndof2*(k-1)+1:ndof2*k)
3237 if (Cmat%item(l0+l) == kk) then
3247 Cp => Cmat%A(ndof2*(ll-1)+1:ndof2*ll)
3248 call blk_matmul_add(ndof, Ap, Bp, Cp)
3251 !write(0,*) 'l0,icnt,index(i)
',Cmat%index(i-1),icnt,Cmat%index(i)
3252 if (l0+icnt /= Cmat%index(i)) stop 'error: multiply_mat_mat: unknown error
'
3257 if (TIMER >= 3) write(0, '(a,f10.4)
') "###### multiply_mat_mat (2) : ",t1-t0
3259 call sort_and_uniq_rows(Cmat)
3261 if (TIMER >= 3) write(0, '(a,f10.4)
') "###### multiply_mat_mat (3) : ",t1-t0
3262 end subroutine multiply_mat_mat
3264 subroutine blk_matmul_add(ndof, A, B, AB)
3266 integer, intent(in) :: ndof
3267 real(kind=kreal), intent(in) :: A(:), B(:)
3268 real(kind=kreal), intent(inout) :: AB(:)
3269 integer :: ndof2, i, j, k, i0, j0, ij, ik, jk
3280 AB(ik)=AB(ik)+A(ij)*B(jk)
3284 end subroutine blk_matmul_add
3286 subroutine hecmw_localmat_make_hecmat(hecMAT, BTtKTmat, hecTKT)
3288 type (hecmwST_matrix), intent(in) :: hecMAT
3289 type (hecmwST_local_matrix), intent(in) :: BTtKTmat
3290 type (hecmwST_matrix), intent(inout) :: hecTKT
3291 call make_new_hecmat(hecMAT, BTtKTmat, hecTKT)
3292 end subroutine hecmw_localmat_make_hecmat
3294 !> \brief Debug write matrix
3296 subroutine debug_write_matrix(Mat, label, level)
3297 type(hecmwST_local_matrix), intent(in) :: Mat !< matrix
3298 character(len=*), intent(in) :: label !< label for matrix
3299 integer(kind=kint), intent(in) :: level !< debug level
3301 integer(kind=kint) :: iunit
3303 if (level <= 0) return
3305 iunit = 700 + hecmw_comm_get_rank()
3306 write(iunit,'(a,a)
') trim(label),'============================================================
'
3307 if (level == 1) then
3308 call hecmw_localmat_write_size(Mat, iunit)
3309 else if (level == 2) then
3310 call hecmw_localmat_write_ij(Mat, iunit)
3312 call hecmw_localmat_write(Mat, iunit)
3314 end subroutine debug_write_matrix
3316 end module hecmw_local_matrix
subroutine, public hecmw_bsearch_int_array(array, istart, iend, val, idx)
recursive subroutine, public hecmw_qsort_int_array(array, istart, iend)
subroutine, public hecmw_uniq_int_array(array, istart, iend, ndup)
subroutine, public hecmw_localmat_init_with_hecmat(BKmat, hecMAT, num_lagrange)
subroutine trimatmul_ttkt(BTtmat, hecMAT, BTmat, BTtKT)
subroutine, public hecmw_trimatmul_ttkt(hecMESH, BTtmat, hecMAT, BTmat, iwS, num_lagrange, hecTKT)
subroutine, public hecmw_localmat_free(Tmat)
subroutine allocate_bt_int(hecMESH, ndof, imp_rows_index, imp_rows_item, BT_int)
subroutine, public hecmw_localmat_add(Amat, Bmat, Cmat)
subroutine count_new_comm_nodes(npe, org_nnb, org_nbpe, org_index, n_add, n_new)
subroutine, public hecmw_localmat_transpose(Tmat, Ttmat)
subroutine free_comm_table(hecCOMM)
subroutine, public hecmw_localmat_multmat(BKmat, BTmat, hecMESH, BKTmat)
subroutine send_recv_bt_ext_contents(hecMESH, BT_ext, exp_rows_index, exp_cols_index, exp_rows_item, exp_cols_item, imp_rows_index, imp_cols_index, imp_rows_item, imp_cols_item, imp_vals_item)
subroutine, public hecmw_localmat_mulvec(BTmat, V, TV)
subroutine count_add_imp_per_rank(n_add_node, add_nodes, npe, n_add_imp)
subroutine hecmw_trimatmul_ttkt_parallel(hecMESH, BTtmat, hecMAT, BTmat, iwS, num_lagrange, hecTKT)
subroutine, public hecmw_localmat_write(Tmat, iunit)
subroutine, public hecmw_localmat_blocking(Tmat, ndof, BTmat)
subroutine, public hecmw_localmat_make_hecmat(hecMAT, BTtKTmat, hecTKT)
subroutine, public hecmw_trimatmul_ttkt_serial(hecMESH, BTtmat, hecMAT, BTmat, iwS, num_lagrange, hecTKT)
subroutine, public hecmw_trimatmul_ttkt_mpc(hecMESH, hecMAT, hecTKT)
subroutine, public hecmw_localmat_assemble(BTmat, hecMESH, hecMESHnew)
subroutine, public hecmw_localmat_add_hecmat(BKmat, hecMAT)
subroutine, public hecmw_pair_array_append(parray, id, i1, i2)
subroutine, public hecmw_pair_array_finalize(parray)
integer(kind=kint) function, public hecmw_pair_array_find_id(parray, i1, i2)
subroutine, public hecmw_pair_array_init(parray, max_num)
subroutine, public hecmw_pair_array_sort(parray)
integer(kind=4), parameter kreal
integer(kind=kint), parameter hecmw_status_size
integer(kind=kint) function hecmw_comm_get_rank()
real(kind=kreal) function hecmw_wtime()
subroutine hecmw_isend_int(sbuf, sc, dest, tag, comm, req)
subroutine hecmw_recv_int(rbuf, rc, source, tag, comm, stat)
subroutine hecmw_isend_r(sbuf, sc, dest, tag, comm, req)
subroutine hecmw_waitall(cnt, reqs, stats)
subroutine hecmw_recv_r(rbuf, rc, source, tag, comm, stat)
subroutine hecmw_alltoall_int(sbuf, sc, rbuf, rc, comm)