14 public matrix_partition_info
19 type matrix_partition_info
20 integer(kind=kint) :: ndm
21 type(child_matrix),
pointer :: dm(:)
22 integer(kind=kint) :: neqns_d
23 real(kind=
kreal),
pointer :: dsln(:,:)
24 real(kind=
kreal),
pointer :: diag(:,:)
25 integer(kind=kint),
pointer :: part_all(:)
26 integer(kind=kint),
pointer :: iperm_all(:)
30 type matrix_partition_node
31 integer(kind=kint) :: id
32 integer(kind=kint) :: depth
33 integer(kind=kint) :: idm
35 integer(kind=kint) :: neqns_a, nttbr_a
36 integer(kind=kint) :: neqns_d
37 integer(kind=kint),
pointer :: irow(:), jcol(:)
38 integer(kind=kint),
pointer :: idx_g_a(:), idx_g_d(:)
41 integer(kind=kint) :: maxdepth
42 integer(kind=kint) :: iend_trunk
43 integer(kind=kint) :: ista_leaf
44 integer(kind=kint) :: iend_leaf
46 type(matrix_partition_node),
pointer :: tree_array(:)
48 integer(kind=kint),
parameter :: ilog = 16
55 integer(kind=kint),
intent(in) :: ndiv
56 type(matrix_partition_info),
intent(out) :: pmi
58 type(matrix_partition_node),
pointer :: mdroot
60 integer(kind=kint) :: i, ndeg, nndeg, ndegt
66 write(6,*)
'METIS 4.0 library is used for matrix partitioning.'
67 write(6,*)
'Copyright 1997, Regents of the University of Minnesota'
68 write(6,*)
'http://glaros.dtc.umn.edu/gkhome/metis/metis/overview'
70 call matrix_partition_tree_initialize(ndiv)
71 call matrix_partition_tree_get_root(mdroot)
72 mdroot%neqns_a=a0%neqns
73 mdroot%nttbr_a=a0%nttbr
74 allocate(mdroot%idx_g_a(a0%neqns))
78 allocate(mdroot%irow(
size(a0%irow)))
79 allocate(mdroot%jcol(
size(a0%jcol)))
82 call make_matrix_partition_tree(mdroot)
85 allocate(pmi%part_all(a0%neqns), pmi%iperm_all(a0%neqns))
86 call mkpart(pmi%part_all, pmi%iperm_all, pmi%neqns_d)
90 ndegt = (ndeg+1)*ndeg/2
91 allocate(pmi%dsln(nndeg, pmi%neqns_d*(pmi%neqns_d - 1) / 2))
92 allocate(pmi%diag(ndegt, pmi%neqns_d))
93 allocate(pmi%dm(2**ndiv))
96 call divmat(a0, pmi%part_all, pmi%iperm_all, pmi%dm, pmi%dsln, pmi%diag, pmi%neqns_d)
102 subroutine matrix_partition_tree_initialize(ndiv)
106 integer(kind=kint),
intent(in) :: ndiv
108 type(matrix_partition_node),
pointer :: this
110 integer(kind=kint) :: tsize, i
118 allocate(tree_array(tsize))
119 iend_trunk = tsize - 2**ndiv
120 ista_leaf = iend_trunk+1
124 if (i .le. iend_trunk)
then
128 this%depth=depthinbinarytree(this%id)
129 else if (i .ge. ista_leaf)
then
132 this%idm=i - iend_trunk
136 end subroutine matrix_partition_tree_initialize
140 subroutine matrix_partition_tree_get_root(root)
142 type(matrix_partition_node),
pointer :: root
144 end subroutine matrix_partition_tree_get_root
148 subroutine matrix_partition_tree_get_left_child(this, left)
150 type(matrix_partition_node),
pointer :: this
151 type(matrix_partition_node),
pointer :: left
152 integer(kind=kint) :: id_this, id_left
155 left => tree_array(id_left)
156 end subroutine matrix_partition_tree_get_left_child
160 subroutine matrix_partition_tree_get_right_child(this, right)
162 type(matrix_partition_node),
pointer :: this
163 type(matrix_partition_node),
pointer :: right
164 integer(kind=kint) :: id_this, id_right
166 id_right = id_this*2+1
167 right => tree_array(id_right)
168 end subroutine matrix_partition_tree_get_right_child
172 recursive subroutine make_matrix_partition_tree(this)
175 type(matrix_partition_node),
pointer :: this, left, right
176 integer(kind=kint),
allocatable :: ip_left(:), ip_right(:), ip_d(:), part(:), iperm(:)
177 integer(kind=kint) :: loc1, loc2, loc3, ipass
178 integer(kind=kint) :: i,j,k,l
180 allocate(ip_left(this%neqns_a), ip_right(this%neqns_a), ip_d(this%neqns_a))
181 allocate(part(this%neqns_a), iperm(this%neqns_a))
184 if (this%depth .eq. maxdepth)
then
188 call matrix_partition_tree_get_left_child(this, left)
189 call matrix_partition_tree_get_right_child(this, right)
191 call bi_part_directive(this%neqns_a, this%nttbr_a, this%irow, this%jcol, left%neqns_a, right%neqns_a, this%neqns_d)
193 if ((left%neqns_a + right%neqns_a + this%neqns_d) .ne. this%neqns_a)
then
194 write(6,*)
'Error: Fail to matrix partitioning in parallel direct solver.'
195 write(6,*)
'Matrix is too small.'
196 write(ilog,*)
'Error: Fail to matrix partitioning in parallel direct solver.'
197 write(ilog,*)
'Matrix is too small.'
201 call get_part_result(left%neqns_a, ip_left, right%neqns_a, ip_right, this%neqns_d, ip_d)
215 allocate(left%idx_g_a(left%neqns_a))
216 allocate(right%idx_g_a(right%neqns_a))
217 allocate(this%idx_g_d(this%neqns_d))
223 if(part(i) .eq. 1)
then
226 left%idx_g_a(loc1)=this%idx_g_a(i)
228 if(part(i) .eq. 2)
then
231 right%idx_g_a(loc2)=this%idx_g_a(i)
233 if(part(i) .eq. 3)
then
236 this%idx_g_d(loc3)=this%idx_g_a(i)
249 if ((part(i) .eq. 1) .and. (part(j) .eq. 1))
then
250 left%nttbr_a=left%nttbr_a + 1
251 if(ipass .eq. 2)
then
252 left%irow(left%nttbr_a)=iperm(i)
253 left%jcol(left%nttbr_a)=iperm(j)
258 if ((part(i) .eq. 2) .and. (part(j) .eq. 2))
then
259 right%nttbr_a=right%nttbr_a + 1
260 if(ipass .eq. 2)
then
261 right%irow(right%nttbr_a)=iperm(i)
262 right%jcol(right%nttbr_a)=iperm(j)
268 if (ipass .eq. 1)
then
269 allocate(left%irow(left%nttbr_a), left%jcol(left%nttbr_a))
270 allocate(right%irow(right%nttbr_a), right%jcol(right%nttbr_a))
274 deallocate(ip_left, ip_right, ip_d, iperm, part, this%irow, this%jcol)
276 call make_matrix_partition_tree(left)
277 call make_matrix_partition_tree(right)
279 end subroutine make_matrix_partition_tree
283 subroutine mkpart(part_g, iperm_g, neqns_d)
286 integer(kind=kint),
intent(out) :: part_g(:)
287 integer(kind=kint),
intent(out) :: iperm_g(:)
288 integer(kind=kint),
intent(out) :: neqns_d
290 type(matrix_partition_node),
pointer :: node
291 integer(kind=kint) :: ncount
292 integer(kind=kint) :: i,j
297 do i=iend_leaf, ista_leaf, -1
302 part_g(node%idx_g_a(j))=node%idm
303 iperm_g(node%idx_g_a(j))=ncount
305 deallocate(node%idx_g_a)
310 do i=iend_trunk, 1, -1
311 node => tree_array(i)
314 part_g(node%idx_g_d(j))=node%idm
315 iperm_g(node%idx_g_d(j))=ncount
317 deallocate(node%idx_g_d)
321 deallocate(tree_array)
323 end subroutine mkpart
327 subroutine divmat(a0, part_g, iperm_g, dm, dsln, diag, neqns_d)
332 integer(kind=kint),
intent(in) :: part_g(:), iperm_g(:)
335 real(kind=
kreal),
intent(out) :: dsln(:,:), diag(:,:)
337 integer(kind=kint),
intent(in) :: neqns_d
341 integer(kind=kint) :: ndeg, ipass, ipos, itmp
342 integer(kind=kint) :: i,j,k,l,m,n, ii, jj
353 dm(k)%a%neqns = dm(k)%a%neqns + 1
361 dm(i)%c%nrows = neqns_d
362 dm(i)%c%ncols = dm(i)%a%neqns
363 dm(i)%ista_c = dm(i)%a%neqns + 1
377 if (part_g(i) .eq. part_g(j))
then
378 if ((part_g(i) .eq. 0) .or. (part_g(j) .eq. 0))
then
379 if (iperm_g(i) .eq. iperm_g(j))
then
383 diag(ipos, iperm_g(i))=a0%val(ndeg*(m-1)+n,l)
388 else if (iperm_g(i) .gt. iperm_g(j))
then
394 k = (ii-1)*(ii-2)/2 + jj
396 dsln(:,k)=a0%val(:,l)
403 k = (ii-1)*(ii-2)/2 + jj
407 dsln((m-1)*ndeg+n,k)=a0%val(m+(n-1)*ndeg,l)
414 dmc%a%nttbr = dmc%a%nttbr + 1
416 dmc%a%irow(dmc%a%nttbr) = iperm_g(i)
417 dmc%a%jcol(dmc%a%nttbr) = iperm_g(j)
418 dmc%a%val(:,dmc%a%nttbr) = a0%val(:,l)
424 if (part_g(i) .eq. 0)
then
426 dmc%c%nttbr = dmc%c%nttbr + 1
428 dmc%c%irow(dmc%c%nttbr)=iperm_g(i)
429 dmc%c%jcol(dmc%c%nttbr)=iperm_g(j)
430 dmc%c%val(:,dmc%c%nttbr)=a0%val(:,l)
435 if (part_g(j) .eq. 0)
then
437 dmc%c%nttbr = dmc%c%nttbr + 1
439 dmc%c%irow(dmc%c%nttbr)=iperm_g(j)
440 dmc%c%jcol(dmc%c%nttbr)=iperm_g(i)
443 dmc%c%val(n+ndeg*(m-1),dmc%c%nttbr)=a0%val(ndeg*(n-1)+m,l)
453 if (ipass .eq. 1)
then
455 allocate(dm(i)%a%irow(dm(i)%a%nttbr))
456 allocate(dm(i)%a%jcol(dm(i)%a%nttbr))
457 allocate(dm(i)%a%val(ndeg*ndeg,dm(i)%a%nttbr))
459 allocate(dm(i)%c%irow(dm(i)%c%nttbr))
460 allocate(dm(i)%c%jcol(dm(i)%c%nttbr))
461 allocate(dm(i)%c%val(ndeg*ndeg,dm(i)%c%nttbr))
467 end subroutine divmat
471 subroutine reovec(r, iperm)
476 integer(kind=kint),
dimension(:),
intent(in) :: iperm
477 real(kind=
kreal),
dimension(:,:),
intent(inout) :: r
479 real(kind=
kreal),
allocatable,
dimension(:,:) :: tmp
480 integer(kind=kint) :: ndeg, neqns
481 integer(kind=kint),
dimension(2) :: ishape
482 integer(kind=kint) :: i,j,k,l
487 allocate(tmp(ndeg, neqns))
492 tmp(j,iperm(i))=r(j,i)
505 function depthinbinarytree(n)
508 integer(kind=kint) :: depthinbinarytree
509 integer(kind=kint),
intent(in) :: n
510 integer(kind=kint) :: i
512 do while (n .ge. 2**(i+1))
515 depthinbinarytree = i