FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
hecmw_solver_direct_parallel.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
5 ! module for Parallel Direct Solver
7 
8 #ifndef HECMW_SERIAL
10  use m_irjc_matrix
12  use m_elap
13 #endif
14 
15  use hecmw_util
16 
17 #ifndef HECMW_SERIAL
20 #endif
21 
22  ! access control !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 
24  private ! default
25 
26  public hecmw_solve_direct_parallel ! only entry point of Parallel Direct Solver is public
27 
28 #ifndef HECMW_SERIAL
29 
30  ! internal type definition !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
31 
32  type procinfo ! process information on MPI
33  integer(kind=kint) :: myid
34  integer(kind=kint) :: imp ! mother process id
35  logical :: isparent ! true if this process is parent
36  logical :: ischild ! true if this process is child
37 
38  integer(kind=kint) :: nchildren ! number of child process
39  integer(kind=kint), pointer :: ichildren(:) ! array of children process number
40 
41  integer(kind=kint) :: ndiv ! count for matrix division.
42  end type procinfo
43 
44  type dsinfo ! direct solver information
45  integer(kind=kint) :: ndeg ! dimension of small matrix
46  integer(kind=kint) :: neqns ! number of equations
47  integer(kind=kint) :: nstop ! beginning point of C
48  integer(kind=kint) :: stage ! calculation stage
49  integer(kind=kint) :: lncol ! length of col
50  integer(kind=kint) :: lndsln ! length of dsln
51 
52  integer(kind=kint), pointer :: zpiv(:) ! in zpivot()
53  integer(kind=kint), pointer :: iperm(:) ! permtation vector
54  integer(kind=kint), pointer :: invp(:) ! inverse permtation of iperm
55  integer(kind=kint), pointer :: parent(:) !
56  integer(kind=kint), pointer :: nch(:) !
57  integer(kind=kint), pointer :: xlnzr(:) ! ia index of whole sparse matrix. (neqns_t + 1)
58  integer(kind=kint), pointer :: colno(:) ! ja index of whole sparse matrix.
59 
60  real(kind=kreal), pointer :: diag(:,:) ! diagonal element
61  real(kind=kreal), pointer :: zln(:,:) ! non diagonal sparse
62  real(kind=kreal), pointer :: dsln(:,:) ! non diagonal dens
63  end type dsinfo
64 
65  ! internal global variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66 
67  type(procinfo) :: m_pds_procinfo ! initialized in initproc()
68  real(kind=kreal), parameter :: rmin = 1.00d-200 ! for inv3() pivot
69 
70  integer :: imsg ! output file handler
71 
72  integer, parameter :: ilog = 16 ! according to FSTR
73  logical, parameter :: ldbg = .false.
74  integer, parameter :: idbg = 52 ! according to FSTR
75  logical :: lelap = .false.
76 
77 #endif
78 
79 contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
80 
81  subroutine hecmw_solve_direct_parallel(hecMESH, hecMAT, ii)
82 
83  implicit none
84 
85  type (hecmwst_local_mesh), intent(inout) :: hecmesh
86  type (hecmwst_matrix ), intent(inout) :: hecmat
87  integer(kind=kint), intent(in) :: ii ! output file handler
88 
89 #ifndef HECMW_SERIAL
90 
91  logical, save :: first_time = .true.
92 
93  integer(kind=kint) :: ierr
94 
95  ! start !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
96 
97  call hecmw_mat_dump(hecmat, hecmesh)
98 
99  imsg=ii ! set message file
100 
101  ! enable the timestamped progress trace
102  if (hecmat%Iarray(24) .ge. 2) then ! = LOGLEVEL >= 2 (-1 when not given)
103  lelap = .true.
104  end if
105 
106  ! set location in process tree
107  if (first_time) then
108  call initproc()
109  hecmat%Iarray(97) = 0 ! numeric factorization done flag
110  hecmat%Iarray(98) = 0 ! symbolic factorization done flag
111  first_time = .false.
112  end if
113 
114  if ((hecmat%Iarray(97) .ne. 0) .or. (hecmat%Iarray(98) .ne. 0)) then
115  write(ilog,*) 'Error: Recalculation of LDU decompose is currently not surported'
117  end if
118 
119  ! set elap time information
120  call initelap(lelap, idbg) !TODO it should be replaced with lelap
121 
122  if (m_pds_procinfo%isparent) then
123  call elapout('hecmw_solve_direct_parallel: entering sp_direct_parent') !elap
124  call sp_direct_parent(hecmesh, hecmat)
125  else if (m_pds_procinfo%ischild) then
126  call elapout('hecmw_solve_direct_parallel: entering sp_direct_child') !elap
127  call sp_direct_child()
128  else
129  call elapout('hecmw_solve_direct_parallel: never come here') !elap
131  end if
132 
133  call mpi_bcast(hecmat%x, hecmesh%n_dof*hecmat%NP, mpi_real8, m_pds_procinfo%imp, mpi_comm_world, ierr)
134 
135  call hecmw_mat_dump_solution(hecmat)
136 
137 #endif
138 
139  return
140  end subroutine hecmw_solve_direct_parallel
141 
142 
143 #ifndef HECMW_SERIAL
144 
145  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
146 
147  subroutine sp_direct_parent(hecMESH, hecMAT)
148 
149  implicit none
150 
151  !I/O !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
152  type (hecmwst_local_mesh), intent(inout) :: hecmesh
153  type (hecmwst_matrix ), intent(inout) :: hecmat
154 
155 
156  !internal !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
157 
158  ! given A0 x = b0
159  type (irjc_square_matrix) :: a0 ! given left side matrix assembled from sp_matrix
160  real(kind=kreal), allocatable :: b(:,:) ! (ndeg,neqns) right hand side value vector of equation.
161 
162  ! for divided matrixes
163  type(matrix_partition_info) :: pmi
164  integer(kind=kint), pointer, save :: iperm_rev(:)
165  integer(kind=kint), pointer, save :: iofst_dm(:)
166 
167  integer(kind=kint), save :: neqns_d ! number of eqns in D matrix
168  real(kind=kreal), pointer, save :: dsln(:,:) ! non-diagonal elements of dens D matrix
169  real(kind=kreal), pointer, save :: diag(:,:) ! diagonal elements of dens D matrix
170  integer(kind=kint), pointer, save :: part_all(:) ! index of corresponding dm of a0 row
171  integer(kind=kint), pointer, save :: iperm_all(:) ! index in partitioned matrix of a0 row
172  type(child_matrix), pointer, save :: dm(:) !divided matrices
173 
174  real(kind=kreal), allocatable :: bd(:,:) ! for right hand side value
175 
176  ! internal use
177  real(kind=kreal), allocatable :: oldb(:,:)
178  logical, save :: nusol_ready = .false.
179  integer(kind=kint), save :: ndeg, nndeg, ndegt
180  integer(kind=kint), save :: ndm
181 
182  ! misc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
183  integer(kind=kint) :: ierr
184  integer(kind=kint) :: i,j,k
185  integer(kind=kint) :: timelog
186  real(kind=kreal) :: t1, t2, t3
187 
188  ! for MPI
189  integer(kind=kint) :: istatus(mpi_status_size)
190  integer(kind=kint) :: icp
191  real(kind=kreal), allocatable :: spdslnval(:,:), diagbuf(:,:), bdbuf(:,:)
192  integer(kind=kint), allocatable :: spdslnidx(:)
193  integer(kind=kint) :: nspdsln
194 
195  ierr=0
196  timelog = hecmat%Iarray(22)
197  t1 = hecmw_wtime()
198  call elapout('sp_direct_parent: entered') !elap
199 
200 
201  if (.not. nusol_ready) then
202 
203  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
204  !
205  ! STEP01: get a0 from FEM data format hecMESH
206  !
207 
208  call geta0(hecmesh, hecmat, a0)
209  ndeg=a0%ndeg
210  nndeg=ndeg*ndeg
211  ndegt = (ndeg+1)*ndeg/2 !triangle element in diag
212 
213  call elapout('sp_direct_parent: make a0 done') !elap
214 
215  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
216  !
217  ! STEP1X: Parallel LDU decompose of given A0
218  !
219  ! STEP11: divide given large matrix A into a1 and a2 ... extend to 2^n division.
220  ! C is added to bottom of A1, A2.
221  ! D is kept as dsln (off-diagonal), diag (diagonal).
222 
223  call elapout('sp_direct_parent: enter matrix partition') !elap
224  call matrix_partition_recursive_bisection(a0, m_pds_procinfo%ndiv, pmi)
225  call elapout('sp_direct_parent: end matrix partition') !elap
226  neqns_d = pmi%neqns_d
227  dsln=>pmi%dsln
228  diag=>pmi%diag
229  part_all=>pmi%part_all
230  iperm_all=>pmi%iperm_all
231  dm=>pmi%dm
232  ndm=pmi%ndm
233 
234  ! permtation vector for right hand side value
235  allocate(iofst_dm(0:ndm), stat=ierr)
236  if(ierr .ne. 0) then
237  call errtrp('stop due to allocation error.')
238  end if
239  iofst_dm(0)=0
240  iofst_dm(1)=neqns_d
241  do i=2,ndm
242  iofst_dm(i)=iofst_dm(i-1)+dm(i-1)%a%neqns
243  end do
244  do i=1,a0%neqns
245  iperm_all(i)=iperm_all(i)+iofst_dm(part_all(i))
246  end do
247 
248  allocate(iperm_rev(a0%neqns), stat=ierr)
249  if(ierr .ne. 0) then
250  call errtrp('stop due to allocation error.')
251  end if
252  do i=1, a0%neqns
253  iperm_rev(iperm_all(i)) = i
254  end do
255 
256  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
257  !
258  ! STEP12: Send divided left hand side matrixes to child processes.
259  !
260  ! nstop (separator of A and C) is also send
261  ! A and C will be LDU decomposed in child processes.
262  ! D region update data will be returned.
263 
264  call elapout('sp_direct_parent: send divided matrix to children') !elap
265  do i=1,m_pds_procinfo%nchildren
266  icp = m_pds_procinfo%ichildren(i)
267  call mpi_send(dm(i)%a%ndeg, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
268  call mpi_send(dm(i)%a%neqns, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
269  call mpi_send(dm(i)%a%nttbr, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
270 
271  call mpi_send(dm(i)%a%irow, dm(i)%a%nttbr, mpi_integer,icp,1,mpi_comm_world,ierr)
272  call mpi_send(dm(i)%a%jcol, dm(i)%a%nttbr, mpi_integer,icp,1,mpi_comm_world,ierr)
273  call mpi_send(dm(i)%a%val, dm(i)%a%nttbr*dm(i)%a%ndeg*dm(i)%a%ndeg, mpi_real8,icp,1,mpi_comm_world,ierr)
274 
275  call mpi_send(dm(i)%c%ndeg, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
276  call mpi_send(dm(i)%c%nttbr, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
277  call mpi_send(dm(i)%c%nrows, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
278  call mpi_send(dm(i)%c%ncols, 1,mpi_integer,icp,1,mpi_comm_world,ierr)
279 
280  call mpi_send(dm(i)%c%irow, dm(i)%c%nttbr, mpi_integer,icp,1,mpi_comm_world,ierr)
281  call mpi_send(dm(i)%c%jcol, dm(i)%c%nttbr, mpi_integer,icp,1,mpi_comm_world,ierr)
282  call mpi_send(dm(i)%c%val, dm(i)%c%nttbr*dm(i)%c%ndeg*dm(i)%c%ndeg, mpi_real8,icp,1,mpi_comm_world,ierr)
283  end do
284 
285  !call MPI_BARRIER(MPI_COMM_WORLD, ierr)
286 
287  ! clean up
288  do i=1,m_pds_procinfo%nchildren
289  deallocate(dm(i)%a%irow,dm(i)%a%jcol,dm(i)%a%val)
290  deallocate(dm(i)%c%irow,dm(i)%c%jcol,dm(i)%c%val)
291  end do
292 
293  call elapout('sp_direct_parent: end send matrix') !elap
294 
295  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
296  !
297  ! STEP13: Receive D region and update D matrix as D' = D - D1' - D2' ...
298  !
299  ! D is receive as dens matrix, which format is given in s3um2() in serial solver.
300  ! to decompose this dens D matrix, use s3um3() on parent.
301 
302  call elapout('sp_direct_parent: receive D matrix element') !elap
303  allocate(diagbuf(ndegt, neqns_d), stat=ierr)
304  if(ierr .ne. 0) then
305  call errtrp('stop due to allocation error.')
306  end if
307 
308  do k=1,m_pds_procinfo%nchildren
309  icp=m_pds_procinfo%ichildren(k)
310  call mpi_recv(nspdsln, 1,mpi_integer,icp,1,mpi_comm_world,istatus,ierr)
311  allocate(spdslnidx(nspdsln),spdslnval(nndeg,nspdsln),stat=ierr)
312  if(ierr .ne. 0) then
313  call errtrp('stop due to allocation error.')
314  end if
315  call mpi_recv(spdslnidx, nspdsln, mpi_integer,icp,1,mpi_comm_world,istatus,ierr)
316  call mpi_recv(spdslnval, nspdsln*nndeg,mpi_real8,icp,1,mpi_comm_world,istatus,ierr)
317  call mpi_recv(diagbuf, neqns_d*ndegt,mpi_real8,icp,1,mpi_comm_world,istatus,ierr)
318 
319  ! off diagonal
320  do i=1,nspdsln
321  dsln(:,spdslnidx(i)) = dsln(:,spdslnidx(i)) + spdslnval(:,i) ! because of child process dsln is already substructed in s3um2()
322  end do
323 
324  ! diagonal
325  do i=1,neqns_d
326  do j=1,ndegt
327  diag(j,i) = diag(j,i) + diagbuf(j,i)
328  end do
329  end do
330  deallocate(spdslnidx, spdslnval)
331  end do
332  deallocate(diagbuf)
333  call elapout('sp_direct_parent: end receive D matrix element') !elap
334 
335  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
336  !
337  ! STEP13: ! LDU decompose dens D
338  !
339  call elapout('sp_direct_parent: LDU decompose of D. entering nufct0_parent') !elap
340  call nufct0_parent(dsln, diag, neqns_d, ndeg)
341  call elapout('sp_direct_parent: exit nufct0_parent') !elap
342 
343 
344  nusol_ready = .true.
345  end if
346  t2 = hecmw_wtime()
347 
348  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
349  !
350  ! STEP2X: Solve Ax=b0
351  !
352  ! STEP21: divide right hand side b0 and send it to child in charge.
353  !
354  ! right hand side vector b is reordered as follows:
355  ! b(1:neqns_d)=for parent process
356  ! b(neqns_d+1:number of b in dm(1)) for dm(1)
357  ! b(end of b1:number of b in dm(2)) for dm(2)
358  ! ..
359  ! b(end of b_n-1:neqns_t) for dm(ndm)
360 
361  ! set right hand side vector (b)
362  allocate(b(ndeg,a0%neqns), stat=ierr)
363  if(ierr .ne. 0) then
364  call errtrp('stop due to allocation error.')
365  end if
366  do i=1,a0%neqns
367  do j=1,ndeg
368  b(j,i)=hecmat%b(ndeg*(i-1)+j)
369  end do
370  end do
371 
372  ! for verify
373  allocate(oldb(ndeg,a0%neqns), stat=ierr)
374  if(ierr .ne. 0) then
375  call errtrp('stop due to allocation error.')
376  end if
377  oldb=b
378 
379  call reovec(b, iperm_all)
380  do i=1,m_pds_procinfo%nchildren
381  icp=m_pds_procinfo%ichildren(i)
382  call mpi_send(b(1,iofst_dm(i)+1), dm(i)%ndeg*dm(i)%a%neqns, mpi_real8, icp, 1,mpi_comm_world, ierr)
383  end do
384 
385  allocate(bd(ndeg,neqns_d), stat=ierr)
386  if(ierr .ne. 0) then
387  call errtrp('stop due to allocation error.')
388  end if
389  bd(:,1:neqns_d) = b(:,1:neqns_d)
390 
391  call elapout('sp_direct_parent: end send b') !elap
392 
393  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
394  !
395  ! STEP22 forward substitution for D region. and get Y
396  !
397  ! b1, b2... are sended to child processes.
398  ! bd is substituted to D in locally, and results from child processes
399  ! (C1-Y1 substitute, C2-Y2 substitute...) are receive from child processes.
400  ! these value also add for Yd
401  call elapout('sp_direct_parent: begin receive bd') !elap
402  allocate(bdbuf(ndeg,neqns_d), stat=ierr)
403  if(ierr .ne. 0) then
404  call errtrp('stop due to allocation error.')
405  end if
406  bdbuf=0
407  do k=1,m_pds_procinfo%nchildren
408  icp=m_pds_procinfo%ichildren(k)
409  call mpi_recv(bdbuf, ndeg*neqns_d, mpi_real8, icp, 1,mpi_comm_world, istatus, ierr)
410  do i=1,neqns_d
411  do j=1,ndeg
412  bd(j,i) = bd(j,i) + bdbuf(j,i)
413  end do
414  end do
415  end do
416 
417  call elapout('sp_direct_parent: end receive bd') !elap
418 
419  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
420  !
421  ! STEP22 solve Ax=b for dens matrix, using updated bd
422  !
423  call elapout('sp_direct_parent: begin solve Ax_d=b_d') !elap
424  call nusol0_parent(dsln, diag, bd, neqns_d, ndeg)
425  call elapout('sp_direct_parent: end solve Ax_d=b_d') !elap
426 
427 
428  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
429  !
430  ! STEP23 send Xd to children
431  !
432  call elapout('sp_direct_parent: begin send Xd') !elap
433  call mpi_bcast(bd, ndeg*neqns_d, mpi_real8, m_pds_procinfo%imp, mpi_comm_world, ierr)
434  call elapout('sp_direct_parent: end send Xd') !elap
435 
436  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
437  !
438  ! STEP24 Receive results Xi from children.
439  !
440  call elapout('sp_direct_parent: begin receive X') !elap
441  do k=1,m_pds_procinfo%nchildren
442  icp=m_pds_procinfo%ichildren(k)
443  call mpi_recv(b(1,iofst_dm(k)+1), dm(k)%ndeg*dm(k)%a%neqns, mpi_real8, icp, 1,mpi_comm_world, istatus, ierr)
444  end do
445  b(:,1:neqns_d)=bd(:,:) ! set xd
446  call elapout('sp_direct_parent: end receive X') !elap
447 
448  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
449  !
450  ! STEP25 restore final result
451  !
452  ! permtation divided matrix => initial order
453  call elapout('sp_direct_parent: begin permutate X') !elap
454  call reovec(b, iperm_rev)
455  call elapout('sp_direct_parent: end permutate X') !elap
456 
457  ! verify result
458  call verif0(a0%neqns, ndeg, a0%nttbr, a0%irow, a0%jcol, a0%val, oldb, b) !verify result oldb will be broken.
459 
460  ! set result to FEM data
461  do i=1,a0%neqns
462  do j=1,ndeg
463  hecmat%x(ndeg*(i-1)+j)=b(j,i)
464  end do
465  end do
466 
467  call elapout('sp_direct_parent: end solve Ax=b') !elap
468  t3 = hecmw_wtime()
469  if (timelog > 0) then
470  write(*,*) 'setup time : ',t2-t1
471  write(*,*) 'solve time : ',t3-t2
472  endif
473  deallocate(b, bd, bdbuf, oldb)
474  return
475  end subroutine sp_direct_parent
476 
477  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
478 
479  subroutine geta0(hecMESH,hecMAT, a0)
480 
481  implicit none
482 
483  type (hecmwst_local_mesh), intent(in) :: hecmesh
484  type (hecmwst_matrix ), intent(in) :: hecmat
485  type (irjc_square_matrix), intent(out) :: a0
486 
487  integer(kind=kint) :: i,j,k,ierr,numnp,ndof,kk,ntotal
488  integer(kind=kint) :: ndof2
489 
490  numnp = hecmat%NP
491  ndof = hecmesh%n_dof
492  ntotal = numnp*ndof
493 
494  !*NUFACT variables
495  a0%neqns = numnp
496  a0%ndeg = ndof
497  a0%nttbr = hecmat%NP+hecmat%NPL !+hecMAT%NPU if unsymmetric
498 
499  !*Allocations
500  allocate(a0%irow(a0%nttbr),stat=ierr)
501  allocate(a0%jcol(a0%nttbr),stat=ierr)
502  allocate(a0%val(a0%ndeg*a0%ndeg, a0%nttbr),stat=ierr)
503  if(ierr .ne. 0) then
504  call errtrp('stop due to allocation error.')
505  end if
506 
507  kk = 0
508  ndof2 = ndof*ndof
509  do j= 1, numnp
510  !*Diagonal
511  kk = kk + 1
512  a0%irow(kk) = j
513  a0%jcol(kk) = j
514  call vlcpy(a0%val(:,kk),hecmat%D(ndof2*(j-1)+1:ndof2*j),ndof)
515  !*Lower
516  do k= hecmat%indexL(j-1)+1, hecmat%indexL(j)
517  i= hecmat%itemL(k)
518  kk = kk + 1
519  a0%irow(kk) = j
520  a0%jcol(kk) = i
521  call vlcpy(a0%val(:,kk),hecmat%AL(ndof2*(k-1)+1:ndof2*k),ndof)
522  enddo
523  enddo
524 
525  return
526 
527  contains
528 
529  subroutine vlcpy(a,b,n)
530  implicit none
531  real(kind=kreal), intent(out) :: a(:)
532  real(kind=kreal), intent(in) :: b(:)
533  integer(kind=kint), intent(in) :: n
534 
535  integer(kind=kint) :: i,j
536 
537  do i = 1,n
538  do j = 1,n
539  a((j-1)*n+i) = b((i-1)*n+j) !transpose
540  end do
541  end do
542  return
543  end subroutine vlcpy
544 
545  end subroutine geta0
546 
547  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
548 
549  subroutine sp_direct_child()
550  ! parallel direct solver child process
551 
552  implicit none
553 
554  type (child_matrix) :: cm
555 
556  real(kind=kreal), allocatable :: b(:,:) ! (ndeg, neqns)
557  type (dsinfo) :: dsi
558  logical, save :: nusol_ready = .false.
559 
560  ! for MPI
561  integer(kind=kint) :: istatus(mpi_status_size)
562  integer(kind=kint) :: imp, ierr
563  integer(kind=kint) :: i
564 
565  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
566 
567  call elapout('sp_direct_child: entered') !elap
568 
569  imp=m_pds_procinfo%imp
570 
571  if (.not. nusol_ready) then
572 
573  call elapout('sp_direct_child: waiting matrix from parent via MPI') !elap
574  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
575  !
576  ! STEP01: get a,c from parent
577  ! C matrix is placed below A.
578  !
579  call mpi_recv(cm%a%ndeg, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
580  call mpi_recv(cm%a%neqns, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
581  call mpi_recv(cm%a%nttbr, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
582  allocate(cm%a%irow(cm%a%nttbr), stat=ierr)
583  if(ierr .ne. 0) then
584  call errtrp('stop due to allocation error.')
585  end if
586  allocate(cm%a%jcol(cm%a%nttbr), stat=ierr)
587  if(ierr .ne. 0) then
588  call errtrp('stop due to allocation error.')
589  end if
590  allocate(cm%a%val(cm%a%ndeg*cm%a%ndeg, cm%a%nttbr), stat=ierr)
591  if(ierr .ne. 0) then
592  call errtrp('stop due to allocation error.')
593  end if
594  call mpi_recv(cm%a%irow, cm%a%nttbr, mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
595  call mpi_recv(cm%a%jcol, cm%a%nttbr, mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
596  call mpi_recv(cm%a%val, cm%a%nttbr*cm%a%ndeg*cm%a%ndeg, mpi_real8,imp,1,mpi_comm_world,istatus,ierr)
597 
598 
599  call mpi_recv(cm%c%ndeg, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
600  call mpi_recv(cm%c%nttbr, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
601  call mpi_recv(cm%c%nrows, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
602  call mpi_recv(cm%c%ncols, 1,mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
603  allocate(cm%c%irow(cm%c%nttbr), stat=ierr)
604  if(ierr .ne. 0) then
605  call errtrp('stop due to allocation error.')
606  end if
607  allocate(cm%c%jcol(cm%c%nttbr), stat=ierr)
608  if(ierr .ne. 0) then
609  call errtrp('stop due to allocation error.')
610  end if
611  allocate(cm%c%val(cm%c%ndeg*cm%c%ndeg, cm%c%nttbr), stat=ierr)
612  if(ierr .ne. 0) then
613  call errtrp('stop due to allocation error.')
614  end if
615  call mpi_recv(cm%c%irow, cm%c%nttbr, mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
616  call mpi_recv(cm%c%jcol, cm%c%nttbr, mpi_integer,imp,1,mpi_comm_world,istatus,ierr)
617  call mpi_recv(cm%c%val, cm%c%nttbr*cm%c%ndeg*cm%c%ndeg, mpi_real8,imp,1,mpi_comm_world,istatus,ierr)
618 
619  cm%ndeg = cm%a%ndeg
620  cm%ista_c = cm%a%neqns+1
621  cm%neqns_t = cm%a%neqns + cm%c%nrows
622  call elapout('sp_direct_child: end get matrix from parent via MPI') !elap
623  !call MPI_BARRIER(MPI_COMM_WORLD, ierr)
624 
625 
626 
627  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
628  !
629  ! STEP1x: LDU decompose for given matrix
630  !
631 
632  ! set up dsi for allocate matrix array for fill-in
633  call elapout('sp_direct_child: entering matini_para') !elap
634  call matini_para(cm, dsi, ierr)
635  call elapout('sp_direct_child: exit matini_para') !elap
636 
637  call elapout('sp_direct_child: entering staij1') !elap
638  ! set real8 value
639  do i=1,cm%a%nttbr
640  call staij1(0, cm%a%irow(i), cm%a%jcol(i), cm%a%val(:,i), dsi, ierr)
641  end do
642  do i=1,cm%c%nttbr
643  ! call staij1(0, cm%c%irow(i)+cm%a%neqns, dsi%iperm(cm%c%jcol(i)), cm%c%val(:,i), dsi, ierr)
644  call staij1(0, cm%c%irow(i)+cm%a%neqns, cm%c%jcol(i), cm%c%val(:,i), dsi, ierr)
645  end do
646  call elapout('sp_direct_child: end staij1') !elap
647 
648  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
649  !
650  ! following STEP12-15 will be done in nufct0_child()
651  !
652  ! STEP12: LDU decompose of A (1..nstop-1)
653  ! STEP13: LDU decompose of C (nstop..neqnsA+neqnsd)
654  ! STEP14: update D region.
655  ! STEP15: send D region to parent
656  call elapout('sp_direct_child: entering nufct0_child') !elap
657  call nufct0_child(dsi, ierr)
658  call elapout('sp_direct_child: exit nufct0_child') !elap
659 
660  nusol_ready = .true.
661  end if
662 
663  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
664  !
665  ! STEP2x: solve ax=b by using forward an backward substitution
666  !
667  ! STEP21: receive b from parent
668  !
669  allocate(b(cm%ndeg, cm%neqns_t), stat=ierr)
670  if(ierr .ne. 0) then
671  call errtrp('stop due to allocation error.')
672  end if
673 
674  ! wait for right hand side vector
675  call mpi_recv(b, cm%ndeg*cm%a%neqns, mpi_real8, imp, 1,mpi_comm_world, istatus, ierr)
676 
677  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
678  !
679  ! following STEP22-24 is done in nusol0-child()
680  !
681  ! STEP22: forward substitution for A
682  ! STEP23: forward substitution for C and send it (yi) to parent
683  ! STEP24: divide with diagonal matrix
684  ! STEP25: receive xd from parent and do backward substitution
685  call elapout('sp_direct_child: enter nusol0_child') !elap
686  call nusol0_child(b, dsi, ierr)
687  call elapout('sp_direct_child: exit nusol0_child') !elap
688 
689  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
690  !
691  ! STEP26: send final result to parent
692  !
693  call elapout('sp_direct_child: begin send result to parent') !elap
694  call mpi_send(b, cm%ndeg*cm%a%neqns, mpi_real8, imp, 1,mpi_comm_world, ierr)
695  call elapout('sp_direct_child: end send result to parent') !elap
696 
697  return
698 
699  end subroutine sp_direct_child
700 
701 
702  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
703 
704  subroutine initproc()
705  implicit none
706 
707  integer(kind=kint) :: npe, myid
708  integer(kind=kint) :: ndiv
709  integer(kind=kint) :: ierr
710  integer(kind=kint) :: i
711 
712  m_pds_procinfo%isparent=.false.
713  m_pds_procinfo%ischild=.false.
714 
715  ! get process number and number of whole processes
716  call mpi_comm_size(mpi_comm_world, npe, ierr)
717  call mpi_comm_rank(mpi_comm_world, myid, ierr)
718 
719  m_pds_procinfo%myid = myid
720 
721  ndiv=0
722  do
723  if (2**(ndiv + 1) .gt. npe) then
724  exit
725  end if
726  ndiv = ndiv + 1
727  end do
728  m_pds_procinfo%ndiv = ndiv
729 
730  if (npe .ne. 2**ndiv + 1) then
731  write(ilog,*) 'Error: please use 2**n+1 (3,5,9,17...) processes for parallel direct solver.'
732  write(6,*) 'Error: please use 2**n+1 (3,5,9,17...) processes for parallel direct solver.'
734  stop
735  end if
736 
737  if (myid.eq.0) then
738  write(idbg,*)'parent process.'
739  m_pds_procinfo%isparent=.true.
740  m_pds_procinfo%nchildren=2**ndiv
741  allocate(m_pds_procinfo%ichildren(m_pds_procinfo%nchildren))
742  do i=1, 2**ndiv
743  m_pds_procinfo%ichildren(i)=i
744  end do
745  else
746  write(idbg,*)'child process.'
747  m_pds_procinfo%ischild=.true.
748  m_pds_procinfo%imp=0
749  end if
750 
751  return
752  end subroutine initproc
753 
754  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
755  subroutine errtrp(mes)
756  character(*) mes
757  write(6,*) 'Error in : process ', m_pds_procinfo%myid
758  write(ilog,*) mes
759 
761  stop
762  end subroutine errtrp
763 
764  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
765 
766  subroutine matini_para(cm,dsi,ir)
767 
768  !----------------------------------------------------------------------
769  !
770  ! matini initializes storage for sparse matrix solver.
771  ! this routine is used for both symmetric matrices
772  ! and must be called once at the beginning
773  !
774  ! (i)
775  ! neqns number of unknowns
776  ! nttbr number of non0s, pattern of non-zero elements are
777  ! given like following.
778  ! nonz(A)={(i,j);i=irow(l),j=jcol(l); 1<= l <= nttbr}
779  ! irow
780  ! jcol to define non-zero pattern
781  ! lenv length of the array v (iv)
782  !
783  ! (o)
784  ! dsi matrix information
785  ! ir return code
786  ! =0 normal
787  ! =-1 non positive index
788  ! =1 too big index
789  ! =10 insufficient storage
790  !
791  !
792  ! stage 10 after initialization
793  ! 20 building up matrix
794  ! 30 after LU decomposition
795  ! 40 after solving
796  !
797  ! # coded by t.arakawa
798  ! # reviced by t.kitayama of Univ. Tokyo on 20071120
799  !
800  !----------------------------------------------------------------------
801 
802  implicit none
803 
804  type(child_matrix), intent(in) :: cm
805  type(dsinfo), intent(out) :: dsi
806  integer(kind=kint), intent(out) :: ir
807 
808  integer(kind=kint), pointer :: irow_a(:), jcol_a(:)
809  integer(kind=kint), pointer :: irow_c(:), jcol_c(:)
810 
811  integer(kind=kint), pointer :: ia(:) ! in stiaja() neqns+2
812  integer(kind=kint), pointer :: ja(:) ! in stiaja() 2*nttbr
813  integer(kind=kint), pointer :: jcpt(:) ! in stsmat() 2*nttbr
814  integer(kind=kint), pointer :: jcolno(:) ! in stsmat() 2*nttbr
815 
816  integer(kind=kint), pointer :: iperm_a(:)
817  integer(kind=kint), pointer :: invp_a(:)
818 
819  integer(kind=kint), pointer :: xlnzr_a(:)
820  integer(kind=kint), pointer :: colno_a(:)
821 
822  integer(kind=kint), pointer :: xlnzr_c(:)
823  integer(kind=kint), pointer :: colno_c(:)
824 
825 
826  integer(kind=kint), pointer :: adjncy(:) ! in genqmd() 2*nttbr
827  integer(kind=kint), pointer :: qlink(:) ! in genqmd() neqne+2
828  integer(kind=kint), pointer :: qsize(:) ! in genqmd() neqne+2
829  integer(kind=kint), pointer :: nbrhd(:) ! in genqmd() neqne+2
830  integer(kind=kint), pointer :: rchset(:) ! in genqmd() neqne+2
831 
832  integer(kind=kint), pointer :: cstr(:)
833 
834  integer(kind=kint), pointer :: adjt(:) ! in rotate() neqne+2
835  integer(kind=kint), pointer :: anc(:) ! in rotate() neqne+2
836 
837  integer(kind=kint), pointer :: lwk3arr(:)
838  integer(kind=kint), pointer :: lwk2arr(:)
839  integer(kind=kint), pointer :: lwk1arr(:)
840  integer(kind=kint), pointer :: lbtreearr(:,:) ! genbtq() (2,neqns+1)
841  integer(kind=kint), pointer :: lleafarr(:)
842  integer(kind=kint), pointer :: lxleafarr(:)
843  integer(kind=kint), pointer :: ladparr(:)
844  integer(kind=kint), pointer :: lpordrarr(:)
845 
846  integer(kind=kint) :: neqns_a, nttbr_a, neqns_a1, nstop, neqns_t, neqns_d, nttbr_c, ndeg
847  integer(kind=kint) :: lncol_a, lncol_c
848  integer(kind=kint) :: neqnsz, nofsub, izz, izz0, lnleaf ! dummy variables
849  integer(kind=kint) :: ir1
850  integer(kind=kint) :: i, ierr
851 
852  ndeg = cm%ndeg
853 
854  neqns_t = cm%neqns_t
855  neqns_d = cm%c%nrows
856 
857  neqns_a = cm%a%neqns
858  nttbr_a = cm%a%nttbr
859  irow_a => cm%a%irow
860  jcol_a => cm%a%jcol
861 
862  nttbr_c = cm%c%nttbr
863  irow_c => cm%c%irow
864  jcol_c => cm%c%jcol
865 
866  dsi%neqns=neqns_t ! because direct solver treat A + C as one matrix.
867  dsi%ndeg=ndeg
868 
869  neqns_a1=neqns_a+2
870  ir=0
871  ierr=0
872  izz0 = 0.0d0
873  !
874  ! set z pivot
875  !
876  allocate(dsi%zpiv(neqns_a), stat=ierr)
877  if(ierr .ne. 0) then
878  call errtrp('stop due to allocation error.')
879  end if
880  call zpivot(neqns_a,neqnsz,nttbr_a,jcol_a,irow_a,dsi%zpiv,ir1)
881  if(ir1.ne.0) then
882  ir=ir1
883  goto 1000
884  endif
885  !
886  ! build jcpt,jcolno
887  !
888  allocate(jcpt(2*nttbr_a), jcolno(2*nttbr_a), stat=ierr)
889  if(ierr .ne. 0) then
890  call errtrp('stop due to allocation error.')
891  end if
892  call stsmat(neqns_a,nttbr_a,irow_a,jcol_a,jcpt,jcolno)
893  !
894  ! build ia,ja
895  !
896  allocate(ia(neqns_a1), ja(2*nttbr_a), stat=ierr)
897  if(ierr .ne. 0) then
898  call errtrp('stop due to allocation error.')
899  end if
900  call stiaja(neqns_a, neqns_a,ia,ja,jcpt,jcolno)
901  !
902  ! get permutation vector iperm,invp
903  !
904 
905  ! setup identity permtation for C matrix
906  allocate(iperm_a(neqns_a), invp_a(neqns_a), stat=ierr)
907  if(ierr .ne. 0) then
908  call errtrp('stop due to allocation error.')
909  end if
910  call idntty(neqns_a,invp_a,iperm_a)
911 
912  ! reorder A matrix
913  allocate(adjncy(2*nttbr_a),qlink(neqns_a1),qsize(neqns_a1),nbrhd(neqns_a1),rchset(neqns_a1), stat=ierr)
914  if(ierr .ne. 0) then
915  call errtrp('stop due to allocation error.')
916  end if
917  allocate(lwk2arr(neqns_a1),lwk1arr(neqns_a1), stat=ierr)
918  if(ierr .ne. 0) then
919  call errtrp('stop due to allocation error.')
920  end if
921  call genqmd(neqns_a,ia,ja,iperm_a,invp_a,lwk1arr,lwk2arr,rchset,nbrhd,qsize,qlink,nofsub,adjncy)
922  deallocate(adjncy, qlink, qsize, nbrhd, rchset)
923 
924  ! set ia, ja
925  call stiaja(neqns_a, neqns_a, ia, ja, jcpt,jcolno)
926 
927  ! build up the parent vector parent vector will be saved in
928  ! work2 for a while
929  allocate(cstr(neqns_a1),adjt(neqns_a1), stat=ierr)
930  if(ierr .ne. 0) then
931  call errtrp('stop due to allocation error.')
932  end if
933 10 continue
934  call genpaq(ia,ja,invp_a,iperm_a,lwk2arr,neqns_a,cstr)
935 
936  ! build up the binary tree
937  allocate (lbtreearr(2,neqns_a1), stat=ierr)
938  if(ierr .ne. 0) then
939  call errtrp('stop due to allocation error.')
940  end if
941  call genbtq(ia, ja, invp_a, iperm_a,lwk2arr,lbtreearr,dsi%zpiv,izz,neqns_a)
942 
943  ! rotate the binary tree to avoid a zero pivot
944  if(izz.eq.0) goto 20
945  if(izz0.eq.0) izz0=izz
946  if(izz0.ne.izz) goto 30
947  call rotate(ia, ja, invp_a, iperm_a, lwk2arr,lbtreearr,izz,neqns_a,anc,adjt,ir1)
948  goto 10
949 30 continue
950  call bringu(dsi%zpiv,iperm_a, invp_a, lwk2arr,izz,neqns_a,ir1)
951  goto 10
952 
953  ! post ordering
954 20 continue
955  allocate(lwk3arr(0:neqns_a1),lpordrarr(neqns_a1),dsi%parent(neqns_a1), dsi%nch(neqns_a1), stat=ierr)
956  if(ierr .ne. 0) then
957  call errtrp('stop due to allocation error.')
958  end if
959  call posord(dsi%parent,lbtreearr,invp_a,iperm_a,lpordrarr,dsi%nch,neqns_a,lwk1arr,lwk2arr,lwk3arr)
960 
961  ! generate skeleton graph
962  allocate(lleafarr(nttbr_a),lxleafarr(neqns_a1),ladparr(neqns_a1), stat=ierr)
963  if(ierr .ne. 0) then
964  call errtrp('stop due to allocation error.')
965  end if
966  call gnleaf(ia, ja, invp_a, iperm_a, lpordrarr,dsi%nch,ladparr,lxleafarr,lleafarr,neqns_a,lnleaf)
967 
968  ! build up xlnzr,colno (this is the symbolic fct.)
969  nstop = cm%ista_c
970  call countclno(dsi%parent, lxleafarr, lleafarr, neqns_a, nstop, lncol_a, ir1) ! only for A
971  allocate(colno_a(lncol_a),xlnzr_a(neqns_a1), stat=ierr)
972  if(ierr .ne. 0) then
973  call errtrp('stop due to allocation error.')
974  end if
975  call gnclno(dsi%parent,lpordrarr,lxleafarr,lleafarr,xlnzr_a, colno_a, neqns_a, nstop,lncol_a,ir1) ! only for A
976  if(ir1.ne.0) then
977  ir=10
978  goto 1000
979  endif
980 
981  ! do symbolic LDU decomposition for C region.
982  call ldudecomposec(xlnzr_a,colno_a,invp_a,iperm_a, ndeg, nttbr_c, irow_c, &
983  jcol_c, cm%c%ncols, cm%c%nrows, xlnzr_c, colno_c, lncol_c)
984 
985  ! set calculated information to dsi.
986  allocate(dsi%xlnzr(neqns_t + 1), stat=ierr)
987  if(ierr .ne. 0) then
988  call errtrp('stop due to allocation error.')
989  end if
990  dsi%xlnzr(1:neqns_a)=xlnzr_a(:)
991  dsi%xlnzr(neqns_a+1:neqns_t+1)=xlnzr_c(:)+xlnzr_a(neqns_a+1)-1
992 
993  dsi%lncol=lncol_a + lncol_c
994  allocate(dsi%colno(lncol_a + lncol_c), stat=ierr)
995  if(ierr .ne. 0) then
996  call errtrp('stop due to allocation error.')
997  end if
998  dsi%colno(1:lncol_a)=colno_a(:)
999  dsi%colno(lncol_a+1:lncol_a+lncol_c)=colno_c(:)
1000 
1001  allocate(dsi%invp(neqns_t), dsi%iperm(neqns_t), stat=ierr)
1002  if(ierr .ne. 0) then
1003  call errtrp('stop due to allocation error.')
1004  end if
1005  dsi%invp(1:neqns_a)=invp_a(1:neqns_a)
1006  dsi%iperm(1:neqns_a)=iperm_a(1:neqns_a)
1007  do i=neqns_a+1,neqns_t
1008  dsi%invp(i)=i
1009  dsi%iperm(i)=i
1010  end do
1011 
1012  deallocate(xlnzr_a, colno_a, xlnzr_c, colno_c, invp_a, iperm_a)
1013 
1014  dsi%nstop=nstop
1015  dsi%stage=10
1016 1000 continue
1017 
1018  return
1019  end subroutine matini_para
1020 
1021  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1022 
1023  subroutine nufct0_child(dsi,ir)
1024 
1025  implicit none
1026  type(dsinfo), intent(inout) :: dsi
1027  integer(kind=kint), intent(out) :: ir
1028  !
1029  ! this performs Cholesky factorization
1030  !
1031 
1032  if(dsi%stage.ne.20) then
1033  ir=40
1034  goto 1000
1035  else
1036  ir=0
1037  endif
1038  if(dsi%ndeg.eq.1) then
1039  call nufct1_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,ir)
1040  else if(dsi%ndeg.eq.2) then
1041  call nufct2_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,ir)
1042  else if(dsi%ndeg.eq.3) then
1043  call nufct3_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,ir)
1044  ! else if(dsi%ndeg.eq.6) then !TODO implement it
1045  ! call nufct6_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,ir)
1046  else
1047  call nufctx_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,dsi%ndeg,ir)
1048  end if
1049 
1050  dsi%stage=30
1051 1000 continue
1052  return
1053  end subroutine nufct0_child
1054 
1055  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1056 
1057  subroutine nufct1_child(xlnzr,colno,zln,diag,neqns,parent,nch,nstop,ir)
1058 
1059  implicit none
1060  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),parent(:)
1061  integer(kind=kint), intent(in) :: neqns, nstop
1062  integer(kind=kint), intent(inout) :: ir
1063  integer(kind=kint), intent(inout) :: nch(:)
1064  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) !zln(1,:), diag(1,:)
1065 
1066  integer(kind=kint) :: neqns_c
1067  integer(kind=kint) :: i,l, ic,ierr,imp
1068  integer(kind=kint) :: nspdsln
1069  integer(kind=kint), pointer :: spdslnidx(:)
1070  real(kind=kreal), pointer :: spdslnval(:,:)
1071 
1072  !----------------------------------------------------------------------
1073  !
1074  ! nufct1 performs cholesky factorization in row order for ndeg=1
1075  !
1076  ! (i) xlnzr,colno,zln,diag
1077  ! symbolicaly factorized
1078  !
1079  ! (o) zln,diag,dsln
1080  !
1081  ! #coded by t.arakawa
1082  !
1083  !----------------------------------------------------------------------
1084 
1085  !
1086  ! phase I
1087  ! LDU decompose of A (1..nstop-1)
1088  !
1089  diag(1,1)=1.0d0/diag(1,1)
1090  l=parent(1)
1091  nch(l)=nch(l)-1
1092  nch(1)=-1
1093  do 100 ic=2,nstop-1
1094  call sum(ic,xlnzr,colno,zln(1,:),diag(1,:),nch,parent,neqns)
1095 100 continue
1096  !
1097  ! phase II
1098  ! LDU decompose of C (nstop..neqnsA+neqnsd)
1099  !
1100  do 200 ic=nstop,neqns
1101  call sum1(ic,xlnzr,colno,zln(1,:),diag(1,:),parent,neqns)
1102 200 continue
1103  !
1104  ! phase III
1105  ! Update D region.
1106  !
1107 
1108  ! clear dummy diagonal value for D region
1109  do i=nstop,neqns
1110  diag(:,i)=0.0
1111  end do
1112 
1113  neqns_c = neqns - nstop + 1
1114  call sum2_child(neqns,nstop,xlnzr,colno,zln(1,:),diag(1,:),spdslnidx,spdslnval,nspdsln)
1115  ! send D region to parent
1116  imp = m_pds_procinfo%imp
1117  call mpi_send(nspdsln, 1,mpi_integer,imp,1,mpi_comm_world,ierr)
1118  call mpi_send(spdslnidx, nspdsln,mpi_integer,imp,1,mpi_comm_world,ierr)
1119  call mpi_send(spdslnval, nspdsln,mpi_real8,imp,1,mpi_comm_world,ierr)
1120  call mpi_send(diag(1,nstop), neqns_c,mpi_real8,imp,1,mpi_comm_world,ierr)
1121  return
1122  end subroutine nufct1_child
1123 
1124  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1125 
1126  subroutine nufct2_child(xlnzr, colno, zln, diag, neqns, parent, nch, nstop, ir)
1127 
1128  implicit none
1129 
1130  integer(kind=kint), intent(in) :: xlnzr(:), colno(:), parent(:)
1131  integer(kind=kint), intent(inout) :: nch(:)
1132  real(kind=kreal), intent(inout) :: zln(:,:), diag(:,:) !zln(6,*), diag(3,*)
1133  integer(kind=kint), intent(in) :: neqns, nstop
1134  integer(kind=kint), intent(inout) :: ir
1135 
1136  integer(kind=kint) :: i,l, ic, imp, ierr, neqns_c
1137  integer(kind=kint) :: nspdsln
1138  integer(kind=kint), pointer :: spdslnidx(:)
1139  real(kind=kreal), pointer :: spdslnval(:,:)
1140 
1141  !----------------------------------------------------------------------
1142  !
1143  ! nufct2 performs cholesky factorization in row order for ndeg=2
1144  !
1145  ! (i) xlnzr,colno,zln,diag
1146  ! symbolicaly factorized
1147  !
1148  ! (o) zln,diag,dsln
1149  !
1150  ! #coded by t.arakawa
1151  !
1152  !----------------------------------------------------------------------
1153 
1154 
1155  ! For parallel calculation, factorization for A and C region
1156  ! will be done.
1157  !
1158  ! Creation for D region also done.
1159  !
1160  ! Factorization for D region is omitted.
1161 
1162  !
1163  ! phase I
1164  ! LDU decompose of A (1..nstop-1)
1165  !
1166  call elapout('nufct2_child: begin phase I LDU decompose of A') !elap
1167  if(nstop.gt.1) call inv2(diag(:,1),ir)
1168  l=parent(1)
1169  nch(l)=nch(l)-1
1170  nch(1)=-1
1171  do ic=2,nstop-1
1172  call s2um(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1173  end do
1174  !
1175  ! phase II
1176  ! LDU decompose of C (nstop..neqnsA+neqnsd)
1177  !
1178  call elapout('nufct2_child: begin phase II LDU decompose of C') !elap
1179  do ic=nstop,neqns
1180  call s2um1(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1181  end do
1182 
1183  !
1184  ! phase III
1185  ! Update D region.
1186  !
1187 
1188  call elapout('nufct2_child: begin phase III update D region') !elap
1189 
1190  ! clear dummy diagonal value for D region ! currently dummy value setting was not done
1191  do i=nstop,neqns
1192  diag(:,i)=0.0
1193  end do
1194 
1195  neqns_c = neqns - nstop + 1
1196  call s2um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
1197 
1198  ! send D region to parent
1199  imp = m_pds_procinfo%imp
1200  call mpi_send(nspdsln, 1,mpi_integer,imp,1,mpi_comm_world,ierr)
1201  call mpi_send(spdslnidx, nspdsln,mpi_integer,imp,1,mpi_comm_world,ierr)
1202  call mpi_send(spdslnval, nspdsln*4,mpi_real8,imp,1,mpi_comm_world,ierr)
1203  call mpi_send(diag(1,nstop), neqns_c*3,mpi_real8,imp,1,mpi_comm_world,ierr)
1204 
1205 
1206  return
1207 
1208  end subroutine nufct2_child
1209 
1210  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1211 
1212  subroutine nufct3_child(xlnzr,colno,zln,diag,neqns,parent,nch,nstop,ir)
1213 
1214  implicit none
1215 
1216  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),parent(:)
1217  integer(kind=kint), intent(inout) :: nch(:)
1218  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) !zln(9,*),diag(6,*)
1219  integer(kind=kint), intent(in) :: neqns, nstop
1220  integer(kind=kint), intent(inout) :: ir
1221 
1222  integer(kind=kint) :: i,l, ic, imp, ierr, neqns_c
1223  integer(kind=kint) :: nspdsln
1224  integer(kind=kint), pointer :: spdslnidx(:)
1225  real(kind=kreal), pointer :: spdslnval(:,:)
1226  !
1227  !----------------------------------------------------------------------
1228  !
1229  ! nufct3 performs cholesky factorization in row order for ndeg=3
1230  !
1231  ! (i) xlnzr,colno,zln,diag
1232  ! symbolicaly factorized
1233  !
1234  ! (o) zln,diag,dsln
1235  !
1236  ! #coded by t.arakawa
1237  !
1238  !----------------------------------------------------------------------
1239 
1240  !
1241  ! For parallel calculation, factorization for A and C region
1242  ! will be done.
1243  !
1244  ! Creation for D region also done.
1245  !
1246  ! Factorization for D region is omitted.
1247  !
1248 
1249  !
1250  ! phase I
1251  ! LDU decompose of A (1..nstop-1)
1252  !
1253  call elapout('nufct3_child: begin phase I LDU decompose of A') !elap
1254  if(nstop.gt.1) call inv3(diag(:,1),ir)
1255  l=parent(1)
1256  nch(l)=nch(l)-1
1257  nch(1)=-1
1258  do 100 ic=2,nstop-1
1259  call s3um(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1260 100 continue
1261  !
1262  ! phase II
1263  ! LDU decompose of C (nstop..neqnsA+neqnsd)
1264  !
1265  call elapout('nufct3_child: begin phase II LDU decompose of C') !elap
1266  do 200 ic=nstop,neqns
1267  call s3um1(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1268 200 continue
1269 
1270  !
1271  ! phase III
1272  ! Update D region.
1273  !
1274 
1275  call elapout('nufct3_child: begin phase III update D region') !elap
1276 
1277  ! clear dummy diagonal value for D region ! currently dummy value setting was not done
1278  do i=nstop,neqns
1279  diag(:,i)=0.0
1280  end do
1281 
1282  neqns_c = neqns - nstop + 1
1283  call s3um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
1284 
1285  ! send D region to parent
1286  imp = m_pds_procinfo%imp
1287  call mpi_send(nspdsln, 1,mpi_integer,imp,1,mpi_comm_world,ierr)
1288  call mpi_send(spdslnidx, nspdsln,mpi_integer,imp,1,mpi_comm_world,ierr)
1289  call mpi_send(spdslnval, nspdsln*9,mpi_real8,imp,1,mpi_comm_world,ierr)
1290  call mpi_send(diag(1,nstop), neqns_c*6,mpi_real8,imp,1,mpi_comm_world,ierr)
1291 
1292  return
1293  end subroutine nufct3_child
1294 
1295  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1296 
1297  !subroutine nufct6_child(xlnzr, colno, zln, diag, neqns, parent, nch, nstop, ir)
1298  !TODO caution! currently this routine is not implemented because of s6um1() is not implemented.
1299  !
1300  !implicit none
1301  !
1302  !integer :: xlnzr(:), colno(:), parent(:), nch(:)
1303  !real(8) :: zln(:,:), diag(:,:) !zln(36,*), diag(21,*)
1304  !
1305  !integer :: neqns, nstop, ir, imp, ierr
1306  !
1307  !integer :: neqns_c
1308  !integer :: l, ic
1309  !integer :: i
1310  !
1311  !real(8), allocatable :: dsln(:,:)
1312  !include 'mpif.h'
1313  !
1314  !!----------------------------------------------------------------------
1315  !!
1316  !! nufct6 performs cholesky factorization in row order for ndeg=3
1317  !!
1318  !! (i) xlnzr,colno,zln,diag
1319  !! symbolicaly factorized
1320  !!
1321  !! (o) zln,diag,dsln
1322  !!
1323  !! #coded by t.arakawa
1324  !!
1325  !!----------------------------------------------------------------------
1326  !
1327  !
1328  !! For parallel calculation, factorization for A and C region
1329  !! will be done.
1330  !!
1331  !! Creation for D region also done.
1332  !!
1333  !! Factorization for D region is omitted.
1334  !!
1335  !
1336  !!
1337  !! phase I
1338  !! LDU decompose of A (1..nstop-1)
1339  !!
1340  !call elapout('nufct6_child: begin phase I LDU decompose of A') !elap
1341  !if(nstop.gt.1) call inv6(diag(:,1),ir)
1342  !l=parent(1)
1343  !nch(l)=nch(l)-1
1344  !nch(1)=-1
1345  !do ic=2,nstop-1
1346  ! call s6um(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1347  !end do
1348  !
1349  !!
1350  !! phase II
1351  !! LDU decompose of C (nstop..neqnsA+neqnsd)
1352  !!
1353  !call elapout('nufct6_child: begin phase II LDU decompose of C') !elap
1354  !do ic=nstop,neqns
1355  ! call s6um1(ic,xlnzr,colno,zln,diag,nch,parent,neqns)
1356  !end do
1357  !end subroutine nufct6_child
1358 
1359  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1360 
1361  subroutine nufctx_child(xlnzr,colno,zln,diag,neqns,parent,nch,nstop,ndeg,ir)
1362 
1363  implicit none
1364 
1365  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),parent(:)
1366  integer(kind=kint), intent(inout) :: nch(:)
1367  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) !zln(9,*),diag(6,*)
1368  integer(kind=kint), intent(in) :: neqns, nstop, ndeg
1369  integer(kind=kint), intent(inout) :: ir
1370 
1371  integer(kind=kint) :: l, ic, neqns_c, ndeg2, ndegl, imp, ierr
1372  integer(kind=kint) :: nspdsln
1373  integer(kind=kint), pointer :: spdslnidx(:)
1374  real(kind=kreal), pointer :: spdslnval(:,:)
1375  !----------------------------------------------------------------------
1376  !
1377  ! nufctx performs cholesky factorization in row order for every ndeg
1378  !
1379  ! (i) xlnzr,colno,zln,diag
1380  ! symbolicaly factorized
1381  !
1382  ! (o) zln,diag,dsln
1383  !
1384  ! #coded by t.arakawa
1385  !
1386  !----------------------------------------------------------------------
1387 
1388  !
1389  ! For parallel calculation, factorization for A and C region
1390  ! will be done.
1391  !
1392  ! Creation for D region also done.
1393  !
1394  ! Factorization for D region is omitted.
1395  !
1396 
1397  ndeg2=ndeg*ndeg
1398  ndegl=(ndeg+1)*ndeg/2
1399  !
1400  ! phase I
1401  ! LDU decompose of A (1..nstop-1)
1402  if(nstop.gt.1) call invx(diag,ndeg,ir)
1403  l=parent(1)
1404  nch(l)=nch(l)-1
1405  nch(1)=-1
1406  do ic=2,nstop-1
1407  call sxum(ic,xlnzr,colno,zln,diag,nch,parent,neqns,ndeg,ndegl)
1408  end do
1409 
1410  !
1411  ! phase II
1412  ! LDU decompose of C (nstop..neqnsA+neqnsd)
1413  !
1414  do ic=nstop,neqns
1415  call sxum1(ic,xlnzr,colno,zln,diag,nch,parent,neqns,ndeg,ndegl)
1416  end do
1417 
1418  !
1419  ! phase III
1420  ! Update D region.
1421  !
1422  neqns_c = neqns - nstop + 1
1423  call sxum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln,ndeg,ndegl)
1424 
1425  ! send D region to parent
1426  imp = m_pds_procinfo%imp
1427  call mpi_send(nspdsln, 1,mpi_integer,imp,1,mpi_comm_world,ierr)
1428  call mpi_send(spdslnidx, nspdsln,mpi_integer,imp,1,mpi_comm_world,ierr)
1429  call mpi_send(spdslnval, nspdsln*ndeg2,mpi_real8,imp,1,mpi_comm_world,ierr)
1430  call mpi_send(diag(1,nstop), neqns_c*ndegl,mpi_real8,imp,1,mpi_comm_world,ierr)
1431  return
1432  end subroutine nufctx_child
1433 
1434  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1435 
1436  subroutine nusol0_child(b,dsi,ir)
1437 
1438  !----------------------------------------------------------------------
1439  !
1440  ! this performs forward elimination and backward substitution
1441  !
1442  ! (i/o)
1443  ! b on entry right hand side vector
1444  ! on exit solution vector
1445  !
1446  ! #coded by t.arakawa
1447  !
1448  !----------------------------------------------------------------------
1449 
1450  implicit none
1451 
1452  real(kind=kreal), intent(inout) :: b(:,:)
1453  type(dsinfo), intent(inout) :: dsi
1454  integer(kind=kint), intent(out) :: ir
1455 
1456  if(dsi%stage.ne.30 .and. dsi%stage.ne.40) then
1457  ir=50
1458  goto 1000
1459  else
1460  ir=0
1461  end if
1462  if(dsi%ndeg.eq.1) then
1463  call nusol1_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%iperm,b,dsi%neqns,dsi%nstop)
1464  else if(dsi%ndeg .eq. 2) then
1465  call nusol2_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%iperm,b,dsi%neqns,dsi%nstop)
1466  else if(dsi%ndeg .eq. 3) then
1467  call nusol3_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%iperm,b,dsi%neqns,dsi%nstop)!org
1468  ! else if(dsi%ndeg .eq. 6) then !TODO implement it
1469  ! call nusol6_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%iperm,b,dsi%neqns,dsi%nstop)
1470  else
1471  call nusolx_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%iperm,b,dsi%neqns,dsi%nstop,dsi%ndeg)
1472  endif
1473  dsi%stage=40
1474 1000 continue
1475  return
1476  end subroutine nusol0_child
1477 
1478  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1479 
1480  subroutine nusol1_child(xlnzr,colno,zln,diag,iperm,b,neqns,nstop)
1481 
1482  implicit none
1483 
1484  integer(kind=kint), intent(in) :: xlnzr(:), colno(:), iperm(:)
1485  real(kind=kreal), intent(in) :: zln(:,:), diag(:,:)
1486  real(kind=kreal), intent(inout) :: b(:,:)
1487  integer(kind=kint), intent(in) :: neqns, nstop
1488 
1489  integer(kind=kint) :: neqns_a, neqns_c
1490  integer(kind=kint) :: k, ks, ke, i, j, imp, ierr
1491  real(kind=kreal), allocatable :: wk(:), wk_d(:)
1492 
1493  ! forward
1494 
1495  ! now nstop is beginning point of C
1496  neqns_a = nstop - 1
1497  neqns_c = neqns - nstop + 1
1498 
1499  allocate(wk(neqns), stat=ierr)
1500  if(ierr .ne. 0) then
1501  call errtrp('stop due to allocation error.')
1502  end if
1503  wk = 0
1504 
1505  do 10 i=1,neqns_a
1506  wk(i)=b(1,iperm(i))
1507 10 continue
1508 
1509  ! STEP22: forward substitution for A
1510  do 100 i=1,neqns_a
1511  ks=xlnzr(i)
1512  ke=xlnzr(i+1)-1
1513  if(ke.lt.ks) goto 110
1514  wk(i)=wk(i)-spdot2(wk,zln(1,:),colno,ks,ke)
1515 110 continue
1516 100 continue
1517 
1518  ! STEP23: forward substitution for C and send it (yi) to parent
1519  allocate(wk_d(nstop:neqns), stat=ierr)
1520  if(ierr .ne. 0) then
1521  call errtrp('stop due to allocation error.')
1522  end if
1523  wk_d=0
1524 
1525  do 101 i=nstop,neqns
1526  ks=xlnzr(i)
1527  ke=xlnzr(i+1)-1
1528  if(ke.lt.ks) goto 111
1529  wk_d(i)=wk_d(i)-spdot2(wk,zln(1,:),colno,ks,ke)
1530 111 continue
1531 101 continue
1532  imp = m_pds_procinfo%imp
1533  call mpi_send(wk_d, neqns_c, mpi_real8, imp, 1,mpi_comm_world, ierr)
1534 
1535  ! STEP24: divide with diagonal matrix
1536  do 120 i=1,neqns
1537  wk(i)=wk(i)*diag(1,i)
1538 120 continue
1539 
1540  ! STEP25: receive xd from parent and do backward substitution
1541  call mpi_bcast(wk_d, neqns_c, mpi_real8, imp, mpi_comm_world, ierr)
1542 
1543  wk(nstop:neqns)=wk_d(nstop:neqns)
1544 
1545  do 200 i=neqns,1,-1
1546  ks=xlnzr(i)
1547  ke=xlnzr(i+1)-1
1548  if(ke.lt.ks) goto 200
1549 
1550  do 210 k=ks,ke
1551  j=colno(k)
1552  wk(j)=wk(j)-wk(i)*zln(1,k)
1553 210 continue
1554 200 continue
1555 
1556  ! permutation
1557  do 300 i=1,neqns
1558  b(1,iperm(i))=wk(i)
1559 300 continue
1560  return
1561 
1562  end subroutine nusol1_child
1563 
1564  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1565 
1566  subroutine nusol2_child(xlnzr, colno, zln, diag, iperm, b, neqns, nstop)
1567  ! perform forward substitution for sparse matrix,
1568  ! send bd to parent and receive xd from parent,
1569  ! backward substitution using xd ad send final result x to parent.
1570 
1571  use m_elap
1572 
1573  implicit none
1574 
1575  integer(kind=kint), intent(in) :: xlnzr(:), colno(:), iperm(:)
1576  real(kind=kreal), intent(in) :: zln(:,:), diag(:,:) !zln(4,*), diag(3,*), b(2,*)
1577  real(kind=kreal), intent(inout) :: b(:,:) ! b(2,*)
1578 
1579  real(kind=kreal), allocatable :: wk(:,:), wk_d(:,:)
1580  integer(kind=kint) :: neqns_c, neqns_a, nstop, neqns, ks, ke
1581  integer(kind=kint) :: i, j, k, imp, ierr
1582 
1583  !now nstop is beginning point of C
1584  neqns_a = nstop - 1
1585  neqns_c = neqns - nstop + 1
1586 
1587  allocate(wk(2,neqns), stat=ierr)
1588  if(ierr .ne. 0) then
1589  call errtrp('stop due to allocation error.')
1590  end if
1591  wk = 0
1592  do i=1,neqns_a
1593  wk(1,i) = b(1,iperm(i))
1594  wk(2,i) = b(2,iperm(i))
1595  end do
1596 
1597  ! STEP22: forward substitution for A
1598  call elapout('nusol2_child: begin forward substitution for A') !elap
1599  do i=1, neqns_a
1600  ks=xlnzr(i)
1601  ke=xlnzr(i+1)-1
1602  if(ke.ge.ks) then
1603  call s2pdot(wk(:,i),wk,zln,colno,ks,ke)
1604  end if
1605  end do
1606 
1607  ! STEP23: forward substitution for C and send it (yi) to parent
1608  call elapout('nusol2_child: begin forward substitution for C') !elap
1609  allocate(wk_d(2,nstop:neqns), stat=ierr)
1610  if(ierr .ne. 0) then
1611  call errtrp('stop due to allocation error.')
1612  end if
1613  wk_d=0
1614 
1615  do i=nstop,neqns
1616  ks=xlnzr(i)
1617  ke=xlnzr(i+1)-1
1618  if(ke.ge.ks) then
1619  call s2pdot(wk_d(:,i),wk,zln,colno,ks,ke)
1620  end if
1621  end do
1622 
1623  call elapout('nusol2_child: wait to send wk_d') !elap
1624  imp = m_pds_procinfo%imp
1625  call mpi_send(wk_d, 2*neqns_c, mpi_real8, imp, 1,mpi_comm_world, ierr)
1626 
1627  ! STEP24: divide with diagonal matrix
1628  do i=1,neqns_a
1629  wk(2,i)=wk(2,i)-wk(1,i)*diag(2,i)
1630  wk(1,i)=wk(1,i)*diag(1,i)
1631  wk(2,i)=wk(2,i)*diag(3,i)
1632  wk(1,i)=wk(1,i)-wk(2,i)*diag(2,i)
1633  end do
1634 
1635  ! STEP25: receive xd from parent and do backward substitution
1636  call elapout('nusol2_child: wait until receive wk_d') !elap
1637  call mpi_bcast(wk_d, 2*neqns_c, mpi_real8, imp, mpi_comm_world, ierr)
1638  call elapout('nusol2_child: end receive wk_d') !elap
1639  call elapout('nusol2_child: begin backward substitution') !elap
1640 
1641  wk(:,nstop:neqns)=wk_d(:,nstop:neqns)
1642  do i=neqns,1,-1
1643  ks=xlnzr(i)
1644  ke=xlnzr(i+1)-1
1645  if(ke.ge.ks) then
1646  do k=ks,ke
1647  j=colno(k)
1648  wk(1,j)=wk(1,j)-wk(1,i)*zln(1,k)-wk(2,i)*zln(2,k)
1649  wk(2,j)=wk(2,j)-wk(1,i)*zln(3,k)-wk(2,i)*zln(4,k)
1650  end do
1651  end if
1652  end do
1653  call elapout('nusol2_child: end backward substitution') !elap
1654 
1655  ! permutation
1656  do i=1,neqns_a
1657  b(1,iperm(i))=wk(1,i)
1658  b(2,iperm(i))=wk(2,i)
1659  end do
1660 
1661  call elapout('nusol2_child: end') !elap
1662  return
1663 
1664  end subroutine nusol2_child
1665 
1666  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1667 
1668  subroutine nusol3_child(xlnzr,colno,zln,diag,iperm,b,neqns, nstop)
1669 
1670  ! perform forward substitution for sparse matrix,
1671  ! send bd to parent and receive xd from parent,
1672  ! backward substitution using xd ad send final result x to parent.
1673 
1674  use m_elap
1675 
1676  implicit none
1677 
1678  integer(kind=kint), intent(in) :: xlnzr(:), colno(:), iperm(:)
1679  real(kind=kreal), intent(in) :: zln(:,:), diag(:,:) !zln(9,*),diag(6,*)
1680  real(kind=kreal), intent(inout) :: b(:,:) ! b(3,*)
1681 
1682  real(kind=kreal), allocatable :: wk(:,:), wk_d(:,:)
1683  integer(kind=kint) :: neqns_c, neqns_a, nstop, neqns, ks, ke
1684  integer(kind=kint) :: i, j, k, imp, ierr
1685 
1686  ! now nstop is beginning point of C
1687 
1688  neqns_a = nstop - 1
1689  neqns_c = neqns - nstop + 1
1690 
1691  call elapout('nusol3_child: entered') !elap
1692 
1693  allocate(wk(3,neqns), stat=ierr)
1694  if(ierr .ne. 0) then
1695  call errtrp('stop due to allocation error.')
1696  end if
1697  wk = 0
1698  do 10 i=1,neqns_a
1699  wk(1,i)=b(1,iperm(i))
1700  wk(2,i)=b(2,iperm(i))
1701  wk(3,i)=b(3,iperm(i))
1702 10 continue
1703 
1704 
1705  ! STEP22: forward substitution for A
1706  call elapout('nusol3_child: begin forward substitution for A') !elap
1707 
1708  do 100 i=1, neqns_a
1709  ks=xlnzr(i)
1710  ke=xlnzr(i+1)-1
1711  if(ke.lt.ks) goto 110
1712  call s3pdot(wk(:,i),wk,zln,colno,ks,ke)
1713 110 continue
1714 100 continue
1715 
1716 
1717  ! STEP23: forward substitution for C and send it (yi) to parent
1718  call elapout('nusol3_child: begin forward substitution for C') !elap
1719  allocate(wk_d(3,nstop:neqns), stat=ierr)
1720  if(ierr .ne. 0) then
1721  call errtrp('stop due to allocation error.')
1722  end if
1723  wk_d=0
1724 
1725  do 101 i=nstop,neqns
1726  ks=xlnzr(i)
1727  ke=xlnzr(i+1)-1
1728  if(ke.lt.ks) goto 111
1729  call s3pdot(wk_d(:,i),wk,zln,colno,ks,ke)
1730 111 continue
1731 101 continue
1732 
1733  call elapout('nusol3_child: wait to send wk_d') !elap
1734  imp = m_pds_procinfo%imp
1735  call mpi_send(wk_d, 3*neqns_c, mpi_real8, imp, 1,mpi_comm_world, ierr)
1736 
1737  ! STEP24: divide with diagonal matrix
1738  call elapout('nusol3_child: divide with diagonal matrix') !elap
1739  do 120 i=1,neqns_a
1740  wk(2,i)=wk(2,i)-wk(1,i)*diag(2,i)
1741  wk(3,i)=wk(3,i)-wk(1,i)*diag(4,i)-wk(2,i)*diag(5,i)
1742  wk(1,i)=wk(1,i)*diag(1,i)
1743  wk(2,i)=wk(2,i)*diag(3,i)
1744  wk(3,i)=wk(3,i)*diag(6,i)
1745  wk(2,i)=wk(2,i)-wk(3,i)*diag(5,i)
1746  wk(1,i)=wk(1,i)-wk(2,i)*diag(2,i)-wk(3,i)*diag(4,i)
1747 120 continue
1748 
1749  ! STEP25: receive xd from parent and do backward substitution
1750  call elapout('nusol3_child: wait until receive wk_d') !elap
1751  call mpi_bcast(wk_d, 3*neqns_c, mpi_real8, imp, mpi_comm_world, ierr)
1752  call elapout('nusol3_child: end receive wk_d') !elap
1753  call elapout('nusol3_child: begin backward substitution') !elap
1754 
1755  wk(:,nstop:neqns)=wk_d(:,nstop:neqns)
1756 
1757  do 200 i=neqns,1,-1
1758  ks=xlnzr(i)
1759  ke=xlnzr(i+1)-1
1760  if(ke.lt.ks) goto 200
1761 
1762  do 210 k=ks,ke
1763  j=colno(k)
1764 
1765  wk(1,j)=wk(1,j)-wk(1,i)*zln(1,k)-wk(2,i)*zln(2,k)-wk(3,i)*zln(3,k)
1766  wk(2,j)=wk(2,j)-wk(1,i)*zln(4,k)-wk(2,i)*zln(5,k)-wk(3,i)*zln(6,k)
1767  wk(3,j)=wk(3,j)-wk(1,i)*zln(7,k)-wk(2,i)*zln(8,k)-wk(3,i)*zln(9,k)
1768 210 continue
1769 200 continue
1770  call elapout('nusol3_child: end backward substitution') !elap
1771 
1772 
1773  ! permutation
1774  do 300 i=1,neqns_a
1775  b(1,iperm(i))=wk(1,i)
1776  b(2,iperm(i))=wk(2,i)
1777  b(3,iperm(i))=wk(3,i)
1778 300 continue
1779 
1780  call elapout('nusol3_child: end') !elap
1781  return
1782  end subroutine nusol3_child
1783 
1784  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1785  subroutine nusolx_child(xlnzr, colno, zln, diag, iperm, b, neqns, nstop, ndeg)
1786 
1787  implicit none
1788 
1789  integer(kind=kint), intent(in) :: xlnzr(:), colno(:), iperm(:)
1790  real(kind=kreal), intent(in) :: zln(:,:), diag(:,:)
1791  real(kind=kreal), intent(inout) :: b(:,:)
1792  integer(kind=kint), intent(in) :: neqns, nstop, ndeg
1793 
1794  real(kind=kreal), allocatable :: wk(:,:), wk_d(:,:)
1795  integer(kind=kint) :: neqns_c, neqns_a, ks, ke, locd, loc1
1796  integer(kind=kint) :: i, j, k, l, m, n, imp, ierr
1797 
1798  !now nstop is beginning point of C
1799  neqns_a = nstop - 1
1800  neqns_c = neqns - nstop + 1
1801 
1802  allocate(wk(ndeg,neqns), stat=ierr)
1803  if(ierr .ne. 0) then
1804  call errtrp('stop due to allocation error.')
1805  end if
1806  wk = 0
1807  do i=1,neqns_a
1808  wk(1,i)=b(1,iperm(i))
1809  wk(2,i)=b(2,iperm(i))
1810  wk(3,i)=b(3,iperm(i))
1811  end do
1812 
1813  ! STEP22: forward substitution for A
1814  do i=1,neqns_a
1815  ks=xlnzr(i)
1816  ke=xlnzr(i+1)-1
1817  if(ke.ge.ks) then
1818  call sxpdot(ndeg,wk(1,i),wk,zln,colno,ks,ke)
1819  end if
1820  end do
1821 
1822  ! STEP23: forward substitution for C and send it (yi) to parent
1823  allocate(wk_d(ndeg,nstop:neqns), stat=ierr)
1824  if(ierr .ne. 0) then
1825  call errtrp('stop due to allocation error.')
1826  end if
1827  wk_d=0
1828  do i=nstop,neqns
1829  ks=xlnzr(i)
1830  ke=xlnzr(i+1)-1
1831  if(ke.ge.ks) then
1832  call sxpdot(ndeg,wk_d(:,i),wk,zln,colno,ks,ke)
1833  end if
1834  end do
1835 
1836  imp = m_pds_procinfo%imp
1837  call mpi_send(wk_d, ndeg*neqns_c, mpi_real8, imp, 1,mpi_comm_world, ierr)
1838 
1839 
1840  ! STEP24: divide with diagonal matrix
1841  do i=1,neqns_a
1842  locd=0
1843  do m=1,ndeg-1
1844  locd=locd+m
1845  loc1=locd+m
1846  do n=m+1,ndeg
1847  wk(n,i)=wk(n,i)-wk(m,i)*diag(loc1,i)
1848  loc1=loc1+n
1849  end do
1850  end do
1851 
1852  locd=0
1853  do m=1,ndeg
1854  locd=locd+m
1855  wk(m,i)=wk(m,i)*diag(locd,i)
1856  end do
1857 
1858  do n=ndeg,2,-1
1859  locd=locd-1
1860  do m=n-1,1,-1
1861  wk(m,i)=wk(m,i)-wk(n,i)*diag(locd,i)
1862  locd=locd-1
1863  end do
1864  end do
1865  end do
1866 
1867  call mpi_bcast(wk_d, ndeg*neqns_c, mpi_real8, imp, mpi_comm_world, ierr)
1868  wk(:,nstop:neqns)=wk_d(:,nstop:neqns)
1869 
1870  ! back ward
1871  do i=neqns,1,-1
1872  ks=xlnzr(i)
1873  ke=xlnzr(i+1)-1
1874  if(ke.ge.ks) then
1875  do k=ks,ke
1876  j=colno(k)
1877  do m=1,ndeg
1878  do n=1,ndeg
1879  wk(m,j)=wk(m,j)-wk(n,i)*zln(n+(m-1)*ndeg,k)
1880  end do
1881  end do
1882  end do
1883  end if
1884  end do
1885 
1886  ! permutation
1887  do l=1,ndeg
1888  do i=1,neqns_a
1889  b(l,iperm(i))=wk(l,i)
1890  end do
1891  end do
1892 
1893  return
1894  end subroutine nusolx_child
1895  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1896 
1897  subroutine nufct0_parent(dsln, diag, neqns, ndeg)
1898  ! select LDU decomposer for dens matrix according to ndeg
1899 
1900  implicit none
1901 
1902  real(kind=kreal), intent(inout) :: dsln(:,:)
1903  real(kind=kreal), intent(inout) :: diag(:,:)
1904  integer(kind=kint), intent(in) :: neqns, ndeg
1905 
1906  integer(kind=kint) :: ndegl
1907 
1908  if (ndeg .eq. 1) then
1909  call sum3(neqns, dsln(1,:), diag(1,:))
1910  else if (ndeg .eq. 3) then
1911  call s3um3(neqns, dsln, diag)
1912  else
1913  ndegl = (ndeg+1)*ndeg/2
1914  call sxum3(neqns, dsln, diag, ndeg, ndegl)
1915  end if
1916 
1917  return
1918  end subroutine nufct0_parent
1919 
1920  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1921 
1922  subroutine nusol0_parent(dsln, diag, b, neqns, ndeg)
1923  ! select solvers according to ndeg
1924 
1925  implicit none
1926 
1927  real(kind=kreal), intent(in) :: dsln(:,:)
1928  real(kind=kreal), intent(in) :: diag(:,:)
1929  real(kind=kreal), intent(inout) :: b(:,:)
1930 
1931  integer(kind=kint), intent(in) :: neqns, ndeg
1932 
1933  if (ndeg .eq. 1) then
1934  call nusol1_parent(dsln(1,:), diag(1,:), b(1,:), neqns)
1935  else if (ndeg .eq. 3) then
1936  call nusol3_parent(dsln, diag, b, neqns)
1937  else
1938  call nusolx_parent(dsln, diag, b, neqns, ndeg)
1939  end if
1940 
1941  return
1942  end subroutine nusol0_parent
1943 
1944  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1945 
1946  subroutine nusol1_parent(dsln, diag, b, neqns)
1947  ! solve Ax=b for dens matrix with ndeg=1
1948  ! require dsln, diag is already LDU decomposed.
1949  ! currently not tested 20071121
1950 
1951  implicit none
1952 
1953  real(kind=kreal), intent(in) :: dsln(:) !((neqns+1)*neqns/2)
1954  real(kind=kreal), intent(in) :: diag(:) !(neqns)
1955  real(kind=kreal), intent(inout) :: b(:) !(3,neqns)
1956  integer(kind=kint), intent(in) :: neqns
1957 
1958  integer(kind=kint) :: i,j,k,loc
1959 
1960  ! forward substitution
1961  do i=2,neqns
1962  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
1963  b(i)=b(i)-dot_product(b(1:i-1),dsln(k:k+i-2))
1964  end do
1965 
1966  ! divide by D (because of diag is already inverted (1/Dii))
1967  b(:)=b(:)*diag(:)
1968 
1969  ! Backward substitution.
1970  ! Substitute Zi into D and get Xd results.
1971  loc=(neqns-1)*neqns/2
1972  do i=neqns,1,-1
1973  do j=i-1,1,-1
1974  b(j)=b(j)-b(i)*dsln(loc)
1975  loc=loc-1
1976  end do
1977  end do
1978 
1979  return
1980  end subroutine nusol1_parent
1981 
1982  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1983 
1984 
1985  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1986 
1987  subroutine nusol3_parent(dsln, diag, b, neqns)
1988  ! solve Ax=b for dens matrix with ndeg=3
1989  ! require dsln, diag is already LDU decomposed.
1990 
1991  implicit none
1992 
1993  real(kind=kreal), intent(in) :: dsln(:,:) !(9,(neqns+1)*neqns/2)
1994  real(kind=kreal), intent(in) :: diag(:,:) !(6,neqns)
1995  real(kind=kreal), intent(inout) :: b(:,:) !(3,neqns)
1996  integer(kind=kint), intent(in) :: neqns
1997 
1998  integer(kind=kint) :: i,j,k,loc
1999 
2000  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2001  !
2002  ! STEP22 forward substitution
2003  !
2004  do i=2,neqns
2005  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
2006  call d3sdot(b(:,i),b,dsln(:, k:k+i-2),i-1)
2007  end do
2008 
2009  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2010  !
2011  ! STEP23 divide Yd by diagonal element of D and get Zi=Yi/Di
2012  !
2013  do i=1,neqns
2014  b(2,i)=b(2,i)-b(1,i)*diag(2,i)
2015  b(3,i)=b(3,i)-b(1,i)*diag(4,i)-b(2,i)*diag(5,i)
2016  b(1,i)=b(1,i)*diag(1,i)
2017  b(2,i)=b(2,i)*diag(3,i)
2018  b(3,i)=b(3,i)*diag(6,i)
2019  b(2,i)=b(2,i)-b(3,i)*diag(5,i)
2020  b(1,i)=b(1,i)-b(2,i)*diag(2,i)-b(3,i)*diag(4,i)
2021  end do
2022 
2023  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2024  !
2025  ! STEP24 Backward substitution.
2026  ! Substitute Zi into D and get Xd results.
2027  !
2028  loc=(neqns-1)*neqns/2
2029  do i=neqns,1,-1
2030  do j=i-1,1,-1
2031  b(1,j)=b(1,j)-b(1,i)*dsln(1,loc)-b(2,i)*dsln(2,loc)-b(3,i)*dsln(3,loc)
2032  b(2,j)=b(2,j)-b(1,i)*dsln(4,loc)-b(2,i)*dsln(5,loc)-b(3,i)*dsln(6,loc)
2033  b(3,j)=b(3,j)-b(1,i)*dsln(7,loc)-b(2,i)*dsln(8,loc)-b(3,i)*dsln(9,loc)
2034  loc=loc-1
2035  end do
2036  end do
2037 
2038  return
2039  end subroutine nusol3_parent
2040 
2041  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2042 
2043  subroutine nusolx_parent (dsln,diag,b,neqns,ndeg)
2044 
2045  implicit none
2046 
2047  real(kind=kreal), intent(in) :: diag(:,:), dsln(:,:)
2048  real(kind=kreal), intent(inout) :: b(:,:)
2049  integer(kind=kint), intent(in) :: neqns, ndeg
2050 
2051  integer(kind=kint) :: i,j,k,m,n,loc, locd, loc1
2052 
2053  ! forward
2054  do i=2,neqns
2055  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
2056  call dxsdot(ndeg,b(:,i),b,dsln(:,k:k+i-2),i-1)
2057  end do
2058 
2059  ! divide
2060  do i=1,neqns
2061  locd=0
2062  do m=1,ndeg-1
2063  locd=locd+m
2064  loc1=locd+m
2065  do n=m+1,ndeg
2066  b(n,i)=b(n,i)-b(m,i)*diag(loc1,i)
2067  loc1=loc1+n
2068  end do
2069  end do
2070 
2071  locd=0
2072  do m=1,ndeg
2073  locd=locd+m
2074  b(m,i)=b(m,i)*diag(locd,i)
2075  end do
2076 
2077  do n=ndeg,2,-1
2078  locd=locd-1
2079  do m=n-1,1,-1
2080  b(m,i)=b(m,i)-b(n,i)*diag(locd,i)
2081  locd=locd-1
2082  end do
2083  end do
2084  end do
2085  ! back ward
2086  loc=(neqns-1)*neqns/2
2087  do i=neqns,1,-1
2088  do j=i-1,1,-1
2089  do m=1,ndeg
2090  do n=1,ndeg
2091  b(m,j)=b(m,j)-b(n,i)*dsln((m-1)*ndeg+n,loc)
2092  end do
2093  end do
2094  loc=loc-1
2095  end do
2096  end do
2097  return
2098  end subroutine nusolx_parent
2099 
2100  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2101 
2102  subroutine s3um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
2103 
2104  implicit none
2105 
2106  integer(kind=kint), intent(in) :: neqns, nstop
2107  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
2108  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) !zln(9,*),diag(6,*),dsln(9,*) !
2109  integer(kind=kint), pointer :: spdslnidx(:)
2110  real(kind=kreal), pointer :: spdslnval(:,:)
2111  integer(kind=kint), intent(out) :: nspdsln
2112 
2113  real(kind=kreal), allocatable :: temp(:,:)
2114  integer(kind=kint), allocatable :: indx(:)
2115  logical :: ftflag
2116  integer(kind=kint) :: j,k, ic,ks,ke,jj,jc,j1,j2,loc,ispdsln, ierr
2117 
2118  allocate(temp(neqns,9),indx(neqns), stat=ierr)
2119  if(ierr .ne. 0) then
2120  call errtrp('stop due to allocation error.')
2121  end if
2122 
2123  nspdsln=0
2124  do ic=nstop,neqns
2125  ks=xlnzr(ic)
2126  ke=xlnzr(ic+1)-1
2127  do k=ks,ke
2128  jj=colno(k)
2129  indx(jj)=ic
2130  end do
2131  do jc=nstop,ic-1
2132  j1=xlnzr(jc)
2133  j2=xlnzr(jc+1)
2134  do jj=xlnzr(jc),xlnzr(jc+1)-1
2135  j=colno(jj)
2136  if(indx(j).eq.ic) then
2137  nspdsln=nspdsln+1
2138  exit
2139  endif
2140  end do
2141  end do
2142  end do
2143  allocate(spdslnidx(nspdsln), stat=ierr)
2144  if(ierr .ne. 0) then
2145  call errtrp('stop due to allocation error.')
2146  end if
2147  allocate(spdslnval(9,nspdsln), stat=ierr)
2148  if(ierr .ne. 0) then
2149  call errtrp('stop due to allocation error.')
2150  end if
2151 
2152  loc=0
2153  ispdsln=0
2154  spdslnval=0
2155  ftflag = .true.
2156  do 100 ic=nstop,neqns
2157  ks=xlnzr(ic)
2158  ke=xlnzr(ic+1)-1
2159  do 110 k=ks,ke
2160  jj=colno(k)
2161  temp(jj,1)=zln(1,k)
2162  temp(jj,2)=zln(2,k)
2163  temp(jj,3)=zln(3,k)
2164  temp(jj,4)=zln(4,k)
2165  temp(jj,5)=zln(5,k)
2166  temp(jj,6)=zln(6,k)
2167  temp(jj,7)=zln(7,k)
2168  temp(jj,8)=zln(8,k)
2169  temp(jj,9)=zln(9,k)
2170  indx(jj)=ic
2171 110 continue
2172  do 111 k=ks,ke
2173  jj=colno(k)
2174  zln(4,k)=temp(jj,4)-temp(jj,1)*diag(2,jj)
2175  zln(7,k)=temp(jj,7)-temp(jj,1)*diag(4,jj)-zln(4,k)*diag(5,jj)
2176  zln(1,k)=temp(jj,1)*diag(1,jj)
2177  zln(4,k)=zln(4,k)*diag(3,jj)
2178  zln(7,k)=zln(7,k)*diag(6,jj)
2179  zln(4,k)=zln(4,k)-zln(7,k)*diag(5,jj)
2180  zln(1,k)=zln(1,k)-zln(4,k)*diag(2,jj)-zln(7,k)*diag(4,jj)
2181  !
2182  zln(5,k)=temp(jj,5)-temp(jj,2)*diag(2,jj)
2183  zln(8,k)=temp(jj,8)-temp(jj,2)*diag(4,jj)-zln(5,k)*diag(5,jj)
2184  zln(2,k)=temp(jj,2)*diag(1,jj)
2185  zln(5,k)=zln(5,k)*diag(3,jj)
2186  zln(8,k)=zln(8,k)*diag(6,jj)
2187  zln(5,k)=zln(5,k)-zln(8,k)*diag(5,jj)
2188  zln(2,k)=zln(2,k)-zln(5,k)*diag(2,jj)-zln(8,k)*diag(4,jj)
2189  !
2190  zln(6,k)=temp(jj,6)-temp(jj,3)*diag(2,jj)
2191  zln(9,k)=temp(jj,9)-temp(jj,3)*diag(4,jj)-zln(6,k)*diag(5,jj)
2192  zln(3,k)=temp(jj,3)*diag(1,jj)
2193  zln(6,k)=zln(6,k)*diag(3,jj)
2194  zln(9,k)=zln(9,k)*diag(6,jj)
2195  zln(6,k)=zln(6,k)-zln(9,k)*diag(5,jj)
2196  zln(3,k)=zln(3,k)-zln(6,k)*diag(2,jj)-zln(9,k)*diag(4,jj)
2197  ! write(60,6000) k,(zln(llll,k),llll=1,9)
2198  !6000 format(i6,3d20.10/6x,3d20.10/6x,3d20.10)
2199 111 continue
2200  !
2201  do 112 k=ks,ke
2202  jj=colno(k)
2203  diag(1,ic)=diag(1,ic)-temp(jj,1)*zln(1,k)-temp(jj,4)*zln(4,k)-temp(jj,7)*zln(7,k)
2204  diag(2,ic)=diag(2,ic)-temp(jj,1)*zln(2,k)-temp(jj,4)*zln(5,k)-temp(jj,7)*zln(8,k)
2205  diag(3,ic)=diag(3,ic)-temp(jj,2)*zln(2,k)-temp(jj,5)*zln(5,k)-temp(jj,8)*zln(8,k)
2206  diag(4,ic)=diag(4,ic)-temp(jj,1)*zln(3,k)-temp(jj,4)*zln(6,k)-temp(jj,7)*zln(9,k)
2207  diag(5,ic)=diag(5,ic)-temp(jj,2)*zln(3,k)-temp(jj,5)*zln(6,k)-temp(jj,8)*zln(9,k)
2208  diag(6,ic)=diag(6,ic)-temp(jj,3)*zln(3,k)-temp(jj,6)*zln(6,k)-temp(jj,9)*zln(9,k)
2209 112 continue
2210  do 120 jc=nstop,ic-1
2211  loc=loc+1
2212  j1=xlnzr(jc)
2213  j2=xlnzr(jc+1)
2214  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
2215  j=colno(jj)
2216  if(indx(j).eq.ic) then
2217  if (ftflag) then
2218  ispdsln=ispdsln+1
2219  ftflag=.false.
2220  end if
2221  spdslnidx(ispdsln)=loc
2222  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-temp(j,1)*zln(1,jj)-temp(j,4)*zln(4,jj)-temp(j,7)*zln(7,jj)
2223  spdslnval(2,ispdsln)=spdslnval(2,ispdsln)-temp(j,2)*zln(1,jj)-temp(j,5)*zln(4,jj)-temp(j,8)*zln(7,jj)
2224  spdslnval(3,ispdsln)=spdslnval(3,ispdsln)-temp(j,3)*zln(1,jj)-temp(j,6)*zln(4,jj)-temp(j,9)*zln(7,jj)
2225  spdslnval(4,ispdsln)=spdslnval(4,ispdsln)-temp(j,1)*zln(2,jj)-temp(j,4)*zln(5,jj)-temp(j,7)*zln(8,jj)
2226  spdslnval(5,ispdsln)=spdslnval(5,ispdsln)-temp(j,2)*zln(2,jj)-temp(j,5)*zln(5,jj)-temp(j,8)*zln(8,jj)
2227  spdslnval(6,ispdsln)=spdslnval(6,ispdsln)-temp(j,3)*zln(2,jj)-temp(j,6)*zln(5,jj)-temp(j,9)*zln(8,jj)
2228  spdslnval(7,ispdsln)=spdslnval(7,ispdsln)-temp(j,1)*zln(3,jj)-temp(j,4)*zln(6,jj)-temp(j,7)*zln(9,jj)
2229  spdslnval(8,ispdsln)=spdslnval(8,ispdsln)-temp(j,2)*zln(3,jj)-temp(j,5)*zln(6,jj)-temp(j,8)*zln(9,jj)
2230  spdslnval(9,ispdsln)=spdslnval(9,ispdsln)-temp(j,3)*zln(3,jj)-temp(j,6)*zln(6,jj)-temp(j,9)*zln(9,jj)
2231  endif
2232 220 continue
2233  ftflag = .true.
2234 120 continue
2235 100 continue
2236  return
2237  end subroutine s3um2_child
2238 
2239  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2240 
2241  subroutine zpivot(neqns,neqnsz,nttbr,jcol,irow,zpiv,ir)
2242 
2243  implicit none
2244 
2245  integer(kind=kint), intent(in) :: jcol(:),irow(:)
2246  integer(kind=kint), intent(out) :: zpiv(:)
2247  integer(kind=kint), intent(in) :: neqns,nttbr
2248  integer(kind=kint), intent(out) :: neqnsz,ir
2249 
2250  integer(kind=kint) :: i,j,l
2251 
2252  ir=0
2253  do 100 l=1,neqns
2254  zpiv(l)=1
2255 100 continue
2256 
2257  do 200 l=1,nttbr
2258  i=irow(l)
2259  j=jcol(l)
2260  if(i.le.0.or.j.le.0) then
2261  ir=-1
2262  goto 1000
2263  elseif(i.gt.neqns.or.j.gt.neqns) then
2264  ir=1
2265  goto 1000
2266  endif
2267  if(i.eq.j) zpiv(i)=0
2268 200 continue
2269 
2270  do 310 i=neqns,1,-1
2271  if(zpiv(i).eq.0) then
2272  neqnsz=i
2273  goto 320
2274  endif
2275 310 continue
2276 320 continue
2277 1000 continue
2278  if(ldbg) write(idbg,*) '# zpivot ########################'
2279  if(ldbg) write(idbg,60) (zpiv(i),i=1,neqns)
2280 60 format(20i3)
2281  return
2282  end subroutine zpivot
2283 
2284  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2285 
2286  subroutine stsmat(neqns,nttbr,irow,jcol,jcpt,jcolno)
2287 
2288  implicit none
2289 
2290  integer(kind=kint), intent(in) :: irow(:), jcol(:)
2291  integer(kind=kint), intent(out) :: jcpt(:), jcolno(:)
2292  integer(kind=kint), intent(in) :: neqns, nttbr
2293 
2294  integer(kind=kint) :: i,j,k,l,loc,locr
2295 
2296  do 10 i=1,2*nttbr
2297  jcpt(i)=0
2298  jcolno(i)=0
2299 10 continue
2300  do 20 i=1,neqns
2301  jcpt(i)=i+neqns
2302  jcolno(i+neqns)=i
2303 20 continue
2304 
2305  k=2*neqns
2306  do 100 l=1,nttbr
2307  i=irow(l)
2308  j=jcol(l)
2309  if(i.eq.j) goto 100
2310  loc=jcpt(i)
2311  locr=i
2312 110 continue
2313  if(loc.eq.0) goto 120
2314  if(jcolno(loc).eq.j) then
2315  goto 100
2316  elseif(jcolno(loc).gt.j) then
2317  goto 130
2318  endif
2319  locr=loc
2320  loc=jcpt(loc)
2321  goto 110
2322 120 continue
2323  k=k+1
2324  jcpt(locr)=k
2325  jcolno(k)=j
2326  goto 150
2327 130 continue
2328  k=k+1
2329  jcpt(locr)=k
2330  jcpt(k)=loc
2331  jcolno(k)=j
2332 150 continue
2333  loc=jcpt(j)
2334  locr=j
2335 160 continue
2336  if(loc.eq.0) goto 170
2337  if(jcolno(loc).eq.i) then
2338  goto 100
2339  elseif(jcolno(loc).gt.i) then
2340  goto 180
2341  endif
2342  locr=loc
2343  loc=jcpt(loc)
2344  goto 160
2345 170 continue
2346  k=k+1
2347  jcpt(locr)=k
2348  jcolno(k)=i
2349  goto 100
2350 180 continue
2351  k=k+1
2352  jcpt(locr)=k
2353  jcpt(k)=loc
2354  jcolno(k)=i
2355 100 continue
2356  if(ldbg) then
2357  write(idbg,*) 'jcolno'
2358  write(idbg,60) (jcolno(i),i=1,k)
2359  write(idbg,*) 'jcpt'
2360  write(idbg,60) (jcpt(i),i=1,k)
2361 60 format(10i7)
2362  endif
2363  return
2364  end subroutine stsmat
2365 
2366  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2367  subroutine stiaja(neqns,neqnsz,ia,ja,jcpt,jcolno)
2368 
2369  implicit none
2370  !
2371  ! coded by t.arakawa
2372  !
2373  integer(kind=kint), intent(in) :: jcpt(:),jcolno(:)
2374  integer(kind=kint), intent(out) :: ia(:),ja(:)
2375  integer(kind=kint), intent(in) :: neqns, neqnsz
2376 
2377  integer(kind=kint) :: i,k,l,ii,loc
2378  !
2379 
2380  ia(1)=1
2381  l=0
2382  do 100 k=1,neqns
2383  loc=jcpt(k)
2384 110 continue
2385  if(loc.eq.0) goto 120
2386  ii=jcolno(loc)
2387  if(ii.eq.k.or.ii.gt.neqnsz) goto 130
2388  l=l+1
2389  ja(l)=ii
2390 130 continue
2391  loc=jcpt(loc)
2392  goto 110
2393 120 ia(k+1)=l+1
2394 100 continue
2395  if(ldbg) then
2396  write(idbg,*) 'stiaja(): ia '
2397  write(idbg,60) (ia(i),i=1,neqns+1)
2398  write(idbg,*) 'stiaja(): ja '
2399  write(idbg,60) (ja(i),i=1,ia(neqns+1))
2400  endif
2401 60 format(10i7)
2402  return
2403  end subroutine stiaja
2404 
2405  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2406 
2407  subroutine idntty(neqns,invp,iperm)
2408 
2409  implicit none
2410 
2411  integer(kind=kint), intent(out) :: invp(:),iperm(:)
2412  integer(kind=kint), intent(in) :: neqns
2413 
2414  integer(kind=kint) :: i
2415 
2416  do 100 i=1,neqns
2417  invp(i)=i
2418  iperm(i)=i
2419 100 continue
2420  return
2421  end subroutine idntty
2422 
2423  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2424 
2425  subroutine genqmd(neqns,xadj,adj0,perm,invp,deg,marker,rchset,nbrhd,qsize,qlink,nofsub,adjncy)
2426 
2427  implicit none
2428 
2429  integer(kind=kint), intent(in) :: adj0(:),xadj(:)
2430  integer(kind=kint), intent(out) :: rchset(:),nbrhd(:),adjncy(:),perm(:),invp(:),deg(:),marker(:),qsize(:),qlink(:)
2431  integer(kind=kint), intent(in) :: neqns
2432  integer(kind=kint), intent(out) :: nofsub
2433 
2434  integer(kind=kint) :: inode,ip,irch,mindeg,nhdsze,node,np,num,nump1,nxnode,rchsze,search,thresh,ndeg
2435  integer(kind=kint) :: i,j
2436 
2437  mindeg=neqns
2438  nofsub=0
2439  do 10 i=1,xadj(neqns+1)-1
2440  adjncy(i)=adj0(i)
2441 10 continue
2442  do 100 node=1,neqns
2443  perm(node)=node
2444  invp(node)=node
2445  marker(node)=0
2446  qsize(node)=1
2447  qlink(node)=0
2448  ndeg=xadj(node+1)-xadj(node)
2449  deg(node)=ndeg
2450  if(ndeg.lt.mindeg) mindeg=ndeg
2451 100 continue
2452 
2453  num=0
2454 200 search=1
2455  thresh=mindeg
2456  mindeg=neqns
2457 300 nump1=num+1
2458  if(nump1.gt.search) search=nump1
2459  do 400 j=search,neqns
2460  node=perm(j)
2461  if(marker(node).lt.0) goto 400
2462  ndeg=deg(node)
2463  if(ndeg.le.thresh) goto 500
2464  if(ndeg.lt.mindeg) mindeg=ndeg
2465 400 continue
2466  goto 200
2467 
2468 500 search=j
2469  nofsub=nofsub+deg(node)
2470  marker(node)=1
2471  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
2472  nxnode=node
2473 600 num=num+1
2474  np=invp(nxnode)
2475  ip=perm(num)
2476  perm(np)=ip
2477  invp(ip)=np
2478  perm(num)=nxnode
2479  invp(nxnode)=num
2480  deg(nxnode)=-1
2481  nxnode=qlink(nxnode)
2482  if(nxnode.gt.0) goto 600
2483  if(rchsze.le.0) goto 800
2484  !
2485  call qmdupd(xadj,adjncy,rchsze,rchset,deg,qsize,qlink,marker,rchset(rchsze+1:),nbrhd(nhdsze+1:))
2486  marker(node)=0
2487  do 700 irch=1,rchsze
2488  inode=rchset(irch)
2489  if(marker(inode).lt.0) goto 700
2490  marker(inode)=0
2491  ndeg=deg(inode)
2492  if(ndeg.lt.mindeg) mindeg=ndeg
2493  if(ndeg.gt.thresh) goto 700
2494  mindeg=thresh
2495  thresh=ndeg
2496  search=invp(inode)
2497 700 continue
2498  if(nhdsze.gt.0) call qmdot(node,xadj,adjncy,marker,rchsze,rchset,nbrhd)
2499 800 if(num.lt.neqns) goto 300
2500  return
2501  end subroutine genqmd
2502 
2503  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2504 
2505  subroutine genpaq(xadj,adjncy,invp,iperm,parent,neqns,ancstr)
2506 
2507  implicit none
2508 
2509  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),invp(:),iperm(:)
2510  integer(kind=kint), intent(out) :: parent(:),ancstr(:)
2511  integer(kind=kint), intent(in) :: neqns
2512 
2513  integer(kind=kint) :: i,k,l,ip,it
2514 
2515  do 100 i=1,neqns
2516  parent(i)=0
2517  ancstr(i)=0
2518  ip=iperm(i)
2519  do 110 k=xadj(ip),xadj(ip+1)-1
2520  l=invp(adjncy(k))
2521  if(l.ge.i) goto 110
2522 112 continue
2523  if(ancstr(l).eq.0) goto 111
2524  if(ancstr(l).eq.i) goto 110
2525  it=ancstr(l)
2526  ancstr(l)=i
2527  l=it
2528  goto 112
2529 111 continue
2530  ancstr(l)=i
2531  parent(l)=i
2532 110 continue
2533 100 continue
2534  do 200 i=1,neqns
2535  if(parent(i).eq.0) parent(i)=neqns+1
2536 200 continue
2537  parent(neqns+1)=0
2538  if(ldbg) write(idbg,6010)
2539  if(ldbg) write(idbg,6000) (i,parent(i),i=1,neqns)
2540 6000 format(2i6)
2541 6010 format(' parent')
2542  return
2543  end subroutine genpaq
2544 
2545  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2546 
2547  subroutine genbtq(xadj,adjncy,invp,iperm,parent,btree,zpiv,izz,neqns)
2548 
2549  implicit none
2550 
2551  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),invp(:),iperm(:),zpiv(:)
2552  integer(kind=kint), intent(out) :: btree(:,:) ! btree is (2,:)
2553  integer(kind=kint), intent(in) :: neqns
2554  integer(kind=kint), intent(out) :: izz
2555 
2556  integer(kind=kint) :: i,ip,ib,inext
2557 
2558  do 10 i=1,neqns+1
2559  btree(1,i)=0
2560  btree(2,i)=0
2561 10 continue
2562  do 100 i=1,neqns+1
2563  ip=parent(i)
2564  if(ip.le.0) goto 100
2565  ib=btree(1,ip)
2566  if(ib.eq.0) then
2567  btree(1,ip)=i
2568  else
2569 101 continue
2570  inext=btree(2,ib)
2571  if(inext.eq.0) then
2572  btree(2,ib)=i
2573  else
2574  ib=inext
2575  goto 101
2576  endif
2577  endif
2578 100 continue
2579  !
2580  ! find zeropivot
2581  !
2582  do 200 i=1,neqns
2583  if(zpiv(i).ne.0) then
2584  if(btree(1,invp(i)).eq.0) then
2585  izz=i
2586  goto 210
2587  endif
2588  endif
2589 200 continue
2590  izz=0
2591 210 continue
2592  if(ldbg) write(idbg,6010)
2593  if(ldbg) write(idbg,6000) (i,btree(1,i),btree(2,i),i=1,neqns)
2594  if(ldbg) write(idbg,6020) izz
2595  ! if(idbg1.ge.2) write(10,6100) neqns
2596  ! if(idbg1.ge.2) write(10,6100) (btree(1,i),btree(2,i),i=1,neqns)
2597 6000 format(i6,'(',2i6,')')
2598 6010 format(' binary tree')
2599 6020 format(' the first zero pivot is ',i4)
2600 6100 format(2i8)
2601  return
2602  end subroutine genbtq
2603 
2604  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2605 
2606  subroutine rotate(xadj,adjncy,invp,iperm,parent,btree,izz,neqns,anc,adjt,irr)
2607 
2608  implicit none
2609 
2610  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),btree(:,:)
2611  integer(kind=kint), intent(out) :: anc(:),adjt(:)
2612  integer(kind=kint), intent(inout) :: invp(:), iperm(:)
2613  integer(kind=kint), intent(in) :: neqns,izz
2614  integer(kind=kint), intent(out) :: irr
2615 
2616  integer(kind=kint) :: i,k,l,izzz,nanc,loc,locc,ll,kk,iy
2617 
2618  !----------------------------------------------------------------------
2619  ! irr return code irr=0 node izz is not a bottom node
2620  ! irr=1 is a bottom node then rotation is
2621  ! performed
2622  !
2623  !----------------------------------------------------------------------
2624  if(izz.eq.0) then
2625  irr=0
2626  return
2627  endif
2628  izzz=invp(izz)
2629  if(btree(1,izzz).ne.0) then
2630  irr=0
2631  ! return
2632  endif
2633  irr=1
2634  !
2635  ! ancestors of izzz
2636  !
2637  nanc=0
2638  loc=izzz
2639 100 continue
2640  nanc=nanc+1
2641  anc(nanc)=loc
2642  loc=parent(loc)
2643  if(loc.ne.0) goto 100
2644  !
2645  ! to find the eligible node from ancestors of izz
2646  !
2647  ! adjt = Adj(Tree(y))
2648  l=1
2649 200 continue
2650  do 210 i=1,neqns
2651  adjt(i)=0
2652 210 continue
2653  locc=anc(l)
2654 220 continue
2655  loc=locc
2656  locc=btree(1,loc)
2657  if(locc.ne.0) goto 220
2658 230 continue
2659  do 240 k=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
2660  adjt(invp(adjncy(k)))=1
2661 240 continue
2662  if(loc.ge.anc(l)) goto 250
2663  locc=btree(2,loc)
2664  if(locc.ne.0) goto 220
2665  loc=parent(loc)
2666  goto 230
2667 250 continue
2668  do 260 ll=l+1,nanc
2669  if(adjt(anc(ll)).eq.0) then
2670  l=l+1
2671  goto 200
2672  endif
2673 260 continue
2674  if(l.eq.1) goto 500
2675 
2676  !
2677  ! anc(l-1) is the eligible node
2678  !
2679  ! (1) number the node not in Ancestor(iy)
2680  iy=anc(l-1)
2681  do 300 i=1,neqns
2682  adjt(i)=0
2683 300 continue
2684  do 310 ll=l,nanc
2685  adjt(anc(ll))=1
2686 310 continue
2687  k=0
2688  do 320 ll=1,neqns
2689  if(adjt(ll).eq.0) then
2690  k=k+1
2691  invp(iperm(ll))=k
2692  endif
2693 320 continue
2694  ! (2) followed by nodes in Ancestor(iy)-Adj(T(iy))
2695 330 continue
2696  do 340 i=1,neqns
2697  adjt(i)=0
2698 340 continue
2699  locc=iy
2700 350 continue
2701  loc=locc
2702  locc=btree(1,loc)
2703  if(locc.ne.0) goto 350
2704 360 continue
2705  do 370 kk=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
2706  adjt(invp(adjncy(kk)))=1
2707 370 continue
2708  if(loc.ge.iy) goto 380
2709  locc=btree(2,loc)
2710  if(locc.ne.0) goto 350
2711  loc=parent(loc)
2712  goto 360
2713 380 continue
2714  do 390 ll=l,nanc
2715  if(adjt(anc(ll)).eq.0) then
2716  k=k+1
2717  invp(iperm(anc(ll)))=k
2718  endif
2719 390 continue
2720  ! (3) and finally number the node in Adj(t(iy))
2721  do 400 ll=l,nanc
2722  if(adjt(anc(ll)).ne.0) then
2723  k=k+1
2724  invp(iperm(anc(ll)))=k
2725  endif
2726 400 continue
2727  goto 600
2728  !
2729  ! izz can be numbered last
2730  !
2731 500 continue
2732  k=0
2733  do 510 i=1,neqns
2734  if(i.eq.izzz) goto 510
2735  k=k+1
2736  invp(iperm(i))=k
2737 510 continue
2738  invp(iperm(izzz))=neqns
2739  !
2740  ! set iperm
2741  !
2742 600 continue
2743  do 610 i=1,neqns
2744  iperm(invp(i))=i
2745 610 continue
2746  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
2747 6000 format(10i6)
2748  return
2749  end subroutine rotate
2750 
2751  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2752 
2753  subroutine bringu(zpiv,iperm,invp,parent,izz,neqns,irr)
2754 
2755  implicit none
2756 
2757  integer(kind=kint), intent(in) :: zpiv(:),parent(:)
2758  integer(kind=kint), intent(inout) :: iperm(:),invp(:)
2759  integer(kind=kint), intent(in) :: neqns,izz
2760  integer(kind=kint), intent(out) :: irr
2761 
2762  integer(kind=kint) :: i,ib0,ib,ibp,izzp
2763 
2764  !----------------------------------------------------------------------
2765  !
2766  ! bringu brings up zero pivots from bottom of the elimination tree
2767  ! to higher nodes
2768  !
2769  ! irr = 0 complete
2770  ! = 1 impossible
2771  !
2772  ! #coded by t.arakawa
2773  !
2774  !----------------------------------------------------------------------
2775 
2776  irr=0
2777  ib0=invp(izz)
2778  ib=ib0
2779 100 continue
2780  if(ib.le.0) goto 1000
2781  ibp=parent(ib)
2782  izzp=iperm(ibp)
2783  if(zpiv(izzp).eq.0) goto 110
2784  ib=ibp
2785  goto 100
2786 110 continue
2787  invp(izz)=ibp
2788  invp(izzp)=ib0
2789  iperm(ibp)=izz
2790  iperm(ib0)=izzp
2791  if(ldbg) then
2792  do 200 i=1,neqns
2793  if(invp(iperm(i)).ne.i) goto 210
2794  if(iperm(invp(i)).ne.i) goto 210
2795 200 continue
2796  goto 220
2797 210 continue
2798  write(20,*) 'permutation error'
2799  stop
2800  endif
2801 220 continue
2802  return
2803 1000 continue
2804  irr=1
2805  end subroutine bringu
2806 
2807  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2808 
2809  subroutine posord(parent,btree,invp,iperm,pordr,nch,neqns,iw,qarent,mch)
2810 
2811  implicit none
2812 
2813  integer(kind=kint), intent(in) :: btree(:,:),qarent(:)
2814  integer(kind=kint), intent(out) :: pordr(:),iperm(:),nch(:),iw(:),parent(:),mch(0:neqns+1)
2815  integer(kind=kint), intent(inout) :: invp(:)
2816  integer(kind=kint), intent(in) :: neqns
2817 
2818  integer(kind=kint) :: i,l,locc,loc,locp,invpos,ipinv,ii
2819 
2820  do 5 i=1,neqns
2821  mch(i)=0
2822  pordr(i)=0
2823 5 continue
2824  l=1
2825  locc=neqns+1
2826 10 continue
2827  loc=locc
2828  locc=btree(1,loc)
2829  if(locc.ne.0) goto 10
2830  locp=qarent(loc)
2831  mch(locp)=mch(locp)+1
2832 20 continue
2833  pordr(loc)=l
2834  if(l.ge.neqns) goto 1000
2835  l=l+1
2836  locc=btree(2,loc)
2837  if(locc.ne.0) goto 10
2838  loc=qarent(loc)
2839  locp=qarent(loc)
2840  mch(locp)=mch(locp)+mch(loc)+1
2841  goto 20
2842 1000 continue
2843  do 100 i=1,neqns
2844  ipinv=pordr(invp(i))
2845  invp(i)=ipinv
2846  iperm(ipinv)=i
2847  iw(pordr(i))=i
2848 100 continue
2849  do 110 i=1,neqns
2850  invpos=iw(i)
2851  nch(i)=mch(invpos)
2852  ii=qarent(invpos)
2853  if(ii.gt.0.and.ii.le.neqns) then
2854  parent(i)=pordr(ii)
2855  else
2856  parent(i)=qarent(invpos)
2857  endif
2858 110 continue
2859  if(ldbg) write(idbg,6020)
2860  if(ldbg) write(idbg,6000) (pordr(i),i=1,neqns)
2861  if(ldbg) write(idbg,6030)
2862  if(ldbg) write(idbg,6050)
2863  if(ldbg) write(idbg,6000) (parent(i),i=1,neqns)
2864  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
2865  if(ldbg) write(idbg,6040)
2866  if(ldbg) write(idbg,6000) (iperm(i),i=1,neqns)
2867  if(ldbg) write(idbg,6010)
2868  if(ldbg) write(idbg,6000) (nch(i),i=1,neqns)
2869 6000 format(10i6)
2870 6010 format(' nch')
2871 6020 format(' post order')
2872 6030 format(/' invp ')
2873 6040 format(/' iperm ')
2874 6050 format(/' parent')
2875  return
2876  end subroutine posord
2877 
2878  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2879 
2880  subroutine gnleaf(xadj,adjncy,invp,iperm,pordr,nch,adjncp,xleaf,leaf,neqns,lnleaf)
2881 
2882  implicit none
2883 
2884  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),pordr(:),nch(:),invp(:),iperm(:)
2885  integer(kind=kint), intent(out) :: xleaf(:),leaf(:),adjncp(:)
2886  integer(kind=kint), intent(in) :: neqns
2887 
2888  integer(kind=kint) i,k,l,m,ik,istart,ip,iq,lnleaf,lc1,lc
2889 
2890  l=1
2891  ik=0
2892  istart=0
2893  do 100 i=1,neqns
2894  xleaf(i)=l
2895  ip=iperm(i)
2896  do 105 k=xadj(ip),xadj(ip+1)-1
2897  iq=invp(adjncy(k))
2898  if(iq.lt.i) then
2899  ik=ik+1
2900  adjncp(ik)=iq
2901  endif
2902 105 continue
2903  m=ik-istart
2904  if(m.eq.0) goto 131
2905  call qqsort(adjncp(istart+1:),m)
2906  lc1=adjncp(istart+1)
2907  if(lc1.ge.i) goto 100
2908  leaf(l)=lc1
2909  l=l+1
2910  do 130 k=istart+2,ik
2911  lc=adjncp(k)
2912  ! if(lc.ge.i) goto 125
2913  if(lc1.lt.lc-nch(lc)) then
2914  leaf(l)=lc
2915  l=l+1
2916  endif
2917 125 continue
2918  lc1=lc
2919 130 continue
2920  ik=1
2921  istart=ik
2922 131 continue
2923 100 continue
2924  xleaf(neqns+1)=l
2925  lnleaf=l-1
2926  if(ldbg) write(idbg,6020)
2927  if(ldbg) write(idbg,6000) (xleaf(i),i=1,neqns+1)
2928  if(ldbg) write(idbg,6010) lnleaf
2929  if(ldbg) write(idbg,6000) (leaf(i),i=1,lnleaf)
2930  return
2931 6000 format(10i6)
2932 6010 format(' leaf (len = ',i6,')')
2933 6020 format(' xleaf')
2934  end subroutine gnleaf
2935 
2936  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2937 
2938  subroutine countclno(parent,xleaf,leaf,neqns,nstop,lncol,ir)
2939 
2940  implicit none
2941 
2942  ! Count total number of non-zero elements
2943  ! which include fill-in.
2944  ! A and C region of given sparse matrix will consider.
2945  ! D region will not consider because of D is treat as
2946  ! dens matrix.
2947  !
2948  integer(kind=kint), intent(in) :: parent(:),xleaf(:),leaf(:)
2949  integer(kind=kint), intent(in) :: neqns, nstop
2950  integer(kind=kint), intent(out) :: lncol, ir
2951 
2952  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
2953 
2954  nc=0
2955  ir=0
2956  l=1
2957  do 100 i=1,neqns
2958  ks=xleaf(i)
2959  ke=xleaf(i+1)-1
2960  if(ke.lt.ks) goto 100
2961  nxleaf=leaf(ks)
2962  do 110 k=ks,ke-1
2963  j=nxleaf
2964  nxleaf=leaf(k+1)
2965 105 continue
2966  if(j.ge.nxleaf) goto 110
2967  if(j.ge.nstop) then
2968  goto 100
2969  endif
2970  l=l+1
2971  j=parent(j)
2972  goto 105
2973 110 continue
2974  j=leaf(ke)
2975 115 continue
2976  if(j.ge.nstop) goto 100
2977  if(j.ge.i.or.j.eq.0) goto 100
2978  l=l+1
2979  j=parent(j)
2980  goto 115
2981 100 continue
2982  lncol=l-1
2983  return
2984  end subroutine countclno
2985 
2986  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2987 
2988  subroutine gnclno(parent,pordr,xleaf,leaf,xlnzr,colno,neqns,nstop,lncol,ir)
2989 
2990  implicit none
2991 
2992  integer(kind=kint), intent(in) :: parent(:),pordr(:),xleaf(:),leaf(:)
2993  integer(kind=kint), intent(out) :: colno(:),xlnzr(:)
2994  integer(kind=kint), intent(in) :: neqns, nstop
2995  integer(kind=kint), intent(out) :: lncol,ir
2996 
2997  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
2998 
2999  nc=0
3000  ir=0
3001  l=1
3002  do 100 i=1,neqns
3003  xlnzr(i)=l
3004  ks=xleaf(i)
3005  ke=xleaf(i+1)-1
3006  if(ke.lt.ks) goto 100
3007  nxleaf=leaf(ks)
3008  do 110 k=ks,ke-1
3009  j=nxleaf
3010  nxleaf=leaf(k+1)
3011 105 continue
3012  if(j.ge.nxleaf) goto 110
3013  if(j.ge.nstop) then
3014  goto 100
3015  endif
3016  colno(l)=j
3017  l=l+1
3018  j=parent(j)
3019  goto 105
3020 110 continue
3021  j=leaf(ke)
3022 115 continue
3023  if(j.ge.nstop) goto 100
3024  if(j.ge.i.or.j.eq.0) goto 100
3025  colno(l)=j
3026  l=l+1
3027  j=parent(j)
3028  goto 115
3029 100 continue
3030  xlnzr(neqns+1)=l
3031  lncol=l-1
3032  if(ldbg) write(idbg,6010)
3033  ! if(idbg1.ne.0) write(6,6000) (xlnzr(i),i=1,neqns+1)
3034  if(ldbg) write(idbg,6020) lncol
3035  if(ldbg) then
3036  do 200 k=1,neqns
3037  write(idbg,6100) k
3038  write(idbg,6000) (colno(i),i=xlnzr(k),xlnzr(k+1)-1)
3039 200 continue
3040  endif
3041 6000 format(10i4)
3042 6010 format(' xlnzr')
3043 6020 format(' colno (lncol =',i10,')')
3044 6100 format(/' row = ',i6)
3045  return
3046  end subroutine gnclno
3047 
3048  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3049 
3050  subroutine qmdrch(root,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
3051 
3052  implicit none
3053 
3054  integer(kind=kint), intent(in) :: deg(:),xadj(:),adjncy(:)
3055  integer(kind=kint), intent(out) :: rchset(:),nbrhd(:)
3056  integer(kind=kint), intent(inout) :: marker(:)
3057  integer(kind=kint), intent(in) :: root
3058  integer(kind=kint), intent(out) :: nhdsze,rchsze
3059 
3060  integer(kind=kint) :: i,j, istrt, istop, jstrt, jstop, nabor, node
3061 
3062  nhdsze=0
3063  rchsze=0
3064  istrt=xadj(root)
3065  istop=xadj(root+1)-1
3066  if(istop.lt.istrt) return
3067  do 600 i=istrt,istop
3068  nabor=adjncy(i)
3069  if(nabor.eq.0) return
3070  if(marker(nabor).ne.0) goto 600
3071  if(deg(nabor).lt.0) goto 200
3072  rchsze=rchsze+1
3073  rchset(rchsze)=nabor
3074  marker(nabor)=1
3075  goto 600
3076 200 marker(nabor)=-1
3077  nhdsze=nhdsze+1
3078  nbrhd(nhdsze)=nabor
3079 300 jstrt=xadj(nabor)
3080  jstop=xadj(nabor+1)-1
3081  do 500 j=jstrt,jstop
3082  node=adjncy(j)
3083  nabor=-node
3084  !if(node) 300,600,400
3085  if(node<0) then
3086  goto 300
3087  elseif(node==0) then
3088  goto 600
3089  endif
3090 400 if(marker(node).ne.0) goto 500
3091  rchsze=rchsze+1
3092  rchset(rchsze)=node
3093  marker(node)=1
3094 500 continue
3095 600 continue
3096  return
3097  end subroutine qmdrch
3098 
3099  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3100 
3101  subroutine qmdupd(xadj,adjncy,nlist,list,deg,qsize,qlink,marker,rchset,nbrhd)
3102 
3103  implicit none
3104 
3105  integer(kind=kint), intent(in) :: adjncy(:),list(:),xadj(:)
3106  integer(kind=kint), intent(out) :: nbrhd(:),rchset(:)
3107  integer(kind=kint), intent(inout) :: marker(:),deg(:),qsize(:),qlink(:)
3108  integer(kind=kint), intent(in) :: nlist
3109 
3110  integer(kind=kint) :: j, deg0,deg1,il,inhd,inode,irch,jstrt,jstop,mark,nabor,nhdsze,node,rchsze
3111 
3112  if(nlist.le.0) return
3113  deg0=0
3114  nhdsze=0
3115  do 200 il=1,nlist
3116  node=list(il)
3117  deg0=deg0+qsize(node)
3118  jstrt=xadj(node)
3119  jstop=xadj(node+1)-1
3120 
3121  do 100 j=jstrt,jstop
3122  nabor=adjncy(j)
3123  if(marker(nabor).ne.0.or.deg(nabor).ge.0) goto 100
3124  marker(nabor)=-1
3125  nhdsze=nhdsze+1
3126  nbrhd(nhdsze)=nabor
3127 100 continue
3128 200 continue
3129 
3130  if(nhdsze.gt.0) call qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,nbrhd(nhdsze+1:))
3131  do 600 il=1,nlist
3132  node=list(il)
3133  mark=marker(node)
3134  if(mark.gt.1.or.mark.lt.0) goto 600
3135  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
3136  deg1=deg0
3137  if(rchsze.le.0) goto 400
3138  do 300 irch=1,rchsze
3139  inode=rchset(irch)
3140  deg1=deg1+qsize(inode)
3141  marker(inode)=0
3142 300 continue
3143 400 deg(node)=deg1-1
3144  if(nhdsze.le.0) goto 600
3145  do 500 inhd=1,nhdsze
3146  inode=nbrhd(inhd)
3147  marker(inode)=0
3148 500 continue
3149 600 continue
3150  return
3151  endsubroutine qmdupd
3152 
3153  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3154 
3155  subroutine qmdot(root,xadj,adjncy,marker,rchsze,rchset,nbrhd)
3156 
3157  implicit none
3158 
3159  integer(kind=kint), intent(in) :: marker(:),rchset(:),nbrhd(:),xadj(:)
3160  integer(kind=kint), intent(inout) :: adjncy(:)
3161  integer(kind=kint), intent(in) :: rchsze,root
3162 
3163  integer(kind=kint) :: j,irch,inhd,node,jstrt,jstop,link,nabor
3164 
3165  irch=0
3166  inhd=0
3167  node=root
3168  100 jstrt=xadj(node)
3169  jstop=xadj(node+1)-2
3170  if(jstop.lt.jstrt) goto 300
3171  do 200 j=jstrt,jstop
3172  irch=irch+1
3173  adjncy(j)=rchset(irch)
3174  if(irch.ge.rchsze) goto 400
3175 200 continue
3176 300 link=adjncy(jstop+1)
3177  node=-link
3178  if(link.lt.0) goto 100
3179  inhd=inhd+1
3180  node=nbrhd(inhd)
3181  adjncy(jstop+1)=-node
3182  goto 100
3183 400 adjncy(j+1)=0
3184  do 600 irch=1,rchsze
3185  node=rchset(irch)
3186  if(marker(node).lt.0) goto 600
3187  jstrt=xadj(node)
3188  jstop=xadj(node+1)-1
3189  do 500 j=jstrt,jstop
3190  nabor=adjncy(j)
3191  if(marker(nabor).ge.0) goto 500
3192  adjncy(j)=root
3193  goto 600
3194 500 continue
3195 600 continue
3196  return
3197  end subroutine qmdot
3198 
3199  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3200 
3201  subroutine qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,ovrlp)
3202 
3203  implicit none
3204 
3205  integer(kind=kint), intent(in) :: adjncy(:),nbrhd(:),xadj(:)
3206  integer(kind=kint), intent(out) :: rchset(:),ovrlp(:)
3207  integer(kind=kint), intent(inout) :: deg(:),marker(:),qsize(:), qlink(:)
3208  integer(kind=kint), intent(in) :: nhdsze
3209 
3210  integer(kind=kint) :: j, deg0,deg1,head,inhd,iov,irch,jstrt,jstop,link,lnode,mark,mrgsze,nabor,node,novrlp,rchsze,root
3211 
3212 
3213  if(nhdsze.le.0) return
3214  do 100 inhd=1,nhdsze
3215  root=nbrhd(inhd)
3216  marker(root)=0
3217 100 continue
3218  do 1400 inhd=1,nhdsze
3219  root=nbrhd(inhd)
3220  marker(root)=-1
3221  rchsze=0
3222  novrlp=0
3223  deg1=0
3224 200 jstrt=xadj(root)
3225  jstop=xadj(root+1)-1
3226  do 600 j=jstrt,jstop
3227  nabor=adjncy(j)
3228  root=-nabor
3229  !if(nabor) 200,700,300
3230  if(nabor<0) then
3231  goto 200
3232  elseif(nabor==0) then
3233  goto 700
3234  endif
3235 300 mark=marker(nabor)
3236  !if(mark)600,400,500
3237  if(mark<0) then
3238  goto 600
3239  elseif(mark>0) then
3240  goto 500
3241  endif
3242 400 rchsze=rchsze+1
3243  rchset(rchsze)=nabor
3244  deg1=deg1+qsize(nabor)
3245  marker(nabor)=1
3246  goto 600
3247 500 if(mark.gt.1) goto 600
3248  novrlp=novrlp+1
3249  ovrlp(novrlp)=nabor
3250  marker(nabor)=2
3251 600 continue
3252 700 head=0
3253  mrgsze=0
3254  do 1100 iov=1,novrlp
3255  node=ovrlp(iov)
3256  jstrt=xadj(node)
3257  jstop=xadj(node+1)-1
3258  do 800 j=jstrt,jstop
3259  nabor=adjncy(j)
3260  if(marker(nabor).ne.0) goto 800
3261  marker(node)=1
3262  goto 1100
3263 800 continue
3264  mrgsze=mrgsze+qsize(node)
3265  marker(node)=-1
3266  lnode=node
3267 900 link=qlink(lnode)
3268  if(link.le.0) goto 1000
3269  lnode=link
3270  goto 900
3271 1000 qlink(lnode)=head
3272  head=node
3273 1100 continue
3274  if(head.le.0) goto 1200
3275  qsize(head)=mrgsze
3276  deg(head)=deg0+deg1-1
3277  marker(head)=2
3278 1200 root=nbrhd(inhd)
3279  marker(root)=0
3280  if(rchsze.le.0) goto 1400
3281  do 1300 irch=1,rchsze
3282  node=rchset(irch)
3283  marker(node)=0
3284 1300 continue
3285 1400 continue
3286  return
3287  end subroutine qmdmrg
3288 
3289  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3290 
3291  subroutine ldudecomposec(xlnzr_a,colno_a,invp_a,iperm_a,ndeg,nttbr_c,irow_c,jcol_c,ncol,nrow,xlnzr_c,colno_c,lncol_c)
3292  ! find fill-in position in C which placed under A and set it in xlnzr_c, colno_c
3293 
3294  use m_crs_matrix
3295  implicit none
3296  !input
3297  integer(kind=kint), intent(in) :: xlnzr_a(:)
3298  integer(kind=kint), intent(in) :: colno_a(:)
3299  integer(kind=kint), intent(in) :: iperm_a(:)
3300  integer(kind=kint), intent(in) :: invp_a(:)
3301  integer(kind=kint), intent(in) :: ndeg
3302  integer(kind=kint), intent(in) :: nttbr_c
3303  integer(kind=kint), intent(in) :: irow_c(:)
3304  integer(kind=kint), intent(inout) :: jcol_c(:)
3305  integer(kind=kint), intent(in) :: ncol
3306  integer(kind=kint), intent(in) :: nrow
3307 
3308  !output
3309  integer(kind=kint), pointer :: xlnzr_c(:)
3310  integer(kind=kint), pointer :: colno_c(:)
3311  integer(kind=kint), intent(out) :: lncol_c
3312 
3313  ! internal
3314  integer(kind=kint) :: i,j,k
3315  integer(kind=kint) :: ks, ke, ipass, ierr
3316  logical, allocatable :: cnz(:)
3317  type(crs_matrix) :: crs_c
3318 
3319  !permtate column in C for crs_c
3320  do i=1,nttbr_c
3321  jcol_c(i)=invp_a(jcol_c(i))
3322  end do
3323 
3324  ! make Compact Column Storoge using symbolic information.
3325  call symbolicirjctocrs(ndeg, nttbr_c, irow_c, jcol_c, ncol, nrow, crs_c)
3326 
3327  ! symbolic LDU factorization for C matrix
3328  allocate(cnz(ncol), stat=ierr)
3329  if(ierr .ne. 0) then
3330  call errtrp('stop due to allocation error.')
3331  end if
3332  do ipass = 1,2
3333  lncol_c = 0
3334  do k=1,nrow
3335  ! set cnz as non-zero pattern of C
3336  cnz = .false.
3337  ks = crs_c%ia(k)
3338  ke = crs_c%ia(k+1)-1
3339  if (ke .lt. ks) then
3340  if (ipass .eq. 2) then
3341  xlnzr_c(k+1)=lncol_c+1
3342  end if
3343  cycle ! in case of zero vector, no need to check dot product.
3344  end if
3345 
3346  do i=ks,ke
3347  cnz(crs_c%ja(i)) = .true.
3348  end do
3349 
3350  ! check for non-zero dot product and update cnz for each point of cnz
3351  do i=2,ncol
3352  ks = xlnzr_a(i)
3353  ke = xlnzr_a(i+1)-1
3354  if (ke .lt. ks) then ! in case of column of A is zero vector.
3355  cycle
3356  end if
3357  do j=ks,ke
3358  if (cnz(colno_a(j))) then
3359  cnz(i) = .true.
3360  exit
3361  end if
3362  end do
3363  end do
3364 
3365  do i=1,ncol
3366  if (cnz(i)) then
3367  lncol_c = lncol_c + 1
3368  if (ipass .eq. 2) then
3369  colno_c(lncol_c) = i
3370  end if
3371  end if
3372  end do
3373  if (ipass .eq. 2) then
3374  xlnzr_c(k+1)=lncol_c + 1
3375  end if
3376  end do
3377 
3378  if (ipass .eq. 1) then
3379  allocate(xlnzr_c(nrow+1),colno_c(lncol_c), stat=ierr)
3380  if(ierr .ne. 0) then
3381  call errtrp('stop due to allocation error.')
3382  end if
3383  xlnzr_c(1)=1
3384  end if
3385  end do
3386 
3387  ! restore order of C column.
3388  do i=1,nttbr_c
3389  jcol_c(i)=iperm_a(jcol_c(i))
3390  end do
3391 
3392  return
3393 
3394  end subroutine ldudecomposec
3395 
3396  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3397 
3398  subroutine qqsort(iw,ik)
3399 
3400  implicit none
3401 
3402  integer(kind=kint), intent(inout) :: iw(:)
3403  integer(kind=kint), intent(in) :: ik
3404 
3405  integer(kind=kint) :: l,m,itemp
3406 
3407  !----------------------------------------------------------------------
3408  ! sort in increasing order up to i
3409  !
3410  ! iw array
3411  ! ik number of input/output
3412  ! i deal with numbers less than this numberi
3413  !
3414  !----------------------------------------------------------------------
3415 
3416  if(ik.le.1) return
3417  do 100 l=1,ik-1
3418  do 110 m=l+1,ik
3419  if(iw(l).lt.iw(m)) goto 110
3420  itemp=iw(l)
3421  iw(l)=iw(m)
3422  iw(m)=itemp
3423 110 continue
3424 100 continue
3425 200 continue
3426  return
3427  end subroutine qqsort
3428 
3429 
3430  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3431 
3432  subroutine staij1(isw,i,j,aij,dsi,ir)
3433 
3434  implicit none
3435 
3436  !----------------------------------------------------------------------
3437  !
3438  ! this routine sets an non-zero entry of the matrix.
3439  ! (symmetric version)
3440  !
3441  ! (i)
3442  ! isw =0 set the value
3443  ! =1 add the value
3444  ! i row entry
3445  ! j column entry
3446  ! aij value
3447  !
3448  ! (o)
3449  ! iv communication array
3450  !
3451  ! #coded by t.arakawa
3452  !
3453  !----------------------------------------------------------------------
3454  !
3455  type(dsinfo) :: dsi
3456  real(kind=kreal), intent(in) :: aij(:) ! ndeg*ndeg
3457  integer(kind=kint), intent(in) :: isw, i, j
3458  integer(kind=kint), intent(out) :: ir
3459 
3460  integer(kind=kint) :: ndeg, neqns, nstop, ndeg2, ndeg2l, ierr
3461  ndeg=dsi%ndeg
3462  neqns=dsi%neqns
3463  nstop=dsi%nstop
3464  ndeg2=ndeg*ndeg
3465  ndeg2l=ndeg*(ndeg+1)/2
3466 
3467  ir=0
3468  ierr=0
3469 
3470 
3471  ! array allocation
3472  if(dsi%stage.ne.20) then
3473  if(dsi%stage.eq.30) write(ilog,*) 'Warning a matrix was build up but never solved.'
3474  !
3475  ! for diagonal
3476  !
3477  allocate(dsi%diag(ndeg2l,neqns), stat=ierr)
3478  if(ierr .ne. 0) then
3479  call errtrp('stop due to allocation error.')
3480  end if
3481  dsi%diag=0
3482  !
3483  ! for lower triangle
3484  !
3485  allocate(dsi%zln(ndeg2,dsi%lncol), stat=ierr)
3486  if(ierr .ne. 0) then
3487  call errtrp('stop due to allocation error.')
3488  end if
3489  dsi%zln=0
3490  !
3491  ! for dense window !TODO delete this and corresponding line in addr3()
3492  !
3493  ! allocate(dsi%dsln(ndeg2,dsi%lndsln))! because of there is no dense window
3494  ! dsi%dsln=0
3495 
3496  dsi%stage=20
3497  endif
3498 
3499  ! set value
3500  if(ndeg.le.2) then
3501  call addr0(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,dsi%ndeg,ir)
3502  elseif(ndeg.eq.3) then
3503  call addr3(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,ir)
3504  else
3505  call addrx(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,ndeg,ndeg2,ndeg2l,ir)
3506  endif
3507 1000 continue
3508  return
3509  end subroutine staij1
3510 
3511  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3512  !
3513  ! After here, routines specialized for ndeg = 1
3514  !
3515  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3516 
3517  ! LDU decompose of A (1..nstop-1) region
3518  subroutine sum(ic,xlnzr,colno,zln,diag,nch,par,neqns)
3519 
3520  implicit none
3521 
3522  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3523  integer(kind=kint), intent(in) :: ic, neqns
3524  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3525  integer(kind=kint), intent(inout) :: nch(:)
3526 
3527  real(kind=kreal) :: s, t, zz, piv
3528  integer(kind=kint) :: ks, ke, kk, k, jc, jj, j, ierr
3529  integer(kind=kint) :: isem
3530  real(kind=kreal),allocatable :: temp(:)
3531  integer(kind=kint),allocatable :: indx(:)
3532  allocate(temp(neqns),indx(neqns), stat=ierr)
3533  if(ierr .ne. 0) then
3534  call errtrp('stop due to allocation error.')
3535  end if
3536 
3537  isem = 0
3538 
3539 2 continue
3540  ks=xlnzr(ic)
3541  ke=xlnzr(ic+1)
3542  t=0.0d0
3543  ! do 100 i=1,ic
3544  ! temp(i)=0.0d0
3545  ! 100 continue
3546  do 200 k=ks,ke-1
3547  jc=colno(k)
3548  indx(jc)=ic
3549  s=0.0d0
3550  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
3551  j=colno(jj)
3552  if(indx(j).eq.ic) then
3553  s=s+temp(j)*zln(jj)
3554  endif
3555 310 continue
3556  ! j1=xlnzr(jc)
3557  ! jj=xlnzr(jc+1)-j1
3558  ! ss=ddoti(jj,zln(j1),colno(j1),temp)
3559  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
3560  zz=zln(k)-s
3561  zln(k)=zz*diag(jc)
3562  temp(jc)=zz
3563  t=t+zz*zln(k)
3564 200 continue
3565  piv=diag(ic)-t
3566  if(dabs(piv).gt.rmin) then
3567  diag(ic)=1.0d0/piv
3568  endif
3569 1 continue
3570  if(isem.eq.1) then
3571  isem=0
3572  nch(ic)=-1
3573  kk=par(ic)
3574  nch(kk)=nch(kk)-1
3575  isem=1
3576  else
3577  goto 1
3578  endif
3579  return
3580  end subroutine sum
3581 
3582  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3583 
3584  ! LDU decompose of C (nstop..neqnsA+neqnsd) region
3585  subroutine sum1(ic,xlnzr,colno,zln,diag,par,neqns)
3586 
3587  implicit none
3588 
3589  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3590  integer(kind=kint), intent(in) :: ic, neqns
3591  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3592 
3593  real(kind=kreal) :: s, t, zz
3594  integer(kind=kint) :: ks, ke, k, jc, j, jj, ierr
3595  real(kind=kreal),allocatable :: temp(:)
3596  integer(kind=kint),allocatable :: indx(:)
3597 
3598  ierr=0
3599 
3600  allocate(temp(neqns),indx(neqns), stat=ierr)
3601  if(ierr .ne. 0) then
3602  call errtrp('stop due to allocation error.')
3603  end if
3604 
3605  ks=xlnzr(ic)
3606  ke=xlnzr(ic+1)
3607  t=0.0d0
3608  ! do 100 i=1,ic
3609  ! temp(i)=0.0d0
3610  ! 100 continue
3611  do 200 k=ks,ke-1
3612  jc=colno(k)
3613  indx(jc)=ic
3614  s=0.0d0
3615  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
3616  j=colno(jj)
3617  if(indx(j).eq.ic) then
3618  s=s+temp(j)*zln(jj)
3619  endif
3620 310 continue
3621  zz=zln(k)-s
3622  ! j1=xlnzr(jc)
3623  ! jj=xlnzr(jc+1)-j1
3624  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
3625  zln(k)=zz
3626  temp(jc)=zz
3627  ! t=t+zz*zz*diag(jc)
3628 200 continue
3629  ! diag(ic)=diag(ic)-t
3630  return
3631  end subroutine sum1
3632 
3633  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3634 
3635  ! LDU decompose and Update D region.
3636  subroutine sum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
3637 
3638  implicit none
3639 
3640  integer(kind=kint), intent(in) :: neqns, nstop
3641  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
3642  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3643  integer(kind=kint), pointer :: spdslnidx(:)
3644  real(kind=kreal), pointer :: spdslnval(:,:)
3645  integer(kind=kint), intent(out) :: nspdsln
3646 
3647  real(kind=kreal) :: s
3648  integer(kind=kint) :: ks, ke, k, jc, jj, j, j1,j2
3649  integer(kind=kint) :: ic, i, loc, ierr
3650  integer(kind=kint) :: ispdsln
3651  logical :: ftflag
3652  real(kind=kreal),allocatable :: temp(:)
3653  integer(kind=kint),allocatable :: indx(:)
3654  ierr=0
3655  allocate(temp(neqns),indx(neqns), stat=ierr)
3656  if(ierr .ne. 0) then
3657  call errtrp('stop due to allocation error.')
3658  end if
3659 
3660  nspdsln=0
3661  do ic=nstop,neqns
3662  ks=xlnzr(ic)
3663  ke=xlnzr(ic+1)-1
3664  do k=ks,ke
3665  jj=colno(k)
3666  indx(jj)=ic
3667  end do
3668  do jc=nstop,ic-1
3669  j1=xlnzr(jc)
3670  j2=xlnzr(jc+1)
3671  do jj=xlnzr(jc),xlnzr(jc+1)-1
3672  j=colno(jj)
3673  if(indx(j).eq.ic) then
3674  nspdsln=nspdsln+1
3675  exit
3676  endif
3677  end do
3678  end do
3679  end do
3680  allocate(spdslnidx(nspdsln),spdslnval(1,nspdsln), stat=ierr)
3681  if(ierr .ne. 0) then
3682  call errtrp('stop due to allocation error.')
3683  end if
3684 
3685  loc=0
3686  ispdsln=0
3687  spdslnval=0
3688  ftflag = .true.
3689  do 100 ic=nstop,neqns
3690  do 105 i=1,nstop
3691  temp(i)=0.0d0
3692 105 continue
3693  ks=xlnzr(ic)
3694  ke=xlnzr(ic+1)-1
3695  do 110 k=ks,ke
3696  jj=colno(k)
3697  temp(jj)=zln(k)
3698  zln(k)=temp(jj)*diag(jj)
3699  indx(jj)=ic
3700  diag(ic)=diag(ic)-temp(jj)*zln(k)
3701 110 continue
3702  do 120 jc=nstop,ic-1
3703  s=0.0d0
3704  loc=loc+1
3705  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
3706  j=colno(jj)
3707  if(indx(j).eq.ic) then
3708  if (ftflag) then
3709  ispdsln=ispdsln+1
3710  ftflag=.false.
3711  end if
3712  s=s+temp(j)*zln(jj)
3713  endif
3714 220 continue
3715  spdslnidx(ispdsln)=loc
3716  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-s
3717  ftflag = .true.
3718  ! j1=xlnzr(jc)
3719  ! jj=xlnzr(jc+1)-j1
3720  ! dsln(loc)=dsln(loc)-ddoti(jj,zln(j1),colno(j1),temp)
3721 120 continue
3722 100 continue
3723  return
3724  end subroutine sum2_child
3725 
3726  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3727 
3728  subroutine sum3(n,dsln,diag)
3729 
3730  implicit none
3731 
3732  real(kind=kreal), intent(inout) :: dsln(:),diag(:)
3733  integer(kind=kint), intent(in) :: n
3734 
3735  integer(kind=kint) :: i, j, loc, ierr
3736  real(kind=kreal),allocatable :: temp(:)
3737  integer(kind=kint),allocatable :: indx(:)
3738  allocate(temp(n),indx(n), stat=ierr)
3739  if(ierr .ne. 0) then
3740  call errtrp('stop due to allocation error.')
3741  end if
3742 
3743  if(n.le.0) goto 1000
3744  indx(1)=0
3745  loc=1
3746  diag(1)=1.0d0/diag(1)
3747  do 100 i=2,n
3748  indx(i)=loc
3749  do 110 j=1,i-1
3750  dsln(loc)=dsln(loc)-dot_product(dsln(indx(i):indx(i)+j-2),dsln(indx(j):indx(j)+j-2))
3751  loc=loc+1
3752 110 continue
3753  temp(1:i-1)=dsln(indx(i):indx(i)+i-2)*diag(1:i-1)
3754  diag(i)=diag(i)-dot_product(temp(1:i-1),dsln(indx(i):indx(i)+i-2))
3755  dsln(indx(i):indx(i)+i-2)=temp(1:i-1)
3756  diag(i)=1.0d0/diag(i)
3757 100 continue
3758 1000 continue
3759  return
3760  end subroutine sum3
3761 
3762  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3763 
3764  real(kind=kreal) function spdot2(b,zln,colno,ks,ke)
3765 
3766  implicit none
3767 
3768  integer(kind=kint), intent(in) :: colno(:)
3769  integer(kind=kint), intent(in) :: ks,ke
3770  real(kind=kreal), intent(in) :: zln(:),b(:)
3771 
3772  integer(kind=kint) :: j,jj
3773  real(kind=kreal) :: s
3774 
3775  !----------------------------------------------------------------------
3776  !
3777  ! spdot1 performs inner product of sparse vectors
3778  !
3779  !
3780  ! #coded by t.arakawa
3781  !
3782  !----------------------------------------------------------------------
3783  !
3784  s=0.0d0
3785  do 100 jj=ks,ke
3786  j=colno(jj)
3787  s=s+zln(jj)*b(j)
3788 100 continue
3789  spdot2=s
3790  end function spdot2
3791 
3792  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3793 
3794  real(kind=kreal) function ddot(a,b,n)
3795 
3796  implicit none
3797 
3798  real(kind=kreal), intent(in) :: a(n),b(n)
3799  integer(kind=kint), intent(in) :: n
3800 
3801  real(kind=kreal) :: s
3802  integer(kind=kint) :: i
3803 
3804  s=0.0d0
3805  do 100 i=1,n
3806  s=s+a(i)*b(i)
3807 100 continue
3808  ddot=s
3809  return
3810  end function ddot
3811 
3812  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3813 
3814  subroutine addr0(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ndeg,ir)
3815 
3816  implicit none
3817 
3818  integer(kind=kint), intent(in) :: isw ! 0: renew diag, dsln, zln other: add to diag, dsln, zln
3819  integer(kind=kint), intent(in) :: i,j,nstop, ndeg, invp(:),xlnzr(:),colno(:)
3820  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:),dsln(:,:)
3821  real(kind=kreal), intent(in) :: aij(:)
3822  integer(kind=kint), intent(out) :: ir
3823 
3824  integer(kind=kint) :: ndeg2, ii, jj, itrans, k, i0, j0, l, ks, ke
3825  integer(kind=kint), parameter :: idbg=0
3826  ndeg2=ndeg*ndeg
3827 
3828  ir=0
3829  ii=invp(i)
3830  jj=invp(j)
3831  if(idbg.ne.0) write(idbg,*) 'addr0',ii,jj,aij
3832  if(ii.eq.jj) then
3833  if(ndeg2.eq.1) then
3834  if(isw.eq.0) then
3835  diag(1,ii)=aij(1)
3836  else
3837  diag(1,ii)=diag(1,ii)+aij(1)
3838  endif
3839  elseif(ndeg2.eq.4) then
3840  if(isw.eq.0) then
3841  diag(1,ii)=aij(1)
3842  diag(2,ii)=aij(2)
3843  diag(3,ii)=aij(4)
3844  else
3845  diag(1,ii)=diag(1,ii)+aij(1)
3846  diag(2,ii)=diag(2,ii)+aij(2)
3847  diag(3,ii)=diag(3,ii)+aij(4)
3848  endif
3849  endif
3850  goto 1000
3851  endif
3852  itrans=0
3853  if(jj.gt.ii) then
3854  k=jj
3855  jj=ii
3856  ii=k
3857  itrans=1
3858  endif
3859  if(jj.ge.nstop) then
3860  i0=ii-nstop
3861  j0=jj-nstop+1
3862  k=i0*(i0-1)/2+j0
3863  if(ndeg2.eq.1) then
3864  dsln(1,k)=aij(1)
3865  goto 1000
3866  elseif(ndeg2.eq.4) then
3867  if(itrans.eq.0) then
3868  do 3 l=1,ndeg2
3869  dsln(l,k)=aij(l)
3870 3 continue
3871  goto 1000
3872  else
3873  dsln(1,k)=aij(1)
3874  dsln(2,k)=aij(3)
3875  dsln(3,k)=aij(2)
3876  dsln(4,k)=aij(4)
3877  goto 1000
3878  endif
3879  endif
3880  endif
3881  ks=xlnzr(ii)
3882  ke=xlnzr(ii+1)-1
3883  do 100 k=ks,ke
3884  if(colno(k).eq.jj) then
3885  if(isw.eq.0) then
3886  if(ndeg2.eq.1) then
3887  zln(1,k)=aij(1)
3888  elseif(ndeg2.eq.4) then
3889  if(itrans.eq.0) then
3890  do 4 l=1,ndeg2
3891  zln(l,k)=aij(l)
3892 4 continue
3893  else
3894  zln(1,k)=aij(1)
3895  zln(2,k)=aij(3)
3896  zln(3,k)=aij(2)
3897  zln(4,k)=aij(4)
3898  endif
3899  endif
3900  else
3901  if(ndeg2.eq.1) then
3902  zln(1,k)=zln(1,k)+aij(1)
3903  elseif(ndeg2.eq.4) then
3904  if(itrans.eq.0) then
3905  do 5 l=1,ndeg2
3906  zln(l,k)=zln(l,k)+aij(l)
3907 5 continue
3908  else
3909  zln(1,k)=zln(1,k)+aij(1)
3910  zln(2,k)=zln(2,k)+aij(3)
3911  zln(3,k)=zln(3,k)+aij(2)
3912  zln(4,k)=zln(4,k)+aij(4)
3913  endif
3914  endif
3915  endif
3916  goto 1000
3917  endif
3918 100 continue
3919  ir=20
3920 1000 continue
3921  return
3922  end subroutine addr0
3923 
3924  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3925  !
3926  ! After here, routines specialized for ndeg = 3
3927  !
3928  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3929 
3930  subroutine s3um(ic,xlnzr,colno,zln,diag,nch,par,neqns)
3931 
3932  implicit none
3933 
3934  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3935  integer(kind=kint), intent(inout) :: nch(:)
3936  real(kind=kreal), intent(inout) :: zln(:,:), diag(:,:) ! zln(9,*),diag(6,*),temp(9,*),indx(*)
3937  integer(kind=kint), intent(in) :: ic,neqns
3938 
3939  real(kind=kreal), allocatable :: temp(:,:)
3940  integer(kind=kint), allocatable :: indx(:)
3941  real(kind=kreal) :: zz(9),t(6)
3942  integer(kind=kint) :: j,k,l,ks,ke,kk,jc,jj,ir, ierr
3943 
3944  allocate(temp(9,neqns),indx(neqns), stat=ierr)
3945  if(ierr .ne. 0) then
3946  call errtrp('stop due to allocation error.')
3947  end if
3948 
3949  ks=xlnzr(ic)
3950  ke=xlnzr(ic+1)
3951  !$dir max_trips(6)
3952  do 100 l=1,6
3953  t(l)=0.0d0
3954 100 continue
3955  do 200 k=ks,ke-1
3956  jc=colno(k)
3957  indx(jc)=ic
3958  !$dir max_trips(9)
3959  do 210 l=1,9
3960  zz(l)=zln(l,k)
3961 210 continue
3962  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
3963  j=colno(jj)
3964  if(indx(j).eq.ic) then
3965  zz(1)=zz(1)-temp(1,j)*zln(1,jj)-temp(4,j)*zln(4,jj)-temp(7,j)*zln(7,jj)
3966  zz(2)=zz(2)-temp(2,j)*zln(1,jj)-temp(5,j)*zln(4,jj)-temp(8,j)*zln(7,jj)
3967  zz(3)=zz(3)-temp(3,j)*zln(1,jj)-temp(6,j)*zln(4,jj)-temp(9,j)*zln(7,jj)
3968  zz(4)=zz(4)-temp(1,j)*zln(2,jj)-temp(4,j)*zln(5,jj)-temp(7,j)*zln(8,jj)
3969  zz(5)=zz(5)-temp(2,j)*zln(2,jj)-temp(5,j)*zln(5,jj)-temp(8,j)*zln(8,jj)
3970  zz(6)=zz(6)-temp(3,j)*zln(2,jj)-temp(6,j)*zln(5,jj)-temp(9,j)*zln(8,jj)
3971  zz(7)=zz(7)-temp(1,j)*zln(3,jj)-temp(4,j)*zln(6,jj)-temp(7,j)*zln(9,jj)
3972  zz(8)=zz(8)-temp(2,j)*zln(3,jj)-temp(5,j)*zln(6,jj)-temp(8,j)*zln(9,jj)
3973  zz(9)=zz(9)-temp(3,j)*zln(3,jj)-temp(6,j)*zln(6,jj)-temp(9,j)*zln(9,jj)
3974  endif
3975 310 continue
3976 
3977  call inv33(zln(:,k),zz,diag(:,jc))
3978 
3979  !$dir max_trips(9)
3980  do 220 l=1,9
3981  temp(l,jc)=zz(l)
3982 220 continue
3983  t(1)=t(1)+zz(1)*zln(1,k)+zz(4)*zln(4,k)+zz(7)*zln(7,k)
3984  t(2)=t(2)+zz(1)*zln(2,k)+zz(4)*zln(5,k)+zz(7)*zln(8,k)
3985  t(3)=t(3)+zz(2)*zln(2,k)+zz(5)*zln(5,k)+zz(8)*zln(8,k)
3986  t(4)=t(4)+zz(1)*zln(3,k)+zz(4)*zln(6,k)+zz(7)*zln(9,k)
3987  t(5)=t(5)+zz(2)*zln(3,k)+zz(5)*zln(6,k)+zz(8)*zln(9,k)
3988  t(6)=t(6)+zz(3)*zln(3,k)+zz(6)*zln(6,k)+zz(9)*zln(9,k)
3989 200 continue
3990  !$dir max_trips(6)
3991  do 320 l=1,6
3992  diag(l,ic)=diag(l,ic)-t(l)
3993 320 continue
3994 
3995  call inv3(diag(:,ic),ir)
3996  nch(ic)=-1
3997  kk=par(ic)
3998  nch(kk)=nch(kk)-1
3999 
4000  return
4001  end subroutine s3um
4002 
4003  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4004 
4005  subroutine s3um1(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4006 
4007  implicit none
4008 
4009  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),nch(:),par(:)
4010  real(kind=kreal), intent(in) :: diag(:,:)! zln(9,*),diag(6,*)
4011  real(kind=kreal), intent(inout) :: zln(:,:)
4012  integer(kind=kint), intent(in) :: ic,neqns
4013 
4014  integer(kind=kint) :: j,k,l,ks,ke,jc,jj,ierr
4015  real(kind=kreal) :: s(9)
4016  real(kind=kreal),allocatable :: temp(:,:)
4017  integer(kind=kint),allocatable :: indx(:)
4018 
4019  ierr=0
4020  allocate(temp(9,neqns),indx(neqns), stat=ierr)
4021  temp = 0.0d0
4022  indx = 0
4023 
4024  ks=xlnzr(ic)
4025  ke=xlnzr(ic+1)
4026  !$dir max_trip(9)
4027  do 100 l=1,9
4028  s(l)=0.0d0
4029 100 continue
4030  do 200 k=ks,ke-1
4031  jc=colno(k)
4032  indx(jc)=ic
4033 
4034  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4035  j=colno(jj)
4036  if(indx(j).eq.ic) then
4037  s(1)=s(1)+temp(1,j)*zln(1,jj)+temp(4,j)*zln(4,jj)+temp(7,j)*zln(7,jj)
4038  s(2)=s(2)+temp(2,j)*zln(1,jj)+temp(5,j)*zln(4,jj)+temp(8,j)*zln(7,jj)
4039  s(3)=s(3)+temp(3,j)*zln(1,jj)+temp(6,j)*zln(4,jj)+temp(9,j)*zln(7,jj)
4040  s(4)=s(4)+temp(1,j)*zln(2,jj)+temp(4,j)*zln(5,jj)+temp(7,j)*zln(8,jj)
4041  s(5)=s(5)+temp(2,j)*zln(2,jj)+temp(5,j)*zln(5,jj)+temp(8,j)*zln(8,jj)
4042  s(6)=s(6)+temp(3,j)*zln(2,jj)+temp(6,j)*zln(5,jj)+temp(9,j)*zln(8,jj)
4043  s(7)=s(7)+temp(1,j)*zln(3,jj)+temp(4,j)*zln(6,jj)+temp(7,j)*zln(9,jj)
4044  s(8)=s(8)+temp(2,j)*zln(3,jj)+temp(5,j)*zln(6,jj)+temp(8,j)*zln(9,jj)
4045  s(9)=s(9)+temp(3,j)*zln(3,jj)+temp(6,j)*zln(6,jj)+temp(9,j)*zln(9,jj)
4046  endif
4047 310 continue
4048  !$dir max_trip(9)
4049  do 320 l=1,9
4050  temp(l,jc)=zln(l,k)-s(l)
4051  zln(l,k)=temp(l,jc)
4052  s(l)=0.0d0
4053 320 continue
4054 
4055 200 continue
4056 
4057  deallocate(temp,indx)
4058  end subroutine s3um1
4059 
4060 
4061  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4062 
4063  subroutine s3um3(n,dsln,diag)
4064 
4065  implicit none
4066 
4067  real(kind=kreal), intent(inout) :: dsln(:,:),diag(:,:)!dsln(9,*),diag(6,*)
4068  integer(kind=kint), intent(in) :: n
4069 
4070  real(kind=kreal) :: t(9)
4071  integer(kind=kint) :: i,j,loc,ir, ierr
4072  real(kind=kreal), allocatable :: temp(:,:)
4073  integer(kind=kint), allocatable :: indx(:)
4074 
4075  allocate(temp(9,n),indx(n), stat=ierr)
4076  if(ierr .ne. 0) then
4077  call errtrp('stop due to allocation error.')
4078  end if
4079 
4080  if(n.le.0) goto 1000
4081  indx(1)=1
4082  loc=1
4083  call inv3(diag(:,1),ir)
4084  do 100 i=2,n
4085  indx(i)=loc
4086  do 110 j=1,i-1
4087  call d3dot(t,dsln(:,indx(i):indx(i)+j-2), dsln(:,indx(j):indx(j)+j-2),j-1)
4088  !$dir max_trips(9)
4089  dsln(:,loc)=dsln(:,loc)-t(:)
4090  loc=loc+1
4091 110 continue
4092  call v3prod(dsln(:,indx(i):indx(i)+i-2), diag,temp,i-1)
4093  call d3dotl(t,temp,dsln(:,indx(i):indx(i)+i-2),i-1)
4094  !$dir max_trips(6)
4095  diag(:,i)=diag(:,i)-t(1:6)
4096  dsln(:,indx(i):indx(i)+i-2)=temp(:,1:i-1)
4097  call inv3(diag(:,i),ir)
4098 100 continue
4099 1000 continue
4100  return
4101  end subroutine s3um3
4102 
4103  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4104 
4105  subroutine d3sdot(wi,a,b,n)
4106 
4107  implicit none
4108 
4109  real(kind=kreal), intent(in) :: a(:,:),b(:,:) !wi(3),a(3,*),b(9,*) !
4110  real(kind=kreal), intent(inout) :: wi(:)
4111  integer(kind=kint), intent(in) :: n
4112 
4113  integer(kind=kint) :: jj
4114  !
4115  !----------------------------------------------------------------------
4116  !
4117  ! spdot1 performs inner product of sparse vectors
4118  !
4119  !
4120  ! #coded by t.arakawa
4121  !
4122  !----------------------------------------------------------------------
4123  !
4124  do 100 jj=1,n
4125  wi(1)=wi(1)-a(1,jj)*b(1,jj)-a(2,jj)*b(4,jj)-a(3,jj)*b(7,jj)
4126  wi(2)=wi(2)-a(1,jj)*b(2,jj)-a(2,jj)*b(5,jj)-a(3,jj)*b(8,jj)
4127  wi(3)=wi(3)-a(1,jj)*b(3,jj)-a(2,jj)*b(6,jj)-a(3,jj)*b(9,jj)
4128 100 continue
4129  return
4130  end subroutine d3sdot
4131 
4132  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4133 
4134  subroutine s3pdot(bi,b,zln,colno,ks,ke)
4135 
4136  implicit none
4137 
4138  integer(kind=kint), intent(in) :: colno(:)
4139  real(kind=kreal), intent(in) :: zln(:,:),b(:,:) !zln(9,*),b(3,*),bi(3) !
4140  real(kind=kreal), intent(inout) :: bi(:)
4141  integer(kind=kint), intent(in) :: ks,ke
4142 
4143  integer(kind=kint) :: j,jj
4144  !
4145  !----------------------------------------------------------------------
4146  !
4147  ! spdot1 performs inner product of sparse vectors
4148  !
4149  !
4150  ! #coded by t.arakawa
4151  !
4152  !----------------------------------------------------------------------
4153  !
4154  do 100 jj=ks,ke
4155  j=colno(jj)
4156  bi(1)=bi(1)-zln(1,jj)*b(1,j)-zln(4,jj)*b(2,j)-zln(7,jj)*b(3,j)
4157  bi(2)=bi(2)-zln(2,jj)*b(1,j)-zln(5,jj)*b(2,j)-zln(8,jj)*b(3,j)
4158  bi(3)=bi(3)-zln(3,jj)*b(1,j)-zln(6,jj)*b(2,j)-zln(9,jj)*b(3,j)
4159 100 continue
4160  return
4161  end subroutine s3pdot
4162 
4163  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4164 
4165  subroutine inv33(zln,zz,diag)
4166 
4167  implicit none
4168 
4169  real(kind=kreal), intent(in) :: zz(9),diag(6)
4170  real(kind=kreal), intent(out) :: zln(9)
4171 
4172  zln(4)=zz(4)-zz(1)*diag(2)
4173  zln(7)=zz(7)-zz(1)*diag(4)-zln(4)*diag(5)
4174  zln(1)=zz(1)*diag(1)
4175  zln(4)=zln(4)*diag(3)
4176  zln(7)=zln(7)*diag(6)
4177  zln(4)=zln(4)-zln(7)*diag(5)
4178  zln(1)=zln(1)-zln(4)*diag(2)-zln(7)*diag(4)
4179  !
4180  zln(5)=zz(5)-zz(2)*diag(2)
4181  zln(8)=zz(8)-zz(2)*diag(4)-zln(5)*diag(5)
4182  zln(2)=zz(2)*diag(1)
4183  zln(5)=zln(5)*diag(3)
4184  zln(8)=zln(8)*diag(6)
4185  zln(5)=zln(5)-zln(8)*diag(5)
4186  zln(2)=zln(2)-zln(5)*diag(2)-zln(8)*diag(4)
4187  !
4188  zln(6)=zz(6)-zz(3)*diag(2)
4189  zln(9)=zz(9)-zz(3)*diag(4)-zln(6)*diag(5)
4190  zln(3)=zz(3)*diag(1)
4191  zln(6)=zln(6)*diag(3)
4192  zln(9)=zln(9)*diag(6)
4193  zln(6)=zln(6)-zln(9)*diag(5)
4194  zln(3)=zln(3)-zln(6)*diag(2)-zln(9)*diag(4)
4195  return
4196  end subroutine inv33
4197 
4198  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4199 
4200  subroutine inv3(dsln,ir)
4201 
4202  implicit none
4203 
4204  real(kind=kreal) :: dsln(6),t(2)
4205  integer(kind=kint) :: ir
4206 
4207  ir=0
4208  if(dabs(dsln(1)).lt.rmin) then
4209  goto 999
4210  endif
4211  dsln(1)=1.0d0/dsln(1)
4212  t(1)=dsln(2)*dsln(1)
4213  dsln(3)=dsln(3)-t(1)*dsln(2)
4214  dsln(2)=t(1)
4215  if(dabs(dsln(3)).lt.rmin) then
4216  goto 999
4217  endif
4218  dsln(3)=1.0d0/dsln(3)
4219  t(1)=dsln(4)*dsln(1)
4220  dsln(5)=dsln(5)-dsln(2)*dsln(4)
4221  t(2)=dsln(5)*dsln(3)
4222  dsln(6)=dsln(6)-t(1)*dsln(4)-t(2)*dsln(5)
4223  dsln(4)=t(1)
4224  dsln(5)=t(2)
4225  if(dabs(dsln(6)).lt.rmin) then
4226  goto 999
4227  endif
4228  dsln(6)=1.0d0/dsln(6)
4229  ! write(6,*) "dsln",dsln(1),dsln(3),dsln(6)
4230  return
4231 999 continue
4232  write(ilog,*) "singular"
4233  dsln(1)=1.0d0
4234  dsln(2)=0.0d0
4235  dsln(3)=1.0d0
4236  dsln(4)=0.0d0
4237  dsln(5)=0.0d0
4238  dsln(6)=1.0d0
4239  return
4240  end subroutine inv3
4241 
4242  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4243 
4244  subroutine d3dot(t,a,b,n)
4245  implicit none
4246 
4247  real(kind=kreal), intent(in) :: a(:,:),b(:,:)
4248  real(kind=kreal), intent(out) :: t(:)
4249  integer(kind=kint),intent(in) :: n
4250 
4251  integer(kind=kint) :: l,jj
4252  ! double precision a(9,n),b(9,n)
4253  ! double precision t(9)
4254  !
4255  !----------------------------------------------------------------------
4256  !
4257  ! spdot1 performs inner product of sparse vectors
4258  !
4259  ! it might be 'DENS' kitayama
4260  !
4261  !
4262  ! #coded by t.arakawa
4263  !
4264  !----------------------------------------------------------------------
4265  !
4266  !$dir max_trips(9)
4267  do 10 l=1,9
4268  t(l)=0.0d0
4269 10 continue
4270  do 100 jj=1,n
4271  t(1)=t(1)+a(1,jj)*b(1,jj)+a(4,jj)*b(4,jj)+a(7,jj)*b(7,jj)
4272  t(2)=t(2)+a(2,jj)*b(1,jj)+a(5,jj)*b(4,jj)+a(8,jj)*b(7,jj)
4273  t(3)=t(3)+a(3,jj)*b(1,jj)+a(6,jj)*b(4,jj)+a(9,jj)*b(7,jj)
4274  t(4)=t(4)+a(1,jj)*b(2,jj)+a(4,jj)*b(5,jj)+a(7,jj)*b(8,jj)
4275  t(5)=t(5)+a(2,jj)*b(2,jj)+a(5,jj)*b(5,jj)+a(8,jj)*b(8,jj)
4276  t(6)=t(6)+a(3,jj)*b(2,jj)+a(6,jj)*b(5,jj)+a(9,jj)*b(8,jj)
4277  t(7)=t(7)+a(1,jj)*b(3,jj)+a(4,jj)*b(6,jj)+a(7,jj)*b(9,jj)
4278  t(8)=t(8)+a(2,jj)*b(3,jj)+a(5,jj)*b(6,jj)+a(8,jj)*b(9,jj)
4279  t(9)=t(9)+a(3,jj)*b(3,jj)+a(6,jj)*b(6,jj)+a(9,jj)*b(9,jj)
4280 100 continue
4281  return
4282  end subroutine d3dot
4283 
4284  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4285 
4286  subroutine v3prod(zln,diag,zz,n)
4287 
4288  implicit none
4289 
4290  real(kind=kreal), intent(in) :: zln(:,:),diag(:,:)
4291  real(kind=kreal), intent(out) :: zz(:,:)
4292  integer(kind=kint), intent(in) :: n
4293 
4294  integer(kind=kint) :: i
4295 
4296  do 100 i=1,n
4297  zz(4,i)=zln(4,i)-zln(1,i)*diag(2,i)
4298  zz(7,i)=zln(7,i)-zln(1,i)*diag(4,i)-zz(4,i)*diag(5,i)
4299  zz(1,i)=zln(1,i)*diag(1,i)
4300  zz(4,i)=zz(4,i)*diag(3,i)
4301  zz(7,i)=zz(7,i)*diag(6,i)
4302  zz(4,i)=zz(4,i)-zz(7,i)*diag(5,i)
4303  zz(1,i)=zz(1,i)-zz(4,i)*diag(2,i)-zz(7,i)*diag(4,i)
4304  !
4305  zz(5,i)=zln(5,i)-zln(2,i)*diag(2,i)
4306  zz(8,i)=zln(8,i)-zln(2,i)*diag(4,i)-zz(5,i)*diag(5,i)
4307  zz(2,i)=zln(2,i)*diag(1,i)
4308  zz(5,i)=zz(5,i)*diag(3,i)
4309  zz(8,i)=zz(8,i)*diag(6,i)
4310  zz(5,i)=zz(5,i)-zz(8,i)*diag(5,i)
4311  zz(2,i)=zz(2,i)-zz(5,i)*diag(2,i)-zz(8,i)*diag(4,i)
4312  !
4313  zz(6,i)=zln(6,i)-zln(3,i)*diag(2,i)
4314  zz(9,i)=zln(9,i)-zln(3,i)*diag(4,i)-zz(6,i)*diag(5,i)
4315  zz(3,i)=zln(3,i)*diag(1,i)
4316  zz(6,i)=zz(6,i)*diag(3,i)
4317  zz(9,i)=zz(9,i)*diag(6,i)
4318  zz(6,i)=zz(6,i)-zz(9,i)*diag(5,i)
4319  zz(3,i)=zz(3,i)-zz(6,i)*diag(2,i)-zz(9,i)*diag(4,i)
4320 100 continue
4321  return
4322  end subroutine v3prod
4323  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4324 
4325  subroutine d3dotl(t,a,b,n)
4326  implicit none
4327 
4328  real(kind=kreal), intent(in) :: a(:,:),b(:,:)
4329  real(kind=kreal), intent(out) :: t(:)
4330  integer(kind=kint), intent(in) :: n
4331 
4332  integer(kind=kint) :: l,jj
4333  ! double precision t(6),a(9,n),b(9,n)
4334  !
4335  !----------------------------------------------------------------------
4336  !
4337  ! spdot1 performs inner product of sparse vectors
4338  !
4339  !
4340  ! #coded by t.arakawa
4341  !
4342  !----------------------------------------------------------------------
4343  !
4344  !$dir max_trips(6)
4345  do 10 l=1,6
4346  t(l)=0.0d0
4347 10 continue
4348  do 100 jj=1,n
4349  t(1)=t(1)+a(1,jj)*b(1,jj)+a(4,jj)*b(4,jj)+a(7,jj)*b(7,jj)
4350  t(2)=t(2)+a(2,jj)*b(1,jj)+a(5,jj)*b(4,jj)+a(8,jj)*b(7,jj)
4351  t(3)=t(3)+a(2,jj)*b(2,jj)+a(5,jj)*b(5,jj)+a(8,jj)*b(8,jj)
4352  t(4)=t(4)+a(3,jj)*b(1,jj)+a(6,jj)*b(4,jj)+a(9,jj)*b(7,jj)
4353  t(5)=t(5)+a(3,jj)*b(2,jj)+a(6,jj)*b(5,jj)+a(9,jj)*b(8,jj)
4354  t(6)=t(6)+a(3,jj)*b(3,jj)+a(6,jj)*b(6,jj)+a(9,jj)*b(9,jj)
4355 100 continue
4356  return
4357  end subroutine d3dotl
4358 
4359  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4360 
4361  subroutine addr3(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ir)
4362 
4363  implicit none
4364 
4365  integer(kind=kint), intent(in) :: invp(:),xlnzr(:),colno(:)
4366  real(kind=kreal), intent(in) :: aij(:) !zln(9,*),diag(6,*),dsln(9,*),aij(9)
4367  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:),dsln(:,:) !zln(9,*),diag(6,*),dsln(9,*),aij(9)
4368  integer(kind=kint), intent(in) :: isw,i,j,nstop
4369  integer(kind=kint), intent(out) :: ir
4370 
4371  integer(kind=kint), parameter :: ndeg2=9
4372  integer(kind=kint), parameter :: ndeg2l=6
4373  integer(kind=kint) :: k,l,ii,jj,itrans,i0,j0,ks,ke
4374 
4375  ir=0
4376  ii=invp(i)
4377  jj=invp(j)
4378  if(ldbg) write(idbg,*) 'addr3',ii,jj,aij
4379 
4380  ! diagonal
4381  if(ii.eq.jj) then
4382  diag(1,ii)=aij(1)
4383  diag(2,ii)=aij(2)
4384  diag(3,ii)=aij(5)
4385  diag(4,ii)=aij(3)
4386  diag(5,ii)=aij(6)
4387  diag(6,ii)=aij(9)
4388  goto 1000
4389  endif
4390  itrans=0
4391  if(jj.gt.ii) then
4392  k=jj
4393  jj=ii
4394  ii=k
4395  itrans=1
4396  endif
4397 
4398  ! D region
4399  if(jj.ge.nstop) then
4400  i0=ii-nstop
4401  j0=jj-nstop+1
4402  k=i0*(i0-1)/2+j0
4403  if(itrans.eq.0) then
4404  do 110 l=1,ndeg2
4405  dsln(l,k)=aij(l)
4406 110 continue
4407  goto 1000
4408  else
4409  dsln(1,k)=aij(1)
4410  dsln(2,k)=aij(4)
4411  dsln(3,k)=aij(7)
4412  dsln(4,k)=aij(2)
4413  dsln(5,k)=aij(5)
4414  dsln(6,k)=aij(8)
4415  dsln(7,k)=aij(3)
4416  dsln(8,k)=aij(6)
4417  dsln(9,k)=aij(9)
4418  goto 1000
4419  endif
4420  endif
4421 
4422  ! A and C region
4423  ks=xlnzr(ii)
4424  ke=xlnzr(ii+1)-1
4425  do 100 k=ks,ke
4426  if(colno(k).eq.jj) then
4427  if(itrans.eq.0) then
4428  do 120 l=1,ndeg2
4429  zln(l,k)=aij(l)
4430 120 continue
4431  else
4432  zln(1,k)=aij(1)
4433  zln(2,k)=aij(4)
4434  zln(3,k)=aij(7)
4435  zln(4,k)=aij(2)
4436  zln(5,k)=aij(5)
4437  zln(6,k)=aij(8)
4438  zln(7,k)=aij(3)
4439  zln(8,k)=aij(6)
4440  zln(9,k)=aij(9)
4441  endif
4442  goto 1000
4443  endif
4444 100 continue
4445  ir=20
4446 1000 continue
4447  return
4448  end subroutine addr3
4449 
4450  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4451 
4452  subroutine s2um(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4453 
4454  implicit none
4455 
4456  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
4457  integer(kind=kint), intent(inout) :: nch(:)
4458  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) ! zln(6,*), diag(3,*)
4459  integer(kind=kint), intent(in) :: ic,neqns
4460 
4461  integer(kind=kint) :: j,k,l,ks,ke,jj,jc,ir,kk, ierr
4462  real(kind=kreal), allocatable :: temp(:,:)
4463  integer(kind=kint), allocatable :: indx(:)
4464  real(kind=kreal) :: s(4),zz(4),t(3)
4465 
4466  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4467  if(ierr .ne. 0) then
4468  call errtrp('stop due to allocation error.')
4469  end if
4470 
4471  ks=xlnzr(ic)
4472  ke=xlnzr(ic+1)
4473  t(1)=0.0d0
4474  t(2)=0.0d0
4475  t(3)=0.0d0
4476  do 200 k=ks,ke-1
4477  jc=colno(k)
4478  indx(jc)=ic
4479  do 210 l=1,4
4480  s(l)=0.0d0
4481  zz(l)=zln(l,k)
4482 210 continue
4483  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4484  j=colno(jj)
4485  if(indx(j).eq.ic) then
4486  zz(1)=zz(1)-temp(1,j)*zln(1,jj)-temp(3,j)*zln(3,jj)
4487  zz(2)=zz(2)-temp(2,j)*zln(1,jj)-temp(4,j)*zln(3,jj)
4488  zz(3)=zz(3)-temp(1,j)*zln(2,jj)-temp(3,j)*zln(4,jj)
4489  zz(4)=zz(4)-temp(2,j)*zln(2,jj)-temp(4,j)*zln(4,jj)
4490  endif
4491 310 continue
4492  call inv22(zln(:,k),zz,diag(:,jc))
4493  do 220 l=1,4
4494  temp(l,jc)=zz(l)
4495 220 continue
4496  t(1)=t(1)+zz(1)*zln(1,k)+zz(3)*zln(3,k)
4497  t(2)=t(2)+zz(2)*zln(1,k)+zz(4)*zln(3,k)
4498  t(3)=t(3)+zz(2)*zln(2,k)+zz(4)*zln(4,k)
4499 200 continue
4500  diag(1,ic)=diag(1,ic)-t(1)
4501  diag(2,ic)=diag(2,ic)-t(2)
4502  diag(3,ic)=diag(3,ic)-t(3)
4503  call inv2(diag(:,ic),ir)
4504  nch(ic)=-1
4505  kk=par(ic)
4506  nch(kk)=nch(kk)-1
4507  return
4508  end subroutine s2um
4509 
4510  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4511 
4512  subroutine s2um1(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4513 
4514  implicit none
4515 
4516  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),nch(:),par(:)
4517  real(kind=kreal), intent(in) :: diag(:,:) !zln(4,*),diag(3,*)
4518  real(kind=kreal), intent(inout) :: zln(:,:)
4519  integer(kind=kint), intent(in) :: ic,neqns
4520 
4521  integer(kind=kint) :: j,k,l,ks,ke,jc,jj, ierr
4522  real(kind=kreal) :: s(4)
4523  real(kind=kreal), allocatable :: temp(:,:)
4524  integer(kind=kint), allocatable :: indx(:)
4525 
4526  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4527  if(ierr .ne. 0) then
4528  call errtrp('stop due to allocation error.')
4529  end if
4530 
4531  ks=xlnzr(ic)
4532  ke=xlnzr(ic+1)
4533  do 100 l=1,4
4534  s(l)=0.0d0
4535 100 continue
4536  do 200 k=ks,ke-1
4537  jc=colno(k)
4538  indx(jc)=ic
4539  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4540  j=colno(jj)
4541  if(indx(j).eq.ic) then
4542  s(1)=s(1)+temp(1,j)*zln(1,jj)+temp(3,j)*zln(3,jj)
4543  s(2)=s(2)+temp(2,j)*zln(1,jj)+temp(4,j)*zln(3,jj)
4544  s(3)=s(3)+temp(1,j)*zln(2,jj)+temp(3,j)*zln(4,jj)
4545  s(4)=s(4)+temp(2,j)*zln(2,jj)+temp(4,j)*zln(4,jj)
4546  endif
4547 310 continue
4548  do 320 l=1,4
4549  temp(l,jc)=zln(l,k)-s(l)
4550  zln(l,k)=temp(l,jc)
4551  s(l)=0.0d0
4552 320 continue
4553 200 continue
4554  return
4555  end subroutine s2um1
4556 
4557  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4558 
4559  subroutine s2um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
4560 
4561  implicit none
4562 
4563  integer(kind=kint), intent(in) :: neqns, nstop
4564  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
4565  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:)!zln(4,*),diag(3,*)
4566  integer(kind=kint), pointer :: spdslnidx(:)
4567  real(kind=kreal), pointer :: spdslnval(:,:)
4568  integer(kind=kint), intent(out) :: nspdsln
4569 
4570  integer(kind=kint) :: j,k, ic,ks,ke,jj,jc,j1,j2,loc,ispdsln, ierr
4571  real(kind=kreal), allocatable :: temp(:,:)
4572  integer(kind=kint), allocatable :: indx(:)
4573  logical :: ftflag
4574 
4575  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4576  if(ierr .ne. 0) then
4577  call errtrp('stop due to allocation error.')
4578  end if
4579 
4580  nspdsln=0
4581  do ic=nstop,neqns
4582  ks=xlnzr(ic)
4583  ke=xlnzr(ic+1)-1
4584  do k=ks,ke
4585  jj=colno(k)
4586  indx(jj)=ic
4587  end do
4588  do jc=nstop,ic-1
4589  j1=xlnzr(jc)
4590  j2=xlnzr(jc+1)
4591  do jj=xlnzr(jc),xlnzr(jc+1)-1
4592  j=colno(jj)
4593  if(indx(j).eq.ic) then
4594  nspdsln=nspdsln+1
4595  exit
4596  endif
4597  end do
4598  end do
4599  end do
4600  allocate(spdslnidx(nspdsln),spdslnval(4,nspdsln), stat=ierr)
4601  if(ierr .ne. 0) then
4602  call errtrp('stop due to allocation error.')
4603  end if
4604 
4605  loc=0
4606  ispdsln=0
4607  spdslnval=0
4608  ftflag = .true.
4609  do 100 ic=nstop,neqns
4610  ks=xlnzr(ic)
4611  ke=xlnzr(ic+1)-1
4612  do 110 k=ks,ke
4613  jj=colno(k)
4614  temp(1,jj)=zln(1,k)
4615  temp(2,jj)=zln(2,k)
4616  temp(3,jj)=zln(3,k)
4617  temp(4,jj)=zln(4,k)
4618  ! call inv22(zln(1,k),temp(1,jj),diag(1,jj))
4619  zln(3,k)=temp(3,jj)-temp(1,jj)*diag(2,jj)
4620  zln(1,k)=temp(1,jj)*diag(1,jj)
4621  zln(3,k)=zln(3,k)*diag(3,jj)
4622  zln(1,k)=zln(1,k)-zln(3,k)*diag(2,jj)
4623  !
4624  zln(4,k)=temp(4,jj)-temp(2,jj)*diag(2,jj)
4625  zln(2,k)=temp(2,jj)*diag(1,jj)
4626  zln(4,k)=zln(4,k)*diag(3,jj)
4627  zln(2,k)=zln(2,k)-zln(4,k)*diag(2,jj)
4628  !
4629  diag(1,ic)=diag(1,ic)-(temp(1,jj)*zln(1,k)+temp(3,jj)*zln(3,k))
4630  diag(2,ic)=diag(2,ic)-(temp(1,jj)*zln(2,k)+temp(3,jj)*zln(4,k))
4631  diag(3,ic)=diag(3,ic)-(temp(2,jj)*zln(2,k)+temp(4,jj)*zln(4,k))
4632  indx(jj)=ic
4633 110 continue
4634  do 120 jc=nstop,ic-1
4635  loc=loc+1
4636  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
4637  j=colno(jj)
4638  if(indx(j).eq.ic) then
4639  if (ftflag) then
4640  ispdsln=ispdsln+1
4641  ftflag=.false.
4642  end if
4643  spdslnidx(ispdsln)=loc
4644  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-(temp(1,j)*zln(1,jj)+temp(3,j)*zln(3,jj))
4645  spdslnval(2,ispdsln)=spdslnval(2,ispdsln)-(temp(2,j)*zln(1,jj)+temp(4,j)*zln(3,jj))
4646  spdslnval(3,ispdsln)=spdslnval(3,ispdsln)-(temp(1,j)*zln(2,jj)+temp(3,j)*zln(4,jj))
4647  spdslnval(4,ispdsln)=spdslnval(4,ispdsln)-(temp(2,j)*zln(2,jj)+temp(4,j)*zln(4,jj))
4648  endif
4649 220 continue
4650  ftflag = .true.
4651 120 continue
4652 100 continue
4653  return
4654  end subroutine s2um2_child
4655 
4656  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4657 
4658  subroutine inv22(zln,zz,diag)
4659 
4660  implicit none
4661 
4662  real(kind=kreal), intent(in) :: zz(4),diag(3)
4663  real(kind=kreal), intent(out) :: zln(4)
4664 
4665  zln(3)=zz(3)-zz(1)*diag(2)
4666  zln(1)=zz(1)*diag(1)
4667  zln(3)=zln(3)*diag(3)
4668  zln(1)=zln(1)-zln(3)*diag(2)
4669 
4670  zln(4)=zz(4)-zz(2)*diag(2)
4671  zln(2)=zz(2)*diag(1)
4672  zln(4)=zln(4)*diag(3)
4673  zln(2)=zln(2)-zln(4)*diag(2)
4674 
4675  return
4676  end subroutine inv22
4677 
4678  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4679 
4680  subroutine inv2(dsln,ir)
4681 
4682  implicit none
4683 
4684  real(kind=kreal), intent(inout) :: dsln(3)
4685  integer(kind=kint), intent(out) :: ir
4686 
4687  real(kind=kreal) :: t
4688 
4689  ir=0
4690  if(dabs(dsln(1)).lt.rmin) then
4691  ir=10
4692  return
4693  endif
4694  dsln(1)=1.0d0/dsln(1)
4695  t=dsln(2)*dsln(1)
4696  dsln(3)=dsln(3)-t*dsln(2)
4697  dsln(2)=t
4698  if(dabs(dsln(3)).lt.rmin) then
4699  ir=10
4700  return
4701  endif
4702  dsln(3)=1.0d0/dsln(3)
4703  return
4704  end subroutine inv2
4705 
4706  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4707 
4708 
4709  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4710 
4711  subroutine s2pdot(bi,b,zln,colno,ks,ke)
4712 
4713  implicit none
4714 
4715  integer(kind=kint), intent(in) :: colno(:)
4716  integer(kind=kint), intent(in) :: ks,ke
4717  real(kind=kreal), intent(in) :: zln(:,:),b(:,:) !zln(4,*),b(2,*),bi(2)
4718  real(kind=kreal), intent(inout) :: bi(:) !zln(4,*),b(2,*),bi(2)
4719 
4720  integer(kind=kint) :: jj,j
4721 
4722  !----------------------------------------------------------------------
4723  !
4724  ! s2pdot performs inner product of sparse vectors
4725  !
4726  !
4727  ! #coded by t.arakawa
4728  !
4729  !----------------------------------------------------------------------
4730 
4731  do 100 jj=ks,ke
4732  j=colno(jj)
4733  bi(1)=bi(1)-zln(1,jj)*b(1,j)-zln(3,jj)*b(2,j)
4734  bi(2)=bi(2)-zln(2,jj)*b(1,j)-zln(4,jj)*b(2,j)
4735 100 continue
4736  return
4737  end subroutine s2pdot
4738 
4739  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4740 
4741  subroutine addrx(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ndeg,ndeg2,ndeg2l,ir)
4742 
4743  implicit none
4744 
4745  integer(kind=kint), intent(in) :: invp(*),xlnzr(*),colno(*)
4746  real(kind=kreal), intent(in) :: aij(ndeg,ndeg)
4747  real(kind=kreal), intent(inout) :: zln(ndeg,ndeg,*),diag(ndeg2l,*),dsln(ndeg,ndeg,*)
4748  integer(kind=kint), intent(in) :: isw,i,j,nstop,ndeg,ndeg2,ndeg2l
4749  integer(kind=kint), intent(out) :: ir
4750 
4751  integer(kind=kint) :: ii,jj,k,l,m,n,ks,ke,itrans,i0,j0
4752 
4753  ir=0
4754  ii=invp(i)
4755  jj=invp(j)
4756  if(ldbg) write(idbg,*) 'addrx',ii,jj,aij
4757  if(ii.eq.jj) then
4758  l=0
4759  do 100 n=1,ndeg
4760  do 110 m=1,n
4761  l=l+1
4762  diag(l,ii)=aij(n,m)
4763 110 continue
4764 100 continue
4765  goto 1000
4766  endif
4767  itrans=0
4768  if(jj.gt.ii) then
4769  k=jj
4770  jj=ii
4771  ii=k
4772  itrans=1
4773  endif
4774  if(jj.ge.nstop) then
4775  i0=ii-nstop
4776  j0=jj-nstop+1
4777  k=i0*(i0-1)/2+j0
4778  if(itrans.eq.0) then
4779  do 120 m=1,ndeg
4780  do 130 n=1,ndeg
4781  dsln(n,m,k)=aij(n,m)
4782 130 continue
4783 120 continue
4784  goto 1000
4785  else
4786  do 140 m=1,ndeg
4787  do 150 n=1,ndeg
4788  dsln(n,m,k)=aij(m,n)
4789 150 continue
4790 140 continue
4791  goto 1000
4792  endif
4793  endif
4794  ks=xlnzr(ii)
4795  ke=xlnzr(ii+1)-1
4796  do 200 k=ks,ke
4797  if(colno(k).eq.jj) then
4798  if(itrans.eq.0) then
4799  do 160 m=1,ndeg
4800  do 170 n=1,ndeg
4801  zln(n,m,k)=aij(n,m)
4802 170 continue
4803 160 continue
4804  else
4805  do 180 m=1,ndeg
4806  do 190 n=1,ndeg
4807  zln(n,m,k)=aij(m,n)
4808 190 continue
4809 180 continue
4810  endif
4811  goto 1000
4812  endif
4813 200 continue
4814  ir=20
4815 1000 continue
4816  return
4817  end subroutine addrx
4818 
4819  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4820 
4821  subroutine dxdot(ndeg,t,a,b,l)
4822 
4823  implicit none
4824 
4825  real(kind=kreal), intent(in) :: a(ndeg,ndeg,*),b(ndeg,ndeg,*)
4826  real(kind=kreal), intent(out) :: t(ndeg,ndeg)
4827  integer(kind=kint), intent(in) :: ndeg,l
4828 
4829  integer(kind=kint) :: k,jj,n,m
4830  !
4831  !----------------------------------------------------------------------
4832  !
4833  ! spdot1 performs inner product of sparse vectors
4834  !
4835  !
4836  ! #coded by t.arakawa
4837  !
4838  !----------------------------------------------------------------------
4839  !
4840  do n=1,ndeg
4841  do m=1,ndeg
4842  t(n,m)=0.0d0
4843  do k=1,ndeg
4844  do jj=1,l
4845  t(n,m)=t(n,m)+a(n,k,jj)*b(m,k,jj)
4846  enddo
4847  enddo
4848  enddo
4849  enddo
4850  return
4851  end subroutine dxdot
4852 
4853  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4854 
4855  subroutine dxdotl(ndeg,t,a,b,l)
4856 
4857  implicit none
4858 
4859  real(kind=kreal), intent(in) :: a(ndeg,ndeg,*),b(ndeg,ndeg,*)
4860  real(kind=kreal), intent(out) :: t(ndeg,ndeg)
4861  integer(kind=kint), intent(in) :: ndeg,l
4862 
4863  integer(kind=kint) :: n,m,jj,k
4864  !
4865  !----------------------------------------------------------------------
4866  !
4867  ! spdot1 performs inner product of sparse vectors
4868  !
4869  !
4870  ! #coded by t.arakawa
4871  !
4872  !----------------------------------------------------------------------
4873  !
4874  do n=1,ndeg
4875  do m=1,n
4876  t(n,m)=0.0d0
4877  do k=1,ndeg
4878  do jj=1,l
4879  t(n,m)=t(n,m)+a(n,k,jj)*b(m,k,jj)
4880  enddo
4881  enddo
4882  enddo
4883  enddo
4884  return
4885  end subroutine dxdotl
4886 
4887  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4888 
4889  subroutine dxsdot(ndeg,wi,a,b,n)
4890 
4891  implicit none
4892 
4893  real(kind=kreal), intent(in) :: a(ndeg,*),b(ndeg,ndeg,*)
4894  real(kind=kreal), intent(inout) :: wi(ndeg)
4895  integer(kind=kint), intent(in) :: ndeg, n
4896 
4897  integer(kind=kint) :: jj, k, l
4898  !
4899  !----------------------------------------------------------------------
4900  !
4901  ! dxsdot performs inner product of dens vectors
4902  !
4903  !
4904  ! #coded by t.arakawa
4905  ! #reviced by t.kitayama 20071122
4906  !
4907  !----------------------------------------------------------------------
4908  !
4909  do jj=1,n
4910  do k=1,ndeg
4911  do l=1,ndeg
4912  wi(l)=wi(l)-b(l,k,jj)*a(k,jj)
4913  end do
4914  end do
4915  end do
4916  return
4917  end subroutine dxsdot
4918 
4919  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4920 
4921  subroutine invx(dsln,ndeg,ir)
4922 
4923  implicit none
4924 
4925  real(kind=kreal), intent(inout) :: dsln(*)
4926  integer(kind=kint), intent(in) :: ndeg
4927  integer(kind=kint), intent(out) :: ir
4928 
4929  integer(kind=kint) :: i,j,k,l,ld,l0,k0,ll
4930  real(kind=kreal) :: tem,t
4931 
4932  ir=0
4933  l=1
4934  dsln(1)=1.0d0/dsln(1)
4935  do 100 i=2,ndeg
4936  ld=0
4937  l0=l
4938  do 110 j=1,i-1
4939  l=l+1
4940  do 120 k=1,j-1
4941  ld=ld+1
4942  dsln(l)=dsln(l)-dsln(l0+k)*dsln(ld)
4943 120 continue
4944  ld=ld+1
4945 110 continue
4946  t=0.0d0
4947  k0=0
4948  ll=0
4949  do 130 k=l-i+2,l
4950  ll=ll+1
4951  k0=k0+ll
4952  tem=dsln(k)*dsln(k0)
4953  t=t+tem*dsln(k)
4954  dsln(k)=tem
4955 130 continue
4956  l=l+1
4957  dsln(l)=dsln(l)-t
4958  dsln(l)=1.0d0/dsln(l)
4959 100 continue
4960  return
4961  end subroutine invx
4962 
4963  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4964 
4965  subroutine invxx(zln,zz,diag,ndeg)
4966 
4967  implicit none
4968 
4969  real(kind=kreal), intent(in) :: zz(ndeg,ndeg),diag(*)
4970  real(kind=kreal), intent(out) :: zln(ndeg,ndeg)
4971  integer(kind=kint), intent(in) :: ndeg
4972 
4973  integer(kind=kint) :: l,m,n,loc,loc1
4974 
4975  zln=zz
4976  do l=1,ndeg
4977  loc=0
4978  do m=1,ndeg
4979  loc=loc+m
4980  loc1=loc+m
4981  do n=m+1,ndeg
4982  zln(l,n)=zln(l,n)-zln(l,m)*diag(loc1)
4983  loc1=loc1+n
4984  enddo
4985  enddo
4986  loc=0
4987  do m=1,ndeg
4988  loc=loc+m
4989  zln(l,m)=zln(l,m)*diag(loc)
4990  enddo
4991  do n=ndeg,1,-1
4992  loc=loc-1
4993  do m=n-1,1,-1
4994  zln(l,m)=zln(l,m)-zln(l,n)*diag(loc)
4995  loc=loc-1
4996  enddo
4997  enddo
4998  enddo
4999  return
5000  end subroutine invxx
5001 
5002  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5003 
5004  subroutine sxpdot(ndeg,bi,b,zln,colno,ks,ke)
5005 
5006  implicit none
5007 
5008  integer(kind=kint), intent(in) :: colno(*)
5009  real(kind=kreal), intent(in) :: zln(ndeg,ndeg,*),b(ndeg,*)
5010  real(kind=kreal), intent(inout) :: bi(ndeg)
5011  integer(kind=kint),intent(in) :: ndeg,ks,ke
5012 
5013  integer(kind=kint) :: j,jj,m,n
5014  !
5015  !----------------------------------------------------------------------
5016  !
5017  ! sxpdot performs inner product of sparse vectors
5018  !
5019  !
5020  ! #coded by t.arakawa
5021  !
5022  !----------------------------------------------------------------------
5023  !
5024  do jj=ks,ke
5025  j=colno(jj)
5026  do m=1,ndeg
5027  do n=1,ndeg
5028  bi(n)=bi(n)-zln(n,m,jj)*b(m,j)
5029  enddo
5030  enddo
5031  enddo
5032  return
5033  end subroutine sxpdot
5034 
5035  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5036 
5037  subroutine sxum(ic,xlnzr,colno,zln,diag,nch,par,neqns,ndeg,ndegl)
5038 
5039  implicit none
5040 
5041  integer(kind=kint), intent(in) :: xlnzr(*),colno(*),par(*)
5042  integer(kind=kint), intent(inout) :: nch(*)
5043  real(kind=kreal), intent(inout) :: zln(ndeg,ndeg,*),diag(ndegl,*)
5044  integer(kind=kint), intent(in) :: ic,neqns,ndeg,ndegl
5045 
5046  real(kind=kreal) :: zz(ndeg,ndeg),t(ndegl)
5047  integer(kind=kint) :: j,k,m,n,ndeg22,ks,ke,jc,loc,jj,kk,ir, ierr
5048  real(kind=kreal),allocatable :: temp(:,:,:)
5049  integer(kind=kint),allocatable :: indx(:)
5050 
5051  ndeg22=ndeg*ndeg
5052  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5053  if(ierr .ne. 0) then
5054  call errtrp('stop due to allocation error.')
5055  end if
5056 
5057  ks=xlnzr(ic)
5058  ke=xlnzr(ic+1)
5059  t=0.0
5060 
5061  do k=ks,ke-1
5062  jc=colno(k)
5063  indx(jc)=ic
5064  zz=zln(:,:,k)
5065  do jj=xlnzr(jc),xlnzr(jc+1)-1
5066  j=colno(jj)
5067  if(indx(j).eq.ic) then
5068  do m=1,ndeg
5069  do n=1,ndeg
5070  do kk=1,ndeg
5071  zz(n,m)=zz(n,m)-temp(n,kk,j)*zln(m,kk,jj)
5072  enddo
5073  enddo
5074  enddo
5075  endif
5076  enddo
5077  call invxx(zln(1,1,k),zz,diag(1,jc),ndeg)
5078  temp(:,:,jc)=zz
5079  loc=0
5080  do n=1,ndeg
5081  do m=1,n
5082  loc=loc+1
5083  do kk=1,ndeg
5084  t(loc)=t(loc)+zz(n,kk)*zln(m,kk,k)
5085  enddo
5086  enddo
5087  enddo
5088  enddo
5089  diag(:,ic)=diag(:,ic)-t
5090  call invx(diag(1,ic),ndeg,ir)
5091  nch(ic)=-1
5092  kk=par(ic)
5093  nch(kk)=nch(kk)-1
5094  return
5095  end subroutine sxum
5096 
5097  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5098 
5099  subroutine sxum1(ic,xlnzr,colno,zln,diag,nch,par,neqns,ndeg,ndegl)
5100 
5101  implicit none
5102 
5103  integer(kind=kint), intent(in) :: xlnzr(*),colno(*),nch(*),par(*)
5104  real(kind=kreal), intent(in) :: diag(ndegl,*)
5105  real(kind=kreal), intent(inout) :: zln(ndeg,ndeg,*)
5106  integer(kind=kint), intent(in) :: ic,neqns,ndeg,ndegl
5107 
5108  real(kind=kreal) :: s(ndeg,ndeg)
5109  integer(kind=kint) :: j,k,m,n,ks,ke,jc,jj,kk, ierr
5110  real(kind=kreal),allocatable :: temp(:,:,:)
5111  integer(kind=kint),allocatable :: indx(:)
5112 
5113  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5114  if(ierr .ne. 0) then
5115  call errtrp('stop due to allocation error.')
5116  end if
5117  ks=xlnzr(ic)
5118  ke=xlnzr(ic+1)
5119  do m=1,ndeg
5120  do n=1,ndeg
5121  s(n,m)=0.0d0
5122  enddo
5123  enddo
5124  do k=ks,ke-1
5125  jc=colno(k)
5126  indx(jc)=ic
5127  do jj=xlnzr(jc),xlnzr(jc+1)-1
5128  j=colno(jj)
5129  if(indx(j).eq.ic) then
5130  do m=1,ndeg
5131  do n=1,ndeg
5132  do kk=1,ndeg
5133  s(n,m)=s(n,m)+temp(n,kk,j)*zln(m,kk,jj)
5134  enddo
5135  enddo
5136  enddo
5137  endif
5138  enddo
5139  do m=1,ndeg
5140  do n=1,ndeg
5141  temp(n,m,jc)=zln(n,m,k)-s(n,m)
5142  zln(n,m,k)=temp(n,m,jc)
5143  s(n,m)=0.0d0
5144  enddo
5145  enddo
5146  enddo
5147  return
5148  end subroutine sxum1
5149 
5150  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5151 
5152  subroutine sxum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln,ndeg,ndegl)
5153 
5154  implicit none
5155 
5156  integer(kind=kint), intent(in) :: neqns, nstop
5157  integer(kind=kint), intent(in) :: xlnzr(*),colno(*)
5158  real(kind=kreal), intent(inout) :: zln(ndeg,ndeg,*),diag(ndegl,*)
5159  integer(kind=kint), pointer :: spdslnidx(:)
5160  real(kind=kreal), pointer :: spdslnval(:,:)
5161  integer(kind=kint), intent(out) :: nspdsln
5162  integer(kind=kint), intent(in) :: ndeg, ndegl
5163 
5164  integer(kind=kint) :: j,k,m,n, ic,ks,ke,jj,jc,j1,j2,loc,locd,kk, ierr
5165  integer(kind=kint) :: ispdsln
5166  real(kind=kreal), allocatable :: temp(:,:,:)
5167  integer(kind=kint), allocatable :: indx(:)
5168  logical :: ftflag
5169 
5170  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5171  if(ierr .ne. 0) then
5172  call errtrp('stop due to allocation error.')
5173  end if
5174 
5175  nspdsln=0
5176  do ic=nstop,neqns
5177  ks=xlnzr(ic)
5178  ke=xlnzr(ic+1)-1
5179  do k=ks,ke
5180  jj=colno(k)
5181  indx(jj)=ic
5182  end do
5183  do jc=nstop,ic-1
5184  j1=xlnzr(jc)
5185  j2=xlnzr(jc+1)
5186  do jj=xlnzr(jc),xlnzr(jc+1)-1
5187  j=colno(jj)
5188  if(indx(j).eq.ic) then
5189  nspdsln=nspdsln+1
5190  exit
5191  endif
5192  end do
5193  end do
5194  end do
5195  allocate(spdslnidx(nspdsln),spdslnval(ndeg*ndeg,nspdsln), stat=ierr)
5196  if(ierr .ne. 0) then
5197  call errtrp('stop due to allocation error.')
5198  end if
5199 
5200  loc=0
5201  ispdsln=0
5202  spdslnval=0
5203  ftflag = .true.
5204  do ic=nstop,neqns
5205  ks=xlnzr(ic)
5206  ke=xlnzr(ic+1)-1
5207  do k=ks,ke
5208  jj=colno(k)
5209  do m=1,ndeg
5210  do n=1,ndeg
5211  temp(n,m,jj)=zln(n,m,k)
5212  indx(jj)=ic
5213  enddo
5214  enddo
5215  enddo
5216  do k=ks,ke
5217  jj=colno(k)
5218  call invxx(zln(1,1,k),temp(1,1,jj),diag(1,jj),ndeg)
5219  enddo
5220  !
5221  locd=0
5222  do n=1,ndeg
5223  do m=1,n
5224  locd=locd+1
5225  do k=ks,ke
5226  jj=colno(k)
5227  do kk=1,ndeg
5228  diag(locd,ic)=diag(locd,ic)-temp(n,kk,jj)*zln(m,kk,k)
5229  enddo
5230  enddo
5231  enddo
5232  enddo
5233  do jc=nstop,ic-1
5234  loc=loc+1
5235  j1=xlnzr(jc)
5236  j2=xlnzr(jc+1)
5237  do jj=xlnzr(jc),xlnzr(jc+1)-1
5238  j=colno(jj)
5239  if(indx(j).eq.ic) then
5240  if (ftflag) then
5241  ispdsln=ispdsln+1
5242  ftflag=.false.
5243  end if
5244  spdslnidx(ispdsln)=loc
5245  do m=1,ndeg
5246  do n=1,ndeg
5247  do k=1,ndeg
5248  spdslnval(ndeg*(m-1)+n,ispdsln)=spdslnval(ndeg*(m-1)+n,ispdsln)-temp(n,k,j)*zln(m,k,jj)
5249  enddo
5250  enddo
5251  enddo
5252  endif
5253  enddo
5254  ftflag = .true.
5255  enddo
5256  enddo
5257  return
5258  end subroutine sxum2_child
5259 
5260  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5261 
5262  subroutine sxum3(neqns,dsln,diag,ndeg,ndegl)
5263 
5264  implicit none
5265 
5266  real(kind=kreal), intent(inout):: dsln(ndeg,ndeg,*),diag(ndegl,*)
5267  integer(kind=kint), intent(in) :: neqns, ndeg, ndegl
5268 
5269  integer(kind=kint) :: loc, locd, ir, i,j,n,m, ierr
5270  integer(kind=kint), allocatable :: indx(:)
5271  real(kind=kreal), allocatable :: temp(:,:,:)
5272  real(kind=kreal), allocatable :: t(:,:)
5273 
5274  allocate(indx(neqns),temp(ndeg,ndeg,neqns),t(ndeg,ndeg), stat=ierr)
5275  if(ierr .ne. 0) then
5276  call errtrp('stop due to allocation error.')
5277  end if
5278 
5279  if(neqns.le.0) goto 1000
5280  indx(1)=1 ! it will work...
5281  loc=1
5282  call invx(diag(1,1),ndeg,ir)
5283  do i=2,neqns
5284  indx(i)=loc
5285  do j=1,i-1
5286  call dxdot(ndeg,t,dsln(1,1,indx(i)),dsln(1,1,indx(j)),j-1)
5287  do m=1,ndeg
5288  do n=1,ndeg
5289  dsln(n,m,loc)=dsln(n,m,loc)-t(n,m)
5290  enddo
5291  enddo
5292  loc=loc+1
5293  enddo
5294  call vxprod(ndeg,ndegl,dsln(1,1,indx(i)),diag,temp,i-1)
5295  call dxdotl(ndeg,t,temp,dsln(1,1,indx(i)),i-1)
5296  locd=0
5297  do n=1,ndeg
5298  do m=1,n
5299  locd=locd+1
5300  diag(locd,i)=diag(locd,i)-t(n,m)
5301  enddo
5302  enddo
5303  call vcopy(temp,dsln(1,1,indx(i)),ndeg*ndeg*(i-1))
5304  call invx(diag(1,i),ndeg,ir)
5305  enddo
5306 1000 continue
5307  return
5308  end subroutine sxum3
5309 
5310  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5311  subroutine vcopy(a,c,n)
5312  implicit none
5313 
5314  integer(kind=kint) :: n
5315  real(kind=kreal) :: a(n),c(n)
5316  ! do 100 i=1,n
5317  ! c(i)=a(i)
5318  ! 100 continue
5319  c=a
5320  return
5321  end subroutine vcopy
5322 
5323  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5324 
5325  subroutine verif0(neqns,ndeg,nttbr,irow,jcol,val,rhs,x)
5326 
5327  implicit none
5328 
5329  integer(kind=kint), intent(in) :: irow(*),jcol(*)
5330  integer(kind=kint), intent(in) :: neqns,ndeg,nttbr
5331  real(kind=kreal), intent(in) :: val(ndeg,ndeg,*),x(ndeg,*)
5332  real(kind=kreal), intent(inout) :: rhs(ndeg,*)
5333 
5334  integer(kind=kint) :: i,j,k,l,m
5335  real(kind=kreal) :: rel,err
5336  !
5337  !----------------------------------------------------------------------
5338  !
5339  ! verify the solution(symmetric matrix)
5340  !
5341  !----------------------------------------------------------------------
5342  !
5343  rel=0.0d0
5344  do i=1,neqns
5345  do l=1,ndeg
5346  rel=rel+dabs(rhs(l,i))
5347  enddo
5348  enddo
5349  do k=1,nttbr
5350  i=irow(k)
5351  j=jcol(k)
5352  do l=1,ndeg
5353  do m=1,ndeg
5354  rhs(l,i)=rhs(l,i)-val(l,m,k)*x(m,j)
5355  if(i.ne.j) rhs(l,j)=rhs(l,j)-val(m,l,k)*x(m,i)
5356  enddo
5357  enddo
5358  enddo
5359  err=0.0d0
5360  do i=1,neqns
5361  do l=1,ndeg
5362  err=err+dabs(rhs(l,i))
5363  enddo
5364  enddo
5365  if (m_pds_procinfo%myid .eq. 0) then
5366  write(imsg,6000) err,rel,err/rel
5367  end if
5368 6000 format(' ***verification***(symmetric)'/&
5369  & 'norm(Ax-b) = ',1pd20.10/&
5370  & 'norm(b) = ',1pd20.10/&
5371  & 'norm(Ax-b)/norm(b) = ',1pd20.10)
5372 6010 format(1p4d15.7)
5373  return
5374  end subroutine verif0
5375 
5376  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5377 
5378  subroutine vxprod(ndeg,ndegl,zln,diag,zz,n)
5379 
5380  implicit none
5381 
5382  real(kind=kreal), intent(in) :: zln(ndeg*ndeg,n),diag(ndegl,n)
5383  real(kind=kreal), intent(out) :: zz(ndeg*ndeg,n)
5384  integer(kind=kint), intent(in) :: ndeg,ndegl,n
5385 
5386  integer(kind=kint) :: i
5387 
5388  do 100 i=1,n
5389  call invxx(zz(1,i),zln(1,i),diag(1,i),ndeg)
5390 100 continue
5391  return
5392  end subroutine vxprod
5393 
5394  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5395 
5396 #endif
5397 
subroutine, public hecmw_mat_dump(hecMAT, hecMESH)
subroutine, public hecmw_mat_dump_solution(hecMAT)
subroutine nusol3_child(xlnzr, colno, zln, diag, iperm, b, neqns, nstop)
subroutine nusolx_child(xlnzr, colno, zln, diag, iperm, b, neqns, nstop, ndeg)
subroutine, public hecmw_solve_direct_parallel(hecMESH, hecMAT, ii)
I/O and Utility.
Definition: hecmw_util_f.F90:7
subroutine hecmw_abort(comm, code)
integer(kind=kint) function hecmw_comm_get_comm()
integer(kind=4), parameter kreal
real(kind=kreal) function hecmw_wtime()
subroutine, public symbolicirjctocrs(ndeg, nttbr, irow, jcol, ncols, nrows, c)
Definition: m_elap.F90:7
subroutine, public initelap(t, i)
Definition: m_elap.F90:22
subroutine, public elapout(mes)
Definition: m_elap.F90:34
subroutine, public reovec(r, iperm)
subroutine, public matrix_partition_recursive_bisection(a0, ndiv, pmi)