FrontISTR  5.7.1
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  subroutine nusol2_parent(dsln, diag, b, neqns)
1975  ! solve Ax=b for dens matrix with ndeg=3
1976  ! require dsln, diag is already LDU decomposed.
1977 
1978  implicit none
1979 
1980  real(kind=kreal), intent(in) :: dsln(:,:) !(4, (neqns+1)*newns/2)
1981  real(kind=kreal), intent(in) :: diag(:,:) !(3,neqns)
1982  real(kind=kreal), intent(inout) :: b(:,:) !(2,neqns)
1983  integer(kind=kint), intent(in) :: neqns
1984 
1985  integer(kind=kint) :: i,j,k,l,loc
1986 
1987  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1988  !
1989  ! STEP22 forward substitution
1990  !
1991  do i=2,neqns
1992  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
1993  call d2sdot(b(:,i),b,dsln(:, k:k+i-2),i-1)
1994  end do
1995 
1996  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1997  !
1998  ! STEP23 divide Yd by diagonal element of D and get Zi=Yi/Di
1999  !
2000  do i=1,neqns
2001  b(2,i)=b(2,i)-b(1,i)*diag(2,i)
2002  b(1,i)=b(1,i)*diag(1,i)
2003  b(2,i)=b(2,i)*diag(3,i)
2004  b(1,i)=b(1,i)-b(2,i)*diag(2,i)
2005  end do
2006 
2007  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2008  !
2009  ! STEP24 Backward substitution.
2010  ! Substitute Zi into D and get Xd results.
2011  !
2012  loc=(neqns-1)*neqns/2
2013  do i=neqns,1,-1
2014  do j=i-1,1,-1
2015  b(1,j)=b(1,j)-b(1,i)*dsln(1,loc)-b(2,i)*dsln(2,loc)
2016  b(2,j)=b(2,j)-b(1,i)*dsln(3,loc)-b(2,i)*dsln(4,loc)
2017  loc=loc-1
2018  end do
2019  end do
2020 
2021  return
2022 
2023  end subroutine nusol2_parent
2024 
2025  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2026 
2027  subroutine nusol3_parent(dsln, diag, b, neqns)
2028  ! solve Ax=b for dens matrix with ndeg=3
2029  ! require dsln, diag is already LDU decomposed.
2030 
2031  implicit none
2032 
2033  real(kind=kreal), intent(in) :: dsln(:,:) !(9,(neqns+1)*neqns/2)
2034  real(kind=kreal), intent(in) :: diag(:,:) !(6,neqns)
2035  real(kind=kreal), intent(inout) :: b(:,:) !(3,neqns)
2036  integer(kind=kint), intent(in) :: neqns
2037 
2038  integer(kind=kint) :: i,j,k,l,loc
2039 
2040  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2041  !
2042  ! STEP22 forward substitution
2043  !
2044  do i=2,neqns
2045  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
2046  call d3sdot(b(:,i),b,dsln(:, k:k+i-2),i-1)
2047  end do
2048 
2049  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2050  !
2051  ! STEP23 divide Yd by diagonal element of D and get Zi=Yi/Di
2052  !
2053  do i=1,neqns
2054  b(2,i)=b(2,i)-b(1,i)*diag(2,i)
2055  b(3,i)=b(3,i)-b(1,i)*diag(4,i)-b(2,i)*diag(5,i)
2056  b(1,i)=b(1,i)*diag(1,i)
2057  b(2,i)=b(2,i)*diag(3,i)
2058  b(3,i)=b(3,i)*diag(6,i)
2059  b(2,i)=b(2,i)-b(3,i)*diag(5,i)
2060  b(1,i)=b(1,i)-b(2,i)*diag(2,i)-b(3,i)*diag(4,i)
2061  end do
2062 
2063  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2064  !
2065  ! STEP24 Backward substitution.
2066  ! Substitute Zi into D and get Xd results.
2067  !
2068  loc=(neqns-1)*neqns/2
2069  do i=neqns,1,-1
2070  do j=i-1,1,-1
2071  b(1,j)=b(1,j)-b(1,i)*dsln(1,loc)-b(2,i)*dsln(2,loc)-b(3,i)*dsln(3,loc)
2072  b(2,j)=b(2,j)-b(1,i)*dsln(4,loc)-b(2,i)*dsln(5,loc)-b(3,i)*dsln(6,loc)
2073  b(3,j)=b(3,j)-b(1,i)*dsln(7,loc)-b(2,i)*dsln(8,loc)-b(3,i)*dsln(9,loc)
2074  loc=loc-1
2075  end do
2076  end do
2077 
2078  return
2079  end subroutine nusol3_parent
2080 
2081  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2082 
2083  subroutine nusolx_parent (dsln,diag,b,neqns,ndeg)
2084 
2085  implicit none
2086 
2087  real(kind=kreal), intent(in) :: diag(:,:), dsln(:,:)
2088  real(kind=kreal), intent(inout) :: b(:,:)
2089  integer(kind=kint), intent(in) :: neqns, ndeg
2090 
2091  integer(kind=kint) :: i,j,k,l,m,n,loc, locd, loc1
2092 
2093  ! forward
2094  do i=2,neqns
2095  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
2096  call dxsdot(ndeg,b(:,i),b,dsln(:,k:k+i-2),i-1)
2097  end do
2098 
2099  ! divide
2100  do i=1,neqns
2101  locd=0
2102  do m=1,ndeg-1
2103  locd=locd+m
2104  loc1=locd+m
2105  do n=m+1,ndeg
2106  b(n,i)=b(n,i)-b(m,i)*diag(loc1,i)
2107  loc1=loc1+n
2108  end do
2109  end do
2110 
2111  locd=0
2112  do m=1,ndeg
2113  locd=locd+m
2114  b(m,i)=b(m,i)*diag(locd,i)
2115  end do
2116 
2117  do n=ndeg,2,-1
2118  locd=locd-1
2119  do m=n-1,1,-1
2120  b(m,i)=b(m,i)-b(n,i)*diag(locd,i)
2121  locd=locd-1
2122  end do
2123  end do
2124  end do
2125  ! back ward
2126  loc=(neqns-1)*neqns/2
2127  do i=neqns,1,-1
2128  do j=i-1,1,-1
2129  do m=1,ndeg
2130  do n=1,ndeg
2131  b(m,j)=b(m,j)-b(n,i)*dsln((m-1)*ndeg+n,loc)
2132  end do
2133  end do
2134  loc=loc-1
2135  end do
2136  end do
2137  return
2138  end subroutine nusolx_parent
2139 
2140  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2141 
2142  subroutine s3um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
2143 
2144  implicit none
2145 
2146  integer(kind=kint), intent(in) :: neqns, nstop
2147  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
2148  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:) !zln(9,*),diag(6,*),dsln(9,*) !
2149  integer(kind=kint), pointer :: spdslnidx(:)
2150  real(kind=kreal), pointer :: spdslnval(:,:)
2151  integer(kind=kint), intent(out) :: nspdsln
2152 
2153  real(kind=kreal), allocatable :: temp(:,:)
2154  integer(kind=kint), allocatable :: indx(:)
2155  logical :: ftflag
2156  integer(kind=kint) :: i,j,k,l,m,n, ic,ks,ke,ii,jj,jc,j1,j2,loc,ispdsln, ierr
2157 
2158  allocate(temp(neqns,9),indx(neqns), stat=ierr)
2159  if(ierr .ne. 0) then
2160  call errtrp('stop due to allocation error.')
2161  end if
2162 
2163  nspdsln=0
2164  do ic=nstop,neqns
2165  ks=xlnzr(ic)
2166  ke=xlnzr(ic+1)-1
2167  do k=ks,ke
2168  jj=colno(k)
2169  indx(jj)=ic
2170  end do
2171  do jc=nstop,ic-1
2172  j1=xlnzr(jc)
2173  j2=xlnzr(jc+1)
2174  do jj=xlnzr(jc),xlnzr(jc+1)-1
2175  j=colno(jj)
2176  if(indx(j).eq.ic) then
2177  nspdsln=nspdsln+1
2178  exit
2179  endif
2180  end do
2181  end do
2182  end do
2183  allocate(spdslnidx(nspdsln), stat=ierr)
2184  if(ierr .ne. 0) then
2185  call errtrp('stop due to allocation error.')
2186  end if
2187  allocate(spdslnval(9,nspdsln), stat=ierr)
2188  if(ierr .ne. 0) then
2189  call errtrp('stop due to allocation error.')
2190  end if
2191 
2192  loc=0
2193  ispdsln=0
2194  spdslnval=0
2195  ftflag = .true.
2196  do 100 ic=nstop,neqns
2197  ! do 105 m=1,9
2198  ! do 105 jj=1,nstop
2199  ! temp(jj,m)=0.0d0
2200  ! 105 continue
2201  ks=xlnzr(ic)
2202  ke=xlnzr(ic+1)-1
2203  do 110 k=ks,ke
2204  jj=colno(k)
2205  temp(jj,1)=zln(1,k)
2206  temp(jj,2)=zln(2,k)
2207  temp(jj,3)=zln(3,k)
2208  temp(jj,4)=zln(4,k)
2209  temp(jj,5)=zln(5,k)
2210  temp(jj,6)=zln(6,k)
2211  temp(jj,7)=zln(7,k)
2212  temp(jj,8)=zln(8,k)
2213  temp(jj,9)=zln(9,k)
2214  indx(jj)=ic
2215 110 continue
2216  do 111 k=ks,ke
2217  jj=colno(k)
2218  zln(4,k)=temp(jj,4)-temp(jj,1)*diag(2,jj)
2219  zln(7,k)=temp(jj,7)-temp(jj,1)*diag(4,jj)-zln(4,k)*diag(5,jj)
2220  zln(1,k)=temp(jj,1)*diag(1,jj)
2221  zln(4,k)=zln(4,k)*diag(3,jj)
2222  zln(7,k)=zln(7,k)*diag(6,jj)
2223  zln(4,k)=zln(4,k)-zln(7,k)*diag(5,jj)
2224  zln(1,k)=zln(1,k)-zln(4,k)*diag(2,jj)-zln(7,k)*diag(4,jj)
2225  !
2226  zln(5,k)=temp(jj,5)-temp(jj,2)*diag(2,jj)
2227  zln(8,k)=temp(jj,8)-temp(jj,2)*diag(4,jj)-zln(5,k)*diag(5,jj)
2228  zln(2,k)=temp(jj,2)*diag(1,jj)
2229  zln(5,k)=zln(5,k)*diag(3,jj)
2230  zln(8,k)=zln(8,k)*diag(6,jj)
2231  zln(5,k)=zln(5,k)-zln(8,k)*diag(5,jj)
2232  zln(2,k)=zln(2,k)-zln(5,k)*diag(2,jj)-zln(8,k)*diag(4,jj)
2233  !
2234  zln(6,k)=temp(jj,6)-temp(jj,3)*diag(2,jj)
2235  zln(9,k)=temp(jj,9)-temp(jj,3)*diag(4,jj)-zln(6,k)*diag(5,jj)
2236  zln(3,k)=temp(jj,3)*diag(1,jj)
2237  zln(6,k)=zln(6,k)*diag(3,jj)
2238  zln(9,k)=zln(9,k)*diag(6,jj)
2239  zln(6,k)=zln(6,k)-zln(9,k)*diag(5,jj)
2240  zln(3,k)=zln(3,k)-zln(6,k)*diag(2,jj)-zln(9,k)*diag(4,jj)
2241  ! write(60,6000) k,(zln(llll,k),llll=1,9)
2242  !6000 format(i6,3d20.10/6x,3d20.10/6x,3d20.10)
2243 111 continue
2244  !
2245  do 112 k=ks,ke
2246  jj=colno(k)
2247  diag(1,ic)=diag(1,ic)-temp(jj,1)*zln(1,k)-temp(jj,4)*zln(4,k)-temp(jj,7)*zln(7,k)
2248  diag(2,ic)=diag(2,ic)-temp(jj,1)*zln(2,k)-temp(jj,4)*zln(5,k)-temp(jj,7)*zln(8,k)
2249  diag(3,ic)=diag(3,ic)-temp(jj,2)*zln(2,k)-temp(jj,5)*zln(5,k)-temp(jj,8)*zln(8,k)
2250  diag(4,ic)=diag(4,ic)-temp(jj,1)*zln(3,k)-temp(jj,4)*zln(6,k)-temp(jj,7)*zln(9,k)
2251  diag(5,ic)=diag(5,ic)-temp(jj,2)*zln(3,k)-temp(jj,5)*zln(6,k)-temp(jj,8)*zln(9,k)
2252  diag(6,ic)=diag(6,ic)-temp(jj,3)*zln(3,k)-temp(jj,6)*zln(6,k)-temp(jj,9)*zln(9,k)
2253 112 continue
2254  do 120 jc=nstop,ic-1
2255  loc=loc+1
2256  j1=xlnzr(jc)
2257  j2=xlnzr(jc+1)
2258  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
2259  j=colno(jj)
2260  if(indx(j).eq.ic) then
2261  if (ftflag) then
2262  ispdsln=ispdsln+1
2263  ftflag=.false.
2264  end if
2265  spdslnidx(ispdsln)=loc
2266  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-temp(j,1)*zln(1,jj)-temp(j,4)*zln(4,jj)-temp(j,7)*zln(7,jj)
2267  spdslnval(2,ispdsln)=spdslnval(2,ispdsln)-temp(j,2)*zln(1,jj)-temp(j,5)*zln(4,jj)-temp(j,8)*zln(7,jj)
2268  spdslnval(3,ispdsln)=spdslnval(3,ispdsln)-temp(j,3)*zln(1,jj)-temp(j,6)*zln(4,jj)-temp(j,9)*zln(7,jj)
2269  spdslnval(4,ispdsln)=spdslnval(4,ispdsln)-temp(j,1)*zln(2,jj)-temp(j,4)*zln(5,jj)-temp(j,7)*zln(8,jj)
2270  spdslnval(5,ispdsln)=spdslnval(5,ispdsln)-temp(j,2)*zln(2,jj)-temp(j,5)*zln(5,jj)-temp(j,8)*zln(8,jj)
2271  spdslnval(6,ispdsln)=spdslnval(6,ispdsln)-temp(j,3)*zln(2,jj)-temp(j,6)*zln(5,jj)-temp(j,9)*zln(8,jj)
2272  spdslnval(7,ispdsln)=spdslnval(7,ispdsln)-temp(j,1)*zln(3,jj)-temp(j,4)*zln(6,jj)-temp(j,7)*zln(9,jj)
2273  spdslnval(8,ispdsln)=spdslnval(8,ispdsln)-temp(j,2)*zln(3,jj)-temp(j,5)*zln(6,jj)-temp(j,8)*zln(9,jj)
2274  spdslnval(9,ispdsln)=spdslnval(9,ispdsln)-temp(j,3)*zln(3,jj)-temp(j,6)*zln(6,jj)-temp(j,9)*zln(9,jj)
2275  endif
2276 220 continue
2277  ftflag = .true.
2278 120 continue
2279 100 continue
2280  return
2281  end subroutine s3um2_child
2282 
2283  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2284 
2285  subroutine zpivot(neqns,neqnsz,nttbr,jcol,irow,zpiv,ir)
2286 
2287  implicit none
2288 
2289  integer(kind=kint), intent(in) :: jcol(:),irow(:)
2290  integer(kind=kint), intent(out) :: zpiv(:)
2291  integer(kind=kint), intent(in) :: neqns,nttbr
2292  integer(kind=kint), intent(out) :: neqnsz,ir
2293 
2294  integer(kind=kint) :: i,j,k,l
2295 
2296  ir=0
2297  do 100 l=1,neqns
2298  zpiv(l)=1
2299 100 continue
2300 
2301  do 200 l=1,nttbr
2302  i=irow(l)
2303  j=jcol(l)
2304  if(i.le.0.or.j.le.0) then
2305  ir=-1
2306  goto 1000
2307  elseif(i.gt.neqns.or.j.gt.neqns) then
2308  ir=1
2309  goto 1000
2310  endif
2311  if(i.eq.j) zpiv(i)=0
2312 200 continue
2313 
2314  do 310 i=neqns,1,-1
2315  if(zpiv(i).eq.0) then
2316  neqnsz=i
2317  goto 320
2318  endif
2319 310 continue
2320 320 continue
2321 1000 continue
2322  if(ldbg) write(idbg,*) '# zpivot ########################'
2323  if(ldbg) write(idbg,60) (zpiv(i),i=1,neqns)
2324 60 format(20i3)
2325  return
2326  end subroutine zpivot
2327 
2328  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2329 
2330  subroutine stsmat(neqns,nttbr,irow,jcol,jcpt,jcolno)
2331 
2332  implicit none
2333 
2334  integer(kind=kint), intent(in) :: irow(:), jcol(:)
2335  integer(kind=kint), intent(out) :: jcpt(:), jcolno(:)
2336  integer(kind=kint), intent(in) :: neqns, nttbr
2337 
2338  integer(kind=kint) :: i,j,k,l,loc,locr
2339 
2340  do 10 i=1,2*nttbr
2341  jcpt(i)=0
2342  jcolno(i)=0
2343 10 continue
2344  do 20 i=1,neqns
2345  jcpt(i)=i+neqns
2346  jcolno(i+neqns)=i
2347 20 continue
2348 
2349  k=2*neqns
2350  do 100 l=1,nttbr
2351  i=irow(l)
2352  j=jcol(l)
2353  if(i.eq.j) goto 100
2354  loc=jcpt(i)
2355  locr=i
2356 110 continue
2357  if(loc.eq.0) goto 120
2358  if(jcolno(loc).eq.j) then
2359  goto 100
2360  elseif(jcolno(loc).gt.j) then
2361  goto 130
2362  endif
2363  locr=loc
2364  loc=jcpt(loc)
2365  goto 110
2366 120 continue
2367  k=k+1
2368  jcpt(locr)=k
2369  jcolno(k)=j
2370  goto 150
2371 130 continue
2372  k=k+1
2373  jcpt(locr)=k
2374  jcpt(k)=loc
2375  jcolno(k)=j
2376 150 continue
2377  loc=jcpt(j)
2378  locr=j
2379 160 continue
2380  if(loc.eq.0) goto 170
2381  if(jcolno(loc).eq.i) then
2382  goto 100
2383  elseif(jcolno(loc).gt.i) then
2384  goto 180
2385  endif
2386  locr=loc
2387  loc=jcpt(loc)
2388  goto 160
2389 170 continue
2390  k=k+1
2391  jcpt(locr)=k
2392  jcolno(k)=i
2393  goto 100
2394 180 continue
2395  k=k+1
2396  jcpt(locr)=k
2397  jcpt(k)=loc
2398  jcolno(k)=i
2399 100 continue
2400  if(ldbg) then
2401  write(idbg,*) 'jcolno'
2402  write(idbg,60) (jcolno(i),i=1,k)
2403  write(idbg,*) 'jcpt'
2404  write(idbg,60) (jcpt(i),i=1,k)
2405 60 format(10i7)
2406  endif
2407  return
2408  end subroutine stsmat
2409 
2410  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2411  subroutine stiaja(neqns,neqnsz,ia,ja,jcpt,jcolno)
2412 
2413  implicit none
2414  !
2415  ! coded by t.arakawa
2416  !
2417  integer(kind=kint), intent(in) :: jcpt(:),jcolno(:)
2418  integer(kind=kint), intent(out) :: ia(:),ja(:)
2419  integer(kind=kint), intent(in) :: neqns, neqnsz
2420 
2421  integer(kind=kint) :: i,j,k,l,ii,loc
2422  !
2423 
2424  ia(1)=1
2425  l=0
2426  do 100 k=1,neqns
2427  loc=jcpt(k)
2428 110 continue
2429  if(loc.eq.0) goto 120
2430  ii=jcolno(loc)
2431  if(ii.eq.k.or.ii.gt.neqnsz) goto 130
2432  l=l+1
2433  ja(l)=ii
2434 130 continue
2435  loc=jcpt(loc)
2436  goto 110
2437 120 ia(k+1)=l+1
2438 100 continue
2439  if(ldbg) then
2440  write(idbg,*) 'stiaja(): ia '
2441  write(idbg,60) (ia(i),i=1,neqns+1)
2442  write(idbg,*) 'stiaja(): ja '
2443  write(idbg,60) (ja(i),i=1,ia(neqns+1))
2444  endif
2445 60 format(10i7)
2446  return
2447  end subroutine stiaja
2448 
2449  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2450 
2451  subroutine idntty(neqns,invp,iperm)
2452 
2453  implicit none
2454 
2455  integer(kind=kint), intent(out) :: invp(:),iperm(:)
2456  integer(kind=kint), intent(in) :: neqns
2457 
2458  integer(kind=kint) :: i
2459 
2460  do 100 i=1,neqns
2461  invp(i)=i
2462  iperm(i)=i
2463 100 continue
2464  return
2465  end subroutine idntty
2466 
2467  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2468 
2469  subroutine genqmd(neqns,xadj,adj0,perm,invp,deg,marker,rchset,nbrhd,qsize,qlink,nofsub,adjncy)
2470 
2471  implicit none
2472 
2473  integer(kind=kint), intent(in) :: adj0(:),xadj(:)
2474  integer(kind=kint), intent(out) :: rchset(:),nbrhd(:),adjncy(:),perm(:),invp(:),deg(:),marker(:),qsize(:),qlink(:)
2475  integer(kind=kint), intent(in) :: neqns
2476  integer(kind=kint), intent(out) :: nofsub
2477 
2478  integer(kind=kint) :: inode,ip,irch,mindeg,nhdsze,node,np,num,nump1,nxnode,rchsze,search,thresh,ndeg
2479  integer(kind=kint) :: i,j,k,l
2480 
2481  mindeg=neqns
2482  nofsub=0
2483  do 10 i=1,xadj(neqns+1)-1
2484  adjncy(i)=adj0(i)
2485 10 continue
2486  do 100 node=1,neqns
2487  perm(node)=node
2488  invp(node)=node
2489  marker(node)=0
2490  qsize(node)=1
2491  qlink(node)=0
2492  ndeg=xadj(node+1)-xadj(node)
2493  deg(node)=ndeg
2494  if(ndeg.lt.mindeg) mindeg=ndeg
2495 100 continue
2496 
2497  num=0
2498 200 search=1
2499  thresh=mindeg
2500  mindeg=neqns
2501 300 nump1=num+1
2502  if(nump1.gt.search) search=nump1
2503  do 400 j=search,neqns
2504  node=perm(j)
2505  if(marker(node).lt.0) goto 400
2506  ndeg=deg(node)
2507  if(ndeg.le.thresh) goto 500
2508  if(ndeg.lt.mindeg) mindeg=ndeg
2509 400 continue
2510  goto 200
2511 
2512 500 search=j
2513  nofsub=nofsub+deg(node)
2514  marker(node)=1
2515  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
2516  nxnode=node
2517 600 num=num+1
2518  np=invp(nxnode)
2519  ip=perm(num)
2520  perm(np)=ip
2521  invp(ip)=np
2522  perm(num)=nxnode
2523  invp(nxnode)=num
2524  deg(nxnode)=-1
2525  nxnode=qlink(nxnode)
2526  if(nxnode.gt.0) goto 600
2527  if(rchsze.le.0) goto 800
2528  !
2529  call qmdupd(xadj,adjncy,rchsze,rchset,deg,qsize,qlink,marker,rchset(rchsze+1:),nbrhd(nhdsze+1:))
2530  marker(node)=0
2531  do 700 irch=1,rchsze
2532  inode=rchset(irch)
2533  if(marker(inode).lt.0) goto 700
2534  marker(inode)=0
2535  ndeg=deg(inode)
2536  if(ndeg.lt.mindeg) mindeg=ndeg
2537  if(ndeg.gt.thresh) goto 700
2538  mindeg=thresh
2539  thresh=ndeg
2540  search=invp(inode)
2541 700 continue
2542  if(nhdsze.gt.0) call qmdot(node,xadj,adjncy,marker,rchsze,rchset,nbrhd)
2543 800 if(num.lt.neqns) goto 300
2544  return
2545  end subroutine genqmd
2546 
2547  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2548 
2549  subroutine genpaq(xadj,adjncy,invp,iperm,parent,neqns,ancstr)
2550 
2551  implicit none
2552 
2553  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),invp(:),iperm(:)
2554  integer(kind=kint), intent(out) :: parent(:),ancstr(:)
2555  integer(kind=kint), intent(in) :: neqns
2556 
2557  integer(kind=kint) :: i,j,k,l,ip,it
2558 
2559  do 100 i=1,neqns
2560  parent(i)=0
2561  ancstr(i)=0
2562  ip=iperm(i)
2563  do 110 k=xadj(ip),xadj(ip+1)-1
2564  l=invp(adjncy(k))
2565  if(l.ge.i) goto 110
2566 112 continue
2567  if(ancstr(l).eq.0) goto 111
2568  if(ancstr(l).eq.i) goto 110
2569  it=ancstr(l)
2570  ancstr(l)=i
2571  l=it
2572  goto 112
2573 111 continue
2574  ancstr(l)=i
2575  parent(l)=i
2576 110 continue
2577 100 continue
2578  do 200 i=1,neqns
2579  if(parent(i).eq.0) parent(i)=neqns+1
2580 200 continue
2581  parent(neqns+1)=0
2582  if(ldbg) write(idbg,6010)
2583  if(ldbg) write(idbg,6000) (i,parent(i),i=1,neqns)
2584 6000 format(2i6)
2585 6010 format(' parent')
2586  return
2587  end subroutine genpaq
2588 
2589  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2590 
2591  subroutine genbtq(xadj,adjncy,invp,iperm,parent,btree,zpiv,izz,neqns)
2592 
2593  implicit none
2594 
2595  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),invp(:),iperm(:),zpiv(:)
2596  integer(kind=kint), intent(out) :: btree(:,:) ! btree is (2,:)
2597  integer(kind=kint), intent(in) :: neqns
2598  integer(kind=kint), intent(out) :: izz
2599 
2600  integer(kind=kint) :: i,j,k,l,ip,ib,inext
2601 
2602  do 10 i=1,neqns+1
2603  btree(1,i)=0
2604  btree(2,i)=0
2605 10 continue
2606  do 100 i=1,neqns+1
2607  ip=parent(i)
2608  if(ip.le.0) goto 100
2609  ib=btree(1,ip)
2610  if(ib.eq.0) then
2611  btree(1,ip)=i
2612  else
2613 101 continue
2614  inext=btree(2,ib)
2615  if(inext.eq.0) then
2616  btree(2,ib)=i
2617  else
2618  ib=inext
2619  goto 101
2620  endif
2621  endif
2622 100 continue
2623  !
2624  ! find zeropivot
2625  !
2626  do 200 i=1,neqns
2627  if(zpiv(i).ne.0) then
2628  if(btree(1,invp(i)).eq.0) then
2629  izz=i
2630  goto 210
2631  endif
2632  endif
2633 200 continue
2634  izz=0
2635 210 continue
2636  if(ldbg) write(idbg,6010)
2637  if(ldbg) write(idbg,6000) (i,btree(1,i),btree(2,i),i=1,neqns)
2638  if(ldbg) write(idbg,6020) izz
2639  ! if(idbg1.ge.2) write(10,6100) neqns
2640  ! if(idbg1.ge.2) write(10,6100) (btree(1,i),btree(2,i),i=1,neqns)
2641 6000 format(i6,'(',2i6,')')
2642 6010 format(' binary tree')
2643 6020 format(' the first zero pivot is ',i4)
2644 6100 format(2i8)
2645  return
2646  end subroutine genbtq
2647 
2648  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2649 
2650  subroutine rotate(xadj,adjncy,invp,iperm,parent,btree,izz,neqns,anc,adjt,irr)
2651 
2652  implicit none
2653 
2654  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),btree(:,:)
2655  integer(kind=kint), intent(out) :: anc(:),adjt(:),invp(:),iperm(:)
2656  integer(kind=kint), intent(in) :: neqns,izz
2657  integer(kind=kint), intent(out) :: irr
2658 
2659  integer(kind=kint) :: i,j,k,l,izzz,nanc,loc,locc,ll,kk,iy
2660 
2661  !----------------------------------------------------------------------
2662  ! irr return code irr=0 node izz is not a bottom node
2663  ! irr=1 is a bottom node then rotation is
2664  ! performed
2665  !
2666  !----------------------------------------------------------------------
2667  if(izz.eq.0) then
2668  irr=0
2669  return
2670  endif
2671  izzz=invp(izz)
2672  if(btree(1,izzz).ne.0) then
2673  irr=0
2674  ! return
2675  endif
2676  irr=1
2677  !
2678  ! ancestors of izzz
2679  !
2680  nanc=0
2681  loc=izzz
2682 100 continue
2683  nanc=nanc+1
2684  anc(nanc)=loc
2685  loc=parent(loc)
2686  if(loc.ne.0) goto 100
2687  !
2688  ! to find the eligible node from ancestors of izz
2689  !
2690  ! adjt = Adj(Tree(y))
2691  l=1
2692 200 continue
2693  do 210 i=1,neqns
2694  adjt(i)=0
2695 210 continue
2696  locc=anc(l)
2697 220 continue
2698  loc=locc
2699  locc=btree(1,loc)
2700  if(locc.ne.0) goto 220
2701 230 continue
2702  do 240 k=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
2703  adjt(invp(adjncy(k)))=1
2704 240 continue
2705  if(loc.ge.anc(l)) goto 250
2706  locc=btree(2,loc)
2707  if(locc.ne.0) goto 220
2708  loc=parent(loc)
2709  goto 230
2710 250 continue
2711  do 260 ll=l+1,nanc
2712  if(adjt(anc(ll)).eq.0) then
2713  l=l+1
2714  goto 200
2715  endif
2716 260 continue
2717  if(l.eq.1) goto 500
2718 
2719  !
2720  ! anc(l-1) is the eligible node
2721  !
2722  ! (1) number the node not in Ancestor(iy)
2723  iy=anc(l-1)
2724  do 300 i=1,neqns
2725  adjt(i)=0
2726 300 continue
2727  do 310 ll=l,nanc
2728  adjt(anc(ll))=1
2729 310 continue
2730  k=0
2731  do 320 ll=1,neqns
2732  if(adjt(ll).eq.0) then
2733  k=k+1
2734  invp(iperm(ll))=k
2735  endif
2736 320 continue
2737  ! (2) followed by nodes in Ancestor(iy)-Adj(T(iy))
2738 330 continue
2739  do 340 i=1,neqns
2740  adjt(i)=0
2741 340 continue
2742  locc=iy
2743 350 continue
2744  loc=locc
2745  locc=btree(1,loc)
2746  if(locc.ne.0) goto 350
2747 360 continue
2748  do 370 kk=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
2749  adjt(invp(adjncy(kk)))=1
2750 370 continue
2751  if(loc.ge.iy) goto 380
2752  locc=btree(2,loc)
2753  if(locc.ne.0) goto 350
2754  loc=parent(loc)
2755  goto 360
2756 380 continue
2757  do 390 ll=l,nanc
2758  if(adjt(anc(ll)).eq.0) then
2759  k=k+1
2760  invp(iperm(anc(ll)))=k
2761  endif
2762 390 continue
2763  ! (3) and finally number the node in Adj(t(iy))
2764  do 400 ll=l,nanc
2765  if(adjt(anc(ll)).ne.0) then
2766  k=k+1
2767  invp(iperm(anc(ll)))=k
2768  endif
2769 400 continue
2770  goto 600
2771  !
2772  ! izz can be numbered last
2773  !
2774 500 continue
2775  k=0
2776  do 510 i=1,neqns
2777  if(i.eq.izzz) goto 510
2778  k=k+1
2779  invp(iperm(i))=k
2780 510 continue
2781  invp(iperm(izzz))=neqns
2782  !
2783  ! set iperm
2784  !
2785 600 continue
2786  do 610 i=1,neqns
2787  iperm(invp(i))=i
2788 610 continue
2789  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
2790 6000 format(10i6)
2791  return
2792  end subroutine rotate
2793 
2794  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2795 
2796  subroutine bringu(zpiv,iperm,invp,parent,izz,neqns,irr)
2797 
2798  implicit none
2799 
2800  integer(kind=kint), intent(in) :: zpiv(:),parent(:)
2801  integer(kind=kint), intent(out) :: iperm(:),invp(:)
2802  integer(kind=kint), intent(in) :: neqns,izz
2803  integer(kind=kint), intent(out) :: irr
2804 
2805  integer(kind=kint) :: i,j,k,l,ib0,ib,ibp,izzp
2806 
2807  !----------------------------------------------------------------------
2808  !
2809  ! bringu brings up zero pivots from bottom of the elimination tree
2810  ! to higher nodes
2811  !
2812  ! irr = 0 complete
2813  ! = 1 impossible
2814  !
2815  ! #coded by t.arakawa
2816  !
2817  !----------------------------------------------------------------------
2818 
2819  irr=0
2820  ib0=invp(izz)
2821  ib=ib0
2822 100 continue
2823  if(ib.le.0) goto 1000
2824  ibp=parent(ib)
2825  izzp=iperm(ibp)
2826  if(zpiv(izzp).eq.0) goto 110
2827  ib=ibp
2828  goto 100
2829 110 continue
2830  invp(izz)=ibp
2831  invp(izzp)=ib0
2832  iperm(ibp)=izz
2833  iperm(ib0)=izzp
2834  if(ldbg) then
2835  do 200 i=1,neqns
2836  if(invp(iperm(i)).ne.i) goto 210
2837  if(iperm(invp(i)).ne.i) goto 210
2838 200 continue
2839  goto 220
2840 210 continue
2841  write(20,*) 'permutation error'
2842  stop
2843  endif
2844 220 continue
2845  return
2846 1000 continue
2847  irr=1
2848  end subroutine bringu
2849 
2850  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2851 
2852  subroutine posord(parent,btree,invp,iperm,pordr,nch,neqns,iw,qarent,mch)
2853 
2854  implicit none
2855 
2856  integer(kind=kint), intent(in) :: btree(:,:),qarent(:)
2857  integer(kind=kint), intent(out) :: pordr(:),invp(:),iperm(:),nch(:),iw(:),parent(:),mch(0:neqns+1)
2858  integer(kind=kint), intent(in) :: neqns
2859 
2860  integer(kind=kint) :: i,j,k,l,locc,loc,locp,invpos,ipinv,ii
2861 
2862  do 5 i=1,neqns
2863  mch(i)=0
2864  pordr(i)=0
2865 5 continue
2866  l=1
2867  locc=neqns+1
2868 10 continue
2869  loc=locc
2870  locc=btree(1,loc)
2871  if(locc.ne.0) goto 10
2872  locp=qarent(loc)
2873  mch(locp)=mch(locp)+1
2874 20 continue
2875  pordr(loc)=l
2876  if(l.ge.neqns) goto 1000
2877  l=l+1
2878  locc=btree(2,loc)
2879  if(locc.ne.0) goto 10
2880  loc=qarent(loc)
2881  locp=qarent(loc)
2882  mch(locp)=mch(locp)+mch(loc)+1
2883  goto 20
2884 1000 continue
2885  do 100 i=1,neqns
2886  ipinv=pordr(invp(i))
2887  invp(i)=ipinv
2888  iperm(ipinv)=i
2889  iw(pordr(i))=i
2890 100 continue
2891  do 110 i=1,neqns
2892  invpos=iw(i)
2893  nch(i)=mch(invpos)
2894  ii=qarent(invpos)
2895  if(ii.gt.0.and.ii.le.neqns) then
2896  parent(i)=pordr(ii)
2897  else
2898  parent(i)=qarent(invpos)
2899  endif
2900 110 continue
2901  if(ldbg) write(idbg,6020)
2902  if(ldbg) write(idbg,6000) (pordr(i),i=1,neqns)
2903  if(ldbg) write(idbg,6030)
2904  if(ldbg) write(idbg,6050)
2905  if(ldbg) write(idbg,6000) (parent(i),i=1,neqns)
2906  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
2907  if(ldbg) write(idbg,6040)
2908  if(ldbg) write(idbg,6000) (iperm(i),i=1,neqns)
2909  if(ldbg) write(idbg,6010)
2910  if(ldbg) write(idbg,6000) (nch(i),i=1,neqns)
2911 6000 format(10i6)
2912 6010 format(' nch')
2913 6020 format(' post order')
2914 6030 format(/' invp ')
2915 6040 format(/' iperm ')
2916 6050 format(/' parent')
2917  return
2918  end subroutine posord
2919 
2920  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2921 
2922  subroutine gnleaf(xadj,adjncy,invp,iperm,pordr,nch,adjncp,xleaf,leaf,neqns,lnleaf)
2923 
2924  implicit none
2925 
2926  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),pordr(:),nch(:),invp(:),iperm(:)
2927  integer(kind=kint), intent(out) :: xleaf(:),leaf(:),adjncp(:)
2928  integer(kind=kint), intent(in) :: neqns
2929 
2930  integer(kind=kint) i,j,k,l,m,n,ik,istart,ip,iq,lnleaf,lc1,lc
2931 
2932  l=1
2933  ik=0
2934  istart=0
2935  do 100 i=1,neqns
2936  xleaf(i)=l
2937  ip=iperm(i)
2938  do 105 k=xadj(ip),xadj(ip+1)-1
2939  iq=invp(adjncy(k))
2940  if(iq.lt.i) then
2941  ik=ik+1
2942  adjncp(ik)=iq
2943  endif
2944 105 continue
2945  m=ik-istart
2946  if(m.eq.0) goto 131
2947  call qqsort(adjncp(istart+1:),m)
2948  lc1=adjncp(istart+1)
2949  if(lc1.ge.i) goto 100
2950  leaf(l)=lc1
2951  l=l+1
2952  do 130 k=istart+2,ik
2953  lc=adjncp(k)
2954  ! if(lc.ge.i) goto 125
2955  if(lc1.lt.lc-nch(lc)) then
2956  leaf(l)=lc
2957  l=l+1
2958  endif
2959 125 continue
2960  lc1=lc
2961 130 continue
2962  ik=1
2963  istart=ik
2964 131 continue
2965 100 continue
2966  xleaf(neqns+1)=l
2967  lnleaf=l-1
2968  if(ldbg) write(idbg,6020)
2969  if(ldbg) write(idbg,6000) (xleaf(i),i=1,neqns+1)
2970  if(ldbg) write(idbg,6010) lnleaf
2971  if(ldbg) write(idbg,6000) (leaf(i),i=1,lnleaf)
2972  return
2973 6000 format(10i6)
2974 6010 format(' leaf (len = ',i6,')')
2975 6020 format(' xleaf')
2976  end subroutine gnleaf
2977 
2978  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2979 
2980  subroutine countclno(parent,xleaf,leaf,neqns,nstop,lncol,ir)
2981 
2982  implicit none
2983 
2984  ! Count total number of non-zero elements
2985  ! which include fill-in.
2986  ! A and C region of given sparse matrix will consider.
2987  ! D region will not consider because of D is treat as
2988  ! dens matrix.
2989  !
2990  integer(kind=kint), intent(in) :: parent(:),xleaf(:),leaf(:)
2991  integer(kind=kint), intent(in) :: neqns, nstop
2992  integer(kind=kint), intent(out) :: lncol, ir
2993 
2994  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
2995 
2996  nc=0
2997  ir=0
2998  l=1
2999  do 100 i=1,neqns
3000  ks=xleaf(i)
3001  ke=xleaf(i+1)-1
3002  if(ke.lt.ks) goto 100
3003  nxleaf=leaf(ks)
3004  do 110 k=ks,ke-1
3005  j=nxleaf
3006  nxleaf=leaf(k+1)
3007 105 continue
3008  if(j.ge.nxleaf) goto 110
3009  if(j.ge.nstop) then
3010  goto 100
3011  endif
3012  l=l+1
3013  j=parent(j)
3014  goto 105
3015 110 continue
3016  j=leaf(ke)
3017 115 continue
3018  if(j.ge.nstop) goto 100
3019  if(j.ge.i.or.j.eq.0) goto 100
3020  l=l+1
3021  j=parent(j)
3022  goto 115
3023 100 continue
3024  lncol=l-1
3025  return
3026  end subroutine countclno
3027 
3028  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3029 
3030  subroutine gnclno(parent,pordr,xleaf,leaf,xlnzr,colno,neqns,nstop,lncol,ir)
3031 
3032  implicit none
3033 
3034  integer(kind=kint), intent(in) :: parent(:),pordr(:),xleaf(:),leaf(:)
3035  integer(kind=kint), intent(out) :: colno(:),xlnzr(:)
3036  integer(kind=kint), intent(in) :: neqns, nstop
3037  integer(kind=kint), intent(out) :: lncol,ir
3038 
3039  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
3040 
3041  nc=0
3042  ir=0
3043  l=1
3044  do 100 i=1,neqns
3045  xlnzr(i)=l
3046  ks=xleaf(i)
3047  ke=xleaf(i+1)-1
3048  if(ke.lt.ks) goto 100
3049  nxleaf=leaf(ks)
3050  do 110 k=ks,ke-1
3051  j=nxleaf
3052  nxleaf=leaf(k+1)
3053 105 continue
3054  if(j.ge.nxleaf) goto 110
3055  if(j.ge.nstop) then
3056  goto 100
3057  endif
3058  colno(l)=j
3059  l=l+1
3060  j=parent(j)
3061  goto 105
3062 110 continue
3063  j=leaf(ke)
3064 115 continue
3065  if(j.ge.nstop) goto 100
3066  if(j.ge.i.or.j.eq.0) goto 100
3067  colno(l)=j
3068  l=l+1
3069  j=parent(j)
3070  goto 115
3071 100 continue
3072  xlnzr(neqns+1)=l
3073  lncol=l-1
3074  if(ldbg) write(idbg,6010)
3075  ! if(idbg1.ne.0) write(6,6000) (xlnzr(i),i=1,neqns+1)
3076  if(ldbg) write(idbg,6020) lncol
3077  if(ldbg) then
3078  do 200 k=1,neqns
3079  write(idbg,6100) k
3080  write(idbg,6000) (colno(i),i=xlnzr(k),xlnzr(k+1)-1)
3081 200 continue
3082  endif
3083 6000 format(10i4)
3084 6010 format(' xlnzr')
3085 6020 format(' colno (lncol =',i10,')')
3086 6100 format(/' row = ',i6)
3087  return
3088  end subroutine gnclno
3089 
3090  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3091 
3092  subroutine qmdrch(root,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
3093 
3094  implicit none
3095 
3096  integer(kind=kint), intent(in) :: deg(:),xadj(:),adjncy(:)
3097  integer(kind=kint), intent(out) :: rchset(:),marker(:),nbrhd(:)
3098  integer(kind=kint), intent(in) :: root
3099  integer(kind=kint), intent(out) :: nhdsze,rchsze
3100 
3101  integer(kind=kint) :: i,j,k,l, istrt, istop, jstrt, jstop, nabor, node
3102 
3103  nhdsze=0
3104  rchsze=0
3105  istrt=xadj(root)
3106  istop=xadj(root+1)-1
3107  if(istop.lt.istrt) return
3108  do 600 i=istrt,istop
3109  nabor=adjncy(i)
3110  if(nabor.eq.0) return
3111  if(marker(nabor).ne.0) goto 600
3112  if(deg(nabor).lt.0) goto 200
3113  rchsze=rchsze+1
3114  rchset(rchsze)=nabor
3115  marker(nabor)=1
3116  goto 600
3117 200 marker(nabor)=-1
3118  nhdsze=nhdsze+1
3119  nbrhd(nhdsze)=nabor
3120 300 jstrt=xadj(nabor)
3121  jstop=xadj(nabor+1)-1
3122  do 500 j=jstrt,jstop
3123  node=adjncy(j)
3124  nabor=-node
3125  !if(node) 300,600,400
3126  if(node<0) then
3127  goto 300
3128  elseif(node==0) then
3129  goto 600
3130  endif
3131 400 if(marker(node).ne.0) goto 500
3132  rchsze=rchsze+1
3133  rchset(rchsze)=node
3134  marker(node)=1
3135 500 continue
3136 600 continue
3137  return
3138  end subroutine qmdrch
3139 
3140  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3141 
3142  subroutine qmdupd(xadj,adjncy,nlist,list,deg,qsize,qlink,marker,rchset,nbrhd)
3143 
3144  implicit none
3145 
3146  integer(kind=kint), intent(in) :: adjncy(:),list(:),xadj(:)
3147  integer(kind=kint), intent(out) :: marker(:),nbrhd(:),rchset(:),deg(:),qsize(:),qlink(:)
3148  integer(kind=kint), intent(in) :: nlist
3149 
3150  integer(kind=kint) :: i,j,k,l, deg0,deg1,il,inhd,inode,irch,jstrt,jstop,mark,nabor,nhdsze,node,rchsze
3151 
3152  if(nlist.le.0) return
3153  deg0=0
3154  nhdsze=0
3155  do 200 il=1,nlist
3156  node=list(il)
3157  deg0=deg0+qsize(node)
3158  jstrt=xadj(node)
3159  jstop=xadj(node+1)-1
3160 
3161  do 100 j=jstrt,jstop
3162  nabor=adjncy(j)
3163  if(marker(nabor).ne.0.or.deg(nabor).ge.0) goto 100
3164  marker(nabor)=-1
3165  nhdsze=nhdsze+1
3166  nbrhd(nhdsze)=nabor
3167 100 continue
3168 200 continue
3169 
3170  if(nhdsze.gt.0) call qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,nbrhd(nhdsze+1:))
3171  do 600 il=1,nlist
3172  node=list(il)
3173  mark=marker(node)
3174  if(mark.gt.1.or.mark.lt.0) goto 600
3175  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
3176  deg1=deg0
3177  if(rchsze.le.0) goto 400
3178  do 300 irch=1,rchsze
3179  inode=rchset(irch)
3180  deg1=deg1+qsize(inode)
3181  marker(inode)=0
3182 300 continue
3183 400 deg(node)=deg1-1
3184  if(nhdsze.le.0) goto 600
3185  do 500 inhd=1,nhdsze
3186  inode=nbrhd(inhd)
3187  marker(inode)=0
3188 500 continue
3189 600 continue
3190  return
3191  endsubroutine qmdupd
3192 
3193  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3194 
3195  subroutine qmdot(root,xadj,adjncy,marker,rchsze,rchset,nbrhd)
3196 
3197  implicit none
3198 
3199  integer(kind=kint), intent(in) :: marker(:),rchset(:),nbrhd(:),xadj(:)
3200  integer(kind=kint), intent(out) :: adjncy(:)
3201  integer(kind=kint), intent(in) :: rchsze,root
3202 
3203  integer(kind=kint) :: i,j,k,l,irch,inhd,node,jstrt,jstop,link,nabor
3204 
3205  irch=0
3206  inhd=0
3207  node=root
3208  100 jstrt=xadj(node)
3209  jstop=xadj(node+1)-2
3210  if(jstop.lt.jstrt) goto 300
3211  do 200 j=jstrt,jstop
3212  irch=irch+1
3213  adjncy(j)=rchset(irch)
3214  if(irch.ge.rchsze) goto 400
3215 200 continue
3216 300 link=adjncy(jstop+1)
3217  node=-link
3218  if(link.lt.0) goto 100
3219  inhd=inhd+1
3220  node=nbrhd(inhd)
3221  adjncy(jstop+1)=-node
3222  goto 100
3223 400 adjncy(j+1)=0
3224  do 600 irch=1,rchsze
3225  node=rchset(irch)
3226  if(marker(node).lt.0) goto 600
3227  jstrt=xadj(node)
3228  jstop=xadj(node+1)-1
3229  do 500 j=jstrt,jstop
3230  nabor=adjncy(j)
3231  if(marker(nabor).ge.0) goto 500
3232  adjncy(j)=root
3233  goto 600
3234 500 continue
3235 600 continue
3236  return
3237  end subroutine qmdot
3238 
3239  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3240 
3241  subroutine qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,ovrlp)
3242 
3243  implicit none
3244 
3245  integer(kind=kint), intent(in) :: adjncy(:),nbrhd(:),xadj(:)
3246  integer(kind=kint), intent(out) :: deg(:),marker(:),rchset(:),ovrlp(:),qsize(:),qlink(:)
3247  integer(kind=kint), intent(in) :: nhdsze
3248 
3249  integer(kind=kint) :: i,j,k,l, deg0,deg1,head,inhd,iov,irch,jstrt,jstop,link,lnode,mark,mrgsze,nabor,node,novrlp,rchsze,root
3250 
3251 
3252  if(nhdsze.le.0) return
3253  do 100 inhd=1,nhdsze
3254  root=nbrhd(inhd)
3255  marker(root)=0
3256 100 continue
3257  do 1400 inhd=1,nhdsze
3258  root=nbrhd(inhd)
3259  marker(root)=-1
3260  rchsze=0
3261  novrlp=0
3262  deg1=0
3263 200 jstrt=xadj(root)
3264  jstop=xadj(root+1)-1
3265  do 600 j=jstrt,jstop
3266  nabor=adjncy(j)
3267  root=-nabor
3268  !if(nabor) 200,700,300
3269  if(nabor<0) then
3270  goto 200
3271  elseif(nabor==0) then
3272  goto 700
3273  endif
3274 300 mark=marker(nabor)
3275  !if(mark)600,400,500
3276  if(mark<0) then
3277  goto 600
3278  elseif(mark>0) then
3279  goto 500
3280  endif
3281 400 rchsze=rchsze+1
3282  rchset(rchsze)=nabor
3283  deg1=deg1+qsize(nabor)
3284  marker(nabor)=1
3285  goto 600
3286 500 if(mark.gt.1) goto 600
3287  novrlp=novrlp+1
3288  ovrlp(novrlp)=nabor
3289  marker(nabor)=2
3290 600 continue
3291 700 head=0
3292  mrgsze=0
3293  do 1100 iov=1,novrlp
3294  node=ovrlp(iov)
3295  jstrt=xadj(node)
3296  jstop=xadj(node+1)-1
3297  do 800 j=jstrt,jstop
3298  nabor=adjncy(j)
3299  if(marker(nabor).ne.0) goto 800
3300  marker(node)=1
3301  goto 1100
3302 800 continue
3303  mrgsze=mrgsze+qsize(node)
3304  marker(node)=-1
3305  lnode=node
3306 900 link=qlink(lnode)
3307  if(link.le.0) goto 1000
3308  lnode=link
3309  goto 900
3310 1000 qlink(lnode)=head
3311  head=node
3312 1100 continue
3313  if(head.le.0) goto 1200
3314  qsize(head)=mrgsze
3315  deg(head)=deg0+deg1-1
3316  marker(head)=2
3317 1200 root=nbrhd(inhd)
3318  marker(root)=0
3319  if(rchsze.le.0) goto 1400
3320  do 1300 irch=1,rchsze
3321  node=rchset(irch)
3322  marker(node)=0
3323 1300 continue
3324 1400 continue
3325  return
3326  end subroutine qmdmrg
3327 
3328  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3329 
3330  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)
3331  ! find fill-in position in C which placed under A and set it in xlnzr_c, colno_c
3332 
3333  use m_crs_matrix
3334  implicit none
3335  !input
3336  integer(kind=kint), intent(in) :: xlnzr_a(:)
3337  integer(kind=kint), intent(in) :: colno_a(:)
3338  integer(kind=kint), intent(in) :: iperm_a(:)
3339  integer(kind=kint), intent(in) :: invp_a(:)
3340  integer(kind=kint), intent(in) :: ndeg
3341  integer(kind=kint), intent(in) :: nttbr_c
3342  integer(kind=kint), intent(in) :: irow_c(:)
3343  integer(kind=kint), intent(inout) :: jcol_c(:)
3344  integer(kind=kint), intent(in) :: ncol
3345  integer(kind=kint), intent(in) :: nrow
3346 
3347  !output
3348  integer(kind=kint), pointer :: xlnzr_c(:)
3349  integer(kind=kint), pointer :: colno_c(:)
3350  integer(kind=kint), intent(out) :: lncol_c
3351 
3352  ! internal
3353  integer(kind=kint) :: i,j,k,l,m,n
3354  integer(kind=kint) :: ks, ke, ipass, ierr
3355  logical, allocatable :: cnz(:)
3356  type(crs_matrix) :: crs_c
3357 
3358  !permtate column in C for crs_c
3359  do i=1,nttbr_c
3360  jcol_c(i)=invp_a(jcol_c(i))
3361  end do
3362 
3363  ! make Compact Column Storoge using symbolic information.
3364  call symbolicirjctocrs(ndeg, nttbr_c, irow_c, jcol_c, ncol, nrow, crs_c)
3365 
3366  ! symbolic LDU factorization for C matrix
3367  allocate(cnz(ncol), stat=ierr)
3368  if(ierr .ne. 0) then
3369  call errtrp('stop due to allocation error.')
3370  end if
3371  do ipass = 1,2
3372  lncol_c = 0
3373  do k=1,nrow
3374  ! set cnz as non-zero pattern of C
3375  cnz = .false.
3376  ks = crs_c%ia(k)
3377  ke = crs_c%ia(k+1)-1
3378  if (ke .lt. ks) then
3379  if (ipass .eq. 2) then
3380  xlnzr_c(k+1)=lncol_c+1
3381  end if
3382  cycle ! in case of zero vector, no need to check dot product.
3383  end if
3384 
3385  do i=ks,ke
3386  cnz(crs_c%ja(i)) = .true.
3387  end do
3388 
3389  ! check for non-zero dot product and update cnz for each point of cnz
3390  do i=2,ncol
3391  ks = xlnzr_a(i)
3392  ke = xlnzr_a(i+1)-1
3393  if (ke .lt. ks) then ! in case of column of A is zero vector.
3394  cycle
3395  end if
3396  do j=ks,ke
3397  if (cnz(colno_a(j))) then
3398  cnz(i) = .true.
3399  exit
3400  end if
3401  end do
3402  end do
3403 
3404  do i=1,ncol
3405  if (cnz(i)) then
3406  lncol_c = lncol_c + 1
3407  if (ipass .eq. 2) then
3408  colno_c(lncol_c) = i
3409  end if
3410  end if
3411  end do
3412  if (ipass .eq. 2) then
3413  xlnzr_c(k+1)=lncol_c + 1
3414  end if
3415  end do
3416 
3417  if (ipass .eq. 1) then
3418  allocate(xlnzr_c(nrow+1),colno_c(lncol_c), stat=ierr)
3419  if(ierr .ne. 0) then
3420  call errtrp('stop due to allocation error.')
3421  end if
3422  xlnzr_c(1)=1
3423  end if
3424  end do
3425 
3426  ! restore order of C column.
3427  do i=1,nttbr_c
3428  jcol_c(i)=iperm_a(jcol_c(i))
3429  end do
3430 
3431  return
3432 
3433  end subroutine ldudecomposec
3434 
3435  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3436 
3437  subroutine qqsort(iw,ik)
3438 
3439  implicit none
3440 
3441  integer(kind=kint), intent(out) :: iw(:)
3442  integer(kind=kint), intent(in) :: ik
3443 
3444  integer(kind=kint) :: l,m,itemp
3445 
3446  !----------------------------------------------------------------------
3447  ! sort in increasing order up to i
3448  !
3449  ! iw array
3450  ! ik number of input/output
3451  ! i deal with numbers less than this numberi
3452  !
3453  !----------------------------------------------------------------------
3454 
3455  if(ik.le.1) return
3456  do 100 l=1,ik-1
3457  do 110 m=l+1,ik
3458  if(iw(l).lt.iw(m)) goto 110
3459  itemp=iw(l)
3460  iw(l)=iw(m)
3461  iw(m)=itemp
3462 110 continue
3463 100 continue
3464 200 continue
3465  return
3466  end subroutine qqsort
3467 
3468 
3469  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3470 
3471  subroutine staij1(isw,i,j,aij,dsi,ir)
3472 
3473  implicit none
3474 
3475  !----------------------------------------------------------------------
3476  !
3477  ! this routine sets an non-zero entry of the matrix.
3478  ! (symmetric version)
3479  !
3480  ! (i)
3481  ! isw =0 set the value
3482  ! =1 add the value
3483  ! i row entry
3484  ! j column entry
3485  ! aij value
3486  !
3487  ! (o)
3488  ! iv communication array
3489  !
3490  ! #coded by t.arakawa
3491  !
3492  !----------------------------------------------------------------------
3493  !
3494  type(dsinfo) :: dsi
3495  real(kind=kreal), intent(out) :: aij(:) ! ndeg*ndeg
3496  integer(kind=kint), intent(in) :: isw, i, j
3497  integer(kind=kint), intent(out) :: ir
3498 
3499  integer(kind=kint) :: ndeg, neqns, nstop, ndeg2, ndeg2l, ierr
3500  ndeg=dsi%ndeg
3501  neqns=dsi%neqns
3502  nstop=dsi%nstop
3503  ndeg2=ndeg*ndeg
3504  ndeg2l=ndeg*(ndeg+1)/2
3505 
3506  ir=0
3507  ierr=0
3508 
3509 
3510  ! array allocation
3511  if(dsi%stage.ne.20) then
3512  if(dsi%stage.eq.30) write(ilog,*) 'Warning a matrix was build up but never solved.'
3513  !
3514  ! for diagonal
3515  !
3516  allocate(dsi%diag(ndeg2l,neqns), stat=ierr)
3517  if(ierr .ne. 0) then
3518  call errtrp('stop due to allocation error.')
3519  end if
3520  dsi%diag=0
3521  !
3522  ! for lower triangle
3523  !
3524  allocate(dsi%zln(ndeg2,dsi%lncol), stat=ierr)
3525  if(ierr .ne. 0) then
3526  call errtrp('stop due to allocation error.')
3527  end if
3528  dsi%zln=0
3529  !
3530  ! for dense window !TODO delete this and corresponding line in addr3()
3531  !
3532  ! allocate(dsi%dsln(ndeg2,dsi%lndsln))! because of there is no dense window
3533  ! dsi%dsln=0
3534 
3535  dsi%stage=20
3536  endif
3537 
3538  ! set value
3539  if(ndeg.le.2) then
3540  call addr0(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,dsi%ndeg,ir)
3541  elseif(ndeg.eq.3) then
3542  call addr3(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,ir)
3543  else
3544  call addrx(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,ndeg,ndeg2,ndeg2l,ir)
3545  endif
3546 1000 continue
3547  return
3548  end subroutine staij1
3549 
3550  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3551  !
3552  ! After here, routines specialized for ndeg = 1
3553  !
3554  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3555 
3556  ! LDU decompose of A (1..nstop-1) region
3557  subroutine sum(ic,xlnzr,colno,zln,diag,nch,par,neqns)
3558 
3559  implicit none
3560 
3561  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3562  integer(kind=kint), intent(in) :: ic, neqns
3563  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3564  integer(kind=kint), intent(out) :: nch(:)
3565 
3566  real(kind=kreal) :: s, t, zz, piv
3567  integer(kind=kint) :: ks, ke, kk, k, jc, jj, j, ierr
3568  integer(kind=kint) :: isem
3569  real(kind=kreal),allocatable :: temp(:)
3570  integer(kind=kint),allocatable :: indx(:)
3571  allocate(temp(neqns),indx(neqns), stat=ierr)
3572  if(ierr .ne. 0) then
3573  call errtrp('stop due to allocation error.')
3574  end if
3575 
3576  isem = 0
3577 
3578 2 continue
3579  ks=xlnzr(ic)
3580  ke=xlnzr(ic+1)
3581  t=0.0d0
3582  ! do 100 i=1,ic
3583  ! temp(i)=0.0d0
3584  ! 100 continue
3585  do 200 k=ks,ke-1
3586  jc=colno(k)
3587  indx(jc)=ic
3588  s=0.0d0
3589  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
3590  j=colno(jj)
3591  if(indx(j).eq.ic) then
3592  s=s+temp(j)*zln(jj)
3593  endif
3594 310 continue
3595  ! j1=xlnzr(jc)
3596  ! jj=xlnzr(jc+1)-j1
3597  ! ss=ddoti(jj,zln(j1),colno(j1),temp)
3598  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
3599  zz=zln(k)-s
3600  zln(k)=zz*diag(jc)
3601  temp(jc)=zz
3602  t=t+zz*zln(k)
3603 200 continue
3604  piv=diag(ic)-t
3605  if(dabs(piv).gt.rmin) then
3606  diag(ic)=1.0d0/piv
3607  endif
3608 1 continue
3609  if(isem.eq.1) then
3610  isem=0
3611  nch(ic)=-1
3612  kk=par(ic)
3613  nch(kk)=nch(kk)-1
3614  isem=1
3615  else
3616  goto 1
3617  endif
3618  return
3619  end subroutine sum
3620 
3621  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3622 
3623  ! LDU decompose of C (nstop..neqnsA+neqnsd) region
3624  subroutine sum1(ic,xlnzr,colno,zln,diag,par,neqns)
3625 
3626  implicit none
3627 
3628  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3629  integer(kind=kint), intent(in) :: ic, neqns
3630  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3631 
3632  real(kind=kreal) :: s, t, zz
3633  integer(kind=kint) :: ks, ke, k, jc, j, jj, ierr
3634  real(kind=kreal),allocatable :: temp(:)
3635  integer(kind=kint),allocatable :: indx(:)
3636 
3637  ierr=0
3638 
3639  allocate(temp(neqns),indx(neqns), stat=ierr)
3640  if(ierr .ne. 0) then
3641  call errtrp('stop due to allocation error.')
3642  end if
3643 
3644  ks=xlnzr(ic)
3645  ke=xlnzr(ic+1)
3646  t=0.0d0
3647  ! do 100 i=1,ic
3648  ! temp(i)=0.0d0
3649  ! 100 continue
3650  do 200 k=ks,ke-1
3651  jc=colno(k)
3652  indx(jc)=ic
3653  s=0.0d0
3654  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
3655  j=colno(jj)
3656  if(indx(j).eq.ic) then
3657  s=s+temp(j)*zln(jj)
3658  endif
3659 310 continue
3660  zz=zln(k)-s
3661  ! j1=xlnzr(jc)
3662  ! jj=xlnzr(jc+1)-j1
3663  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
3664  zln(k)=zz
3665  temp(jc)=zz
3666  ! t=t+zz*zz*diag(jc)
3667 200 continue
3668  ! diag(ic)=diag(ic)-t
3669  return
3670  end subroutine sum1
3671 
3672  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3673 
3674  ! LDU decompose and Update D region.
3675  subroutine sum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
3676 
3677  implicit none
3678 
3679  integer(kind=kint), intent(in) :: neqns, nstop
3680  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
3681  real(kind=kreal), intent(inout) :: zln(:),diag(:)
3682  integer(kind=kint), pointer :: spdslnidx(:)
3683  real(kind=kreal), pointer :: spdslnval(:,:)
3684  integer(kind=kint), intent(out) :: nspdsln
3685 
3686  real(kind=kreal) :: s, t
3687  integer(kind=kint) :: ks, ke, kk, k, jc, jj, j, j1,j2
3688  integer(kind=kint) :: ic, i, loc, ierr
3689  integer(kind=kint) :: ispdsln
3690  logical :: ftflag
3691  real(kind=kreal),allocatable :: temp(:)
3692  integer(kind=kint),allocatable :: indx(:)
3693  ierr=0
3694  allocate(temp(neqns),indx(neqns), stat=ierr)
3695  if(ierr .ne. 0) then
3696  call errtrp('stop due to allocation error.')
3697  end if
3698 
3699  nspdsln=0
3700  do ic=nstop,neqns
3701  ks=xlnzr(ic)
3702  ke=xlnzr(ic+1)-1
3703  do k=ks,ke
3704  jj=colno(k)
3705  indx(jj)=ic
3706  end do
3707  do jc=nstop,ic-1
3708  j1=xlnzr(jc)
3709  j2=xlnzr(jc+1)
3710  do jj=xlnzr(jc),xlnzr(jc+1)-1
3711  j=colno(jj)
3712  if(indx(j).eq.ic) then
3713  nspdsln=nspdsln+1
3714  exit
3715  endif
3716  end do
3717  end do
3718  end do
3719  allocate(spdslnidx(nspdsln),spdslnval(1,nspdsln), stat=ierr)
3720  if(ierr .ne. 0) then
3721  call errtrp('stop due to allocation error.')
3722  end if
3723 
3724  loc=0
3725  ispdsln=0
3726  spdslnval=0
3727  ftflag = .true.
3728  do 100 ic=nstop,neqns
3729  do 105 i=1,nstop
3730  temp(i)=0.0d0
3731 105 continue
3732  ks=xlnzr(ic)
3733  ke=xlnzr(ic+1)-1
3734  do 110 k=ks,ke
3735  jj=colno(k)
3736  temp(jj)=zln(k)
3737  zln(k)=temp(jj)*diag(jj)
3738  indx(jj)=ic
3739  diag(ic)=diag(ic)-temp(jj)*zln(k)
3740 110 continue
3741  do 120 jc=nstop,ic-1
3742  s=0.0d0
3743  loc=loc+1
3744  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
3745  j=colno(jj)
3746  if(indx(j).eq.ic) then
3747  if (ftflag) then
3748  ispdsln=ispdsln+1
3749  ftflag=.false.
3750  end if
3751  s=s+temp(j)*zln(jj)
3752  endif
3753 220 continue
3754  spdslnidx(ispdsln)=loc
3755  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-s
3756  ftflag = .true.
3757  ! j1=xlnzr(jc)
3758  ! jj=xlnzr(jc+1)-j1
3759  ! dsln(loc)=dsln(loc)-ddoti(jj,zln(j1),colno(j1),temp)
3760 120 continue
3761 100 continue
3762  return
3763  end subroutine sum2_child
3764 
3765  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3766 
3767  subroutine sum3(n,dsln,diag)
3768 
3769  implicit none
3770 
3771  real(kind=kreal), intent(inout) :: dsln(:),diag(:)
3772  integer(kind=kint), intent(in) :: n
3773 
3774  integer(kind=kint) :: i, j, loc, ierr
3775  real(kind=kreal),allocatable :: temp(:)
3776  integer(kind=kint),allocatable :: indx(:)
3777  allocate(temp(n),indx(n), stat=ierr)
3778  if(ierr .ne. 0) then
3779  call errtrp('stop due to allocation error.')
3780  end if
3781 
3782  if(n.le.0) goto 1000
3783  indx(1)=0
3784  loc=1
3785  diag(1)=1.0d0/diag(1)
3786  do 100 i=2,n
3787  indx(i)=loc
3788  do 110 j=1,i-1
3789  dsln(loc)=dsln(loc)-dot_product(dsln(indx(i):indx(i)+j-2),dsln(indx(j):indx(j)+j-2))
3790  loc=loc+1
3791 110 continue
3792  temp(1:i-1)=dsln(indx(i):indx(i)+i-2)*diag(1:i-1)
3793  diag(i)=diag(i)-dot_product(temp(1:i-1),dsln(indx(i):indx(i)+i-2))
3794  dsln(indx(i):indx(i)+i-2)=temp(1:i-1)
3795  diag(i)=1.0d0/diag(i)
3796 100 continue
3797 1000 continue
3798  return
3799  end subroutine sum3
3800 
3801  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3802 
3803  real(kind=kreal) function spdot2(b,zln,colno,ks,ke)
3804 
3805  implicit none
3806 
3807  integer(kind=kint), intent(in) :: colno(:)
3808  integer(kind=kint), intent(in) :: ks,ke
3809  real(kind=kreal), intent(in) :: zln(:),b(:)
3810 
3811  integer(kind=kint) :: j,jj
3812  real(kind=kreal) :: s
3813 
3814  !----------------------------------------------------------------------
3815  !
3816  ! spdot1 performs inner product of sparse vectors
3817  !
3818  !
3819  ! #coded by t.arakawa
3820  !
3821  !----------------------------------------------------------------------
3822  !
3823  s=0.0d0
3824  do 100 jj=ks,ke
3825  j=colno(jj)
3826  s=s+zln(jj)*b(j)
3827 100 continue
3828  spdot2=s
3829  end function spdot2
3830 
3831  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3832 
3833  real(kind=kreal) function ddot(a,b,n)
3834 
3835  implicit none
3836 
3837  real(kind=kreal), intent(in) :: a(n),b(n)
3838  integer(kind=kint), intent(in) :: n
3839 
3840  real(kind=kreal) :: s
3841  integer(kind=kint) :: i
3842 
3843  s=0.0d0
3844  do 100 i=1,n
3845  s=s+a(i)*b(i)
3846 100 continue
3847  ddot=s
3848  return
3849  end function ddot
3850 
3851  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3852 
3853  subroutine addr0(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ndeg,ir)
3854 
3855  implicit none
3856 
3857  integer(kind=kint), intent(in) :: isw ! 0: renew diag, dsln, zln other: add to diag, dsln, zln
3858  integer(kind=kint), intent(in) :: i,j,nstop, ndeg, invp(:),xlnzr(:),colno(:)
3859  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:),dsln(:,:),aij(:)
3860  integer(kind=kint), intent(out) :: ir
3861 
3862  integer(kind=kint) :: ndeg2, ii, jj, itrans, k, i0, j0, l, ks, ke
3863  integer(kind=kint), parameter :: idbg=0
3864  ndeg2=ndeg*ndeg
3865 
3866  ir=0
3867  ii=invp(i)
3868  jj=invp(j)
3869  if(idbg.ne.0) write(idbg,*) 'addr0',ii,jj,aij
3870  if(ii.eq.jj) then
3871  if(ndeg2.eq.1) then
3872  if(isw.eq.0) then
3873  diag(1,ii)=aij(1)
3874  else
3875  diag(1,ii)=diag(1,ii)+aij(1)
3876  endif
3877  elseif(ndeg2.eq.4) then
3878  if(isw.eq.0) then
3879  diag(1,ii)=aij(1)
3880  diag(2,ii)=aij(2)
3881  diag(3,ii)=aij(4)
3882  else
3883  diag(1,ii)=diag(1,ii)+aij(1)
3884  diag(2,ii)=diag(2,ii)+aij(2)
3885  diag(3,ii)=diag(3,ii)+aij(4)
3886  endif
3887  endif
3888  goto 1000
3889  endif
3890  itrans=0
3891  if(jj.gt.ii) then
3892  k=jj
3893  jj=ii
3894  ii=k
3895  itrans=1
3896  endif
3897  if(jj.ge.nstop) then
3898  i0=ii-nstop
3899  j0=jj-nstop+1
3900  k=i0*(i0-1)/2+j0
3901  if(ndeg2.eq.1) then
3902  dsln(1,k)=aij(1)
3903  goto 1000
3904  elseif(ndeg2.eq.4) then
3905  if(itrans.eq.0) then
3906  do 3 l=1,ndeg2
3907  dsln(l,k)=aij(l)
3908 3 continue
3909  goto 1000
3910  else
3911  dsln(1,k)=aij(1)
3912  dsln(2,k)=aij(3)
3913  dsln(3,k)=aij(2)
3914  dsln(4,k)=aij(4)
3915  goto 1000
3916  endif
3917  endif
3918  endif
3919  ks=xlnzr(ii)
3920  ke=xlnzr(ii+1)-1
3921  do 100 k=ks,ke
3922  if(colno(k).eq.jj) then
3923  if(isw.eq.0) then
3924  if(ndeg2.eq.1) then
3925  zln(1,k)=aij(1)
3926  elseif(ndeg2.eq.4) then
3927  if(itrans.eq.0) then
3928  do 4 l=1,ndeg2
3929  zln(l,k)=aij(l)
3930 4 continue
3931  else
3932  zln(1,k)=aij(1)
3933  zln(2,k)=aij(3)
3934  zln(3,k)=aij(2)
3935  zln(4,k)=aij(4)
3936  endif
3937  endif
3938  else
3939  if(ndeg2.eq.1) then
3940  zln(1,k)=zln(1,k)+aij(1)
3941  elseif(ndeg2.eq.4) then
3942  if(itrans.eq.0) then
3943  do 5 l=1,ndeg2
3944  zln(l,k)=zln(l,k)+aij(l)
3945 5 continue
3946  else
3947  zln(1,k)=zln(1,k)+aij(1)
3948  zln(2,k)=zln(2,k)+aij(3)
3949  zln(3,k)=zln(3,k)+aij(2)
3950  zln(4,k)=zln(4,k)+aij(4)
3951  endif
3952  endif
3953  endif
3954  goto 1000
3955  endif
3956 100 continue
3957  ir=20
3958 1000 continue
3959  return
3960  end subroutine addr0
3961 
3962  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3963  !
3964  ! After here, routines specialized for ndeg = 3
3965  !
3966  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3967 
3968  subroutine s3um(ic,xlnzr,colno,zln,diag,nch,par,neqns)
3969 
3970  implicit none
3971 
3972  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
3973  integer(kind=kint), intent(out) :: nch(:)
3974  real(kind=kreal), intent(out) :: zln(:,:), diag(:,:) ! zln(9,*),diag(6,*),temp(9,*),indx(*)
3975  integer(kind=kint), intent(in) :: ic,neqns
3976 
3977  real(kind=kreal), allocatable :: temp(:,:)
3978  integer(kind=kint), allocatable :: indx(:)
3979  real(kind=kreal) :: zz(9),t(6)
3980  integer(kind=kint) :: i,j,k,l,ks,ke,kk,jc,jj,ir, ierr
3981 
3982  allocate(temp(9,neqns),indx(neqns), stat=ierr)
3983  if(ierr .ne. 0) then
3984  call errtrp('stop due to allocation error.')
3985  end if
3986 
3987  ks=xlnzr(ic)
3988  ke=xlnzr(ic+1)
3989  !$dir max_trips(6)
3990  do 100 l=1,6
3991  t(l)=0.0d0
3992 100 continue
3993  do 200 k=ks,ke-1
3994  jc=colno(k)
3995  indx(jc)=ic
3996  !$dir max_trips(9)
3997  do 210 l=1,9
3998  zz(l)=zln(l,k)
3999 210 continue
4000  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4001  j=colno(jj)
4002  if(indx(j).eq.ic) then
4003  zz(1)=zz(1)-temp(1,j)*zln(1,jj)-temp(4,j)*zln(4,jj)-temp(7,j)*zln(7,jj)
4004  zz(2)=zz(2)-temp(2,j)*zln(1,jj)-temp(5,j)*zln(4,jj)-temp(8,j)*zln(7,jj)
4005  zz(3)=zz(3)-temp(3,j)*zln(1,jj)-temp(6,j)*zln(4,jj)-temp(9,j)*zln(7,jj)
4006  zz(4)=zz(4)-temp(1,j)*zln(2,jj)-temp(4,j)*zln(5,jj)-temp(7,j)*zln(8,jj)
4007  zz(5)=zz(5)-temp(2,j)*zln(2,jj)-temp(5,j)*zln(5,jj)-temp(8,j)*zln(8,jj)
4008  zz(6)=zz(6)-temp(3,j)*zln(2,jj)-temp(6,j)*zln(5,jj)-temp(9,j)*zln(8,jj)
4009  zz(7)=zz(7)-temp(1,j)*zln(3,jj)-temp(4,j)*zln(6,jj)-temp(7,j)*zln(9,jj)
4010  zz(8)=zz(8)-temp(2,j)*zln(3,jj)-temp(5,j)*zln(6,jj)-temp(8,j)*zln(9,jj)
4011  zz(9)=zz(9)-temp(3,j)*zln(3,jj)-temp(6,j)*zln(6,jj)-temp(9,j)*zln(9,jj)
4012  endif
4013 310 continue
4014 
4015  call inv33(zln(:,k),zz,diag(:,jc))
4016 
4017  !$dir max_trips(9)
4018  do 220 l=1,9
4019  temp(l,jc)=zz(l)
4020 220 continue
4021  t(1)=t(1)+zz(1)*zln(1,k)+zz(4)*zln(4,k)+zz(7)*zln(7,k)
4022  t(2)=t(2)+zz(1)*zln(2,k)+zz(4)*zln(5,k)+zz(7)*zln(8,k)
4023  t(3)=t(3)+zz(2)*zln(2,k)+zz(5)*zln(5,k)+zz(8)*zln(8,k)
4024  t(4)=t(4)+zz(1)*zln(3,k)+zz(4)*zln(6,k)+zz(7)*zln(9,k)
4025  t(5)=t(5)+zz(2)*zln(3,k)+zz(5)*zln(6,k)+zz(8)*zln(9,k)
4026  t(6)=t(6)+zz(3)*zln(3,k)+zz(6)*zln(6,k)+zz(9)*zln(9,k)
4027 200 continue
4028  !$dir max_trips(6)
4029  do 320 l=1,6
4030  diag(l,ic)=diag(l,ic)-t(l)
4031 320 continue
4032 
4033  call inv3(diag(:,ic),ir)
4034  nch(ic)=-1
4035  kk=par(ic)
4036  nch(kk)=nch(kk)-1
4037 
4038  return
4039  end subroutine s3um
4040 
4041  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4042 
4043  subroutine s3um1(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4044 
4045  implicit none
4046 
4047  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),nch(:),par(:)
4048  real(kind=kreal), intent(in) :: diag(:,:)! zln(9,*),diag(6,*)
4049  real(kind=kreal), intent(out) :: zln(:,:)
4050  integer(kind=kint), intent(in) :: ic,neqns
4051 
4052  integer(kind=kint) :: i,j,k,l,ks,ke,jc,jj,ierr
4053  real(kind=kreal) :: s(9),zz(9)
4054  real(kind=kreal),allocatable :: temp(:,:)
4055  integer(kind=kint),allocatable :: indx(:)
4056 
4057  ierr=0
4058  allocate(temp(9,neqns),indx(neqns), stat=ierr)
4059  temp = 0.0d0
4060  indx = 0
4061 
4062  ks=xlnzr(ic)
4063  ke=xlnzr(ic+1)
4064  !$dir max_trip(9)
4065  do 100 l=1,9
4066  s(l)=0.0d0
4067 100 continue
4068  do 200 k=ks,ke-1
4069  jc=colno(k)
4070  indx(jc)=ic
4071 
4072  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4073  j=colno(jj)
4074  if(indx(j).eq.ic) then
4075  s(1)=s(1)+temp(1,j)*zln(1,jj)+temp(4,j)*zln(4,jj)+temp(7,j)*zln(7,jj)
4076  s(2)=s(2)+temp(2,j)*zln(1,jj)+temp(5,j)*zln(4,jj)+temp(8,j)*zln(7,jj)
4077  s(3)=s(3)+temp(3,j)*zln(1,jj)+temp(6,j)*zln(4,jj)+temp(9,j)*zln(7,jj)
4078  s(4)=s(4)+temp(1,j)*zln(2,jj)+temp(4,j)*zln(5,jj)+temp(7,j)*zln(8,jj)
4079  s(5)=s(5)+temp(2,j)*zln(2,jj)+temp(5,j)*zln(5,jj)+temp(8,j)*zln(8,jj)
4080  s(6)=s(6)+temp(3,j)*zln(2,jj)+temp(6,j)*zln(5,jj)+temp(9,j)*zln(8,jj)
4081  s(7)=s(7)+temp(1,j)*zln(3,jj)+temp(4,j)*zln(6,jj)+temp(7,j)*zln(9,jj)
4082  s(8)=s(8)+temp(2,j)*zln(3,jj)+temp(5,j)*zln(6,jj)+temp(8,j)*zln(9,jj)
4083  s(9)=s(9)+temp(3,j)*zln(3,jj)+temp(6,j)*zln(6,jj)+temp(9,j)*zln(9,jj)
4084  endif
4085 310 continue
4086  !$dir max_trip(9)
4087  do 320 l=1,9
4088  temp(l,jc)=zln(l,k)-s(l)
4089  zln(l,k)=temp(l,jc)
4090  s(l)=0.0d0
4091 320 continue
4092 
4093 200 continue
4094 
4095  deallocate(temp,indx)
4096  end subroutine s3um1
4097 
4098 
4099  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4100 
4101  subroutine s3um3(n,dsln,diag)
4102 
4103  implicit none
4104 
4105  real(kind=kreal), intent(out) :: dsln(:,:),diag(:,:)!dsln(9,*),diag(6,*)
4106  integer(kind=kint), intent(in) :: n
4107 
4108  real(kind=kreal) :: t(9)
4109  integer(kind=kint) :: i,j,k,l,loc,ir, ierr
4110  real(kind=kreal), allocatable :: temp(:,:)
4111  integer(kind=kint), allocatable :: indx(:)
4112 
4113  allocate(temp(9,n),indx(n), stat=ierr)
4114  if(ierr .ne. 0) then
4115  call errtrp('stop due to allocation error.')
4116  end if
4117 
4118  if(n.le.0) goto 1000
4119  indx(1)=1
4120  loc=1
4121  call inv3(diag(:,1),ir)
4122  do 100 i=2,n
4123  indx(i)=loc
4124  do 110 j=1,i-1
4125  call d3dot(t,dsln(:,indx(i):indx(i)+j-2), dsln(:,indx(j):indx(j)+j-2),j-1)
4126  !$dir max_trips(9)
4127  ! do 111 l=1,9
4128  ! dsln(l,loc)=dsln(l,loc)-t(l)
4129  ! 111 continue
4130  dsln(:,loc)=dsln(:,loc)-t(:)
4131  loc=loc+1
4132 110 continue
4133  call v3prod(dsln(:,indx(i):indx(i)+i-2), diag,temp,i-1)
4134  call d3dotl(t,temp,dsln(:,indx(i):indx(i)+i-2),i-1)
4135  !$dir max_trips(6)
4136  ! do 112 l=1,6
4137  ! diag(l,i)=diag(l,i)-t(l)
4138  ! 112 continue
4139  diag(:,i)=diag(:,i)-t(1:6)
4140  dsln(:,indx(i):indx(i)+i-2)=temp(:,1:i-1)
4141  call inv3(diag(:,i),ir)
4142 100 continue
4143 1000 continue
4144  return
4145  end subroutine s3um3
4146 
4147  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4148 
4149  subroutine d3sdot(wi,a,b,n)
4150 
4151  implicit none
4152 
4153  real(kind=kreal), intent(in) :: a(:,:),b(:,:) !wi(3),a(3,*),b(9,*) !
4154  real(kind=kreal), intent(out) :: wi(:)
4155  integer(kind=kint), intent(in) :: n
4156 
4157  integer(kind=kint) :: jj
4158  !
4159  !----------------------------------------------------------------------
4160  !
4161  ! spdot1 performs inner product of sparse vectors
4162  !
4163  !
4164  ! #coded by t.arakawa
4165  !
4166  !----------------------------------------------------------------------
4167  !
4168  do 100 jj=1,n
4169  wi(1)=wi(1)-a(1,jj)*b(1,jj)-a(2,jj)*b(4,jj)-a(3,jj)*b(7,jj)
4170  wi(2)=wi(2)-a(1,jj)*b(2,jj)-a(2,jj)*b(5,jj)-a(3,jj)*b(8,jj)
4171  wi(3)=wi(3)-a(1,jj)*b(3,jj)-a(2,jj)*b(6,jj)-a(3,jj)*b(9,jj)
4172 100 continue
4173  return
4174  end subroutine d3sdot
4175 
4176  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4177 
4178  subroutine s3pdot(bi,b,zln,colno,ks,ke)
4179 
4180  implicit none
4181 
4182  integer(kind=kint), intent(in) :: colno(:)
4183  real(kind=kreal), intent(in) :: zln(:,:),b(:,:) !zln(9,*),b(3,*),bi(3) !
4184  real(kind=kreal), intent(out) :: bi(:)
4185  integer(kind=kint), intent(in) :: ks,ke
4186 
4187  integer(kind=kint) :: j,jj
4188  !
4189  !----------------------------------------------------------------------
4190  !
4191  ! spdot1 performs inner product of sparse vectors
4192  !
4193  !
4194  ! #coded by t.arakawa
4195  !
4196  !----------------------------------------------------------------------
4197  !
4198  do 100 jj=ks,ke
4199  j=colno(jj)
4200  bi(1)=bi(1)-zln(1,jj)*b(1,j)-zln(4,jj)*b(2,j)-zln(7,jj)*b(3,j)
4201  bi(2)=bi(2)-zln(2,jj)*b(1,j)-zln(5,jj)*b(2,j)-zln(8,jj)*b(3,j)
4202  bi(3)=bi(3)-zln(3,jj)*b(1,j)-zln(6,jj)*b(2,j)-zln(9,jj)*b(3,j)
4203 100 continue
4204  return
4205  end subroutine s3pdot
4206 
4207  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4208 
4209  subroutine inv33(zln,zz,diag)
4210 
4211  implicit none
4212 
4213  real(kind=kreal), intent(in) :: zz(9),diag(6)
4214  real(kind=kreal), intent(out) :: zln(9)
4215 
4216  zln(4)=zz(4)-zz(1)*diag(2)
4217  zln(7)=zz(7)-zz(1)*diag(4)-zln(4)*diag(5)
4218  zln(1)=zz(1)*diag(1)
4219  zln(4)=zln(4)*diag(3)
4220  zln(7)=zln(7)*diag(6)
4221  zln(4)=zln(4)-zln(7)*diag(5)
4222  zln(1)=zln(1)-zln(4)*diag(2)-zln(7)*diag(4)
4223  !
4224  zln(5)=zz(5)-zz(2)*diag(2)
4225  zln(8)=zz(8)-zz(2)*diag(4)-zln(5)*diag(5)
4226  zln(2)=zz(2)*diag(1)
4227  zln(5)=zln(5)*diag(3)
4228  zln(8)=zln(8)*diag(6)
4229  zln(5)=zln(5)-zln(8)*diag(5)
4230  zln(2)=zln(2)-zln(5)*diag(2)-zln(8)*diag(4)
4231  !
4232  zln(6)=zz(6)-zz(3)*diag(2)
4233  zln(9)=zz(9)-zz(3)*diag(4)-zln(6)*diag(5)
4234  zln(3)=zz(3)*diag(1)
4235  zln(6)=zln(6)*diag(3)
4236  zln(9)=zln(9)*diag(6)
4237  zln(6)=zln(6)-zln(9)*diag(5)
4238  zln(3)=zln(3)-zln(6)*diag(2)-zln(9)*diag(4)
4239  return
4240  end subroutine inv33
4241 
4242  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4243 
4244  subroutine inv3(dsln,ir)
4245 
4246  implicit none
4247 
4248  real(kind=kreal) :: dsln(6),t(2)
4249  integer(kind=kint) :: ir
4250 
4251  ir=0
4252  if(dabs(dsln(1)).lt.rmin) then
4253  goto 999
4254  endif
4255  dsln(1)=1.0d0/dsln(1)
4256  t(1)=dsln(2)*dsln(1)
4257  dsln(3)=dsln(3)-t(1)*dsln(2)
4258  dsln(2)=t(1)
4259  if(dabs(dsln(3)).lt.rmin) then
4260  goto 999
4261  endif
4262  dsln(3)=1.0d0/dsln(3)
4263  t(1)=dsln(4)*dsln(1)
4264  dsln(5)=dsln(5)-dsln(2)*dsln(4)
4265  t(2)=dsln(5)*dsln(3)
4266  dsln(6)=dsln(6)-t(1)*dsln(4)-t(2)*dsln(5)
4267  dsln(4)=t(1)
4268  dsln(5)=t(2)
4269  if(dabs(dsln(6)).lt.rmin) then
4270  goto 999
4271  endif
4272  dsln(6)=1.0d0/dsln(6)
4273  ! write(6,*) "dsln",dsln(1),dsln(3),dsln(6)
4274  return
4275 999 continue
4276  write(ilog,*) "singular"
4277  dsln(1)=1.0d0
4278  dsln(2)=0.0d0
4279  dsln(3)=1.0d0
4280  dsln(4)=0.0d0
4281  dsln(5)=0.0d0
4282  dsln(6)=1.0d0
4283  return
4284  end subroutine inv3
4285 
4286  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4287 
4288  subroutine d3dot(t,a,b,n)
4289  implicit none
4290 
4291  real(kind=kreal), intent(in) :: a(:,:),b(:,:)
4292  real(kind=kreal), intent(out) :: t(:)
4293  integer(kind=kint),intent(in) :: n
4294 
4295  integer(kind=kint) :: l,jj
4296  ! double precision a(9,n),b(9,n)
4297  ! double precision t(9)
4298  !
4299  !----------------------------------------------------------------------
4300  !
4301  ! spdot1 performs inner product of sparse vectors
4302  !
4303  ! it might be 'DENS' kitayama
4304  !
4305  !
4306  ! #coded by t.arakawa
4307  !
4308  !----------------------------------------------------------------------
4309  !
4310  !$dir max_trips(9)
4311  do 10 l=1,9
4312  t(l)=0.0d0
4313 10 continue
4314  do 100 jj=1,n
4315  t(1)=t(1)+a(1,jj)*b(1,jj)+a(4,jj)*b(4,jj)+a(7,jj)*b(7,jj)
4316  t(2)=t(2)+a(2,jj)*b(1,jj)+a(5,jj)*b(4,jj)+a(8,jj)*b(7,jj)
4317  t(3)=t(3)+a(3,jj)*b(1,jj)+a(6,jj)*b(4,jj)+a(9,jj)*b(7,jj)
4318  t(4)=t(4)+a(1,jj)*b(2,jj)+a(4,jj)*b(5,jj)+a(7,jj)*b(8,jj)
4319  t(5)=t(5)+a(2,jj)*b(2,jj)+a(5,jj)*b(5,jj)+a(8,jj)*b(8,jj)
4320  t(6)=t(6)+a(3,jj)*b(2,jj)+a(6,jj)*b(5,jj)+a(9,jj)*b(8,jj)
4321  t(7)=t(7)+a(1,jj)*b(3,jj)+a(4,jj)*b(6,jj)+a(7,jj)*b(9,jj)
4322  t(8)=t(8)+a(2,jj)*b(3,jj)+a(5,jj)*b(6,jj)+a(8,jj)*b(9,jj)
4323  t(9)=t(9)+a(3,jj)*b(3,jj)+a(6,jj)*b(6,jj)+a(9,jj)*b(9,jj)
4324 100 continue
4325  return
4326  end subroutine d3dot
4327 
4328  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4329 
4330  subroutine v3prod(zln,diag,zz,n)
4331 
4332  implicit none
4333 
4334  real(kind=kreal), intent(in) :: zln(:,:),diag(:,:)
4335  real(kind=kreal), intent(out) :: zz(:,:)
4336  integer(kind=kint), intent(in) :: n
4337 
4338  integer(kind=kint) :: i
4339 
4340  do 100 i=1,n
4341  zz(4,i)=zln(4,i)-zln(1,i)*diag(2,i)
4342  zz(7,i)=zln(7,i)-zln(1,i)*diag(4,i)-zz(4,i)*diag(5,i)
4343  zz(1,i)=zln(1,i)*diag(1,i)
4344  zz(4,i)=zz(4,i)*diag(3,i)
4345  zz(7,i)=zz(7,i)*diag(6,i)
4346  zz(4,i)=zz(4,i)-zz(7,i)*diag(5,i)
4347  zz(1,i)=zz(1,i)-zz(4,i)*diag(2,i)-zz(7,i)*diag(4,i)
4348  !
4349  zz(5,i)=zln(5,i)-zln(2,i)*diag(2,i)
4350  zz(8,i)=zln(8,i)-zln(2,i)*diag(4,i)-zz(5,i)*diag(5,i)
4351  zz(2,i)=zln(2,i)*diag(1,i)
4352  zz(5,i)=zz(5,i)*diag(3,i)
4353  zz(8,i)=zz(8,i)*diag(6,i)
4354  zz(5,i)=zz(5,i)-zz(8,i)*diag(5,i)
4355  zz(2,i)=zz(2,i)-zz(5,i)*diag(2,i)-zz(8,i)*diag(4,i)
4356  !
4357  zz(6,i)=zln(6,i)-zln(3,i)*diag(2,i)
4358  zz(9,i)=zln(9,i)-zln(3,i)*diag(4,i)-zz(6,i)*diag(5,i)
4359  zz(3,i)=zln(3,i)*diag(1,i)
4360  zz(6,i)=zz(6,i)*diag(3,i)
4361  zz(9,i)=zz(9,i)*diag(6,i)
4362  zz(6,i)=zz(6,i)-zz(9,i)*diag(5,i)
4363  zz(3,i)=zz(3,i)-zz(6,i)*diag(2,i)-zz(9,i)*diag(4,i)
4364 100 continue
4365  return
4366  end subroutine v3prod
4367  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4368 
4369  subroutine d3dotl(t,a,b,n)
4370  implicit none
4371 
4372  real(kind=kreal), intent(in) :: a(:,:),b(:,:)
4373  real(kind=kreal), intent(out) :: t(:)
4374  integer(kind=kint), intent(in) :: n
4375 
4376  integer(kind=kint) :: l,jj
4377  ! double precision t(6),a(9,n),b(9,n)
4378  !
4379  !----------------------------------------------------------------------
4380  !
4381  ! spdot1 performs inner product of sparse vectors
4382  !
4383  !
4384  ! #coded by t.arakawa
4385  !
4386  !----------------------------------------------------------------------
4387  !
4388  !$dir max_trips(6)
4389  do 10 l=1,6
4390  t(l)=0.0d0
4391 10 continue
4392  do 100 jj=1,n
4393  t(1)=t(1)+a(1,jj)*b(1,jj)+a(4,jj)*b(4,jj)+a(7,jj)*b(7,jj)
4394  t(2)=t(2)+a(2,jj)*b(1,jj)+a(5,jj)*b(4,jj)+a(8,jj)*b(7,jj)
4395  t(3)=t(3)+a(2,jj)*b(2,jj)+a(5,jj)*b(5,jj)+a(8,jj)*b(8,jj)
4396  t(4)=t(4)+a(3,jj)*b(1,jj)+a(6,jj)*b(4,jj)+a(9,jj)*b(7,jj)
4397  t(5)=t(5)+a(3,jj)*b(2,jj)+a(6,jj)*b(5,jj)+a(9,jj)*b(8,jj)
4398  t(6)=t(6)+a(3,jj)*b(3,jj)+a(6,jj)*b(6,jj)+a(9,jj)*b(9,jj)
4399 100 continue
4400  return
4401  end subroutine d3dotl
4402 
4403  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4404 
4405  subroutine addr3(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ir)
4406 
4407  implicit none
4408 
4409  integer(kind=kint), intent(in) :: invp(:),xlnzr(:),colno(:)
4410  real(kind=kreal), intent(in) :: aij(:) !zln(9,*),diag(6,*),dsln(9,*),aij(9)
4411  real(kind=kreal), intent(out) :: zln(:,:),diag(:,:),dsln(:,:) !zln(9,*),diag(6,*),dsln(9,*),aij(9)
4412  integer(kind=kint), intent(in) :: isw,i,j,nstop
4413  integer(kind=kint), intent(out) :: ir
4414 
4415  integer(kind=kint), parameter :: ndeg2=9
4416  integer(kind=kint), parameter :: ndeg2l=6
4417  integer(kind=kint) :: k,l,ii,jj,itrans,i0,j0,ks,ke
4418 
4419  ir=0
4420  ii=invp(i)
4421  jj=invp(j)
4422  if(ldbg) write(idbg,*) 'addr3',ii,jj,aij
4423 
4424  ! diagonal
4425  if(ii.eq.jj) then
4426  diag(1,ii)=aij(1)
4427  diag(2,ii)=aij(2)
4428  diag(3,ii)=aij(5)
4429  diag(4,ii)=aij(3)
4430  diag(5,ii)=aij(6)
4431  diag(6,ii)=aij(9)
4432  goto 1000
4433  endif
4434  itrans=0
4435  if(jj.gt.ii) then
4436  k=jj
4437  jj=ii
4438  ii=k
4439  itrans=1
4440  endif
4441 
4442  ! D region
4443  if(jj.ge.nstop) then
4444  i0=ii-nstop
4445  j0=jj-nstop+1
4446  k=i0*(i0-1)/2+j0
4447  if(itrans.eq.0) then
4448  do 110 l=1,ndeg2
4449  dsln(l,k)=aij(l)
4450 110 continue
4451  goto 1000
4452  else
4453  dsln(1,k)=aij(1)
4454  dsln(2,k)=aij(4)
4455  dsln(3,k)=aij(7)
4456  dsln(4,k)=aij(2)
4457  dsln(5,k)=aij(5)
4458  dsln(6,k)=aij(8)
4459  dsln(7,k)=aij(3)
4460  dsln(8,k)=aij(6)
4461  dsln(9,k)=aij(9)
4462  goto 1000
4463  endif
4464  endif
4465 
4466  ! A and C region
4467  ks=xlnzr(ii)
4468  ke=xlnzr(ii+1)-1
4469  do 100 k=ks,ke
4470  if(colno(k).eq.jj) then
4471  if(itrans.eq.0) then
4472  do 120 l=1,ndeg2
4473  zln(l,k)=aij(l)
4474 120 continue
4475  else
4476  zln(1,k)=aij(1)
4477  zln(2,k)=aij(4)
4478  zln(3,k)=aij(7)
4479  zln(4,k)=aij(2)
4480  zln(5,k)=aij(5)
4481  zln(6,k)=aij(8)
4482  zln(7,k)=aij(3)
4483  zln(8,k)=aij(6)
4484  zln(9,k)=aij(9)
4485  endif
4486  goto 1000
4487  endif
4488 100 continue
4489  ir=20
4490 1000 continue
4491  return
4492  end subroutine addr3
4493 
4494  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4495 
4496  subroutine s2um(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4497 
4498  implicit none
4499 
4500  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
4501  integer(kind=kint), intent(out) :: nch(:)
4502  real(kind=kreal), intent(out) :: zln(:,:),diag(:,:) ! zln(6,*), diag(3,*)
4503  integer(kind=kint), intent(in) :: ic,neqns
4504 
4505  integer(kind=kint) :: i,j,k,l,ks,ke,jj,jc,ir,kk, ierr
4506  real(kind=kreal), allocatable :: temp(:,:)
4507  integer(kind=kint), allocatable :: indx(:)
4508  real(kind=kreal) :: s(4),zz(4),t(3)
4509 
4510  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4511  if(ierr .ne. 0) then
4512  call errtrp('stop due to allocation error.')
4513  end if
4514 
4515  ks=xlnzr(ic)
4516  ke=xlnzr(ic+1)
4517  t(1)=0.0d0
4518  t(2)=0.0d0
4519  t(3)=0.0d0
4520  do 200 k=ks,ke-1
4521  jc=colno(k)
4522  indx(jc)=ic
4523  do 210 l=1,4
4524  s(l)=0.0d0
4525  zz(l)=zln(l,k)
4526 210 continue
4527  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4528  j=colno(jj)
4529  if(indx(j).eq.ic) then
4530  zz(1)=zz(1)-temp(1,j)*zln(1,jj)-temp(3,j)*zln(3,jj)
4531  zz(2)=zz(2)-temp(2,j)*zln(1,jj)-temp(4,j)*zln(3,jj)
4532  zz(3)=zz(3)-temp(1,j)*zln(2,jj)-temp(3,j)*zln(4,jj)
4533  zz(4)=zz(4)-temp(2,j)*zln(2,jj)-temp(4,j)*zln(4,jj)
4534  endif
4535 310 continue
4536  call inv22(zln(:,k),zz,diag(:,jc))
4537  do 220 l=1,4
4538  temp(l,jc)=zz(l)
4539 220 continue
4540  t(1)=t(1)+zz(1)*zln(1,k)+zz(3)*zln(3,k)
4541  t(2)=t(2)+zz(2)*zln(1,k)+zz(4)*zln(3,k)
4542  t(3)=t(3)+zz(2)*zln(2,k)+zz(4)*zln(4,k)
4543 200 continue
4544  diag(1,ic)=diag(1,ic)-t(1)
4545  diag(2,ic)=diag(2,ic)-t(2)
4546  diag(3,ic)=diag(3,ic)-t(3)
4547  call inv2(diag(:,ic),ir)
4548  nch(ic)=-1
4549  kk=par(ic)
4550  nch(kk)=nch(kk)-1
4551  return
4552  end subroutine s2um
4553 
4554  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4555 
4556  subroutine s2um1(ic,xlnzr,colno,zln,diag,nch,par,neqns)
4557 
4558  implicit none
4559 
4560  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),nch(:),par(:)
4561  real(kind=kreal), intent(in) :: diag(:,:) !zln(4,*),diag(3,*)
4562  real(kind=kreal), intent(out) :: zln(:,:)
4563  integer(kind=kint), intent(in) :: ic,neqns
4564 
4565  integer(kind=kint) :: i,j,k,l,ks,ke,jc,jj, ierr
4566  real(kind=kreal) :: s(4),zz(4)
4567  real(kind=kreal), allocatable :: temp(:,:)
4568  integer(kind=kint), allocatable :: indx(:)
4569 
4570  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4571  if(ierr .ne. 0) then
4572  call errtrp('stop due to allocation error.')
4573  end if
4574 
4575  ks=xlnzr(ic)
4576  ke=xlnzr(ic+1)
4577  do 100 l=1,4
4578  s(l)=0.0d0
4579 100 continue
4580  do 200 k=ks,ke-1
4581  jc=colno(k)
4582  indx(jc)=ic
4583  do 310 jj=xlnzr(jc),xlnzr(jc+1)-1
4584  j=colno(jj)
4585  if(indx(j).eq.ic) then
4586  s(1)=s(1)+temp(1,j)*zln(1,jj)+temp(3,j)*zln(3,jj)
4587  s(2)=s(2)+temp(2,j)*zln(1,jj)+temp(4,j)*zln(3,jj)
4588  s(3)=s(3)+temp(1,j)*zln(2,jj)+temp(3,j)*zln(4,jj)
4589  s(4)=s(4)+temp(2,j)*zln(2,jj)+temp(4,j)*zln(4,jj)
4590  endif
4591 310 continue
4592  do 320 l=1,4
4593  temp(l,jc)=zln(l,k)-s(l)
4594  zln(l,k)=temp(l,jc)
4595  s(l)=0.0d0
4596 320 continue
4597 200 continue
4598  return
4599  end subroutine s2um1
4600 
4601  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4602 
4603  subroutine s2um2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
4604 
4605  implicit none
4606 
4607  integer(kind=kint), intent(in) :: neqns, nstop
4608  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
4609  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:)!zln(4,*),diag(3,*)
4610  integer(kind=kint), pointer :: spdslnidx(:)
4611  real(kind=kreal), pointer :: spdslnval(:,:)
4612  integer(kind=kint), intent(out) :: nspdsln
4613 
4614  integer(kind=kint) :: i,j,k,l,m,n, ic,ks,ke,ii,jj,jc,j1,j2,loc,ispdsln, ierr
4615  real(kind=kreal), allocatable :: temp(:,:)
4616  integer(kind=kint), allocatable :: indx(:)
4617  logical :: ftflag
4618 
4619  allocate(temp(4,neqns),indx(neqns), stat=ierr)
4620  if(ierr .ne. 0) then
4621  call errtrp('stop due to allocation error.')
4622  end if
4623 
4624  nspdsln=0
4625  do ic=nstop,neqns
4626  ks=xlnzr(ic)
4627  ke=xlnzr(ic+1)-1
4628  do k=ks,ke
4629  jj=colno(k)
4630  indx(jj)=ic
4631  end do
4632  do jc=nstop,ic-1
4633  j1=xlnzr(jc)
4634  j2=xlnzr(jc+1)
4635  do jj=xlnzr(jc),xlnzr(jc+1)-1
4636  j=colno(jj)
4637  if(indx(j).eq.ic) then
4638  nspdsln=nspdsln+1
4639  exit
4640  endif
4641  end do
4642  end do
4643  end do
4644  allocate(spdslnidx(nspdsln),spdslnval(4,nspdsln), stat=ierr)
4645  if(ierr .ne. 0) then
4646  call errtrp('stop due to allocation error.')
4647  end if
4648 
4649  loc=0
4650  ispdsln=0
4651  spdslnval=0
4652  ftflag = .true.
4653  do 100 ic=nstop,neqns
4654  ks=xlnzr(ic)
4655  ke=xlnzr(ic+1)-1
4656  do 110 k=ks,ke
4657  jj=colno(k)
4658  temp(1,jj)=zln(1,k)
4659  temp(2,jj)=zln(2,k)
4660  temp(3,jj)=zln(3,k)
4661  temp(4,jj)=zln(4,k)
4662  ! call inv22(zln(1,k),temp(1,jj),diag(1,jj))
4663  zln(3,k)=temp(3,jj)-temp(1,jj)*diag(2,jj)
4664  zln(1,k)=temp(1,jj)*diag(1,jj)
4665  zln(3,k)=zln(3,k)*diag(3,jj)
4666  zln(1,k)=zln(1,k)-zln(3,k)*diag(2,jj)
4667  !
4668  zln(4,k)=temp(4,jj)-temp(2,jj)*diag(2,jj)
4669  zln(2,k)=temp(2,jj)*diag(1,jj)
4670  zln(4,k)=zln(4,k)*diag(3,jj)
4671  zln(2,k)=zln(2,k)-zln(4,k)*diag(2,jj)
4672  !
4673  diag(1,ic)=diag(1,ic)-(temp(1,jj)*zln(1,k)+temp(3,jj)*zln(3,k))
4674  diag(2,ic)=diag(2,ic)-(temp(1,jj)*zln(2,k)+temp(3,jj)*zln(4,k))
4675  diag(3,ic)=diag(3,ic)-(temp(2,jj)*zln(2,k)+temp(4,jj)*zln(4,k))
4676  indx(jj)=ic
4677 110 continue
4678  do 120 jc=nstop,ic-1
4679  loc=loc+1
4680  do 220 jj=xlnzr(jc),xlnzr(jc+1)-1
4681  j=colno(jj)
4682  if(indx(j).eq.ic) then
4683  if (ftflag) then
4684  ispdsln=ispdsln+1
4685  ftflag=.false.
4686  end if
4687  spdslnidx(ispdsln)=loc
4688  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-(temp(1,j)*zln(1,jj)+temp(3,j)*zln(3,jj))
4689  spdslnval(2,ispdsln)=spdslnval(2,ispdsln)-(temp(2,j)*zln(1,jj)+temp(4,j)*zln(3,jj))
4690  spdslnval(3,ispdsln)=spdslnval(3,ispdsln)-(temp(1,j)*zln(2,jj)+temp(3,j)*zln(4,jj))
4691  spdslnval(4,ispdsln)=spdslnval(4,ispdsln)-(temp(2,j)*zln(2,jj)+temp(4,j)*zln(4,jj))
4692  endif
4693 220 continue
4694  ftflag = .true.
4695 120 continue
4696 100 continue
4697  return
4698  end subroutine s2um2_child
4699 
4700  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4701 
4702  subroutine inv22(zln,zz,diag)
4703 
4704  implicit none
4705 
4706  real(kind=kreal), intent(in) :: zz(4),diag(3)
4707  real(kind=kreal), intent(out) :: zln(4)
4708 
4709  zln(3)=zz(3)-zz(1)*diag(2)
4710  zln(1)=zz(1)*diag(1)
4711  zln(3)=zln(3)*diag(3)
4712  zln(1)=zln(1)-zln(3)*diag(2)
4713 
4714  zln(4)=zz(4)-zz(2)*diag(2)
4715  zln(2)=zz(2)*diag(1)
4716  zln(4)=zln(4)*diag(3)
4717  zln(2)=zln(2)-zln(4)*diag(2)
4718 
4719  return
4720  end subroutine inv22
4721 
4722  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4723 
4724  subroutine inv2(dsln,ir)
4725 
4726  implicit none
4727 
4728  real(kind=kreal), intent(out) :: dsln(3)
4729  integer(kind=kint), intent(out) :: ir
4730 
4731  real(kind=kreal) :: t
4732 
4733  ir=0
4734  if(dabs(dsln(1)).lt.rmin) then
4735  ir=10
4736  return
4737  endif
4738  dsln(1)=1.0d0/dsln(1)
4739  t=dsln(2)*dsln(1)
4740  dsln(3)=dsln(3)-t*dsln(2)
4741  dsln(2)=t
4742  if(dabs(dsln(3)).lt.rmin) then
4743  ir=10
4744  return
4745  endif
4746  dsln(3)=1.0d0/dsln(3)
4747  return
4748  end subroutine inv2
4749 
4750  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4751 
4752  subroutine d2sdot(wi,a,b,n)
4753 
4754  implicit none
4755 
4756  real(kind=kreal), intent(in) :: a(:,:),b(:,:)!wi(2),a(2,*),b(4,*)
4757  real(kind=kreal), intent(inout) :: wi(:)
4758  integer(kind=kint), intent(in) :: n
4759 
4760  integer(kind=kint) :: jj
4761  !
4762  !----------------------------------------------------------------------
4763  !
4764  ! d2sdot performs inner product of dens vectors
4765  !
4766  !
4767  ! #coded by t.arakawa
4768  !
4769  !----------------------------------------------------------------------
4770  !
4771  do 100 jj=1,n
4772  wi(1)=wi(1)-a(1,jj)*b(1,jj)-a(2,jj)*b(3,jj)
4773  wi(2)=wi(2)-a(1,jj)*b(2,jj)-a(2,jj)*b(4,jj)
4774 100 continue
4775  return
4776  end subroutine d2sdot
4777 
4778  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4779 
4780  subroutine s2pdot(bi,b,zln,colno,ks,ke)
4781 
4782  implicit none
4783 
4784  integer(kind=kint), intent(in) :: colno(:)
4785  integer(kind=kint), intent(in) :: ks,ke
4786  real(kind=kreal), intent(in) :: zln(:,:),b(:,:) !zln(4,*),b(2,*),bi(2)
4787  real(kind=kreal), intent(out) :: bi(:) !zln(4,*),b(2,*),bi(2)
4788 
4789  integer(kind=kint) :: jj,j
4790 
4791  !----------------------------------------------------------------------
4792  !
4793  ! s2pdot performs inner product of sparse vectors
4794  !
4795  !
4796  ! #coded by t.arakawa
4797  !
4798  !----------------------------------------------------------------------
4799 
4800  do 100 jj=ks,ke
4801  j=colno(jj)
4802  bi(1)=bi(1)-zln(1,jj)*b(1,j)-zln(3,jj)*b(2,j)
4803  bi(2)=bi(2)-zln(2,jj)*b(1,j)-zln(4,jj)*b(2,j)
4804 100 continue
4805  return
4806  end subroutine s2pdot
4807 
4808  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4809 
4810  subroutine addrx(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ndeg,ndeg2,ndeg2l,ir)
4811 
4812  implicit none
4813 
4814  integer(kind=kint), intent(in) :: invp(*),xlnzr(*),colno(*)
4815  real(kind=kreal), intent(in) :: aij(ndeg,ndeg)
4816  real(kind=kreal), intent(out) :: zln(ndeg,ndeg,*),diag(ndeg2l,*),dsln(ndeg,ndeg,*)
4817  integer(kind=kint), intent(in) :: isw,i,j,nstop,ndeg,ndeg2,ndeg2l
4818  integer(kind=kint), intent(out) :: ir
4819 
4820  integer(kind=kint) :: ii,jj,k,l,m,n,ks,ke,itrans,i0,j0
4821 
4822  ir=0
4823  ii=invp(i)
4824  jj=invp(j)
4825  if(ldbg) write(idbg,*) 'addrx',ii,jj,aij
4826  if(ii.eq.jj) then
4827  l=0
4828  do 100 n=1,ndeg
4829  do 110 m=1,n
4830  l=l+1
4831  diag(l,ii)=aij(n,m)
4832 110 continue
4833 100 continue
4834  goto 1000
4835  endif
4836  itrans=0
4837  if(jj.gt.ii) then
4838  k=jj
4839  jj=ii
4840  ii=k
4841  itrans=1
4842  endif
4843  if(jj.ge.nstop) then
4844  i0=ii-nstop
4845  j0=jj-nstop+1
4846  k=i0*(i0-1)/2+j0
4847  if(itrans.eq.0) then
4848  do 120 m=1,ndeg
4849  do 130 n=1,ndeg
4850  dsln(n,m,k)=aij(n,m)
4851 130 continue
4852 120 continue
4853  goto 1000
4854  else
4855  do 140 m=1,ndeg
4856  do 150 n=1,ndeg
4857  dsln(n,m,k)=aij(m,n)
4858 150 continue
4859 140 continue
4860  goto 1000
4861  endif
4862  endif
4863  ks=xlnzr(ii)
4864  ke=xlnzr(ii+1)-1
4865  do 200 k=ks,ke
4866  if(colno(k).eq.jj) then
4867  if(itrans.eq.0) then
4868  do 160 m=1,ndeg
4869  do 170 n=1,ndeg
4870  zln(n,m,k)=aij(n,m)
4871 170 continue
4872 160 continue
4873  else
4874  do 180 m=1,ndeg
4875  do 190 n=1,ndeg
4876  zln(n,m,k)=aij(m,n)
4877 190 continue
4878 180 continue
4879  endif
4880  goto 1000
4881  endif
4882 200 continue
4883  ir=20
4884 1000 continue
4885  return
4886  end subroutine addrx
4887 
4888  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4889 
4890  subroutine dxdot(ndeg,t,a,b,l)
4891 
4892  implicit none
4893 
4894  real(kind=kreal), intent(in) :: a(ndeg,ndeg,*),b(ndeg,ndeg,*)
4895  real(kind=kreal), intent(out) :: t(ndeg,ndeg)
4896  integer(kind=kint), intent(in) :: ndeg,l
4897 
4898  integer(kind=kint) :: k,jj,n,m
4899  !
4900  !----------------------------------------------------------------------
4901  !
4902  ! spdot1 performs inner product of sparse vectors
4903  !
4904  !
4905  ! #coded by t.arakawa
4906  !
4907  !----------------------------------------------------------------------
4908  !
4909  do n=1,ndeg
4910  do m=1,ndeg
4911  t(n,m)=0.0d0
4912  do k=1,ndeg
4913  do jj=1,l
4914  t(n,m)=t(n,m)+a(n,k,jj)*b(m,k,jj)
4915  enddo
4916  enddo
4917  enddo
4918  enddo
4919  return
4920  end subroutine dxdot
4921 
4922  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4923 
4924  subroutine dxdotl(ndeg,t,a,b,l)
4925 
4926  implicit none
4927 
4928  real(kind=kreal), intent(in) :: a(ndeg,ndeg,*),b(ndeg,ndeg,*)
4929  real(kind=kreal), intent(out) :: t(ndeg,ndeg)
4930  integer(kind=kint), intent(in) :: ndeg,l
4931 
4932  integer(kind=kint) :: n,m,jj,k
4933  !
4934  !----------------------------------------------------------------------
4935  !
4936  ! spdot1 performs inner product of sparse vectors
4937  !
4938  !
4939  ! #coded by t.arakawa
4940  !
4941  !----------------------------------------------------------------------
4942  !
4943  do n=1,ndeg
4944  do m=1,n
4945  t(n,m)=0.0d0
4946  do k=1,ndeg
4947  do jj=1,l
4948  t(n,m)=t(n,m)+a(n,k,jj)*b(m,k,jj)
4949  enddo
4950  enddo
4951  enddo
4952  enddo
4953  return
4954  end subroutine dxdotl
4955 
4956  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4957 
4958  subroutine dxsdot(ndeg,wi,a,b,n)
4959 
4960  implicit none
4961 
4962  real(kind=kreal), intent(in) :: a(ndeg,*),b(ndeg,ndeg,*)
4963  real(kind=kreal), intent(out) :: wi(ndeg)
4964  integer(kind=kint), intent(in) :: ndeg, n
4965 
4966  integer(kind=kint) :: jj, k, l
4967  !
4968  !----------------------------------------------------------------------
4969  !
4970  ! dxsdot performs inner product of dens vectors
4971  !
4972  !
4973  ! #coded by t.arakawa
4974  ! #reviced by t.kitayama 20071122
4975  !
4976  !----------------------------------------------------------------------
4977  !
4978  do jj=1,n
4979  do k=1,ndeg
4980  do l=1,ndeg
4981  wi(l)=wi(l)-b(l,k,jj)*a(k,jj)
4982  end do
4983  end do
4984  end do
4985  return
4986  end subroutine dxsdot
4987 
4988  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4989 
4990  subroutine invx(dsln,ndeg,ir)
4991 
4992  implicit none
4993 
4994  real(kind=kreal), intent(inout) :: dsln(*)
4995  integer(kind=kint), intent(in) :: ndeg
4996  integer(kind=kint), intent(out) :: ir
4997 
4998  integer(kind=kint) :: i,j,k,l,ld,l0,k0,ll
4999  real(kind=kreal) :: tem,t
5000 
5001  ir=0
5002  l=1
5003  dsln(1)=1.0d0/dsln(1)
5004  do 100 i=2,ndeg
5005  ld=0
5006  l0=l
5007  do 110 j=1,i-1
5008  l=l+1
5009  do 120 k=1,j-1
5010  ld=ld+1
5011  dsln(l)=dsln(l)-dsln(l0+k)*dsln(ld)
5012 120 continue
5013  ld=ld+1
5014 110 continue
5015  t=0.0d0
5016  k0=0
5017  ll=0
5018  do 130 k=l-i+2,l
5019  ll=ll+1
5020  k0=k0+ll
5021  tem=dsln(k)*dsln(k0)
5022  t=t+tem*dsln(k)
5023  dsln(k)=tem
5024 130 continue
5025  l=l+1
5026  dsln(l)=dsln(l)-t
5027  dsln(l)=1.0d0/dsln(l)
5028 100 continue
5029  return
5030  end subroutine invx
5031 
5032  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5033 
5034  subroutine invxx(zln,zz,diag,ndeg)
5035 
5036  implicit none
5037 
5038  real(kind=kreal), intent(in) :: zz(ndeg,ndeg),diag(*)
5039  real(kind=kreal), intent(out) :: zln(ndeg,ndeg)
5040  integer(kind=kint), intent(in) :: ndeg
5041 
5042  integer(kind=kint) :: i,j,k,l,m,n,loc,loc1
5043 
5044  zln=zz
5045  do l=1,ndeg
5046  loc=0
5047  do m=1,ndeg
5048  loc=loc+m
5049  loc1=loc+m
5050  do n=m+1,ndeg
5051  zln(l,n)=zln(l,n)-zln(l,m)*diag(loc1)
5052  loc1=loc1+n
5053  enddo
5054  enddo
5055  loc=0
5056  do m=1,ndeg
5057  loc=loc+m
5058  zln(l,m)=zln(l,m)*diag(loc)
5059  enddo
5060  do n=ndeg,1,-1
5061  loc=loc-1
5062  do m=n-1,1,-1
5063  zln(l,m)=zln(l,m)-zln(l,n)*diag(loc)
5064  loc=loc-1
5065  enddo
5066  enddo
5067  enddo
5068  return
5069  end subroutine invxx
5070 
5071  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5072 
5073  subroutine sxpdot(ndeg,bi,b,zln,colno,ks,ke)
5074 
5075  implicit none
5076 
5077  integer(kind=kint), intent(in) :: colno(*)
5078  real(kind=kreal), intent(in) :: zln(ndeg,ndeg,*),b(ndeg,*)
5079  real(kind=kreal), intent(out) :: bi(ndeg)
5080  integer(kind=kint),intent(in) :: ndeg,ks,ke
5081 
5082  integer(kind=kint) :: j,jj,m,n
5083  !
5084  !----------------------------------------------------------------------
5085  !
5086  ! sxpdot performs inner product of sparse vectors
5087  !
5088  !
5089  ! #coded by t.arakawa
5090  !
5091  !----------------------------------------------------------------------
5092  !
5093  do jj=ks,ke
5094  j=colno(jj)
5095  do m=1,ndeg
5096  do n=1,ndeg
5097  bi(n)=bi(n)-zln(n,m,jj)*b(m,j)
5098  enddo
5099  enddo
5100  enddo
5101  return
5102  end subroutine sxpdot
5103 
5104  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5105 
5106  subroutine sxum(ic,xlnzr,colno,zln,diag,nch,par,neqns,ndeg,ndegl)
5107 
5108  implicit none
5109 
5110  integer(kind=kint), intent(in) :: xlnzr(*),colno(*),par(*)
5111  integer(kind=kint), intent(out) :: nch(*)
5112  real(kind=kreal), intent(out) :: zln(ndeg,ndeg,*),diag(ndegl,*)
5113  integer(kind=kint), intent(in) :: ic,neqns,ndeg,ndegl
5114 
5115  real(kind=kreal) :: zz(ndeg,ndeg),t(ndegl)
5116  integer(kind=kint) :: i,j,k,l,m,n,ndeg22,ks,ke,jc,loc,jj,kk,ir, ierr
5117  real(kind=kreal),allocatable :: temp(:,:,:)
5118  integer(kind=kint),allocatable :: indx(:)
5119 
5120  ndeg22=ndeg*ndeg
5121  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5122  if(ierr .ne. 0) then
5123  call errtrp('stop due to allocation error.')
5124  end if
5125 
5126  ks=xlnzr(ic)
5127  ke=xlnzr(ic+1)
5128  t=0.0
5129 
5130  do k=ks,ke-1
5131  jc=colno(k)
5132  indx(jc)=ic
5133  zz=zln(:,:,k)
5134  do jj=xlnzr(jc),xlnzr(jc+1)-1
5135  j=colno(jj)
5136  if(indx(j).eq.ic) then
5137  do m=1,ndeg
5138  do n=1,ndeg
5139  do kk=1,ndeg
5140  zz(n,m)=zz(n,m)-temp(n,kk,j)*zln(m,kk,jj)
5141  enddo
5142  enddo
5143  enddo
5144  endif
5145  enddo
5146  call invxx(zln(1,1,k),zz,diag(1,jc),ndeg)
5147  temp(:,:,jc)=zz
5148  loc=0
5149  do n=1,ndeg
5150  do m=1,n
5151  loc=loc+1
5152  do kk=1,ndeg
5153  t(loc)=t(loc)+zz(n,kk)*zln(m,kk,k)
5154  enddo
5155  enddo
5156  enddo
5157  enddo
5158  diag(:,ic)=diag(:,ic)-t
5159  call invx(diag(1,ic),ndeg,ir)
5160  nch(ic)=-1
5161  kk=par(ic)
5162  nch(kk)=nch(kk)-1
5163  return
5164  end subroutine sxum
5165 
5166  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5167 
5168  subroutine sxum1(ic,xlnzr,colno,zln,diag,nch,par,neqns,ndeg,ndegl)
5169 
5170  implicit none
5171 
5172  integer(kind=kint), intent(in) :: xlnzr(*),colno(*),nch(*),par(*)
5173  real(kind=kreal), intent(in) :: diag(ndegl,*)
5174  real(kind=kreal), intent(out) :: zln(ndeg,ndeg,*)
5175  integer(kind=kint), intent(in) :: ic,neqns,ndeg,ndegl
5176 
5177  real(kind=kreal) :: s(ndeg,ndeg)
5178  integer(kind=kint) :: i,j,k,l,m,n,ks,ke,jc,jj,kk, ierr
5179  real(kind=kreal),allocatable :: temp(:,:,:)
5180  integer(kind=kint),allocatable :: indx(:)
5181 
5182  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5183  if(ierr .ne. 0) then
5184  call errtrp('stop due to allocation error.')
5185  end if
5186  ks=xlnzr(ic)
5187  ke=xlnzr(ic+1)
5188  do m=1,ndeg
5189  do n=1,ndeg
5190  s(n,m)=0.0d0
5191  enddo
5192  enddo
5193  do k=ks,ke-1
5194  jc=colno(k)
5195  indx(jc)=ic
5196  do jj=xlnzr(jc),xlnzr(jc+1)-1
5197  j=colno(jj)
5198  if(indx(j).eq.ic) then
5199  do m=1,ndeg
5200  do n=1,ndeg
5201  do kk=1,ndeg
5202  s(n,m)=s(n,m)+temp(n,kk,j)*zln(m,kk,jj)
5203  enddo
5204  enddo
5205  enddo
5206  endif
5207  enddo
5208  do m=1,ndeg
5209  do n=1,ndeg
5210  temp(n,m,jc)=zln(n,m,k)-s(n,m)
5211  zln(n,m,k)=temp(n,m,jc)
5212  s(n,m)=0.0d0
5213  enddo
5214  enddo
5215  enddo
5216  return
5217  end subroutine sxum1
5218 
5219  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5220 
5221  subroutine sxum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln,ndeg,ndegl)
5222 
5223  implicit none
5224 
5225  integer(kind=kint), intent(in) :: neqns, nstop
5226  integer(kind=kint), intent(in) :: xlnzr(*),colno(*)
5227  real(kind=kreal), intent(inout) :: zln(ndeg,ndeg,*),diag(ndegl,*)
5228  integer(kind=kint), pointer :: spdslnidx(:)
5229  real(kind=kreal), pointer :: spdslnval(:,:)
5230  integer(kind=kint), intent(out) :: nspdsln
5231  integer(kind=kint), intent(in) :: ndeg, ndegl
5232 
5233  integer(kind=kint) :: i,j,k,l,m,n, ic,ks,ke,ii,jj,jc,j1,j2,loc,locd,kk, ierr
5234  integer(kind=kint) :: ispdsln
5235  real(kind=kreal), allocatable :: temp(:,:,:)
5236  integer(kind=kint), allocatable :: indx(:)
5237  logical :: ftflag
5238 
5239  allocate(temp(ndeg,ndeg,neqns),indx(neqns), stat=ierr)
5240  if(ierr .ne. 0) then
5241  call errtrp('stop due to allocation error.')
5242  end if
5243 
5244  nspdsln=0
5245  do ic=nstop,neqns
5246  ks=xlnzr(ic)
5247  ke=xlnzr(ic+1)-1
5248  do k=ks,ke
5249  jj=colno(k)
5250  indx(jj)=ic
5251  end do
5252  do jc=nstop,ic-1
5253  j1=xlnzr(jc)
5254  j2=xlnzr(jc+1)
5255  do jj=xlnzr(jc),xlnzr(jc+1)-1
5256  j=colno(jj)
5257  if(indx(j).eq.ic) then
5258  nspdsln=nspdsln+1
5259  exit
5260  endif
5261  end do
5262  end do
5263  end do
5264  allocate(spdslnidx(nspdsln),spdslnval(ndeg*ndeg,nspdsln), stat=ierr)
5265  if(ierr .ne. 0) then
5266  call errtrp('stop due to allocation error.')
5267  end if
5268 
5269  loc=0
5270  ispdsln=0
5271  spdslnval=0
5272  ftflag = .true.
5273  do ic=nstop,neqns
5274  ks=xlnzr(ic)
5275  ke=xlnzr(ic+1)-1
5276  do k=ks,ke
5277  jj=colno(k)
5278  do m=1,ndeg
5279  do n=1,ndeg
5280  temp(n,m,jj)=zln(n,m,k)
5281  indx(jj)=ic
5282  enddo
5283  enddo
5284  enddo
5285  do k=ks,ke
5286  jj=colno(k)
5287  call invxx(zln(1,1,k),temp(1,1,jj),diag(1,jj),ndeg)
5288  enddo
5289  !
5290  locd=0
5291  do n=1,ndeg
5292  do m=1,n
5293  locd=locd+1
5294  do k=ks,ke
5295  jj=colno(k)
5296  do kk=1,ndeg
5297  diag(locd,ic)=diag(locd,ic)-temp(n,kk,jj)*zln(m,kk,k)
5298  enddo
5299  enddo
5300  enddo
5301  enddo
5302  do jc=nstop,ic-1
5303  loc=loc+1
5304  j1=xlnzr(jc)
5305  j2=xlnzr(jc+1)
5306  do jj=xlnzr(jc),xlnzr(jc+1)-1
5307  j=colno(jj)
5308  if(indx(j).eq.ic) then
5309  if (ftflag) then
5310  ispdsln=ispdsln+1
5311  ftflag=.false.
5312  end if
5313  spdslnidx(ispdsln)=loc
5314  do m=1,ndeg
5315  do n=1,ndeg
5316  do k=1,ndeg
5317  spdslnval(ndeg*(m-1)+n,ispdsln)=spdslnval(ndeg*(m-1)+n,ispdsln)-temp(n,k,j)*zln(m,k,jj)
5318  enddo
5319  enddo
5320  enddo
5321  endif
5322  enddo
5323  ftflag = .true.
5324  enddo
5325  enddo
5326  return
5327  end subroutine sxum2_child
5328 
5329  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5330 
5331  subroutine sxum3(neqns,dsln,diag,ndeg,ndegl)
5332 
5333  implicit none
5334 
5335  real(kind=kreal), intent(inout):: dsln(ndeg,ndeg,*),diag(ndegl,*)
5336  integer(kind=kint), intent(in) :: neqns, ndeg, ndegl
5337 
5338  integer(kind=kint) :: loc, locd, ir, i,j,n,m, ierr
5339  integer(kind=kint), allocatable :: indx(:)
5340  real(kind=kreal), allocatable :: temp(:,:,:)
5341  real(kind=kreal), allocatable :: t(:,:)
5342 
5343  allocate(indx(neqns),temp(ndeg,ndeg,neqns),t(ndeg,ndeg), stat=ierr)
5344  if(ierr .ne. 0) then
5345  call errtrp('stop due to allocation error.')
5346  end if
5347 
5348  if(neqns.le.0) goto 1000
5349  indx(1)=1 ! it will work...
5350  loc=1
5351  call invx(diag(1,1),ndeg,ir)
5352  do i=2,neqns
5353  indx(i)=loc
5354  do j=1,i-1
5355  call dxdot(ndeg,t,dsln(1,1,indx(i)),dsln(1,1,indx(j)),j-1)
5356  do m=1,ndeg
5357  do n=1,ndeg
5358  dsln(n,m,loc)=dsln(n,m,loc)-t(n,m)
5359  enddo
5360  enddo
5361  loc=loc+1
5362  enddo
5363  call vxprod(ndeg,ndegl,dsln(1,1,indx(i)),diag,temp,i-1)
5364  call dxdotl(ndeg,t,temp,dsln(1,1,indx(i)),i-1)
5365  locd=0
5366  do n=1,ndeg
5367  do m=1,n
5368  locd=locd+1
5369  diag(locd,i)=diag(locd,i)-t(n,m)
5370  enddo
5371  enddo
5372  call vcopy(temp,dsln(1,1,indx(i)),ndeg*ndeg*(i-1))
5373  call invx(diag(1,i),ndeg,ir)
5374  enddo
5375 1000 continue
5376  return
5377  end subroutine sxum3
5378 
5379  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5380  subroutine vcopy(a,c,n)
5381  implicit none
5382 
5383  integer(kind=kint) :: n
5384  real(kind=kreal) :: a(n),c(n)
5385  ! do 100 i=1,n
5386  ! c(i)=a(i)
5387  ! 100 continue
5388  c=a
5389  return
5390  end subroutine vcopy
5391 
5392  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5393 
5394  subroutine verif0(neqns,ndeg,nttbr,irow,jcol,val,rhs,x)
5395 
5396  implicit none
5397 
5398  integer(kind=kint), intent(in) :: irow(*),jcol(*)
5399  integer(kind=kint), intent(in) :: neqns,ndeg,nttbr
5400  real(kind=kreal), intent(in) :: val(ndeg,ndeg,*),x(ndeg,*)
5401  real(kind=kreal), intent(out) :: rhs(ndeg,*)
5402 
5403  integer(kind=kint) :: i,j,k,l,m
5404  real(kind=kreal) :: rel,err
5405  !
5406  !----------------------------------------------------------------------
5407  !
5408  ! verify the solution(symmetric matrix)
5409  !
5410  !----------------------------------------------------------------------
5411  !
5412  rel=0.0d0
5413  do i=1,neqns
5414  do l=1,ndeg
5415  rel=rel+dabs(rhs(l,i))
5416  enddo
5417  enddo
5418  do k=1,nttbr
5419  i=irow(k)
5420  j=jcol(k)
5421  do l=1,ndeg
5422  do m=1,ndeg
5423  rhs(l,i)=rhs(l,i)-val(l,m,k)*x(m,j)
5424  if(i.ne.j) rhs(l,j)=rhs(l,j)-val(m,l,k)*x(m,i)
5425  enddo
5426  enddo
5427  enddo
5428  err=0.0d0
5429  do i=1,neqns
5430  do l=1,ndeg
5431  err=err+dabs(rhs(l,i))
5432  enddo
5433  enddo
5434  if (m_pds_procinfo%myid .eq. 0) then
5435  write(imsg,6000) err,rel,err/rel
5436  end if
5437 6000 format(' ***verification***(symmetric)'/&
5438  & 'norm(Ax-b) = ',1pd20.10/&
5439  & 'norm(b) = ',1pd20.10/&
5440  & 'norm(Ax-b)/norm(b) = ',1pd20.10)
5441 6010 format(1p4d15.7)
5442  return
5443  end subroutine verif0
5444 
5445  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5446 
5447  subroutine vxprod(ndeg,ndegl,zln,diag,zz,n)
5448 
5449  implicit none
5450 
5451  real(kind=kreal), intent(in) :: zln(ndeg*ndeg,n),diag(ndegl,n)
5452  real(kind=kreal), intent(out) :: zz(ndeg*ndeg,n)
5453  integer(kind=kint), intent(in) :: ndeg,ndegl,n
5454 
5455  integer(kind=kint) :: i
5456 
5457  do 100 i=1,n
5458  call invxx(zz(1,i),zln(1,i),diag(1,i),ndeg)
5459 100 continue
5460  return
5461  end subroutine vxprod
5462 
5463  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5464 
5465 #endif
5466 
subroutine verif0(Neqns, Ndeg, Nttbr, Irow, Jcol, Val, Rhs, X)
subroutine idntty(Neqns, Invp, Iperm)
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
integer(kind=kint) function hecmw_comm_get_comm()
integer(kind=4), parameter kreal
subroutine hecmw_abort(comm)
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)