FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_solver_direct_serial_lag.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 
11 
12  ! access control !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
13 
14  private ! default
15 
16  public hecmw_solve_direct_serial_lag ! only entry point of Parallel Direct Solver is public
17 
18  ! internal type definition !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
19 
20 
21  type dsinfo ! direct solver information
22  integer(kind=kint) :: ndeg ! dimension of small matrix
23  integer(kind=kint) :: neqns ! number of equations
24  integer(kind=kint) :: nstop ! beginning point of C
25  integer(kind=kint) :: stage ! calculation stage
26  integer(kind=kint) :: lncol ! length of col
27  integer(kind=kint) :: lndsln ! length of dsln
28 
29  integer(kind=kint), pointer :: zpiv(:) ! in zpivot()
30  integer(kind=kint), pointer :: iperm(:) ! permtation vector
31  integer(kind=kint), pointer :: invp(:) ! inverse permtation of iperm
32  integer(kind=kint), pointer :: parent(:) !
33  integer(kind=kint), pointer :: nch(:) !
34  integer(kind=kint), pointer :: xlnzr(:) ! ia index of whole sparse matrix. (neqns_t + 1)
35  integer(kind=kint), pointer :: colno(:) ! ja index of whole sparse matrix.
36 
37  real(kind=kreal), pointer :: diag(:,:) ! diagonal element
38  real(kind=kreal), pointer :: zln(:,:) ! non diagonal sparse
39  real(kind=kreal), pointer :: dsln(:,:) ! non diagonal dens
40  end type dsinfo
41 
42  ! internal global variables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
43 
44  real(kind=kreal), parameter :: rmin = 1.00d-200 ! for inv3() pivot
45 
46  integer :: imsg ! output file handler
47 
48  integer, parameter :: ilog = 16 ! according to FSTR
49  logical, parameter :: ldbg = .false.
50  !integer, parameter :: idbg = 52 ! according to FSTR
51  integer :: idbg = 10 ! debug output fort.*
52  logical :: lelap = .false. ! debug out
53 
54 contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
55 
56  subroutine hecmw_solve_direct_serial_lag(nrows, ilag_sta, nttbr, pointers, indices, values, b)
57  ! wrapper for parallel direct solver hecmw_solve_direct_parallel_internal()
58 
59  implicit none
60 
61 
62  ! arguments !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
63 
64  ! input
65  ! CRS style matrix
66  integer(kind=kint), intent(in) :: nrows ! number of rows of whole square matrix, including lagrange elements
67  integer(kind=kint), intent(in) :: ilag_sta ! row index of start point of lagrange elements
68  integer(kind=kint), intent(in) :: nttbr ! number of none zero elements of whole square matrix. include lagrange elements and both lower, upper matrix
69  integer(kind=kint), intent(in) :: pointers(:) ! whole matrix in CRS format. size is (0:nrows)
70  integer(kind=kint), intent(in) :: indices(:) ! whole matrix in CRS format. size is (nttbr)
71  real(kind=kreal), intent(in) :: values(:) ! whole matrix in CRS format. size is (nttbr)
72 
73  !input/output
74  real(kind=kreal), intent(inout) :: b(:) ! right hand side vector. result will return via this array.
75 
76 
77  ! internal valuables !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
78 
79  ! stiffness matrix
80  type(irjc_square_matrix), target :: a0
81 
82  ! lagrange elements
83  type(irjc_mn_matrix), target :: lag
84 
85  ! degree of freedom is fixed as 1
86  integer(kind=kint), parameter :: ndeg_prm = 1
87 
88  ! for ASTOM matrix
89  type(irjc_square_matrix), target :: a0tmp
90  type(irjc_mn_matrix), target :: lagtmp
91 
92  ! misc
93  integer(kind=kint) :: i,j,k,l,ii,jj,kk,ll
94 
95  ! change CRS style matrix to irow jcol style !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
96 
97  ! set up a0
98  a0%neqns = ilag_sta - 1 ! non lagrange region only
99  a0%ndeg = ndeg_prm
100 
101  ! count ordinally A0 elements in upper triangle matrix from ASTOM
102  a0%nttbr = 0
103  do i= 1, nrows
104  do l= pointers(i), pointers(i+1)-1
105  j= indices(l)
106  if (j .le. a0%neqns) then
107  a0%nttbr = a0%nttbr+1
108  end if
109  enddo
110  enddo
111  !write (idbg,*) 'a0%nttbr', a0%nttbr
112  allocate( a0%irow(a0%nttbr), a0%jcol(a0%nttbr), a0%val(ndeg_prm,a0%nttbr))
113  allocate( a0tmp%irow(a0%nttbr), a0tmp%jcol(a0%nttbr), a0tmp%val(ndeg_prm,a0%nttbr))
114 
115  kk = 0
116  do i= 1, nrows
117  do l= pointers(i), pointers(i+1)-1
118  j= indices(l)
119  if (j .le. a0%neqns) then
120  !*Lower
121  kk = kk + 1
122  a0tmp%irow(kk) = i
123  a0tmp%jcol(kk) = j
124  a0tmp%val(1,kk)=values(l)
125  end if
126  enddo
127  enddo
128 
129  ! exchange irow and jcol, reordering
130  kk=0
131  do i=1,a0%neqns
132  do k=1,a0%nttbr
133  if (a0tmp%jcol(k) == i) then
134  kk=kk+1
135  a0%irow(kk)=a0tmp%jcol(k)
136  a0%jcol(kk)=a0tmp%irow(k)
137  a0%val(1,kk)=a0tmp%val(1,k)
138  end if
139  end do
140  end do
141 
142  ! set up lagrange elements !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
143  lag%nrows = nrows - ilag_sta + 1 ! number of rows of lagrange region
144  lag%ncols = ilag_sta - 1 ! none lagrange region only
145  lag%ndeg = ndeg_prm
146 
147  ! count and allocate lagrange matrix
148  lag%nttbr = 0
149  do i= 1, nrows ! loop for whole matrix
150  do l= pointers(i), pointers(i+1)-1
151  j= indices(l)
152  if ((j .ge. ilag_sta) .and. (i .lt. ilag_sta) ) then
153  lag%nttbr = lag%nttbr+1
154  end if
155  enddo
156  enddo
157  !write (idbg,*) 'lag%nttbr', lag%nttbr
158  allocate( lag%irow(lag%nttbr), lag%jcol(lag%nttbr), lag%val(ndeg_prm,lag%nttbr))
159  allocate( lagtmp%irow(lag%nttbr), lagtmp%jcol(lag%nttbr), lagtmp%val(ndeg_prm,lag%nttbr))
160 
161  kk = 0
162  do i= 1, nrows
163  do l= pointers(i), pointers(i+1)-1
164  j= indices(l)
165  if ((j .ge. ilag_sta) .and. (i .lt. ilag_sta) ) then
166  kk = kk + 1
167  lagtmp%irow(kk) = i
168  lagtmp%jcol(kk) = j - ilag_sta +1
169  lagtmp%val(1,kk)=values(l)
170  end if
171  enddo
172  enddo
173 
174  ! exchange irow and jcol, reordering
175  kk=0
176  do i=1,lag%nrows
177  do k=1,lag%nttbr
178  if (lagtmp%jcol(k) == i) then
179  kk=kk+1
180  lag%irow(kk)=lagtmp%jcol(k)
181  lag%jcol(kk)=lagtmp%irow(k)
182  lag%val(1,kk)=lagtmp%val(1,k)
183  end if
184  end do
185  end do
186  call hecmw_solve_direct_serial_lag_in(a0,lag, b)
187 
188  return
189  end subroutine hecmw_solve_direct_serial_lag
190 
191  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
192 
193  subroutine hecmw_solve_direct_serial_lag_in(a0,lag, b)
194 
195  implicit none
196 
197 
198  type (irjc_square_matrix), intent(inout) :: a0 ! given left side matrix assembled from sp_matrix
199  type (irjc_mn_matrix), intent(inout) :: lag ! lagrange elements
200  real(kind=kreal), intent(inout) :: b(:) ! (a0%neqns) right hand side value vector include both original stifness matrix and followed by lagrange right hand side value.
201 
202  logical, save :: first_time = .true.
203 
204  integer(kind=kint) :: ierr
205 
206 
207  ! start !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
208 
209  imsg=99 ! set message file
210 
211  call sp_direct_parent(a0,lag,b)
212 
213  return
214  end subroutine hecmw_solve_direct_serial_lag_in
215 
216  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
217 
218  subroutine sp_direct_parent(a0, lag, b_in)
219 
220  implicit none
221 
222 
223  !I/O !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
224  ! given A0 x = b0
225  type (irjc_square_matrix), intent(inout) :: a0 ! given left side matrix assembled from sp_matrix
226  type (irjc_mn_matrix), intent(inout) :: lag ! lagrange elements
227  real(kind=kreal), intent(inout) :: b_in(:) ! (ndeg,neqns) right hand side value vector of equation.
228 
229  !internal !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
230 
231 
232  ! for sp_direct_child
233  type (child_matrix) :: cm ! irow, jcol matrix
234  type (dsinfo) :: dsi ! direct solver info
235 
236 
237  integer(kind=kint) :: neqns_a ! number of eqns in A matrix
238  integer(kind=kint) :: neqns_lag ! number of eqns in D matrix
239  real(kind=kreal), pointer :: dsln(:,:) ! non-diagonal elements of dens D matrix
240  real(kind=kreal), pointer :: diag(:,:) ! diagonal elements of dens D matrix
241  type(child_matrix), pointer :: dm(:) !divided matrices
242 
243  real(kind=kreal), allocatable :: bd(:,:) ! for right hand side value
244 
245  ! internal use
246  real(kind=kreal), allocatable :: b(:,:)
247  real(kind=kreal), allocatable :: oldb(:,:)
248  real(kind=kreal), allocatable :: b_a(:)
249  real(kind=kreal), allocatable :: b_lag(:)
250 
251 
252 
253  logical, save :: nusol_ready = .false.
254  integer(kind=kint), save :: ndeg, nndeg, ndegt
255  integer(kind=kint), save :: neqns_c, iofst_a2, iofst_c, ndm
256 
257  ! misc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
258  integer(kind=kint) :: ierr
259  integer(kind=kint) :: i,j,k,l,m,n
260 
261 
262  real(kind=kreal), pointer :: spdslnval(:,:), bdbuf(:,:)
263  integer(kind=kint), pointer :: spdslnidx(:)
264  integer(kind=kint) :: nspdsln
265 
266 
267  !! temporary
268  integer(kind=kint), pointer :: iperm_all_inc_lag(:), part_all_inc_lag(:), iperm_rev_inc_lag(:)
269  integer(kind=kint) :: child_lag_nrows, child_lag_ncols, child_lag_nttbr, offset_irow
270  integer(kind=kint) :: ii, jj
271  real(kind=kreal), pointer :: dsln_lag(:,:)
272  real(kind=kreal), pointer :: diag_lag(:,:)
273  real(kind=kreal), allocatable :: wk(:), wk_d(:)
274  integer(kind=kint) :: ks, ke
275 
276 
277  ierr=0
278 
279 
280  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
281  !
282  ! STEP01: get a0 from FEM data format hecMAT
283  !
284 
285  ndeg=a0%ndeg
286  nndeg=ndeg*ndeg
287  ndegt = (ndeg+1)*ndeg/2 !triangle element in diag
288 
289 
290  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
291  !
292  ! STEP1X: LDU decompose of given A0
293  !
294  ! STEP11: build up matrix.
295  ! A is given a0
296  ! C is lagrange region
297  ! D is kept as dsln (off-diagonal), diag (diagonal).
298 
299 
300  neqns_a = a0%neqns
301  neqns_lag = lag%nrows
302  allocate(dsln_lag(1,neqns_lag*(neqns_lag - 1)/2)) ! size of lagrange
303  allocate(diag_lag(1,neqns_lag)) ! size of lagrange
304  dsln_lag=0.0d0 ! because of lagrange
305  diag_lag=0.0d0 ! because of lagrange
306 
307  ! set matrix for LDU decomposition
308 
309 
310  ! A matrix
311  cm%a%ndeg = a0%ndeg
312  cm%a%neqns = a0%neqns
313  cm%a%nttbr = a0%nttbr
314  allocate(cm%a%irow(cm%a%nttbr), cm%a%jcol(cm%a%nttbr), cm%a%val(1, cm%a%nttbr))
315  cm%a%irow(:) = a0%irow(:)
316  cm%a%jcol(:) = a0%jcol(:)
317  cm%a%val(1,:) = a0%val(1,:)
318 
319  ! C matrix (lagrange region)
320  cm%c%ndeg = lag%ndeg
321  cm%c%nttbr = lag%nttbr
322  cm%c%nrows = lag%nrows
323  cm%c%ncols = lag%ncols
324  allocate(cm%c%irow(cm%c%nttbr), cm%c%jcol(cm%c%nttbr), cm%c%val(1, cm%c%nttbr))
325  cm%c%irow(:) = lag%irow(:)
326  cm%c%jcol(:) = lag%jcol(:)
327  cm%c%val(1,:) = lag%val(1,:)
328 
329  cm%ndeg = cm%a%ndeg
330  cm%ista_c = cm%a%neqns+1
331  cm%neqns_t = cm%a%neqns + cm%c%nrows
332 
333 
334  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
335  !
336  ! STEP1x: LDU decompose for given matrix
337  !
338 
339  ! set up dsi for allocate matrix array for fill-in
340  call matini_para(cm, dsi, ierr)
341 
342  ! set real8 value
343  do i=1,cm%a%nttbr
344  call staij1(0, cm%a%irow(i), cm%a%jcol(i), cm%a%val(:,i), dsi, ierr)
345  end do
346  do i=1,cm%c%nttbr
347  ! call staij1(0, cm%c%irow(i)+cm%a%neqns, dsi%iperm(cm%c%jcol(i)), cm%c%val(:,i), dsi, ierr)
348  call staij1(0, cm%c%irow(i)+cm%a%neqns, cm%c%jcol(i), cm%c%val(:,i), dsi, ierr)
349  end do
350 
351  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
352  !
353  ! following STEP12-15 will be done in nufct0_child()
354  ! and return D region
355  !
356  ! STEP12: LDU decompose of A (1..nstop-1)
357  ! STEP13: LDU decompose of C (nstop..neqnsA+neqnsd)
358  ! STEP14: update D region.
359 
360  call nufct0_child(dsi, ierr, nspdsln, spdslnidx, spdslnval, diag_lag)
361 
362  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
363  !
364  ! STEP13: Receive D region and update D matrix as D' = D - D1' - D2' ...
365  !
366  ! D is receive as dens matrix, which format is given in s3um2() in serial solver.
367  ! to decompose this dens D matrix, use s3um3() on parent.
368 
369  ! off diagonal
370  do i=1,nspdsln
371  dsln_lag(:,spdslnidx(i)) = dsln_lag(:,spdslnidx(i)) + spdslnval(:,i) ! because of child process dsln is already substructed in s3um2()
372  end do
373 
374  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375  !
376  ! STEP13: ! LDU decompose dens D
377  !
378  call nufct0_parent(dsln_lag, diag_lag, neqns_lag, ndeg)
379 
380  nusol_ready = .true.
381 
382  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
383  !
384  ! STEP2X: Solve Ax=b0
385  !
386 
387  ! forward substitution for A region
388 
389  ! set right hand side vector (b)
390  allocate(b(ndeg,a0%neqns+lag%nrows), stat=ierr)
391  if(ierr .ne. 0) then
392  call errtrp('stop due to allocation error.')
393  end if
394  do i=1,a0%neqns+lag%nrows
395  b(1,i)=b_in(i) !for ndeg=1
396  end do
397 
398  ! for verify
399  allocate(oldb(ndeg,a0%neqns+lag%nrows), stat=ierr)
400  if(ierr .ne. 0) then
401  call errtrp('stop due to allocation error.')
402  end if
403  do i=1, a0%neqns
404  oldb(ndeg,i)=b(ndeg,i)
405  end do
406  do i=a0%neqns+1, a0%neqns+lag%nrows
407  oldb(ndeg,i)=b(ndeg,i)
408  end do
409 
410  allocate(b_a(neqns_a))
411  do i=1,neqns_a
412  b_a(i)=b_in(i)
413  end do
414 
415  allocate(b_lag(neqns_lag))
416  do i=1, neqns_lag
417  b_lag(i)=b_in(neqns_a + i)
418  end do
419 
420  ! old nusol0_child !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
421  ! STEP22: forward substitution for A
422  allocate(wk(neqns_a+neqns_lag), stat=ierr)
423  if(ierr .ne. 0) then
424  call errtrp('stop due to allocation error.')
425  end if
426  wk = 0
427 
428  do i=1,neqns_a
429  wk(i)=b_a(dsi%iperm(i)) ! it sholud be permtated
430  end do
431 
432  ! STEP22: forward substitution for A
433  do i=1,neqns_a
434  ks=dsi%xlnzr(i)
435  ke=dsi%xlnzr(i+1)-1
436  if(ke.lt.ks) then ! logic inverted
437  cycle
438  end if
439  wk(i)=wk(i)-spdot2(wk,dsi%zln(1,:),dsi%colno,ks,ke)
440  end do
441 
442  ! STEP23: forward substitution for C and send it (yi) to parent
443  allocate(wk_d(dsi%nstop:dsi%neqns), stat=ierr)
444  if(ierr .ne. 0) then
445  call errtrp('stop due to allocation error.')
446  end if
447  wk_d=0
448 
449  do i=dsi%nstop,dsi%neqns
450  ks=dsi%xlnzr(i)
451  ke=dsi%xlnzr(i+1)-1
452  if(ke.lt.ks) then ! logic inverted
453  cycle
454  end if
455  wk_d(i)=wk_d(i)-spdot2(wk,dsi%zln(1,:),dsi%colno,ks,ke)
456  end do
457  ! Now wk_d is given. it should be used in parent.
458 
459 
460  ! end old nusol0_child !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
461 
462  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
463  !
464  ! STEP22 forward substitution for D region. and get Y
465  !
466  ! b1, b2... are sended to child processes.
467  ! bd is substituted to D in locally, and results from child processes
468  ! (C1-Y1 substitute, C2-Y2 substitute...) are receive from child processes.
469  ! these value also add for Yd
470 
471  ! update b_lag
472  do i=1, neqns_lag
473  b_lag(i)=b_lag(i) + wk_d(neqns_a + i)
474  end do
475 
476  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
477  !
478  ! STEP22 solve Ax=b for dens matrix, using updated bd
479  !
480  call nusol1_parent(dsln_lag(1,:), diag_lag(1,:), b_lag, neqns_lag)
481  !now b_lag is correct answer
482 
483 
484  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
485  !
486  ! STEP23 solve A region
487  !
488 
489  ! prepare Z
490  do i=1,neqns_a
491  wk(i)=wk(i)*dsi%diag(1,i)
492  end do
493 
494  ! D region is already solved
495  do i=1,neqns_lag
496  wk(neqns_a + i)=b_lag(i)
497  end do
498 
499  do i=dsi%neqns,1,-1
500  ks=dsi%xlnzr(i)
501  ke=dsi%xlnzr(i+1)-1
502  if(ke.lt.ks) then
503  cycle
504  end if
505  do k=ks,ke
506  j=dsi%colno(k)
507  wk(j)=wk(j)-wk(i)*dsi%zln(1,k)
508  end do
509  end do
510 
511  do i=1, neqns_a
512  b(1,dsi%iperm(i))=wk(i)
513  end do
514  do i=1, neqns_lag
515  b(1,neqns_a +i )=b_lag(i)
516  end do
517 
518 
519  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
520  !
521  ! STEP25 restore final result
522  !
523 
524  ! verify result
525  call verif0(ndeg, a0%neqns, a0%nttbr, a0%irow, a0%jcol, a0%val, lag%nrows, lag%nttbr, lag%irow, lag%jcol, lag%val, oldb, b) !verify result oldb will be broken.
526 
527  do i=1,a0%neqns+lag%nrows
528  b_in(i)=b(1,i)
529  end do
530 
531 
532  deallocate(spdslnidx, spdslnval)
533  deallocate(dsln_lag, diag_lag)
534 
535  deallocate(b, oldb, b_a, b_lag)
536 
537  deallocate(cm%a%irow, cm%a%jcol, cm%a%val)
538  deallocate(cm%c%irow, cm%c%jcol, cm%c%val)
539  deallocate(dsi%zpiv)
540  deallocate(dsi%iperm)
541  deallocate(dsi%invp)
542  deallocate(dsi%parent)
543  deallocate(dsi%nch)
544  deallocate(dsi%xlnzr)
545  deallocate(dsi%colno)
546  deallocate(dsi%diag)
547  deallocate(dsi%zln)
548  !deallocate(dsi%dsln) ! not allocated
549 
550  return
551  end subroutine sp_direct_parent
552 
553 
554  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
555  subroutine errtrp(mes)
556  character(*) mes
557  write(ilog,*) mes
558 
559  stop
560  end subroutine errtrp
561 
562  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
563 
564  subroutine matini_para(cm,dsi,ir)
565 
566  !----------------------------------------------------------------------
567  !
568  ! matini initializes storage for sparse matrix solver.
569  ! this routine is used for both symmetric matrices
570  ! and must be called once at the beginning
571  !
572  ! (i)
573  ! neqns number of unknowns
574  ! nttbr number of non0s, pattern of non-zero elements are
575  ! given like following.
576  ! nonz(A)={(i,j);i=irow(l),j=jcol(l); 1<= l <= nttbr}
577  ! irow
578  ! jcol to define non-zero pattern
579  ! lenv length of the array v (iv)
580  !
581  ! (o)
582  ! dsi matrix information
583  ! ir return code
584  ! =0 normal
585  ! =-1 non positive index
586  ! =1 too big index
587  ! =10 insufficient storage
588  !
589  !
590  ! stage 10 after initialization
591  ! 20 building up matrix
592  ! 30 after LU decomposition
593  ! 40 after solving
594  !
595  ! # coded by t.arakawa
596  ! # reviced by t.kitayama of Univ. Tokyo on 20071120
597  !
598  !----------------------------------------------------------------------
599 
600  implicit none
601 
602  type(child_matrix), intent(in) :: cm
603  type(dsinfo), intent(out) :: dsi
604  integer(kind=kint), intent(out) :: ir
605 
606  integer(kind=kint), pointer :: irow_a(:), jcol_a(:)
607  integer(kind=kint), pointer :: irow_c(:), jcol_c(:)
608 
609  integer(kind=kint), pointer :: ia(:) ! in stiaja() neqns+2
610  integer(kind=kint), pointer :: ja(:) ! in stiaja() 2*nttbr
611  integer(kind=kint), pointer :: jcpt(:) ! in stsmat() 2*nttbr
612  integer(kind=kint), pointer :: jcolno(:) ! in stsmat() 2*nttbr
613 
614  integer(kind=kint), pointer :: iperm_a(:)
615  integer(kind=kint), pointer :: invp_a(:)
616 
617  integer(kind=kint), pointer :: xlnzr_a(:)
618  integer(kind=kint), pointer :: colno_a(:)
619 
620  integer(kind=kint), pointer :: xlnzr_c(:)
621  integer(kind=kint), pointer :: colno_c(:)
622 
623 
624  integer(kind=kint), pointer :: adjncy(:) ! in genqmd() 2*nttbr
625  integer(kind=kint), pointer :: qlink(:) ! in genqmd() neqne+2
626  integer(kind=kint), pointer :: qsize(:) ! in genqmd() neqne+2
627  integer(kind=kint), pointer :: nbrhd(:) ! in genqmd() neqne+2
628  integer(kind=kint), pointer :: rchset(:) ! in genqmd() neqne+2
629 
630  integer(kind=kint), pointer :: cstr(:)
631 
632  integer(kind=kint), pointer :: adjt(:) ! in rotate() neqne+2
633  integer(kind=kint), pointer :: anc(:) ! in rotate() neqne+2
634 
635  integer(kind=kint), pointer :: lwk3arr(:)
636  integer(kind=kint), pointer :: lwk2arr(:)
637  integer(kind=kint), pointer :: lwk1arr(:)
638  integer(kind=kint), pointer :: lbtreearr(:,:) ! genbtq() (2,neqns+1)
639  integer(kind=kint), pointer :: lleafarr(:)
640  integer(kind=kint), pointer :: lxleafarr(:)
641  integer(kind=kint), pointer :: ladparr(:)
642  integer(kind=kint), pointer :: lpordrarr(:)
643 
644  integer(kind=kint) :: neqns_a, nttbr_a, neqns_a1, nstop, neqns_t, neqns_d, nttbr_c, ndeg
645  integer(kind=kint) :: lncol_a, lncol_c
646  integer(kind=kint) :: neqnsz, nofsub, izz, izz0, lnleaf ! dummy variables
647  integer(kind=kint) :: ir1
648  integer(kind=kint) :: i, j, k , ipass, ks, ke, ierr
649 
650  ndeg = cm%ndeg
651 
652  neqns_t = cm%neqns_t
653  neqns_d = cm%c%nrows
654 
655  neqns_a = cm%a%neqns
656  nttbr_a = cm%a%nttbr
657  irow_a => cm%a%irow
658  jcol_a => cm%a%jcol
659 
660  nttbr_c = cm%c%nttbr
661  irow_c => cm%c%irow
662  jcol_c => cm%c%jcol
663 
664  dsi%neqns=neqns_t ! because direct solver treat A + C as one matrix.
665  dsi%ndeg=ndeg
666 
667  neqns_a1=neqns_a+2
668  ir=0
669  ierr=0
670  izz0=0
671  !
672  ! set z pivot
673  !
674  allocate(dsi%zpiv(neqns_a), stat=ierr)
675  if(ierr .ne. 0) then
676  call errtrp('stop due to allocation error.')
677  end if
678  call zpivot(neqns_a,neqnsz,nttbr_a,jcol_a,irow_a,dsi%zpiv,ir1)
679  if(ir1.ne.0) then
680  ir=ir1
681  goto 1000
682  endif
683  !
684  ! build jcpt,jcolno
685  !
686  allocate(jcpt(2*nttbr_a), jcolno(2*nttbr_a), stat=ierr)
687  if(ierr .ne. 0) then
688  call errtrp('stop due to allocation error.')
689  end if
690  call stsmat(neqns_a,nttbr_a,irow_a,jcol_a,jcpt,jcolno)
691  !
692  ! build ia,ja
693  !
694  allocate(ia(neqns_a1), ja(2*nttbr_a), stat=ierr)
695  if(ierr .ne. 0) then
696  call errtrp('stop due to allocation error.')
697  end if
698  call stiaja(neqns_a, neqns_a,ia,ja,jcpt,jcolno)
699  !
700  ! get permutation vector iperm,invp
701  !
702 
703  ! setup identity permtation for C matrix
704  allocate(iperm_a(neqns_a), invp_a(neqns_a), stat=ierr)
705  if(ierr .ne. 0) then
706  call errtrp('stop due to allocation error.')
707  end if
708  call idntty(neqns_a,invp_a,iperm_a)
709 
710  ! reorder A matrix
711  allocate(adjncy(2*nttbr_a),qlink(neqns_a1),qsize(neqns_a1),nbrhd(neqns_a1),rchset(neqns_a1), stat=ierr)
712  if(ierr .ne. 0) then
713  call errtrp('stop due to allocation error.')
714  end if
715  allocate(lwk2arr(neqns_a1),lwk1arr(neqns_a1), stat=ierr)
716  if(ierr .ne. 0) then
717  call errtrp('stop due to allocation error.')
718  end if
719  call genqmd(neqns_a,ia,ja,iperm_a,invp_a,lwk1arr,lwk2arr,rchset,nbrhd,qsize,qlink,nofsub,adjncy)
720  deallocate(adjncy, qlink, qsize, nbrhd, rchset)
721 
722  ! set ia, ja
723  call stiaja(neqns_a, neqns_a, ia, ja, jcpt,jcolno)
724 
725  ! build up the parent vector parent vector will be saved in
726  ! work2 for a while
727  allocate(cstr(neqns_a1),adjt(neqns_a1), stat=ierr)
728  if(ierr .ne. 0) then
729  call errtrp('stop due to allocation error.')
730  end if
731 10 continue
732  call genpaq(ia,ja,invp_a,iperm_a,lwk2arr,neqns_a,cstr)
733 
734  ! build up the binary tree
735  allocate (lbtreearr(2,neqns_a1), stat=ierr)
736  if(ierr .ne. 0) then
737  call errtrp('stop due to allocation error.')
738  end if
739  call genbtq(ia, ja, invp_a, iperm_a,lwk2arr,lbtreearr,dsi%zpiv,izz,neqns_a)
740 
741  ! rotate the binary tree to avoid a zero pivot
742  if(izz.eq.0) goto 20
743  if(izz0.eq.0) izz0=izz
744  if(izz0.ne.izz) goto 30
745  call rotate(ia, ja, invp_a, iperm_a, lwk2arr,lbtreearr,izz,neqns_a,anc,adjt,ir1)
746  goto 10
747 30 continue
748  call bringu(dsi%zpiv,iperm_a, invp_a, lwk2arr,izz,neqns_a,ir1)
749  goto 10
750 
751  ! post ordering
752 20 continue
753  allocate(lwk3arr(0:neqns_a1),lpordrarr(neqns_a1),dsi%parent(neqns_a1), dsi%nch(neqns_a1), stat=ierr)
754  if(ierr .ne. 0) then
755  call errtrp('stop due to allocation error.')
756  end if
757  call posord(dsi%parent,lbtreearr,invp_a,iperm_a,lpordrarr,dsi%nch,neqns_a,lwk1arr,lwk2arr,lwk3arr)
758 
759  ! generate skeleton graph
760  allocate(lleafarr(nttbr_a),lxleafarr(neqns_a1),ladparr(neqns_a1), stat=ierr)
761  if(ierr .ne. 0) then
762  call errtrp('stop due to allocation error.')
763  end if
764  call gnleaf(ia, ja, invp_a, iperm_a, lpordrarr,dsi%nch,ladparr,lxleafarr,lleafarr,neqns_a,lnleaf)
765 
766  ! build up xlnzr,colno (this is the symbolic fct.)
767  nstop = cm%ista_c
768  call countclno(dsi%parent, lxleafarr, lleafarr, neqns_a, nstop, lncol_a, ir1) ! only for A
769  allocate(colno_a(lncol_a),xlnzr_a(neqns_a1), stat=ierr)
770  if(ierr .ne. 0) then
771  call errtrp('stop due to allocation error.')
772  end if
773  call gnclno(dsi%parent,lpordrarr,lxleafarr,lleafarr,xlnzr_a, colno_a, neqns_a, nstop,lncol_a,ir1) ! only for A
774  if(ir1.ne.0) then
775  ir=10
776  goto 1000
777  endif
778 
779  ! do symbolic LDU decomposition for C region.
780  call ldudecomposec(xlnzr_a,colno_a,invp_a,iperm_a, ndeg, nttbr_c, irow_c, &
781  jcol_c, cm%c%ncols, cm%c%nrows, xlnzr_c, colno_c, lncol_c)
782 
783  ! set calculated information to dsi.
784  allocate(dsi%xlnzr(neqns_t + 1), stat=ierr)
785  if(ierr .ne. 0) then
786  call errtrp('stop due to allocation error.')
787  end if
788  dsi%xlnzr(1:neqns_a)=xlnzr_a(:)
789  dsi%xlnzr(neqns_a+1:neqns_t+1)=xlnzr_c(:)+xlnzr_a(neqns_a+1)-1
790 
791  dsi%lncol=lncol_a + lncol_c
792  allocate(dsi%colno(lncol_a + lncol_c), stat=ierr)
793  if(ierr .ne. 0) then
794  call errtrp('stop due to allocation error.')
795  end if
796 
797  do i=1,lncol_a
798  dsi%colno(i)=colno_a(i)
799  end do
800  do i=1, lncol_c
801  dsi%colno(lncol_a + i)=colno_c(i)
802  end do
803 
804  allocate(dsi%invp(neqns_t), dsi%iperm(neqns_t), stat=ierr)
805  if(ierr .ne. 0) then
806  call errtrp('stop due to allocation error.')
807  end if
808  dsi%invp(1:neqns_a)=invp_a(1:neqns_a)
809  dsi%iperm(1:neqns_a)=iperm_a(1:neqns_a)
810  do i=neqns_a+1,neqns_t
811  dsi%invp(i)=i
812  dsi%iperm(i)=i
813  end do
814 
815  deallocate(xlnzr_a, colno_a, xlnzr_c, colno_c, invp_a, iperm_a)
816 
817  dsi%nstop=nstop
818  dsi%stage=10
819 1000 continue
820 
821  return
822  end subroutine matini_para
823 
824  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
825 
826  subroutine nufct0_child(dsi,ir, nspdsln, spdslnidx, spdslnval, diag_lag)
827 
828  implicit none
829  type(dsinfo), intent(inout) :: dsi
830  integer(kind=kint), intent(out) :: ir
831 
832  integer(kind=kint), intent(inout) :: nspdsln
833  real(kind=kreal), pointer :: spdslnval(:,:), bdbuf(:,:)
834  integer(kind=kint), pointer :: spdslnidx(:)
835 
836  real(kind=kreal), intent(inout) :: diag_lag(:,:)
837 
838  !
839  ! this performs Cholesky factorization
840  !
841 
842  if(dsi%stage.ne.20) then
843  ir=40
844  goto 1000
845  else
846  ir=0
847  endif
848  if(dsi%ndeg.eq.1) then
849  call nufct1_child(dsi%xlnzr,dsi%colno,dsi%zln,dsi%diag,dsi%neqns,dsi%parent,dsi%nch,dsi%nstop,ir, &
850  nspdsln, spdslnidx, spdslnval, diag_lag)
851  else if(dsi%ndeg.eq.2) then
852  write(idbg,*) 'ndeg=1 only'
853  stop
854  else if(dsi%ndeg.eq.3) then
855  write(idbg,*) 'ndeg=1 only'
856  stop
857  else if(dsi%ndeg.eq.6) then
858  write(idbg,*) 'ndeg=1 only'
859  stop
860  else
861  write(idbg,*) 'ndeg=1 only'
862  stop
863  end if
864 
865  dsi%stage=30
866 1000 continue
867  return
868  end subroutine nufct0_child
869 
870  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
871 
872  subroutine nufct1_child(xlnzr,colno,zln,diag,neqns,parent,nch,nstop,ir, nspdsln, spdslnidx, spdslnval, diag_lag)
873 
874  implicit none
875  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),parent(:)
876  integer(kind=kint), intent(in) :: neqns, nstop, ir
877  integer(kind=kint), intent(out) :: nch(:)
878  real(kind=kreal), intent(out) :: zln(:,:),diag(:,:) !zln(1,:), diag(1,:)
879 
880  integer(kind=kint) :: neqns_c
881  integer(kind=kint) :: i,j,k,l, ic,ierr,imp
882  integer(kind=kint) :: nspdsln
883  integer(kind=kint), pointer :: spdslnidx(:)
884  real(kind=kreal), pointer :: spdslnval(:,:)
885  real(kind=kreal), intent(out) :: diag_lag(:,:) ! diag(1,:)
886 
887  !----------------------------------------------------------------------
888  !
889  ! nufct1 performs cholesky factorization in row order for ndeg=1
890  !
891  ! (i) xlnzr,colno,zln,diag
892  ! symbolicaly factorized
893  !
894  ! (o) zln,diag,dsln
895  !
896  ! #coded by t.arakawa
897  !
898  !----------------------------------------------------------------------
899 
900  !
901  ! phase I
902  ! LDU decompose of A (1..nstop-1)
903  !
904  diag(1,1)=1.0d0/diag(1,1)
905  l=parent(1)
906  nch(l)=nch(l)-1
907  nch(1)=-1
908  do ic=2,nstop-1
909  call sum(ic,xlnzr,colno,zln(1,:),diag(1,:),nch,parent,neqns)
910  enddo
911 
912  !
913  ! phase II
914  ! LDU decompose of C (nstop..neqnsA+neqnsd)
915  !
916  do ic=nstop,neqns
917  call sum1(ic,xlnzr,colno,zln(1,:),diag(1,:),parent,neqns)
918  enddo
919 
920  !
921  ! phase III
922  ! Update D region.
923  !
924 
925  ! clear dummy diagonal value for D region
926  do i=nstop,neqns
927  diag(:,i)=0.0
928  end do
929 
930  neqns_c = neqns - nstop + 1
931  call sum2_child(neqns,nstop,xlnzr,colno,zln(1,:),diag(1,:),spdslnidx,spdslnval,nspdsln)
932  ! send D region to parent
933  ! imp = m_pds_procinfo%imp
934  ! call MPI_SEND(nspdsln, 1,MPI_INTEGER,IMP,1,MPI_COMM_WORLD,ierr)
935  ! call MPI_SEND(spdslnidx, nspdsln,MPI_INTEGER,IMP,1,MPI_COMM_WORLD,ierr)
936  ! call MPI_SEND(spdslnval, nspdsln,MPI_REAL8,IMP,1,MPI_COMM_WORLD,ierr)
937  ! call MPI_SEND(diag(1,nstop), neqns_c,MPI_REAL8,IMP,1,MPI_COMM_WORLD,ierr)
938 
939  do i=1, neqns_c
940  diag_lag(1,i) = diag(1,nstop+i-1) ! lagrange region
941  end do
942 
943  return
944  end subroutine nufct1_child
945 
946 
947 
948  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
949 
950  subroutine nufct0_parent(dsln, diag, neqns, ndeg)
951  ! select LDU decomposer for dens matrix according to ndeg
952 
953  implicit none
954 
955  real(kind=kreal), intent(inout) :: dsln(:,:)
956  real(kind=kreal), intent(inout) :: diag(:,:)
957  integer(kind=kint), intent(in) :: neqns, ndeg
958 
959  integer(kind=kint) :: ndegl
960 
961  if (ndeg .eq. 1) then
962  call sum3(neqns, dsln(1,:), diag(1,:))
963  else if (ndeg .eq. 3) then
964  write(idbg,*) 'ndeg=1 only'
965  stop
966  else
967  write(idbg,*) 'ndeg=1 only'
968  stop
969  end if
970 
971  return
972  end subroutine nufct0_parent
973 
974  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
975 
976 
977  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
978 
979  subroutine nusol1_parent(dsln, diag, b, neqns)
980  ! solve Ax=b for dens matrix with ndeg=1
981  ! require dsln, diag is already LDU decomposed.
982  ! currently not tested 20071121
983 
984  implicit none
985 
986  real(kind=kreal), intent(in) :: dsln(:) !((neqns+1)*neqns/2)
987  real(kind=kreal), intent(in) :: diag(:) !(neqns)
988  real(kind=kreal), intent(inout) :: b(:) !(3,neqns)
989  integer(kind=kint), intent(in) :: neqns
990 
991  integer(kind=kint) :: i,j,k,l,loc
992 
993  ! forward substitution
994  do i=2,neqns
995  k=(i-1)*(i-2)/2 + 1 ! first element of i'th row.
996  b(i)=b(i)-dot_product(b(1:i-1),dsln(k:k+i-2))
997  end do
998 
999  ! divide by D (because of diag is already inverted (1/Dii))
1000  b(:)=b(:)*diag(:)
1001 
1002  ! Backward substitution.
1003  ! Substitute Zi into D and get Xd results.
1004  loc=(neqns-1)*neqns/2
1005  do i=neqns,1,-1
1006  do j=i-1,1,-1
1007  b(j)=b(j)-b(i)*dsln(loc)
1008  loc=loc-1
1009  end do
1010  end do
1011 
1012  return
1013  end subroutine nusol1_parent
1014 
1015  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1016 
1017 
1018  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1019 
1020  subroutine zpivot(neqns,neqnsz,nttbr,jcol,irow,zpiv,ir)
1021 
1022  implicit none
1023 
1024  integer(kind=kint), intent(in) :: jcol(:),irow(:)
1025  integer(kind=kint), intent(out) :: zpiv(:)
1026  integer(kind=kint), intent(in) :: neqns,nttbr
1027  integer(kind=kint), intent(out) :: neqnsz,ir
1028 
1029  integer(kind=kint) :: i,j,k,l
1030 
1031  ir=0
1032  do l=1,neqns
1033  zpiv(l)=1
1034  enddo
1035 
1036  do l=1,nttbr
1037  i=irow(l)
1038  j=jcol(l)
1039  if(i.le.0.or.j.le.0) then
1040  ir=-1
1041  goto 1000
1042  elseif(i.gt.neqns.or.j.gt.neqns) then
1043  ir=1
1044  goto 1000
1045  endif
1046  if(i.eq.j) zpiv(i)=0
1047  enddo
1048 
1049  do i=neqns,1,-1
1050  if(zpiv(i).eq.0) then
1051  neqnsz=i
1052  goto 320
1053  endif
1054  enddo
1055 320 continue
1056 1000 continue
1057  if(ldbg) write(idbg,*) '# zpivot ########################'
1058  if(ldbg) write(idbg,60) (zpiv(i),i=1,neqns)
1059 60 format(20i3)
1060  return
1061  end subroutine zpivot
1062 
1063  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1064 
1065  subroutine stsmat(neqns,nttbr,irow,jcol,jcpt,jcolno)
1066 
1067  implicit none
1068 
1069  integer(kind=kint), intent(in) :: irow(:), jcol(:)
1070  integer(kind=kint), intent(out) :: jcpt(:), jcolno(:)
1071  integer(kind=kint), intent(in) :: neqns, nttbr
1072 
1073  integer(kind=kint) :: i,j,k,l,loc,locr
1074 
1075  do i=1,2*nttbr
1076  jcpt(i)=0
1077  jcolno(i)=0
1078  enddo
1079  do i=1,neqns
1080  jcpt(i)=i+neqns
1081  jcolno(i+neqns)=i
1082  enddo
1083 
1084  k=2*neqns
1085  do 100 l=1,nttbr
1086  i=irow(l)
1087  j=jcol(l)
1088  if(i.eq.j) goto 100
1089  loc=jcpt(i)
1090  locr=i
1091 110 continue
1092  if(loc.eq.0) goto 120
1093  if(jcolno(loc).eq.j) then
1094  goto 100
1095  elseif(jcolno(loc).gt.j) then
1096  goto 130
1097  endif
1098  locr=loc
1099  loc=jcpt(loc)
1100  goto 110
1101 120 continue
1102  k=k+1
1103  jcpt(locr)=k
1104  jcolno(k)=j
1105  goto 150
1106 130 continue
1107  k=k+1
1108  jcpt(locr)=k
1109  jcpt(k)=loc
1110  jcolno(k)=j
1111 150 continue
1112  loc=jcpt(j)
1113  locr=j
1114 160 continue
1115  if(loc.eq.0) goto 170
1116  if(jcolno(loc).eq.i) then
1117  goto 100
1118  elseif(jcolno(loc).gt.i) then
1119  goto 180
1120  endif
1121  locr=loc
1122  loc=jcpt(loc)
1123  goto 160
1124 170 continue
1125  k=k+1
1126  jcpt(locr)=k
1127  jcolno(k)=i
1128  goto 100
1129 180 continue
1130  k=k+1
1131  jcpt(locr)=k
1132  jcpt(k)=loc
1133  jcolno(k)=i
1134 100 continue
1135  if(ldbg) then
1136  write(idbg,*) 'jcolno'
1137  write(idbg,60) (jcolno(i),i=1,k)
1138  write(idbg,*) 'jcpt'
1139  write(idbg,60) (jcpt(i),i=1,k)
1140 60 format(10i7)
1141  endif
1142  return
1143  end subroutine stsmat
1144 
1145  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1146  subroutine stiaja(neqns,neqnsz,ia,ja,jcpt,jcolno)
1147 
1148  implicit none
1149  !
1150  ! coded by t.arakawa
1151  !
1152  integer(kind=kint), intent(in) :: jcpt(:),jcolno(:)
1153  integer(kind=kint), intent(out) :: ia(:),ja(:)
1154  integer(kind=kint), intent(in) :: neqns, neqnsz
1155 
1156  integer(kind=kint) :: i,j,k,l,ii,loc
1157  !
1158 
1159  ia(1)=1
1160  l=0
1161  do k=1,neqns
1162  loc=jcpt(k)
1163 110 continue
1164  if(loc.eq.0) goto 120
1165  ii=jcolno(loc)
1166  if(ii.eq.k.or.ii.gt.neqnsz) goto 130
1167  l=l+1
1168  ja(l)=ii
1169 130 continue
1170  loc=jcpt(loc)
1171  goto 110
1172 120 ia(k+1)=l+1
1173  enddo
1174  if(ldbg) then
1175  write(idbg,*) 'stiaja(): ia '
1176  write(idbg,60) (ia(i),i=1,neqns+1)
1177  write(idbg,*) 'stiaja(): ja '
1178  write(idbg,60) (ja(i),i=1,ia(neqns+1))
1179  endif
1180 60 format(10i7)
1181  return
1182  end subroutine stiaja
1183 
1184  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1185 
1186  subroutine idntty(neqns,invp,iperm)
1187 
1188  implicit none
1189 
1190  integer(kind=kint), intent(out) :: invp(:),iperm(:)
1191  integer(kind=kint), intent(in) :: neqns
1192 
1193  integer(kind=kint) :: i
1194 
1195  do i=1,neqns
1196  invp(i)=i
1197  iperm(i)=i
1198  enddo
1199  return
1200  end subroutine idntty
1201 
1202  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1203 
1204  subroutine genqmd(neqns,xadj,adj0,perm,invp,deg,marker,rchset,nbrhd,qsize,qlink,nofsub,adjncy)
1205 
1206  implicit none
1207 
1208  integer(kind=kint), intent(in) :: adj0(:),xadj(:)
1209  integer(kind=kint), intent(out) :: rchset(:),nbrhd(:),adjncy(:),perm(:),invp(:),deg(:),marker(:),qsize(:),qlink(:)
1210  integer(kind=kint), intent(in) :: neqns
1211  integer(kind=kint), intent(out) :: nofsub
1212 
1213  integer(kind=kint) :: inode,ip,irch,mindeg,nhdsze,node,np,num,nump1,nxnode,rchsze,search,thresh,ndeg
1214  integer(kind=kint) :: i,j,k,l
1215 
1216  mindeg=neqns
1217  nofsub=0
1218  do i=1,xadj(neqns+1)-1
1219  adjncy(i)=adj0(i)
1220  enddo
1221  do node=1,neqns
1222  perm(node)=node
1223  invp(node)=node
1224  marker(node)=0
1225  qsize(node)=1
1226  qlink(node)=0
1227  ndeg=xadj(node+1)-xadj(node)
1228  deg(node)=ndeg
1229  if(ndeg.lt.mindeg) mindeg=ndeg
1230  enddo
1231 
1232  num=0
1233 200 search=1
1234  thresh=mindeg
1235  mindeg=neqns
1236 300 nump1=num+1
1237  if(nump1.gt.search) search=nump1
1238  do 400 j=search,neqns
1239  node=perm(j)
1240  if(marker(node).lt.0) goto 400
1241  ndeg=deg(node)
1242  if(ndeg.le.thresh) goto 500
1243  if(ndeg.lt.mindeg) mindeg=ndeg
1244 400 continue
1245  goto 200
1246 
1247 500 search=j
1248  nofsub=nofsub+deg(node)
1249  marker(node)=1
1250  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
1251  nxnode=node
1252 600 num=num+1
1253  np=invp(nxnode)
1254  ip=perm(num)
1255  perm(np)=ip
1256  invp(ip)=np
1257  perm(num)=nxnode
1258  invp(nxnode)=num
1259  deg(nxnode)=-1
1260  nxnode=qlink(nxnode)
1261  if(nxnode.gt.0) goto 600
1262  if(rchsze.le.0) goto 800
1263  !
1264  call qmdupd(xadj,adjncy,rchsze,rchset,deg,qsize,qlink,marker,rchset(rchsze+1:),nbrhd(nhdsze+1:))
1265  marker(node)=0
1266  do 700 irch=1,rchsze
1267  inode=rchset(irch)
1268  if(marker(inode).lt.0) goto 700
1269  marker(inode)=0
1270  ndeg=deg(inode)
1271  if(ndeg.lt.mindeg) mindeg=ndeg
1272  if(ndeg.gt.thresh) goto 700
1273  mindeg=thresh
1274  thresh=ndeg
1275  search=invp(inode)
1276 700 continue
1277  if(nhdsze.gt.0) call qmdot(node,xadj,adjncy,marker,rchsze,rchset,nbrhd)
1278 800 if(num.lt.neqns) goto 300
1279  return
1280  end subroutine genqmd
1281 
1282  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1283 
1284  subroutine genpaq(xadj,adjncy,invp,iperm,parent,neqns,ancstr)
1285 
1286  implicit none
1287 
1288  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),invp(:),iperm(:)
1289  integer(kind=kint), intent(out) :: parent(:),ancstr(:)
1290  integer(kind=kint), intent(in) :: neqns
1291 
1292  integer(kind=kint) :: i,j,k,l,ip,it
1293 
1294  do i=1,neqns
1295  parent(i)=0
1296  ancstr(i)=0
1297  ip=iperm(i)
1298  do 110 k=xadj(ip),xadj(ip+1)-1
1299  l=invp(adjncy(k))
1300  if(l.ge.i) goto 110
1301 112 continue
1302  if(ancstr(l).eq.0) goto 111
1303  if(ancstr(l).eq.i) goto 110
1304  it=ancstr(l)
1305  ancstr(l)=i
1306  l=it
1307  goto 112
1308 111 continue
1309  ancstr(l)=i
1310  parent(l)=i
1311 110 continue
1312  enddo
1313  do i=1,neqns
1314  if(parent(i).eq.0) parent(i)=neqns+1
1315  enddo
1316  parent(neqns+1)=0
1317  if(ldbg) write(idbg,6010)
1318  if(ldbg) write(idbg,6000) (i,parent(i),i=1,neqns)
1319 6000 format(2i6)
1320 6010 format(' parent')
1321  return
1322  end subroutine genpaq
1323 
1324  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1325 
1326  subroutine genbtq(xadj,adjncy,invp,iperm,parent,btree,zpiv,izz,neqns)
1327 
1328  implicit none
1329 
1330  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),invp(:),iperm(:),zpiv(:)
1331  integer(kind=kint), intent(out) :: btree(:,:) ! btree is (2,:)
1332  integer(kind=kint), intent(in) :: neqns
1333  integer(kind=kint), intent(out) :: izz
1334 
1335  integer(kind=kint) :: i,j,k,l,ip,ib,inext
1336 
1337  do i=1,neqns+1
1338  btree(1,i)=0
1339  btree(2,i)=0
1340  enddo
1341  do 100 i=1,neqns+1
1342  ip=parent(i)
1343  if(ip.le.0) goto 100
1344  ib=btree(1,ip)
1345  if(ib.eq.0) then
1346  btree(1,ip)=i
1347  else
1348 101 continue
1349  inext=btree(2,ib)
1350  if(inext.eq.0) then
1351  btree(2,ib)=i
1352  else
1353  ib=inext
1354  goto 101
1355  endif
1356  endif
1357 100 continue
1358  !
1359  ! find zeropivot
1360  !
1361  do i=1,neqns
1362  if(zpiv(i).ne.0) then
1363  if(btree(1,invp(i)).eq.0) then
1364  izz=i
1365  goto 210
1366  endif
1367  endif
1368  enddo
1369  izz=0
1370 210 continue
1371  if(ldbg) write(idbg,6010)
1372  if(ldbg) write(idbg,6000) (i,btree(1,i),btree(2,i),i=1,neqns)
1373  if(ldbg) write(idbg,6020) izz
1374  ! if(idbg1.ge.2) write(10,6100) neqns
1375  ! if(idbg1.ge.2) write(10,6100) (btree(1,i),btree(2,i),i=1,neqns)
1376 6000 format(i6,'(',2i6,')')
1377 6010 format(' binary tree')
1378 6020 format(' the first zero pivot is ',i4)
1379 6100 format(2i8)
1380  return
1381  end subroutine genbtq
1382 
1383  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1384 
1385  subroutine rotate(xadj,adjncy,invp,iperm,parent,btree,izz,neqns,anc,adjt,irr)
1386 
1387  implicit none
1388 
1389  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),parent(:),btree(:,:)
1390  integer(kind=kint), intent(out) :: anc(:),adjt(:),invp(:),iperm(:)
1391  integer(kind=kint), intent(in) :: neqns,izz
1392  integer(kind=kint), intent(out) :: irr
1393 
1394  integer(kind=kint) :: i,j,k,l,izzz,nanc,loc,locc,ll,kk,iy
1395 
1396  !----------------------------------------------------------------------
1397  ! irr return code irr=0 node izz is not a bottom node
1398  ! irr=1 is a bottom node then rotation is
1399  ! performed
1400  !
1401  !----------------------------------------------------------------------
1402  if(izz.eq.0) then
1403  irr=0
1404  return
1405  endif
1406  izzz=invp(izz)
1407  if(btree(1,izzz).ne.0) then
1408  irr=0
1409  ! return
1410  endif
1411  irr=1
1412  !
1413  ! ancestors of izzz
1414  !
1415  nanc=0
1416  loc=izzz
1417 100 continue
1418  nanc=nanc+1
1419  anc(nanc)=loc
1420  loc=parent(loc)
1421  if(loc.ne.0) goto 100
1422  !
1423  ! to find the eligible node from ancestors of izz
1424  !
1425  ! adjt = Adj(Tree(y))
1426  l=1
1427 200 continue
1428  do i=1,neqns
1429  adjt(i)=0
1430  enddo
1431  locc=anc(l)
1432 220 continue
1433  loc=locc
1434  locc=btree(1,loc)
1435  if(locc.ne.0) goto 220
1436 230 continue
1437  do k=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
1438  adjt(invp(adjncy(k)))=1
1439  enddo
1440  if(loc.ge.anc(l)) goto 250
1441  locc=btree(2,loc)
1442  if(locc.ne.0) goto 220
1443  loc=parent(loc)
1444  goto 230
1445 250 continue
1446  do ll=l+1,nanc
1447  if(adjt(anc(ll)).eq.0) then
1448  l=l+1
1449  goto 200
1450  endif
1451  enddo
1452  if(l.eq.1) goto 500
1453 
1454  !
1455  ! anc(l-1) is the eligible node
1456  !
1457  ! (1) number the node not in Ancestor(iy)
1458  iy=anc(l-1)
1459  do i=1,neqns
1460  adjt(i)=0
1461  enddo
1462  do ll=l,nanc
1463  adjt(anc(ll))=1
1464  enddo
1465  k=0
1466  do ll=1,neqns
1467  if(adjt(ll).eq.0) then
1468  k=k+1
1469  invp(iperm(ll))=k
1470  endif
1471  enddo
1472  ! (2) followed by nodes in Ancestor(iy)-Adj(T(iy))
1473 330 continue
1474  do i=1,neqns
1475  adjt(i)=0
1476  enddo
1477  locc=iy
1478 350 continue
1479  loc=locc
1480  locc=btree(1,loc)
1481  if(locc.ne.0) goto 350
1482 360 continue
1483  do kk=xadj(iperm(loc)),xadj(iperm(loc)+1)-1
1484  adjt(invp(adjncy(kk)))=1
1485  enddo
1486  if(loc.ge.iy) goto 380
1487  locc=btree(2,loc)
1488  if(locc.ne.0) goto 350
1489  loc=parent(loc)
1490  goto 360
1491 380 continue
1492  do ll=l,nanc
1493  if(adjt(anc(ll)).eq.0) then
1494  k=k+1
1495  invp(iperm(anc(ll)))=k
1496  endif
1497  enddo
1498  ! (3) and finally number the node in Adj(t(iy))
1499  do ll=l,nanc
1500  if(adjt(anc(ll)).ne.0) then
1501  k=k+1
1502  invp(iperm(anc(ll)))=k
1503  endif
1504  enddo
1505  goto 600
1506  !
1507  ! izz can be numbered last
1508  !
1509 500 continue
1510  k=0
1511  do 510 i=1,neqns
1512  if(i.eq.izzz) goto 510
1513  k=k+1
1514  invp(iperm(i))=k
1515 510 continue
1516  invp(iperm(izzz))=neqns
1517  !
1518  ! set iperm
1519  !
1520 600 continue
1521  do i=1,neqns
1522  iperm(invp(i))=i
1523  enddo
1524  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
1525 6000 format(10i6)
1526  return
1527  end subroutine rotate
1528 
1529  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1530 
1531  subroutine bringu(zpiv,iperm,invp,parent,izz,neqns,irr)
1532 
1533  implicit none
1534 
1535  integer(kind=kint), intent(in) :: zpiv(:),parent(:)
1536  integer(kind=kint), intent(out) :: iperm(:),invp(:)
1537  integer(kind=kint), intent(in) :: neqns,izz
1538  integer(kind=kint), intent(out) :: irr
1539 
1540  integer(kind=kint) :: i,j,k,l,ib0,ib,ibp,izzp
1541 
1542  !----------------------------------------------------------------------
1543  !
1544  ! bringu brings up zero pivots from bottom of the elimination tree
1545  ! to higher nodes
1546  !
1547  ! irr = 0 complete
1548  ! = 1 impossible
1549  !
1550  ! #coded by t.arakawa
1551  !
1552  !----------------------------------------------------------------------
1553 
1554  irr=0
1555  ib0=invp(izz)
1556  ib=ib0
1557 100 continue
1558  if(ib.le.0) goto 1000
1559  ibp=parent(ib)
1560  izzp=iperm(ibp)
1561  if(zpiv(izzp).eq.0) goto 110
1562  ib=ibp
1563  goto 100
1564 110 continue
1565  invp(izz)=ibp
1566  invp(izzp)=ib0
1567  iperm(ibp)=izz
1568  iperm(ib0)=izzp
1569  if(ldbg) then
1570  do i=1,neqns
1571  if(invp(iperm(i)).ne.i) goto 210
1572  if(iperm(invp(i)).ne.i) goto 210
1573  enddo
1574  goto 220
1575 210 continue
1576  write(20,*) 'permutation error'
1577  stop
1578  endif
1579 220 continue
1580  return
1581 1000 continue
1582  irr=1
1583  end subroutine bringu
1584 
1585  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1586 
1587  subroutine posord(parent,btree,invp,iperm,pordr,nch,neqns,iw,qarent,mch)
1588 
1589  implicit none
1590 
1591  integer(kind=kint), intent(in) :: btree(:,:),qarent(:)
1592  integer(kind=kint), intent(out) :: pordr(:),invp(:),iperm(:),nch(:),iw(:),parent(:),mch(0:neqns+1)
1593  integer(kind=kint), intent(in) :: neqns
1594 
1595  integer(kind=kint) :: i,j,k,l,locc,loc,locp,invpos,ipinv,ii
1596 
1597  do i=1,neqns
1598  mch(i)=0
1599  pordr(i)=0
1600  enddo
1601  l=1
1602  locc=neqns+1
1603 10 continue
1604  loc=locc
1605  locc=btree(1,loc)
1606  if(locc.ne.0) goto 10
1607  locp=qarent(loc)
1608  mch(locp)=mch(locp)+1
1609 20 continue
1610  pordr(loc)=l
1611  if(l.ge.neqns) goto 1000
1612  l=l+1
1613  locc=btree(2,loc)
1614  if(locc.ne.0) goto 10
1615  loc=qarent(loc)
1616  locp=qarent(loc)
1617  mch(locp)=mch(locp)+mch(loc)+1
1618  goto 20
1619 1000 continue
1620  do i=1,neqns
1621  ipinv=pordr(invp(i))
1622  invp(i)=ipinv
1623  iperm(ipinv)=i
1624  iw(pordr(i))=i
1625  enddo
1626  do i=1,neqns
1627  invpos=iw(i)
1628  nch(i)=mch(invpos)
1629  ii=qarent(invpos)
1630  if(ii.gt.0.and.ii.le.neqns) then
1631  parent(i)=pordr(ii)
1632  else
1633  parent(i)=qarent(invpos)
1634  endif
1635  enddo
1636  if(ldbg) write(idbg,6020)
1637  if(ldbg) write(idbg,6000) (pordr(i),i=1,neqns)
1638  if(ldbg) write(idbg,6030)
1639  if(ldbg) write(idbg,6050)
1640  if(ldbg) write(idbg,6000) (parent(i),i=1,neqns)
1641  if(ldbg) write(idbg,6000) (invp(i),i=1,neqns)
1642  if(ldbg) write(idbg,6040)
1643  if(ldbg) write(idbg,6000) (iperm(i),i=1,neqns)
1644  if(ldbg) write(idbg,6010)
1645  if(ldbg) write(idbg,6000) (nch(i),i=1,neqns)
1646 6000 format(10i6)
1647 6010 format(' nch')
1648 6020 format(' post order')
1649 6030 format(/' invp ')
1650 6040 format(/' iperm ')
1651 6050 format(/' parent')
1652  return
1653  end subroutine posord
1654 
1655  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1656 
1657  subroutine gnleaf(xadj,adjncy,invp,iperm,pordr,nch,adjncp,xleaf,leaf,neqns,lnleaf)
1658 
1659  implicit none
1660 
1661  integer(kind=kint), intent(in) :: xadj(:),adjncy(:),pordr(:),nch(:),invp(:),iperm(:)
1662  integer(kind=kint), intent(out) :: xleaf(:),leaf(:),adjncp(:)
1663  integer(kind=kint), intent(in) :: neqns
1664 
1665  integer(kind=kint) i,j,k,l,m,n,ik,istart,ip,iq,lnleaf,lc1,lc
1666 
1667  l=1
1668  ik=0
1669  istart=0
1670  do 100 i=1,neqns
1671  xleaf(i)=l
1672  ip=iperm(i)
1673  do k=xadj(ip),xadj(ip+1)-1
1674  iq=invp(adjncy(k))
1675  if(iq.lt.i) then
1676  ik=ik+1
1677  adjncp(ik)=iq
1678  endif
1679  enddo
1680  m=ik-istart
1681  if(m.eq.0) goto 131
1682  call qqsort(adjncp(istart+1:),m)
1683  lc1=adjncp(istart+1)
1684  if(lc1.ge.i) goto 100
1685  leaf(l)=lc1
1686  l=l+1
1687  do k=istart+2,ik
1688  lc=adjncp(k)
1689  ! if(lc.ge.i) goto 125
1690  if(lc1.lt.lc-nch(lc)) then
1691  leaf(l)=lc
1692  l=l+1
1693  endif
1694 125 continue
1695  lc1=lc
1696  enddo
1697  ik=1
1698  istart=ik
1699 131 continue
1700 100 continue
1701  xleaf(neqns+1)=l
1702  lnleaf=l-1
1703  if(ldbg) write(idbg,6020)
1704  if(ldbg) write(idbg,6000) (xleaf(i),i=1,neqns+1)
1705  if(ldbg) write(idbg,6010) lnleaf
1706  if(ldbg) write(idbg,6000) (leaf(i),i=1,lnleaf)
1707  return
1708 6000 format(10i6)
1709 6010 format(' leaf (len = ',i6,')')
1710 6020 format(' xleaf')
1711  end subroutine gnleaf
1712 
1713  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1714 
1715  subroutine countclno(parent,xleaf,leaf,neqns,nstop,lncol,ir)
1716 
1717  implicit none
1718 
1719  ! Count total number of non-zero elements
1720  ! which include fill-in.
1721  ! A and C region of given sparse matrix will consider.
1722  ! D region will not consider because of D is treat as
1723  ! dens matrix.
1724  !
1725  integer(kind=kint), intent(in) :: parent(:),xleaf(:),leaf(:)
1726  integer(kind=kint), intent(in) :: neqns, nstop
1727  integer(kind=kint), intent(out) :: lncol, ir
1728 
1729  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
1730 
1731  nc=0
1732  ir=0
1733  l=1
1734  do 100 i=1,neqns
1735  ks=xleaf(i)
1736  ke=xleaf(i+1)-1
1737  if(ke.lt.ks) goto 100
1738  nxleaf=leaf(ks)
1739  do 110 k=ks,ke-1
1740  j=nxleaf
1741  nxleaf=leaf(k+1)
1742 105 continue
1743  if(j.ge.nxleaf) goto 110
1744  if(j.ge.nstop) then
1745  goto 100
1746  endif
1747  l=l+1
1748  j=parent(j)
1749  goto 105
1750 110 continue
1751  j=leaf(ke)
1752 115 continue
1753  if(j.ge.nstop) goto 100
1754  if(j.ge.i.or.j.eq.0) goto 100
1755  l=l+1
1756  j=parent(j)
1757  goto 115
1758 100 continue
1759  lncol=l-1
1760  return
1761  end subroutine countclno
1762 
1763  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1764 
1765  subroutine gnclno(parent,pordr,xleaf,leaf,xlnzr,colno,neqns,nstop,lncol,ir)
1766 
1767  implicit none
1768 
1769  integer(kind=kint), intent(in) :: parent(:),pordr(:),xleaf(:),leaf(:)
1770  integer(kind=kint), intent(out) :: colno(:),xlnzr(:)
1771  integer(kind=kint), intent(in) :: neqns, nstop
1772  integer(kind=kint), intent(out) :: lncol,ir
1773 
1774  integer(kind=kint) :: i,j,k,l,nc,ks,ke,nxleaf
1775 
1776  nc=0
1777  ir=0
1778  l=1
1779  do 100 i=1,neqns
1780  xlnzr(i)=l
1781  ks=xleaf(i)
1782  ke=xleaf(i+1)-1
1783  if(ke.lt.ks) goto 100
1784  nxleaf=leaf(ks)
1785  do 110 k=ks,ke-1
1786  j=nxleaf
1787  nxleaf=leaf(k+1)
1788 105 continue
1789  if(j.ge.nxleaf) goto 110
1790  if(j.ge.nstop) then
1791  goto 100
1792  endif
1793  colno(l)=j
1794  l=l+1
1795  j=parent(j)
1796  goto 105
1797 110 continue
1798  j=leaf(ke)
1799 115 continue
1800  if(j.ge.nstop) goto 100
1801  if(j.ge.i.or.j.eq.0) goto 100
1802  colno(l)=j
1803  l=l+1
1804  j=parent(j)
1805  goto 115
1806 100 continue
1807  xlnzr(neqns+1)=l
1808  lncol=l-1
1809  if(ldbg) write(idbg,6010)
1810  ! if(idbg1.ne.0) write(6,6000) (xlnzr(i),i=1,neqns+1)
1811  if(ldbg) write(idbg,6020) lncol
1812  if(ldbg) then
1813  do k=1,neqns
1814  write(idbg,6100) k
1815  write(idbg,6000) (colno(i),i=xlnzr(k),xlnzr(k+1)-1)
1816  enddo
1817  endif
1818 6000 format(10i4)
1819 6010 format(' xlnzr')
1820 6020 format(' colno (lncol =',i10,')')
1821 6100 format(/' row = ',i6)
1822  return
1823  end subroutine gnclno
1824 
1825  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1826 
1827  subroutine qmdrch(root,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
1828 
1829  implicit none
1830 
1831  integer(kind=kint), intent(in) :: deg(:),xadj(:),adjncy(:)
1832  integer(kind=kint), intent(out) :: rchset(:),marker(:),nbrhd(:)
1833  integer(kind=kint), intent(in) :: root
1834  integer(kind=kint), intent(out) :: nhdsze,rchsze
1835 
1836  integer(kind=kint) :: i,j,k,l, istrt, istop, jstrt, jstop, nabor, node
1837 
1838  nhdsze=0
1839  rchsze=0
1840  istrt=xadj(root)
1841  istop=xadj(root+1)-1
1842  if(istop.lt.istrt) return
1843  do 600 i=istrt,istop
1844  nabor=adjncy(i)
1845  if(nabor.eq.0) return
1846  if(marker(nabor).ne.0) goto 600
1847  if(deg(nabor).lt.0) goto 200
1848  rchsze=rchsze+1
1849  rchset(rchsze)=nabor
1850  marker(nabor)=1
1851  goto 600
1852 200 marker(nabor)=-1
1853  nhdsze=nhdsze+1
1854  nbrhd(nhdsze)=nabor
1855 300 jstrt=xadj(nabor)
1856  jstop=xadj(nabor+1)-1
1857  do 500 j=jstrt,jstop
1858  node=adjncy(j)
1859  nabor=-node
1860  !if(node) 300,600,400
1861  if(node<0) then
1862  goto 300
1863  elseif(node==0) then
1864  goto 600
1865  endif
1866 400 if(marker(node).ne.0) goto 500
1867  rchsze=rchsze+1
1868  rchset(rchsze)=node
1869  marker(node)=1
1870 500 continue
1871 600 continue
1872  return
1873  end subroutine qmdrch
1874 
1875  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1876 
1877  subroutine qmdupd(xadj,adjncy,nlist,list,deg,qsize,qlink,marker,rchset,nbrhd)
1878 
1879  implicit none
1880 
1881  integer(kind=kint), intent(in) :: adjncy(:),list(:),xadj(:)
1882  integer(kind=kint), intent(out) :: marker(:),nbrhd(:),rchset(:),deg(:),qsize(:),qlink(:)
1883  integer(kind=kint), intent(in) :: nlist
1884 
1885  integer(kind=kint) :: i,j,k,l, deg0,deg1,il,inhd,inode,irch,jstrt,jstop,mark,nabor,nhdsze,node,rchsze
1886 
1887  if(nlist.le.0) return
1888  deg0=0
1889  nhdsze=0
1890  do il=1,nlist
1891  node=list(il)
1892  deg0=deg0+qsize(node)
1893  jstrt=xadj(node)
1894  jstop=xadj(node+1)-1
1895 
1896  do 100 j=jstrt,jstop
1897  nabor=adjncy(j)
1898  if(marker(nabor).ne.0.or.deg(nabor).ge.0) goto 100
1899  marker(nabor)=-1
1900  nhdsze=nhdsze+1
1901  nbrhd(nhdsze)=nabor
1902 100 continue
1903  enddo
1904 
1905  if(nhdsze.gt.0) call qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,nbrhd(nhdsze+1:))
1906  do 600 il=1,nlist
1907  node=list(il)
1908  mark=marker(node)
1909  if(mark.gt.1.or.mark.lt.0) goto 600
1910  call qmdrch(node,xadj,adjncy,deg,marker,rchsze,rchset,nhdsze,nbrhd)
1911  deg1=deg0
1912  if(rchsze.le.0) goto 400
1913  do irch=1,rchsze
1914  inode=rchset(irch)
1915  deg1=deg1+qsize(inode)
1916  marker(inode)=0
1917  enddo
1918 400 deg(node)=deg1-1
1919  if(nhdsze.le.0) goto 600
1920  do inhd=1,nhdsze
1921  inode=nbrhd(inhd)
1922  marker(inode)=0
1923  enddo
1924 600 continue
1925  return
1926  end subroutine qmdupd
1927 
1928  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1929 
1930  subroutine qmdot(root,xadj,adjncy,marker,rchsze,rchset,nbrhd)
1931 
1932  implicit none
1933 
1934  integer(kind=kint), intent(in) :: marker(:),rchset(:),nbrhd(:),xadj(:)
1935  integer(kind=kint), intent(out) :: adjncy(:)
1936  integer(kind=kint), intent(in) :: rchsze,root
1937 
1938  integer(kind=kint) :: i,j,k,l,irch,inhd,node,jstrt,jstop,link,nabor
1939 
1940  irch=0
1941  inhd=0
1942  node=root
1943 100 jstrt=xadj(node)
1944  jstop=xadj(node+1)-2
1945  if(jstop.lt.jstrt) goto 300
1946  do j=jstrt,jstop
1947  irch=irch+1
1948  adjncy(j)=rchset(irch)
1949  if(irch.ge.rchsze) goto 400
1950  enddo
1951 300 link=adjncy(jstop+1)
1952  node=-link
1953  if(link.lt.0) goto 100
1954  inhd=inhd+1
1955  node=nbrhd(inhd)
1956  adjncy(jstop+1)=-node
1957  goto 100
1958 400 adjncy(j+1)=0
1959  do 600 irch=1,rchsze
1960  node=rchset(irch)
1961  if(marker(node).lt.0) goto 600
1962  jstrt=xadj(node)
1963  jstop=xadj(node+1)-1
1964  do 500 j=jstrt,jstop
1965  nabor=adjncy(j)
1966  if(marker(nabor).ge.0) goto 500
1967  adjncy(j)=root
1968  goto 600
1969 500 continue
1970 600 continue
1971  return
1972  end subroutine qmdot
1973 
1974  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1975 
1976  subroutine qmdmrg(xadj,adjncy,deg,qsize,qlink,marker,deg0,nhdsze,nbrhd,rchset,ovrlp)
1977 
1978  implicit none
1979 
1980  integer(kind=kint), intent(in) :: adjncy(:),nbrhd(:),xadj(:)
1981  integer(kind=kint), intent(out) :: deg(:),marker(:),rchset(:),ovrlp(:),qsize(:),qlink(:)
1982  integer(kind=kint), intent(in) :: nhdsze
1983 
1984  integer(kind=kint) :: i,j,k,l, deg0,deg1,head,inhd,iov,irch,jstrt,jstop,link,lnode,mark,mrgsze,nabor,node,novrlp,rchsze,root
1985 
1986 
1987  if(nhdsze.le.0) return
1988  do inhd=1,nhdsze
1989  root=nbrhd(inhd)
1990  marker(root)=0
1991  enddo
1992  do 1400 inhd=1,nhdsze
1993  root=nbrhd(inhd)
1994  marker(root)=-1
1995  rchsze=0
1996  novrlp=0
1997  deg1=0
1998 200 jstrt=xadj(root)
1999  jstop=xadj(root+1)-1
2000  do 600 j=jstrt,jstop
2001  nabor=adjncy(j)
2002  root=-nabor
2003  !if(nabor) 200,700,300
2004  if(nabor<0) then
2005  goto 200
2006  elseif(nabor==0) then
2007  goto 700
2008  endif
2009 300 mark=marker(nabor)
2010  !if(mark)600,400,500
2011  if(mark<0) then
2012  goto 600
2013  elseif(mark>0) then
2014  goto 500
2015  endif
2016 400 rchsze=rchsze+1
2017  rchset(rchsze)=nabor
2018  deg1=deg1+qsize(nabor)
2019  marker(nabor)=1
2020  goto 600
2021 500 if(mark.gt.1) goto 600
2022  novrlp=novrlp+1
2023  ovrlp(novrlp)=nabor
2024  marker(nabor)=2
2025 600 continue
2026 700 head=0
2027  mrgsze=0
2028  do 1100 iov=1,novrlp
2029  node=ovrlp(iov)
2030  jstrt=xadj(node)
2031  jstop=xadj(node+1)-1
2032  do 800 j=jstrt,jstop
2033  nabor=adjncy(j)
2034  if(marker(nabor).ne.0) goto 800
2035  marker(node)=1
2036  goto 1100
2037 800 continue
2038  mrgsze=mrgsze+qsize(node)
2039  marker(node)=-1
2040  lnode=node
2041 900 link=qlink(lnode)
2042  if(link.le.0) goto 1000
2043  lnode=link
2044  goto 900
2045 1000 qlink(lnode)=head
2046  head=node
2047 1100 continue
2048  if(head.le.0) goto 1200
2049  qsize(head)=mrgsze
2050  deg(head)=deg0+deg1-1
2051  marker(head)=2
2052 1200 root=nbrhd(inhd)
2053  marker(root)=0
2054  if(rchsze.le.0) goto 1400
2055  do irch=1,rchsze
2056  node=rchset(irch)
2057  marker(node)=0
2058  enddo
2059 1400 continue
2060  return
2061  end subroutine qmdmrg
2062 
2063  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2064 
2065  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)
2066  ! find fill-in position in C which placed under A and set it in xlnzr_c, colno_c
2067 
2068  use m_crs_matrix_lag
2069  implicit none
2070  !input
2071  integer(kind=kint), intent(in) :: xlnzr_a(:)
2072  integer(kind=kint), intent(in) :: colno_a(:)
2073  integer(kind=kint), intent(in) :: iperm_a(:)
2074  integer(kind=kint), intent(in) :: invp_a(:)
2075  integer(kind=kint), intent(in) :: ndeg
2076  integer(kind=kint), intent(in) :: nttbr_c
2077  integer(kind=kint), intent(in) :: irow_c(:)
2078  integer(kind=kint), intent(inout) :: jcol_c(:)
2079  integer(kind=kint), intent(in) :: ncol
2080  integer(kind=kint), intent(in) :: nrow
2081 
2082  !output
2083  integer(kind=kint), pointer :: xlnzr_c(:)
2084  integer(kind=kint), pointer :: colno_c(:)
2085  integer(kind=kint), intent(out) :: lncol_c
2086 
2087  ! internal
2088  integer(kind=kint) :: i,j,k,l,m,n
2089  integer(kind=kint) :: ks, ke, ipass, ierr
2090  logical, allocatable :: cnz(:)
2091  type(crs_matrix) :: crs_c
2092 
2093  !permtate column in C for crs_c
2094  do i=1,nttbr_c
2095  jcol_c(i)=invp_a(jcol_c(i))
2096  end do
2097 
2098  ! make Compact Column Storoge using symbolic information.
2099  call symbolicirjctocrs(ndeg, nttbr_c, irow_c, jcol_c, ncol, nrow, crs_c)
2100 
2101  ! symbolic LDU factorization for C matrix
2102  allocate(cnz(ncol), stat=ierr)
2103  if(ierr .ne. 0) then
2104  call errtrp('stop due to allocation error.')
2105  end if
2106  do ipass = 1,2
2107  lncol_c = 0
2108  do k=1,nrow
2109  ! set cnz as non-zero pattern of C
2110  cnz = .false.
2111  ks = crs_c%ia(k)
2112  ke = crs_c%ia(k+1)-1
2113  if (ke .lt. ks) then
2114  if (ipass .eq. 2) then
2115  xlnzr_c(k+1)=lncol_c+1
2116  end if
2117  cycle ! in case of zero vector, no need to check dot product. not cycle?
2118  end if
2119 
2120  do i=ks,ke
2121  cnz(crs_c%ja(i)) = .true.
2122  end do
2123 
2124  ! check for non-zero dot product and update cnz for each point of cnz
2125  do i=2,ncol
2126  ks = xlnzr_a(i)
2127  ke = xlnzr_a(i+1)-1
2128  if (ke .lt. ks) then ! in case of column of A is zero vector.
2129  cycle
2130  end if
2131  do j=ks,ke
2132  if (cnz(colno_a(j))) then
2133  cnz(i) = .true.
2134  exit
2135  end if
2136  end do
2137  end do
2138 
2139  do i=1,ncol
2140  if (cnz(i)) then
2141  lncol_c = lncol_c + 1
2142  if (ipass .eq. 2) then
2143  colno_c(lncol_c) = i
2144  end if
2145  end if
2146  end do
2147  if (ipass .eq. 2) then
2148  xlnzr_c(k+1)=lncol_c + 1
2149  end if
2150  end do
2151 
2152  if (ipass .eq. 1) then
2153  allocate(xlnzr_c(nrow+1),colno_c(lncol_c), stat=ierr)
2154  if(ierr .ne. 0) then
2155  call errtrp('stop due to allocation error.')
2156  end if
2157  xlnzr_c(1)=1
2158  end if
2159  end do
2160 
2161  ! restore order of C column.
2162  do i=1,nttbr_c
2163  jcol_c(i)=iperm_a(jcol_c(i))
2164  end do
2165 
2166  return
2167 
2168  end subroutine ldudecomposec
2169 
2170  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2171 
2172  subroutine qqsort(iw,ik)
2173 
2174  implicit none
2175 
2176  integer(kind=kint), intent(out) :: iw(:)
2177  integer(kind=kint), intent(in) :: ik
2178 
2179  integer(kind=kint) :: l,m,itemp
2180 
2181  !----------------------------------------------------------------------
2182  ! sort in increasing order up to i
2183  !
2184  ! iw array
2185  ! ik number of input/output
2186  ! i deal with numbers less than this numberi
2187  !
2188  !----------------------------------------------------------------------
2189 
2190  if(ik.le.1) return
2191  do l=1,ik-1
2192  do 110 m=l+1,ik
2193  if(iw(l).lt.iw(m)) goto 110
2194  itemp=iw(l)
2195  iw(l)=iw(m)
2196  iw(m)=itemp
2197 110 continue
2198  enddo
2199 200 continue
2200  return
2201  end subroutine qqsort
2202 
2203 
2204  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2205 
2206  subroutine staij1(isw,i,j,aij,dsi,ir)
2207 
2208  implicit none
2209 
2210  !----------------------------------------------------------------------
2211  !
2212  ! this routine sets an non-zero entry of the matrix.
2213  ! (symmetric version)
2214  !
2215  ! (i)
2216  ! isw =0 set the value
2217  ! =1 add the value
2218  ! i row entry
2219  ! j column entry
2220  ! aij value
2221  !
2222  ! (o)
2223  ! iv communication array
2224  !
2225  ! #coded by t.arakawa
2226  !
2227  !----------------------------------------------------------------------
2228  !
2229  type(dsinfo) :: dsi
2230  real(kind=kreal), intent(out) :: aij(:) ! ndeg*ndeg
2231  integer(kind=kint), intent(in) :: isw, i, j
2232  integer(kind=kint), intent(out) :: ir
2233 
2234  integer(kind=kint) :: ndeg, neqns, nstop, ndeg2, ndeg2l, ierr
2235  ndeg=dsi%ndeg
2236  neqns=dsi%neqns
2237  nstop=dsi%nstop
2238  ndeg2=ndeg*ndeg
2239  ndeg2l=ndeg*(ndeg+1)/2
2240 
2241  ir=0
2242  ierr=0
2243 
2244 
2245  ! array allocation
2246  if(dsi%stage.ne.20) then
2247  if(dsi%stage.eq.30) write(ilog,*) 'Warning a matrix was build up but never solved.'
2248  !
2249  ! for diagonal
2250  !
2251  allocate(dsi%diag(ndeg2l,neqns), stat=ierr)
2252  if(ierr .ne. 0) then
2253  call errtrp('stop due to allocation error.')
2254  end if
2255  dsi%diag=0
2256  !
2257  ! for lower triangle
2258  !
2259  allocate(dsi%zln(ndeg2,dsi%lncol), stat=ierr)
2260  if(ierr .ne. 0) then
2261  call errtrp('stop due to allocation error.')
2262  end if
2263  dsi%zln=0
2264  !
2265  ! for dense window !TODO delete this and corresponding line in addr3()
2266  !
2267  ! allocate(dsi%dsln(ndeg2,dsi%lndsln))! because of there is no dense window
2268  ! dsi%dsln=0
2269 
2270  dsi%stage=20
2271  endif
2272 
2273  ! set value
2274  if(ndeg.le.2) then
2275  call addr0(isw,i,j,aij,dsi%invp,dsi%xlnzr,dsi%colno,dsi%diag,dsi%zln,dsi%dsln,nstop,dsi%ndeg,ir)
2276  elseif(ndeg.eq.3) then
2277  write(idbg,*) 'ndeg=1 only'
2278  stop
2279  else
2280  write(idbg,*) 'ndeg=1 only'
2281  stop
2282  endif
2283 1000 continue
2284  return
2285  end subroutine staij1
2286 
2287  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2288  !
2289  ! After here, routines specialized for ndeg = 1
2290  !
2291  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2292 
2293  ! LDU decompose of A (1..nstop-1) region
2294  subroutine sum(ic,xlnzr,colno,zln,diag,nch,par,neqns)
2295 
2296  implicit none
2297 
2298  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
2299  integer(kind=kint), intent(in) :: ic, neqns
2300  real(kind=kreal), intent(inout) :: zln(:),diag(:)
2301  integer(kind=kint), intent(out) :: nch(:)
2302 
2303  real(kind=kreal) :: s, t, zz, piv
2304  integer(kind=kint) :: ks, ke, kk, k, jc, jj, j, ierr
2305  integer(kind=kint) :: isem
2306  real(kind=kreal),allocatable :: temp(:)
2307  integer(kind=kint),allocatable :: indx(:)
2308  allocate(temp(neqns),indx(neqns), stat=ierr)
2309  if(ierr .ne. 0) then
2310  call errtrp('stop due to allocation error.')
2311  end if
2312 
2313 2 continue
2314  ks=xlnzr(ic)
2315  ke=xlnzr(ic+1)
2316  t=0.0d0
2317  ! do 100 i=1,ic
2318  ! temp(i)=0.0d0
2319  ! 100 continue
2320  do k=ks,ke-1
2321  jc=colno(k)
2322  indx(jc)=ic
2323  s=0.0d0
2324  do jj=xlnzr(jc),xlnzr(jc+1)-1
2325  j=colno(jj)
2326  if(indx(j).eq.ic) then
2327  s=s+temp(j)*zln(jj)
2328  endif
2329  enddo
2330  ! j1=xlnzr(jc)
2331  ! jj=xlnzr(jc+1)-j1
2332  ! ss=ddoti(jj,zln(j1),colno(j1),temp)
2333  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
2334  zz=zln(k)-s
2335  zln(k)=zz*diag(jc)
2336  temp(jc)=zz
2337  t=t+zz*zln(k)
2338  enddo
2339  piv=diag(ic)-t
2340  if(dabs(piv).gt.rmin) then
2341  diag(ic)=1.0d0/piv
2342  endif
2343 1 continue
2344  ! if(isem.eq.1) then !DBG
2345  isem=0
2346  nch(ic)=-1
2347  kk=par(ic)
2348  nch(kk)=nch(kk)-1
2349  isem=1
2350  ! else !DBG
2351  ! goto 1 !DBG
2352  ! endi !DBG
2353  return
2354  end subroutine sum
2355 
2356  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2357 
2358  ! LDU decompose of C (nstop..neqnsA+neqnsd) region
2359  subroutine sum1(ic,xlnzr,colno,zln,diag,par,neqns)
2360 
2361  implicit none
2362 
2363  integer(kind=kint), intent(in) :: xlnzr(:),colno(:),par(:)
2364  integer(kind=kint), intent(in) :: ic, neqns
2365  real(kind=kreal), intent(inout) :: zln(:),diag(:)
2366 
2367  real(kind=kreal) :: s, t, zz
2368  integer(kind=kint) :: ks, ke, k, jc, j, jj, ierr
2369  real(kind=kreal),allocatable :: temp(:)
2370  integer(kind=kint),allocatable :: indx(:)
2371  integer(kind=kint) :: i
2372 
2373  ierr=0
2374 
2375  allocate(temp(neqns),indx(neqns), stat=ierr)
2376  if(ierr .ne. 0) then
2377  call errtrp('stop due to allocation error.')
2378  end if
2379 
2380  do i=1,neqns
2381  temp(i)=0
2382  end do
2383 
2384  ks=xlnzr(ic)
2385  ke=xlnzr(ic+1)
2386  t=0.0d0
2387  ! do 100 i=1,ic
2388  ! temp(i)=0.0d0
2389  ! 100 continue
2390  do k=ks,ke-1
2391  jc=colno(k)
2392  indx(jc)=ic
2393  s=0.0d0
2394  do jj=xlnzr(jc),xlnzr(jc+1)-1
2395  j=colno(jj)
2396  if(indx(j).eq.ic) then
2397  s=s+temp(j)*zln(jj)
2398  endif
2399  enddo
2400  zz=zln(k)-s
2401  ! j1=xlnzr(jc)
2402  ! jj=xlnzr(jc+1)-j1
2403  ! zz=zln(k)-ddoti(jj,zln(j1),colno(j1),temp)
2404  zln(k)=zz
2405  temp(jc)=zz
2406  ! t=t+zz*zz*diag(jc)
2407  enddo
2408  ! diag(ic)=diag(ic)-t
2409  return
2410  end subroutine sum1
2411 
2412  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2413 
2414  ! LDU decompose and Update D region.
2415  subroutine sum2_child(neqns,nstop,xlnzr,colno,zln,diag,spdslnidx,spdslnval,nspdsln)
2416 
2417  implicit none
2418 
2419  integer(kind=kint), intent(in) :: neqns, nstop
2420  integer(kind=kint), intent(in) :: xlnzr(:),colno(:)
2421  real(kind=kreal), intent(inout) :: zln(:),diag(:)
2422  integer(kind=kint), pointer :: spdslnidx(:)
2423  real(kind=kreal), pointer :: spdslnval(:,:)
2424  integer(kind=kint), intent(out) :: nspdsln
2425 
2426  real(kind=kreal) :: s, t
2427  integer(kind=kint) :: ks, ke, kk, k, jc, jj, j, j1,j2
2428  integer(kind=kint) :: ic, i, loc, ierr
2429  integer(kind=kint) :: ispdsln
2430  logical :: ftflag
2431  real(kind=kreal),allocatable :: temp(:)
2432  integer(kind=kint),allocatable :: indx(:)
2433  ierr=0
2434  allocate(temp(neqns),indx(neqns), stat=ierr)
2435  if(ierr .ne. 0) then
2436  call errtrp('stop due to allocation error.')
2437  end if
2438  temp=0
2439 
2440  nspdsln=0
2441  do ic=nstop,neqns
2442  ks=xlnzr(ic)
2443  ke=xlnzr(ic+1)-1
2444  do k=ks,ke
2445  jj=colno(k)
2446  indx(jj)=ic
2447  end do
2448  do jc=nstop,ic-1
2449  j1=xlnzr(jc)
2450  j2=xlnzr(jc+1)
2451  do jj=xlnzr(jc),xlnzr(jc+1)-1
2452  j=colno(jj)
2453  if(indx(j).eq.ic) then
2454  nspdsln=nspdsln+1
2455  exit
2456  endif
2457  end do
2458  end do
2459  end do
2460  allocate(spdslnidx(nspdsln),spdslnval(1,nspdsln), stat=ierr)
2461  if(ierr .ne. 0) then
2462  call errtrp('stop due to allocation error.')
2463  end if
2464 
2465  loc=0
2466  ispdsln=0
2467  spdslnval=0
2468  ftflag = .true.
2469  do ic=nstop,neqns
2470  do i=1,nstop
2471  temp(i)=0.0d0
2472  enddo
2473  ks=xlnzr(ic)
2474  ke=xlnzr(ic+1)-1
2475  do k=ks,ke
2476  jj=colno(k)
2477  temp(jj)=zln(k)
2478  zln(k)=temp(jj)*diag(jj)
2479  indx(jj)=ic
2480  diag(ic)=diag(ic)-temp(jj)*zln(k)
2481  enddo
2482  do jc=nstop,ic-1
2483  loc=loc+1
2484  do jj=xlnzr(jc),xlnzr(jc+1)-1
2485  j=colno(jj)
2486  if(indx(j).eq.ic) then
2487  if (ftflag) then
2488  ispdsln=ispdsln+1
2489  ftflag=.false.
2490  end if
2491  spdslnidx(ispdsln)=loc
2492  spdslnval(1,ispdsln)=spdslnval(1,ispdsln)-temp(j)*zln(jj)
2493  endif
2494  enddo
2495  ftflag = .true.
2496  ! j1=xlnzr(jc)
2497  ! jj=xlnzr(jc+1)-j1
2498  ! dsln(loc)=dsln(loc)-ddoti(jj,zln(j1),colno(j1),temp)
2499  enddo
2500  enddo
2501  return
2502  end subroutine sum2_child
2503 
2504  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2505 
2506  subroutine sum3(n,dsln,diag)
2507 
2508  implicit none
2509 
2510  real(kind=kreal), intent(inout) :: dsln(:),diag(:)
2511  integer(kind=kint), intent(in) :: n
2512 
2513  integer(kind=kint) :: i, j, loc, ierr
2514  real(kind=kreal),allocatable :: temp(:)
2515  integer(kind=kint),allocatable :: indx(:)
2516  allocate(temp(n),indx(n), stat=ierr)
2517  if(ierr .ne. 0) then
2518  call errtrp('stop due to allocation error.')
2519  end if
2520 
2521  if(n.le.0) goto 1000
2522  indx(1)=0
2523  loc=1
2524  diag(1)=1.0d0/diag(1)
2525  do i=2,n
2526  indx(i)=loc
2527  do j=1,i-1
2528  dsln(loc)=dsln(loc)-dot_product(dsln(indx(i):indx(i)+j-2),dsln(indx(j):indx(j)+j-2))
2529  loc=loc+1
2530  enddo
2531  temp(1:i-1)=dsln(indx(i):indx(i)+i-2)*diag(1:i-1)
2532  diag(i)=diag(i)-dot_product(temp(1:i-1),dsln(indx(i):indx(i)+i-2))
2533  dsln(indx(i):indx(i)+i-2)=temp(1:i-1)
2534  diag(i)=1.0d0/diag(i)
2535  enddo
2536 1000 continue
2537 
2538  return
2539  end subroutine sum3
2540 
2541  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2542 
2543  real(kind=kreal) function spdot2(b,zln,colno,ks,ke)
2544 
2545  implicit none
2546 
2547  integer(kind=kint), intent(in) :: colno(:)
2548  integer(kind=kint), intent(in) :: ks,ke
2549  real(kind=kreal), intent(in) :: zln(:),b(:)
2550 
2551  integer(kind=kint) :: j,jj
2552  real(kind=kreal) :: s
2553 
2554  !----------------------------------------------------------------------
2555  !
2556  ! spdot1 performs inner product of sparse vectors
2557  !
2558  !
2559  ! #coded by t.arakawa
2560  !
2561  !----------------------------------------------------------------------
2562  !
2563  s=0.0d0
2564  do jj=ks,ke
2565  j=colno(jj)
2566  s=s+zln(jj)*b(j)
2567  enddo
2568  spdot2=s
2569  end function spdot2
2570 
2571  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2572 
2573  real(kind=kreal) function ddot(a,b,n)
2574 
2575  implicit none
2576 
2577  real(kind=kreal), intent(in) :: a(n),b(n)
2578  integer(kind=kint), intent(in) :: n
2579 
2580  real(kind=kreal) :: s
2581  integer(kind=kint) :: i
2582 
2583  s=0.0d0
2584  do i=1,n
2585  s=s+a(i)*b(i)
2586  enddo
2587  ddot=s
2588  return
2589  end function ddot
2590 
2591  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2592 
2593  subroutine addr0(isw,i,j,aij,invp,xlnzr,colno,diag,zln,dsln,nstop,ndeg,ir)
2594 
2595  implicit none
2596 
2597  integer(kind=kint), intent(in) :: isw ! 0: renew diag, dsln, zln other: add to diag, dsln, zln
2598  integer(kind=kint), intent(in) :: i,j,nstop, ndeg, invp(:),xlnzr(:),colno(:)
2599  real(kind=kreal), intent(inout) :: zln(:,:),diag(:,:),dsln(:,:),aij(:)
2600  integer(kind=kint), intent(out) :: ir
2601 
2602  integer(kind=kint) :: ndeg2, ii, jj, itrans, k, i0, j0, l, ks, ke
2603  integer(kind=kint), parameter :: idbg=0
2604  ndeg2=ndeg*ndeg
2605 
2606  ir=0
2607  ii=invp(i)
2608  jj=invp(j)
2609  if(idbg.ne.0) write(idbg,*) 'addr0',ii,jj,aij
2610  if(ii.eq.jj) then
2611  if(ndeg2.eq.1) then
2612  if(isw.eq.0) then
2613  diag(1,ii)=aij(1)
2614  else
2615  diag(1,ii)=diag(1,ii)+aij(1)
2616  endif
2617  elseif(ndeg2.eq.4) then
2618  if(isw.eq.0) then
2619  diag(1,ii)=aij(1)
2620  diag(2,ii)=aij(2)
2621  diag(3,ii)=aij(4)
2622  else
2623  diag(1,ii)=diag(1,ii)+aij(1)
2624  diag(2,ii)=diag(2,ii)+aij(2)
2625  diag(3,ii)=diag(3,ii)+aij(4)
2626  endif
2627  endif
2628  goto 1000
2629  endif
2630  itrans=0
2631  if(jj.gt.ii) then
2632  k=jj
2633  jj=ii
2634  ii=k
2635  itrans=1
2636  endif
2637  if(jj.ge.nstop) then
2638  i0=ii-nstop
2639  j0=jj-nstop+1
2640  k=i0*(i0-1)/2+j0
2641  if(ndeg2.eq.1) then
2642  dsln(1,k)=aij(1)
2643  goto 1000
2644  elseif(ndeg2.eq.4) then
2645  if(itrans.eq.0) then
2646  do l=1,ndeg2
2647  dsln(l,k)=aij(l)
2648  enddo
2649  goto 1000
2650  else
2651  dsln(1,k)=aij(1)
2652  dsln(2,k)=aij(3)
2653  dsln(3,k)=aij(2)
2654  dsln(4,k)=aij(4)
2655  goto 1000
2656  endif
2657  endif
2658  endif
2659  ks=xlnzr(ii)
2660  ke=xlnzr(ii+1)-1
2661  do k=ks,ke
2662  if(colno(k).eq.jj) then
2663  if(isw.eq.0) then
2664  if(ndeg2.eq.1) then
2665  zln(1,k)=aij(1)
2666  elseif(ndeg2.eq.4) then
2667  if(itrans.eq.0) then
2668  do l=1,ndeg2
2669  zln(l,k)=aij(l)
2670  enddo
2671  else
2672  zln(1,k)=aij(1)
2673  zln(2,k)=aij(3)
2674  zln(3,k)=aij(2)
2675  zln(4,k)=aij(4)
2676  endif
2677  endif
2678  else
2679  if(ndeg2.eq.1) then
2680  zln(1,k)=zln(1,k)+aij(1)
2681  elseif(ndeg2.eq.4) then
2682  if(itrans.eq.0) then
2683  do l=1,ndeg2
2684  zln(l,k)=zln(l,k)+aij(l)
2685  enddo
2686  else
2687  zln(1,k)=zln(1,k)+aij(1)
2688  zln(2,k)=zln(2,k)+aij(3)
2689  zln(3,k)=zln(3,k)+aij(2)
2690  zln(4,k)=zln(4,k)+aij(4)
2691  endif
2692  endif
2693  endif
2694  goto 1000
2695  endif
2696  enddo
2697  ir=20
2698 1000 continue
2699  return
2700  end subroutine addr0
2701 
2702  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2703 
2704  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2705 
2706  subroutine verif0(ndeg,neqns_a0,nttbr_a0,irow_a0,jcol_a0,val_a0,neqns_l,nttbr_l,irow_l,jcol_l,val_l,rhs,x)
2707 
2708  implicit none
2709 
2710  integer(kind=kint), intent(in) :: ndeg
2711 
2712  integer(kind=kint), intent(in) :: irow_a0(:),jcol_a0(:)
2713  integer(kind=kint), intent(in) :: neqns_a0,nttbr_a0
2714  real(kind=kreal), intent(in) :: val_a0(:,:)
2715  integer(kind=kint), intent(in) :: irow_l(:),jcol_l(:)
2716  integer(kind=kint), intent(in) :: neqns_l,nttbr_l
2717  real(kind=kreal), intent(in) :: val_l(:,:)
2718 
2719  real(kind=kreal), intent(in) :: x(:,:)
2720  real(kind=kreal), intent(out) :: rhs(:,:)
2721 
2722  integer(kind=kint) :: i,j,k,l,m
2723  real(kind=kreal) :: rel,err
2724  !
2725  !----------------------------------------------------------------------
2726  !
2727  ! verify the solution(symmetric matrix)
2728  !
2729  ! ndeg=1 only
2730  !
2731  ! include lagrange elements as L region.
2732  !
2733  ! A0 | +
2734  ! A0 | |
2735  ! A0 | | neqns_a0
2736  ! A0 | |
2737  ! A0| +
2738  ! ----------+--- -
2739  ! |0 +
2740  ! | 0 | neqns_l
2741  ! laglange | 0 +
2742  !
2743  !
2744  !----------------------------------------------------------------------
2745  !
2746  rel=0.0d0
2747  do i=1,neqns_a0+neqns_l
2748  do l=1,ndeg
2749  rel=rel+dabs(rhs(l,i))
2750  enddo
2751  enddo
2752 
2753  ! A0 region
2754  do k=1,nttbr_a0
2755  i=irow_a0(k)
2756  j=jcol_a0(k)
2757  do l=1,ndeg
2758  do m=1,ndeg
2759  rhs(l,i)=rhs(l,i)-val_a0(1,k)*x(m,j)
2760  if(i.ne.j) rhs(l,j)=rhs(l,j)-val_a0(1,k)*x(m,i)
2761  end do
2762  end do
2763  end do
2764 
2765  ! lagrange region
2766  do k=1,nttbr_l
2767  i=irow_l(k)+neqns_a0
2768  j=jcol_l(k)
2769  do l=1,ndeg
2770  do m=1,ndeg
2771  rhs(l,i)=rhs(l,i)-val_l(1,k)*x(m,j)
2772  if(i.ne.j) rhs(l,j)=rhs(l,j)-val_l(1,k)*x(m,i)
2773  end do
2774  end do
2775  end do
2776 
2777  err=0.0d0
2778  do i=1,neqns_a0 + neqns_l
2779  do l=1,ndeg
2780  err=err+dabs(rhs(l,i))
2781  enddo
2782  enddo
2783 
2784  write(imsg,6000) err,rel,err/rel
2785 6000 format(' ***verification***(symmetric)'/&
2786  & 'norm(Ax-b) = ',1pd20.10/&
2787  & 'norm(b) = ',1pd20.10/&
2788  & 'norm(Ax-b)/norm(b) = ',1pd20.10)
2789 6010 format(1p4d15.7)
2790  return
2791  end subroutine verif0
2792 
subroutine, public hecmw_solve_direct_serial_lag(nrows, ilag_sta, nttbr, pointers, indices, values, b)
subroutine, public symbolicirjctocrs(ndeg, nttbr, irow, jcol, ncols, nrows, c)
integer(kind=4), parameter kreal