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