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